• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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