1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "config.h"
22 #include "RenderView.h"
23
24 #include "Document.h"
25 #include "Element.h"
26 #include "FloatQuad.h"
27 #include "Frame.h"
28 #include "FrameView.h"
29 #include "GraphicsContext.h"
30 #include "HitTestResult.h"
31 #include "RenderLayer.h"
32 #include "RenderSelectionInfo.h"
33 #include "RenderWidget.h"
34 #include "TransformState.h"
35
36 #if USE(ACCELERATED_COMPOSITING)
37 #include "RenderLayerCompositor.h"
38 #endif
39
40 #ifdef ANDROID_LAYOUT
41 #include "Settings.h"
42 #endif
43
44 namespace WebCore {
45
RenderView(Node * node,FrameView * view)46 RenderView::RenderView(Node* node, FrameView* view)
47 : RenderBlock(node)
48 , m_frameView(view)
49 , m_selectionStart(0)
50 , m_selectionEnd(0)
51 , m_selectionStartPos(-1)
52 , m_selectionEndPos(-1)
53 , m_printImages(true)
54 , m_maximalOutlineSize(0)
55 , m_layoutState(0)
56 , m_layoutStateDisableCount(0)
57 {
58 // Clear our anonymous bit, set because RenderObject assumes
59 // any renderer with document as the node is anonymous.
60 setIsAnonymous(false);
61
62 // init RenderObject attributes
63 setInline(false);
64
65 m_minPrefWidth = 0;
66 m_maxPrefWidth = 0;
67
68 setPrefWidthsDirty(true, false);
69
70 setPositioned(true); // to 0,0 :)
71
72 // Create a new root layer for our layer hierarchy.
73 m_layer = new (node->document()->renderArena()) RenderLayer(this);
74 setHasLayer(true);
75 }
76
~RenderView()77 RenderView::~RenderView()
78 {
79 }
80
calcHeight()81 void RenderView::calcHeight()
82 {
83 if (!printing() && m_frameView)
84 setHeight(viewHeight());
85 }
86
calcWidth()87 void RenderView::calcWidth()
88 {
89 if (!printing() && m_frameView)
90 setWidth(viewWidth());
91 #ifdef ANDROID_LAYOUT
92 const Settings * settings = document()->settings();
93 ASSERT(settings);
94 if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen)
95 m_visibleWidth = m_frameView->screenWidth();
96 if (settings->useWideViewport() && settings->viewportWidth() == -1 && width() < minPrefWidth())
97 setWidth(m_minPrefWidth);
98 #endif
99 m_marginLeft = 0;
100 m_marginRight = 0;
101 }
102
calcPrefWidths()103 void RenderView::calcPrefWidths()
104 {
105 ASSERT(prefWidthsDirty());
106
107 RenderBlock::calcPrefWidths();
108
109 m_maxPrefWidth = m_minPrefWidth;
110 }
111
layout()112 void RenderView::layout()
113 {
114 if (printing())
115 m_minPrefWidth = m_maxPrefWidth = width();
116
117 // Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
118 bool relayoutChildren = !printing() && (!m_frameView || width() != viewWidth() || height() != viewHeight());
119 if (relayoutChildren) {
120 setChildNeedsLayout(true, false);
121 for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
122 if (child->style()->height().isPercent() || child->style()->minHeight().isPercent() || child->style()->maxHeight().isPercent())
123 child->setChildNeedsLayout(true, false);
124 }
125 }
126
127 ASSERT(!m_layoutState);
128 LayoutState state;
129 // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
130 state.m_clipped = false;
131 m_layoutState = &state;
132
133 if (needsLayout())
134 RenderBlock::layout();
135
136 // Reset overflow and then replace it with docWidth and docHeight.
137 m_overflow.clear();
138 addLayoutOverflow(IntRect(0, 0, docWidth(), docHeight()));
139
140
141 ASSERT(layoutDelta() == IntSize());
142 ASSERT(m_layoutStateDisableCount == 0);
143 ASSERT(m_layoutState == &state);
144 m_layoutState = 0;
145 setNeedsLayout(false);
146 }
147
mapLocalToContainer(RenderBoxModelObject * repaintContainer,bool fixed,bool,TransformState & transformState) const148 void RenderView::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool /*useTransforms*/, TransformState& transformState) const
149 {
150 // If a container was specified, and was not 0 or the RenderView,
151 // then we should have found it by now.
152 ASSERT_UNUSED(repaintContainer, !repaintContainer || repaintContainer == this);
153
154 #ifdef ANDROID_FIXED_ELEMENTS
155 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
156 const Settings * settings = document()->settings();
157 if (settings && (settings->viewportWidth() == -1 || settings->viewportWidth() == 0) &&
158 !settings->viewportUserScalable())
159 #else
160 if (false)
161 #endif
162 #endif
163 if (fixed && m_frameView)
164 transformState.move(m_frameView->scrollOffset());
165 }
166
mapAbsoluteToLocalPoint(bool fixed,bool,TransformState & transformState) const167 void RenderView::mapAbsoluteToLocalPoint(bool fixed, bool /*useTransforms*/, TransformState& transformState) const
168 {
169 #ifdef ANDROID_FIXED_ELEMENTS
170 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
171 const Settings * settings = document()->settings();
172 if (settings && (settings->viewportWidth() == -1 || settings->viewportWidth() == 0) &&
173 !settings->viewportUserScalable())
174 #else
175 if (false)
176 #endif
177 #endif
178 if (fixed && m_frameView)
179 transformState.move(-m_frameView->scrollOffset());
180 }
181
paint(PaintInfo & paintInfo,int tx,int ty)182 void RenderView::paint(PaintInfo& paintInfo, int tx, int ty)
183 {
184 // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
185 ASSERT(!needsLayout());
186
187 // Cache the print rect because the dirty rect could get changed during painting.
188 if (printing())
189 setPrintRect(paintInfo.rect);
190 else
191 setPrintRect(IntRect());
192 paintObject(paintInfo, tx, ty);
193 }
194
rendererObscuresBackground(RenderObject * object)195 static inline bool rendererObscuresBackground(RenderObject* object)
196 {
197 return object && object->style()->visibility() == VISIBLE && object->style()->opacity() == 1 && !object->style()->hasTransform();
198 }
199
paintBoxDecorations(PaintInfo & paintInfo,int,int)200 void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int, int)
201 {
202 // Check to see if we are enclosed by a layer that requires complex painting rules. If so, we cannot blit
203 // when scrolling, and we need to use slow repaints. Examples of layers that require this are transparent layers,
204 // layers with reflections, or transformed layers.
205 // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being inside
206 // a transform, transparency layer, etc.
207 Element* elt;
208 for (elt = document()->ownerElement(); view() && elt && elt->renderer(); elt = elt->document()->ownerElement()) {
209 RenderLayer* layer = elt->renderer()->enclosingLayer();
210 if (layer->requiresSlowRepaints()) {
211 frameView()->setUseSlowRepaints();
212 break;
213 }
214 }
215
216 // If painting will entirely fill the view, no need to fill the background.
217 if (elt || rendererObscuresBackground(firstChild()) || !view())
218 return;
219
220 // This code typically only executes if the root element's visibility has been set to hidden,
221 // or there is a transform on the <html>.
222 // Only fill with the base background color (typically white) if we're the root document,
223 // since iframes/frames with no background in the child document should show the parent's background.
224 if (view()->isTransparent()) // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being transparent.
225 frameView()->setUseSlowRepaints(); // The parent must show behind the child.
226 else {
227 Color baseColor = frameView()->baseBackgroundColor();
228 if (baseColor.alpha() > 0) {
229 paintInfo.context->save();
230 paintInfo.context->setCompositeOperation(CompositeCopy);
231 paintInfo.context->fillRect(paintInfo.rect, baseColor, style()->colorSpace());
232 paintInfo.context->restore();
233 } else
234 paintInfo.context->clearRect(paintInfo.rect);
235 }
236 }
237
shouldRepaint(const IntRect & r) const238 bool RenderView::shouldRepaint(const IntRect& r) const
239 {
240 if (printing() || r.width() == 0 || r.height() == 0)
241 return false;
242
243 if (!m_frameView)
244 return false;
245
246 return true;
247 }
248
repaintViewRectangle(const IntRect & ur,bool immediate)249 void RenderView::repaintViewRectangle(const IntRect& ur, bool immediate)
250 {
251 if (!shouldRepaint(ur))
252 return;
253
254 // We always just invalidate the root view, since we could be an iframe that is clipped out
255 // or even invisible.
256 Element* elt = document()->ownerElement();
257 if (!elt)
258 m_frameView->repaintContentRectangle(ur, immediate);
259 else if (RenderBox* obj = elt->renderBox()) {
260 IntRect vr = viewRect();
261 IntRect r = intersection(ur, vr);
262
263 // Subtract out the contentsX and contentsY offsets to get our coords within the viewing
264 // rectangle.
265 r.move(-vr.x(), -vr.y());
266
267 // FIXME: Hardcoded offsets here are not good.
268 r.move(obj->borderLeft() + obj->paddingLeft(),
269 obj->borderTop() + obj->paddingTop());
270 obj->repaintRectangle(r, immediate);
271 }
272 }
273
repaintRectangleInViewAndCompositedLayers(const IntRect & ur,bool immediate)274 void RenderView::repaintRectangleInViewAndCompositedLayers(const IntRect& ur, bool immediate)
275 {
276 if (!shouldRepaint(ur))
277 return;
278
279 repaintViewRectangle(ur, immediate);
280
281 #if USE(ACCELERATED_COMPOSITING)
282 // If we're a frame, repaintViewRectangle will have repainted via a RenderObject in the
283 // parent document.
284 if (document()->ownerElement())
285 return;
286
287 if (compositor()->inCompositingMode())
288 compositor()->repaintCompositedLayersAbsoluteRect(ur);
289 #endif
290 }
291
computeRectForRepaint(RenderBoxModelObject * repaintContainer,IntRect & rect,bool fixed)292 void RenderView::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed)
293 {
294 // If a container was specified, and was not 0 or the RenderView,
295 // then we should have found it by now.
296 ASSERT_UNUSED(repaintContainer, !repaintContainer || repaintContainer == this);
297
298 if (printing())
299 return;
300
301 #ifdef ANDROID_FIXED_ELEMENTS
302 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
303 const Settings * settings = document()->settings();
304 if (settings && (settings->viewportWidth() == -1 || settings->viewportWidth() == 0) &&
305 !settings->viewportUserScalable())
306 #else
307 if (false)
308 #endif
309 #endif
310 if (fixed && m_frameView)
311 rect.move(m_frameView->scrollX(), m_frameView->scrollY());
312
313 // Apply our transform if we have one (because of full page zooming).
314 if (m_layer && m_layer->transform())
315 rect = m_layer->transform()->mapRect(rect);
316 }
317
absoluteRects(Vector<IntRect> & rects,int tx,int ty)318 void RenderView::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
319 {
320 rects.append(IntRect(tx, ty, m_layer->width(), m_layer->height()));
321 }
322
absoluteQuads(Vector<FloatQuad> & quads)323 void RenderView::absoluteQuads(Vector<FloatQuad>& quads)
324 {
325 quads.append(FloatRect(0, 0, m_layer->width(), m_layer->height()));
326 }
327
rendererAfterPosition(RenderObject * object,unsigned offset)328 static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
329 {
330 if (!object)
331 return 0;
332
333 RenderObject* child = object->childAt(offset);
334 return child ? child : object->nextInPreOrderAfterChildren();
335 }
336
selectionBounds(bool clipToVisibleContent) const337 IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
338 {
339 document()->updateStyleIfNeeded();
340
341 typedef HashMap<RenderObject*, RenderSelectionInfo*> SelectionMap;
342 SelectionMap selectedObjects;
343
344 RenderObject* os = m_selectionStart;
345 RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
346 while (os && os != stop) {
347 if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
348 // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
349 selectedObjects.set(os, new RenderSelectionInfo(os, clipToVisibleContent));
350 RenderBlock* cb = os->containingBlock();
351 while (cb && !cb->isRenderView()) {
352 RenderSelectionInfo* blockInfo = selectedObjects.get(cb);
353 if (blockInfo)
354 break;
355 selectedObjects.set(cb, new RenderSelectionInfo(cb, clipToVisibleContent));
356 cb = cb->containingBlock();
357 }
358 }
359
360 os = os->nextInPreOrder();
361 }
362
363 // Now create a single bounding box rect that encloses the whole selection.
364 IntRect selRect;
365 SelectionMap::iterator end = selectedObjects.end();
366 for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
367 RenderSelectionInfo* info = i->second;
368 // RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
369 IntRect currRect = info->rect();
370 if (RenderBoxModelObject* repaintContainer = info->repaintContainer()) {
371 FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currRect));
372 currRect = absQuad.enclosingBoundingBox();
373 }
374 selRect.unite(currRect);
375 delete info;
376 }
377 return selRect;
378 }
379
380 #if USE(ACCELERATED_COMPOSITING)
381 // Compositing layer dimensions take outline size into account, so we have to recompute layer
382 // bounds when it changes.
383 // FIXME: This is ugly; it would be nice to have a better way to do this.
setMaximalOutlineSize(int o)384 void RenderView::setMaximalOutlineSize(int o)
385 {
386 if (o != m_maximalOutlineSize) {
387 m_maximalOutlineSize = o;
388
389 // maximalOutlineSize affects compositing layer dimensions.
390 compositor()->setCompositingLayersNeedRebuild(); // FIXME: this really just needs to be a geometry update.
391 }
392 }
393 #endif
394
setSelection(RenderObject * start,int startPos,RenderObject * end,int endPos,SelectionRepaintMode blockRepaintMode)395 void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
396 {
397 // Make sure both our start and end objects are defined.
398 // Check www.msnbc.com and try clicking around to find the case where this happened.
399 if ((start && !end) || (end && !start))
400 return;
401
402 // Just return if the selection hasn't changed.
403 if (m_selectionStart == start && m_selectionStartPos == startPos &&
404 m_selectionEnd == end && m_selectionEndPos == endPos)
405 return;
406
407 // Record the old selected objects. These will be used later
408 // when we compare against the new selected objects.
409 int oldStartPos = m_selectionStartPos;
410 int oldEndPos = m_selectionEndPos;
411
412 // Objects each have a single selection rect to examine.
413 typedef HashMap<RenderObject*, RenderSelectionInfo*> SelectedObjectMap;
414 SelectedObjectMap oldSelectedObjects;
415 SelectedObjectMap newSelectedObjects;
416
417 // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
418 // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
419 // the union of those rects might remain the same even when changes have occurred.
420 typedef HashMap<RenderBlock*, RenderBlockSelectionInfo*> SelectedBlockMap;
421 SelectedBlockMap oldSelectedBlocks;
422 SelectedBlockMap newSelectedBlocks;
423
424 RenderObject* os = m_selectionStart;
425 RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
426 while (os && os != stop) {
427 if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
428 // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
429 oldSelectedObjects.set(os, new RenderSelectionInfo(os, true));
430 RenderBlock* cb = os->containingBlock();
431 while (cb && !cb->isRenderView()) {
432 RenderBlockSelectionInfo* blockInfo = oldSelectedBlocks.get(cb);
433 if (blockInfo)
434 break;
435 oldSelectedBlocks.set(cb, new RenderBlockSelectionInfo(cb));
436 cb = cb->containingBlock();
437 }
438 }
439
440 os = os->nextInPreOrder();
441 }
442
443 // Now clear the selection.
444 SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
445 for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
446 i->first->setSelectionState(SelectionNone);
447
448 // set selection start and end
449 m_selectionStart = start;
450 m_selectionStartPos = startPos;
451 m_selectionEnd = end;
452 m_selectionEndPos = endPos;
453
454 // Update the selection status of all objects between m_selectionStart and m_selectionEnd
455 if (start && start == end)
456 start->setSelectionState(SelectionBoth);
457 else {
458 if (start)
459 start->setSelectionState(SelectionStart);
460 if (end)
461 end->setSelectionState(SelectionEnd);
462 }
463
464 RenderObject* o = start;
465 stop = rendererAfterPosition(end, endPos);
466
467 while (o && o != stop) {
468 if (o != start && o != end && o->canBeSelectionLeaf())
469 o->setSelectionState(SelectionInside);
470 o = o->nextInPreOrder();
471 }
472
473 m_layer->clearBlockSelectionGapsBounds();
474
475 // Now that the selection state has been updated for the new objects, walk them again and
476 // put them in the new objects list.
477 o = start;
478 while (o && o != stop) {
479 if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
480 newSelectedObjects.set(o, new RenderSelectionInfo(o, true));
481 RenderBlock* cb = o->containingBlock();
482 while (cb && !cb->isRenderView()) {
483 RenderBlockSelectionInfo* blockInfo = newSelectedBlocks.get(cb);
484 if (blockInfo)
485 break;
486 newSelectedBlocks.set(cb, new RenderBlockSelectionInfo(cb));
487 cb = cb->containingBlock();
488 }
489 }
490
491 o = o->nextInPreOrder();
492 }
493
494 if (!m_frameView) {
495 // We built the maps, but we aren't going to use them.
496 // We need to delete the values, otherwise they'll all leak!
497 deleteAllValues(oldSelectedObjects);
498 deleteAllValues(newSelectedObjects);
499 deleteAllValues(oldSelectedBlocks);
500 deleteAllValues(newSelectedBlocks);
501 return;
502 }
503
504 m_frameView->beginDeferredRepaints();
505
506 // Have any of the old selected objects changed compared to the new selection?
507 for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
508 RenderObject* obj = i->first;
509 RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
510 RenderSelectionInfo* oldInfo = i->second;
511 if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
512 (m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
513 (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
514 oldInfo->repaint();
515 if (newInfo) {
516 newInfo->repaint();
517 newSelectedObjects.remove(obj);
518 delete newInfo;
519 }
520 }
521 delete oldInfo;
522 }
523
524 // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
525 SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
526 for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i) {
527 RenderSelectionInfo* newInfo = i->second;
528 newInfo->repaint();
529 delete newInfo;
530 }
531
532 // Have any of the old blocks changed?
533 SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
534 for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
535 RenderBlock* block = i->first;
536 RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
537 RenderBlockSelectionInfo* oldInfo = i->second;
538 if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
539 if (blockRepaintMode == RepaintNewXOROld)
540 oldInfo->repaint();
541 if (newInfo) {
542 newInfo->repaint();
543 newSelectedBlocks.remove(block);
544 delete newInfo;
545 }
546 }
547 delete oldInfo;
548 }
549
550 // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
551 SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
552 for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i) {
553 RenderBlockSelectionInfo* newInfo = i->second;
554 newInfo->repaint();
555 delete newInfo;
556 }
557
558 m_frameView->endDeferredRepaints();
559 }
560
clearSelection()561 void RenderView::clearSelection()
562 {
563 m_layer->repaintBlockSelectionGaps();
564 setSelection(0, -1, 0, -1, RepaintNewMinusOld);
565 }
566
selectionStartEnd(int & startPos,int & endPos) const567 void RenderView::selectionStartEnd(int& startPos, int& endPos) const
568 {
569 startPos = m_selectionStartPos;
570 endPos = m_selectionEndPos;
571 }
572
printing() const573 bool RenderView::printing() const
574 {
575 return document()->printing();
576 }
577
updateWidgetPositions()578 void RenderView::updateWidgetPositions()
579 {
580 RenderWidgetSet::iterator end = m_widgets.end();
581 for (RenderWidgetSet::iterator it = m_widgets.begin(); it != end; ++it)
582 (*it)->updateWidgetPosition();
583 }
584
addWidget(RenderWidget * o)585 void RenderView::addWidget(RenderWidget* o)
586 {
587 m_widgets.add(o);
588 }
589
removeWidget(RenderWidget * o)590 void RenderView::removeWidget(RenderWidget* o)
591 {
592 m_widgets.remove(o);
593 }
594
viewRect() const595 IntRect RenderView::viewRect() const
596 {
597 if (printing())
598 return IntRect(0, 0, width(), height());
599 if (m_frameView)
600 return m_frameView->visibleContentRect();
601 return IntRect();
602 }
603
docHeight() const604 int RenderView::docHeight() const
605 {
606 int h = lowestPosition();
607
608 // FIXME: This doesn't do any margin collapsing.
609 // Instead of this dh computation we should keep the result
610 // when we call RenderBlock::layout.
611 int dh = 0;
612 for (RenderBox* c = firstChildBox(); c; c = c->nextSiblingBox())
613 dh += c->height() + c->marginTop() + c->marginBottom();
614
615 if (dh > h)
616 h = dh;
617
618 return h;
619 }
620
docWidth() const621 int RenderView::docWidth() const
622 {
623 int w = rightmostPosition();
624
625 for (RenderBox* c = firstChildBox(); c; c = c->nextSiblingBox()) {
626 int dw = c->width() + c->marginLeft() + c->marginRight();
627 if (dw > w)
628 w = dw;
629 }
630
631 return w;
632 }
633
viewHeight() const634 int RenderView::viewHeight() const
635 {
636 int height = 0;
637 if (!printing() && m_frameView) {
638 height = m_frameView->layoutHeight();
639 height = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(height)) : height;
640 }
641 return height;
642 }
643
viewWidth() const644 int RenderView::viewWidth() const
645 {
646 int width = 0;
647 if (!printing() && m_frameView) {
648 width = m_frameView->layoutWidth();
649 width = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(width)) : width;
650 }
651 return width;
652 }
653
zoomFactor() const654 float RenderView::zoomFactor() const
655 {
656 if (m_frameView->frame() && m_frameView->frame()->shouldApplyPageZoom())
657 return m_frameView->frame()->zoomFactor();
658
659 return 1.0f;
660 }
661
662 // The idea here is to take into account what object is moving the pagination point, and
663 // thus choose the best place to chop it.
setBestTruncatedAt(int y,RenderBoxModelObject * forRenderer,bool forcedBreak)664 void RenderView::setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak)
665 {
666 // Nobody else can set a page break once we have a forced break.
667 if (m_forcedPageBreak)
668 return;
669
670 // Forced breaks always win over unforced breaks.
671 if (forcedBreak) {
672 m_forcedPageBreak = true;
673 m_bestTruncatedAt = y;
674 return;
675 }
676
677 // Prefer the widest object that tries to move the pagination point
678 IntRect boundingBox = forRenderer->borderBoundingBox();
679 if (boundingBox.width() > m_truncatorWidth) {
680 m_truncatorWidth = boundingBox.width();
681 m_bestTruncatedAt = y;
682 }
683 }
684
pushLayoutState(RenderObject * root)685 void RenderView::pushLayoutState(RenderObject* root)
686 {
687 ASSERT(!doingFullRepaint());
688 ASSERT(m_layoutStateDisableCount == 0);
689 ASSERT(m_layoutState == 0);
690
691 m_layoutState = new (renderArena()) LayoutState(root);
692 }
693
shouldDisableLayoutStateForSubtree(RenderObject * renderer) const694 bool RenderView::shouldDisableLayoutStateForSubtree(RenderObject* renderer) const
695 {
696 RenderObject* o = renderer;
697 while (o) {
698 if (o->hasColumns() || o->hasTransform() || o->hasReflection())
699 return true;
700 o = o->container();
701 }
702 return false;
703 }
704
updateHitTestResult(HitTestResult & result,const IntPoint & point)705 void RenderView::updateHitTestResult(HitTestResult& result, const IntPoint& point)
706 {
707 if (result.innerNode())
708 return;
709
710 Node* node = document()->documentElement();
711 if (node) {
712 result.setInnerNode(node);
713 if (!result.innerNonSharedNode())
714 result.setInnerNonSharedNode(node);
715 result.setLocalPoint(point);
716 }
717 }
718
719 #if USE(ACCELERATED_COMPOSITING)
usesCompositing() const720 bool RenderView::usesCompositing() const
721 {
722 return m_compositor && m_compositor->inCompositingMode();
723 }
724
compositor()725 RenderLayerCompositor* RenderView::compositor()
726 {
727 if (!m_compositor)
728 m_compositor.set(new RenderLayerCompositor(this));
729
730 return m_compositor.get();
731 }
732 #endif
733
didMoveOnscreen()734 void RenderView::didMoveOnscreen()
735 {
736 #if USE(ACCELERATED_COMPOSITING)
737 if (m_compositor)
738 m_compositor->didMoveOnscreen();
739 #endif
740 }
741
willMoveOffscreen()742 void RenderView::willMoveOffscreen()
743 {
744 #if USE(ACCELERATED_COMPOSITING)
745 if (m_compositor)
746 m_compositor->willMoveOffscreen();
747 #endif
748 }
749
750 } // namespace WebCore
751