• 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 "core/rendering/RenderView.h"
23 
24 #include "RuntimeEnabledFeatures.h"
25 #include "core/dom/Document.h"
26 #include "core/dom/Element.h"
27 #include "core/html/HTMLDialogElement.h"
28 #include "core/html/HTMLFrameOwnerElement.h"
29 #include "core/html/HTMLIFrameElement.h"
30 #include "core/frame/Frame.h"
31 #include "core/page/Page.h"
32 #include "core/rendering/ColumnInfo.h"
33 #include "core/rendering/CompositedLayerMapping.h"
34 #include "core/rendering/FlowThreadController.h"
35 #include "core/rendering/GraphicsContextAnnotator.h"
36 #include "core/rendering/HitTestResult.h"
37 #include "core/rendering/LayoutRectRecorder.h"
38 #include "core/rendering/RenderFlowThread.h"
39 #include "core/rendering/RenderGeometryMap.h"
40 #include "core/rendering/RenderLayer.h"
41 #include "core/rendering/RenderLayerCompositor.h"
42 #include "core/rendering/RenderSelectionInfo.h"
43 #include "core/rendering/RenderWidget.h"
44 #include "core/svg/SVGDocumentExtensions.h"
45 #include "platform/geometry/FloatQuad.h"
46 #include "platform/geometry/TransformState.h"
47 #include "platform/graphics/GraphicsContext.h"
48 #include "platform/graphics/filters/custom/CustomFilterGlobalContext.h"
49 
50 namespace WebCore {
51 
RenderView(Document * document)52 RenderView::RenderView(Document* document)
53     : RenderBlockFlow(document)
54     , m_frameView(document->view())
55     , m_selectionStart(0)
56     , m_selectionEnd(0)
57     , m_selectionStartPos(-1)
58     , m_selectionEndPos(-1)
59     , m_maximalOutlineSize(0)
60     , m_pageLogicalHeight(0)
61     , m_pageLogicalHeightChanged(false)
62     , m_layoutState(0)
63     , m_layoutStateDisableCount(0)
64     , m_renderQuoteHead(0)
65     , m_renderCounterCount(0)
66 {
67     // init RenderObject attributes
68     setInline(false);
69 
70     m_minPreferredLogicalWidth = 0;
71     m_maxPreferredLogicalWidth = 0;
72 
73     setPreferredLogicalWidthsDirty(MarkOnlyThis);
74 
75     setPositionState(AbsolutePosition); // to 0,0 :)
76 }
77 
~RenderView()78 RenderView::~RenderView()
79 {
80 }
81 
hitTest(const HitTestRequest & request,HitTestResult & result)82 bool RenderView::hitTest(const HitTestRequest& request, HitTestResult& result)
83 {
84     return hitTest(request, result.hitTestLocation(), result);
85 }
86 
hitTest(const HitTestRequest & request,const HitTestLocation & location,HitTestResult & result)87 bool RenderView::hitTest(const HitTestRequest& request, const HitTestLocation& location, HitTestResult& result)
88 {
89     // We have to recursively update layout/style here because otherwise, when the hit test recurses
90     // into a child document, it could trigger a layout on the parent document, which can destroy RenderLayers
91     // that are higher up in the call stack, leading to crashes.
92     // Note that Document::updateLayout calls its parent's updateLayout.
93     // FIXME: It should be the caller's responsibility to ensure an up-to-date layout.
94     frameView()->updateLayoutAndStyleIfNeededRecursive();
95     return layer()->hitTest(request, location, result);
96 }
97 
computeLogicalHeight(LayoutUnit logicalHeight,LayoutUnit,LogicalExtentComputedValues & computedValues) const98 void RenderView::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit, LogicalExtentComputedValues& computedValues) const
99 {
100     computedValues.m_extent = (!shouldUsePrintingLayout() && m_frameView) ? LayoutUnit(viewLogicalHeight()) : logicalHeight;
101 }
102 
updateLogicalWidth()103 void RenderView::updateLogicalWidth()
104 {
105     if (!shouldUsePrintingLayout() && m_frameView)
106         setLogicalWidth(viewLogicalWidth());
107 }
108 
availableLogicalHeight(AvailableLogicalHeightType heightType) const109 LayoutUnit RenderView::availableLogicalHeight(AvailableLogicalHeightType heightType) const
110 {
111     // If we have columns, then the available logical height is reduced to the column height.
112     if (hasColumns())
113         return columnInfo()->columnHeight();
114     return RenderBlock::availableLogicalHeight(heightType);
115 }
116 
isChildAllowed(RenderObject * child,RenderStyle *) const117 bool RenderView::isChildAllowed(RenderObject* child, RenderStyle*) const
118 {
119     return child->isBox();
120 }
121 
dialogNeedsCentering(const RenderStyle * style)122 static bool dialogNeedsCentering(const RenderStyle* style)
123 {
124     return style->position() == AbsolutePosition && style->hasAutoTopAndBottom();
125 }
126 
positionDialog(RenderBox * box)127 void RenderView::positionDialog(RenderBox* box)
128 {
129     HTMLDialogElement* dialog = toHTMLDialogElement(box->node());
130     if (dialog->centeringMode() == HTMLDialogElement::NotCentered)
131         return;
132     if (dialog->centeringMode() == HTMLDialogElement::Centered) {
133         if (dialogNeedsCentering(box->style()))
134             box->setY(dialog->centeredPosition());
135         return;
136     }
137 
138     if (!dialogNeedsCentering(box->style())) {
139         dialog->setNotCentered();
140         return;
141     }
142     FrameView* frameView = document().view();
143     int scrollTop = frameView->scrollOffset().height();
144     int visibleHeight = frameView->visibleContentRect(ScrollableArea::IncludeScrollbars).height();
145     LayoutUnit top = scrollTop;
146     if (box->height() < visibleHeight)
147         top += (visibleHeight - box->height()) / 2;
148     box->setY(top);
149     dialog->setCentered(top);
150 }
151 
positionDialogs()152 void RenderView::positionDialogs()
153 {
154     TrackedRendererListHashSet* positionedDescendants = positionedObjects();
155     if (!positionedDescendants)
156         return;
157     TrackedRendererListHashSet::iterator end = positionedDescendants->end();
158     for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
159         RenderBox* box = *it;
160         if (box->node() && box->node()->hasTagName(HTMLNames::dialogTag))
161             positionDialog(box);
162     }
163 }
164 
layoutContent(const LayoutState & state)165 void RenderView::layoutContent(const LayoutState& state)
166 {
167     ASSERT(needsLayout());
168 
169     LayoutRectRecorder recorder(*this);
170     RenderBlock::layout();
171 
172     if (RuntimeEnabledFeatures::dialogElementEnabled())
173         positionDialogs();
174 
175     if (m_frameView->partialLayout().isStopping())
176         return;
177 
178     if (hasRenderNamedFlowThreads())
179         flowThreadController()->layoutRenderNamedFlowThreads();
180 
181 #ifndef NDEBUG
182     checkLayoutState(state);
183 #endif
184 }
185 
186 #ifndef NDEBUG
checkLayoutState(const LayoutState & state)187 void RenderView::checkLayoutState(const LayoutState& state)
188 {
189     ASSERT(layoutDeltaMatches(LayoutSize()));
190     ASSERT(!m_layoutStateDisableCount);
191     ASSERT(m_layoutState == &state);
192 }
193 #endif
194 
enclosingSeamlessRenderer(const Document & doc)195 static RenderBox* enclosingSeamlessRenderer(const Document& doc)
196 {
197     Element* ownerElement = doc.seamlessParentIFrame();
198     if (!ownerElement)
199         return 0;
200     return ownerElement->renderBox();
201 }
202 
addChild(RenderObject * newChild,RenderObject * beforeChild)203 void RenderView::addChild(RenderObject* newChild, RenderObject* beforeChild)
204 {
205     // Seamless iframes are considered part of an enclosing render flow thread from the parent document. This is necessary for them to look
206     // up regions in the parent document during layout.
207     if (newChild && !newChild->isRenderFlowThread()) {
208         RenderBox* seamlessBox = enclosingSeamlessRenderer(document());
209         if (seamlessBox && seamlessBox->flowThreadContainingBlock())
210             newChild->setFlowThreadState(seamlessBox->flowThreadState());
211     }
212     RenderBlock::addChild(newChild, beforeChild);
213 }
214 
initializeLayoutState(LayoutState & state)215 bool RenderView::initializeLayoutState(LayoutState& state)
216 {
217     bool isSeamlessAncestorInFlowThread = false;
218 
219     // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
220     state.m_clipped = false;
221 
222     // Check the writing mode of the seamless ancestor. It has to match our document's writing mode, or we won't inherit any
223     // pagination information.
224     RenderBox* seamlessAncestor = enclosingSeamlessRenderer(document());
225     LayoutState* seamlessLayoutState = seamlessAncestor ? seamlessAncestor->view()->layoutState() : 0;
226     bool shouldInheritPagination = seamlessLayoutState && !m_pageLogicalHeight && seamlessAncestor->style()->writingMode() == style()->writingMode();
227 
228     state.m_pageLogicalHeight = shouldInheritPagination ? seamlessLayoutState->m_pageLogicalHeight : m_pageLogicalHeight;
229     state.m_pageLogicalHeightChanged = shouldInheritPagination ? seamlessLayoutState->m_pageLogicalHeightChanged : m_pageLogicalHeightChanged;
230     state.m_isPaginated = state.m_pageLogicalHeight;
231     if (state.m_isPaginated && shouldInheritPagination) {
232         // Set up the correct pagination offset. We can use a negative offset in order to push the top of the RenderView into its correct place
233         // on a page. We can take the iframe's offset from the logical top of the first page and make the negative into the pagination offset within the child
234         // view.
235         bool isFlipped = seamlessAncestor->style()->isFlippedBlocksWritingMode();
236         LayoutSize layoutOffset = seamlessLayoutState->layoutOffset();
237         LayoutSize iFrameOffset(layoutOffset.width() + seamlessAncestor->x() + (!isFlipped ? seamlessAncestor->borderLeft() + seamlessAncestor->paddingLeft() :
238             seamlessAncestor->borderRight() + seamlessAncestor->paddingRight()),
239             layoutOffset.height() + seamlessAncestor->y() + (!isFlipped ? seamlessAncestor->borderTop() + seamlessAncestor->paddingTop() :
240             seamlessAncestor->borderBottom() + seamlessAncestor->paddingBottom()));
241 
242         LayoutSize offsetDelta = seamlessLayoutState->m_pageOffset - iFrameOffset;
243         state.m_pageOffset = offsetDelta;
244 
245         // Set the current render flow thread to point to our ancestor. This will allow the seamless document to locate the correct
246         // regions when doing a layout.
247         if (seamlessAncestor->flowThreadContainingBlock()) {
248             flowThreadController()->setCurrentRenderFlowThread(seamlessAncestor->view()->flowThreadController()->currentRenderFlowThread());
249             isSeamlessAncestorInFlowThread = true;
250         }
251     }
252 
253     // FIXME: We need to make line grids and exclusions work with seamless iframes as well here. Basically all layout state information needs
254     // to propagate here and not just pagination information.
255     return isSeamlessAncestorInFlowThread;
256 }
257 
258 // The algorithm below assumes this is a full layout. In case there are previously computed values for regions, supplemental steps are taken
259 // to ensure the results are the same as those obtained from a full layout (i.e. the auto-height regions from all the flows are marked as needing
260 // layout).
261 // 1. The flows are laid out from the outer flow to the inner flow. This successfully computes the outer non-auto-height regions size so the
262 // inner flows have the necessary information to correctly fragment the content.
263 // 2. The flows are laid out from the inner flow to the outer flow. After an inner flow is laid out it goes into the constrained layout phase
264 // and marks the auto-height regions they need layout. This means the outer flows will relayout if they depend on regions with auto-height regions
265 // belonging to inner flows. This step will correctly set the computedAutoHeight for the auto-height regions. It's possible for non-auto-height
266 // regions to relayout if they depend on auto-height regions. This will invalidate the inner flow threads and mark them as needing layout.
267 // 3. The last step is to do one last layout if there are pathological dependencies between non-auto-height regions and auto-height regions
268 // as detected in the previous step.
layoutContentInAutoLogicalHeightRegions(const LayoutState & state)269 void RenderView::layoutContentInAutoLogicalHeightRegions(const LayoutState& state)
270 {
271     if (!m_frameView->partialLayout().isStopping()) {
272         // Disable partial layout for any two-pass layout algorithm.
273         m_frameView->partialLayout().reset();
274     }
275 
276     // We need to invalidate all the flows with auto-height regions if one such flow needs layout.
277     // If none is found we do a layout a check back again afterwards.
278     if (!flowThreadController()->updateFlowThreadsNeedingLayout()) {
279         // Do a first layout of the content. In some cases more layouts are not needed (e.g. only flows with non-auto-height regions have changed).
280         layoutContent(state);
281 
282         // If we find no named flow needing a two step layout after the first layout, exit early.
283         // Otherwise, initiate the two step layout algorithm and recompute all the flows.
284         if (!flowThreadController()->updateFlowThreadsNeedingTwoStepLayout())
285             return;
286     }
287 
288     // Layout to recompute all the named flows with auto-height regions.
289     layoutContent(state);
290 
291     // Propagate the computed auto-height values upwards.
292     // Non-auto-height regions may invalidate the flow thread because they depended on auto-height regions, but that's ok.
293     flowThreadController()->updateFlowThreadsIntoConstrainedPhase();
294 
295     // Do one last layout that should update the auto-height regions found in the main flow
296     // and solve pathological dependencies between regions (e.g. a non-auto-height region depending
297     // on an auto-height one).
298     if (needsLayout())
299         layoutContent(state);
300 }
301 
layout()302 void RenderView::layout()
303 {
304     if (!document().paginated())
305         setPageLogicalHeight(0);
306 
307     if (shouldUsePrintingLayout())
308         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = logicalWidth();
309 
310     SubtreeLayoutScope layoutScope(this);
311 
312     // Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
313     bool relayoutChildren = !shouldUsePrintingLayout() && (!m_frameView || width() != viewWidth() || height() != viewHeight());
314     if (relayoutChildren) {
315         layoutScope.setChildNeedsLayout(this);
316         for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
317             if (child->isSVGRoot())
318                 continue;
319 
320             if ((child->isBox() && toRenderBox(child)->hasRelativeLogicalHeight())
321                     || child->style()->logicalHeight().isPercent()
322                     || child->style()->logicalMinHeight().isPercent()
323                     || child->style()->logicalMaxHeight().isPercent()
324                     || child->style()->logicalHeight().isViewportPercentage()
325                     || child->style()->logicalMinHeight().isViewportPercentage()
326                     || child->style()->logicalMaxHeight().isViewportPercentage())
327                 layoutScope.setChildNeedsLayout(child);
328         }
329 
330         if (document().svgExtensions())
331             document().accessSVGExtensions()->invalidateSVGRootsWithRelativeLengthDescendents(&layoutScope);
332     }
333 
334     ASSERT(!m_layoutState);
335     if (!needsLayout())
336         return;
337 
338     LayoutState state;
339     bool isSeamlessAncestorInFlowThread = initializeLayoutState(state);
340 
341     m_pageLogicalHeightChanged = false;
342     m_layoutState = &state;
343 
344     if (checkTwoPassLayoutForAutoHeightRegions())
345         layoutContentInAutoLogicalHeightRegions(state);
346     else
347         layoutContent(state);
348 
349     if (m_frameView->partialLayout().isStopping()) {
350         m_layoutState = 0;
351         return;
352     }
353 
354 #ifndef NDEBUG
355     checkLayoutState(state);
356 #endif
357     m_layoutState = 0;
358     clearNeedsLayout();
359 
360     if (isSeamlessAncestorInFlowThread)
361         flowThreadController()->setCurrentRenderFlowThread(0);
362 }
363 
mapLocalToContainer(const RenderLayerModelObject * repaintContainer,TransformState & transformState,MapCoordinatesFlags mode,bool * wasFixed) const364 void RenderView::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
365 {
366     ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == static_cast<bool>(mode & IsFixed));
367 
368     if (!repaintContainer && mode & UseTransforms && shouldUseTransformFromContainer(0)) {
369         TransformationMatrix t;
370         getTransformFromContainer(0, LayoutSize(), t);
371         transformState.applyTransform(t);
372     }
373 
374     if (mode & IsFixed && m_frameView)
375         transformState.move(m_frameView->scrollOffsetForFixedPosition());
376 
377     if (repaintContainer == this)
378         return;
379 
380     if (mode & TraverseDocumentBoundaries) {
381         if (RenderObject* parentDocRenderer = frame()->ownerRenderer()) {
382             transformState.move(-frame()->view()->scrollOffset());
383             if (parentDocRenderer->isBox())
384                 transformState.move(toLayoutSize(toRenderBox(parentDocRenderer)->contentBoxRect().location()));
385             parentDocRenderer->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
386             return;
387         }
388     }
389 
390     // If a container was specified, and was not 0 or the RenderView,
391     // then we should have found it by now.
392     ASSERT_ARG(repaintContainer, !repaintContainer);
393 }
394 
pushMappingToContainer(const RenderLayerModelObject * ancestorToStopAt,RenderGeometryMap & geometryMap) const395 const RenderObject* RenderView::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
396 {
397     LayoutSize offsetForFixedPosition;
398     LayoutSize offset;
399     RenderObject* container = 0;
400 
401     if (m_frameView)
402         offsetForFixedPosition = m_frameView->scrollOffsetForFixedPosition();
403 
404     if (geometryMap.mapCoordinatesFlags() & TraverseDocumentBoundaries) {
405         if (RenderPart* parentDocRenderer = frame()->ownerRenderer()) {
406             offset = -m_frameView->scrollOffset();
407             offset += toLayoutSize(parentDocRenderer->contentBoxRect().location());
408             container = parentDocRenderer;
409         }
410     }
411 
412     // If a container was specified, and was not 0 or the RenderView, then we
413     // should have found it by now unless we're traversing to a parent document.
414     ASSERT_ARG(ancestorToStopAt, !ancestorToStopAt || ancestorToStopAt == this || container);
415 
416     if ((!ancestorToStopAt || container) && shouldUseTransformFromContainer(container)) {
417         TransformationMatrix t;
418         getTransformFromContainer(container, LayoutSize(), t);
419         geometryMap.push(this, t, false, false, false, true, offsetForFixedPosition);
420     } else {
421         geometryMap.push(this, offset, false, false, false, false, offsetForFixedPosition);
422     }
423 
424     return container;
425 }
426 
mapAbsoluteToLocalPoint(MapCoordinatesFlags mode,TransformState & transformState) const427 void RenderView::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
428 {
429     if (mode & IsFixed && m_frameView)
430         transformState.move(m_frameView->scrollOffsetForFixedPosition());
431 
432     if (mode & UseTransforms && shouldUseTransformFromContainer(0)) {
433         TransformationMatrix t;
434         getTransformFromContainer(0, LayoutSize(), t);
435         transformState.applyTransform(t);
436     }
437 }
438 
computeSelfHitTestRects(Vector<LayoutRect> & rects,const LayoutPoint &) const439 void RenderView::computeSelfHitTestRects(Vector<LayoutRect>& rects, const LayoutPoint&) const
440 {
441     // Record the entire size of the contents of the frame. Note that we don't just
442     // use the viewport size (containing block) here because we want to ensure this includes
443     // all children (so we can avoid walking them explicitly).
444     rects.append(LayoutRect(LayoutPoint::zero(), frameView()->contentsSize()));
445 }
446 
requiresColumns(int desiredColumnCount) const447 bool RenderView::requiresColumns(int desiredColumnCount) const
448 {
449     if (m_frameView)
450         return m_frameView->pagination().mode != Pagination::Unpaginated;
451 
452     return RenderBlock::requiresColumns(desiredColumnCount);
453 }
454 
calcColumnWidth()455 void RenderView::calcColumnWidth()
456 {
457     int columnWidth = contentLogicalWidth();
458     if (m_frameView && style()->hasInlineColumnAxis()) {
459         if (int pageLength = m_frameView->pagination().pageLength)
460             columnWidth = pageLength;
461     }
462     setDesiredColumnCountAndWidth(1, columnWidth);
463 }
464 
paginationUnit() const465 ColumnInfo::PaginationUnit RenderView::paginationUnit() const
466 {
467     if (m_frameView)
468         return m_frameView->pagination().behavesLikeColumns ? ColumnInfo::Column : ColumnInfo::Page;
469 
470     return ColumnInfo::Page;
471 }
472 
paint(PaintInfo & paintInfo,const LayoutPoint & paintOffset)473 void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
474 {
475     // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
476     ASSERT(!needsLayout());
477     // RenderViews should never be called to paint with an offset not on device pixels.
478     ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);
479 
480     ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this);
481 
482     // This avoids painting garbage between columns if there is a column gap.
483     if (m_frameView && m_frameView->pagination().mode != Pagination::Unpaginated)
484         paintInfo.context->fillRect(paintInfo.rect, m_frameView->baseBackgroundColor());
485 
486     paintObject(paintInfo, paintOffset);
487 }
488 
rendererObscuresBackground(RenderObject * rootObject)489 static inline bool rendererObscuresBackground(RenderObject* rootObject)
490 {
491     if (!rootObject)
492         return false;
493 
494     RenderStyle* style = rootObject->style();
495     if (style->visibility() != VISIBLE
496         || style->opacity() != 1
497         || style->hasTransform())
498         return false;
499 
500     if (rootObject->compositingState() == PaintsIntoOwnBacking)
501         return false;
502 
503     const RenderObject* rootRenderer = rootObject->rendererForRootBackground();
504     if (rootRenderer->style()->backgroundClip() == TextFillBox)
505         return false;
506 
507     return true;
508 }
509 
paintBoxDecorations(PaintInfo & paintInfo,const LayoutPoint &)510 void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
511 {
512     // Check to see if we are enclosed by a layer that requires complex painting rules.  If so, we cannot blit
513     // when scrolling, and we need to use slow repaints.  Examples of layers that require this are transparent layers,
514     // layers with reflections, or transformed layers.
515     // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being inside
516     // a transform, transparency layer, etc.
517     Element* elt;
518     for (elt = document().ownerElement(); view() && elt && elt->renderer(); elt = elt->document().ownerElement()) {
519         RenderLayer* layer = elt->renderer()->enclosingLayer();
520         if (layer->cannotBlitToWindow()) {
521             frameView()->setCannotBlitToWindow();
522             break;
523         }
524 
525         if (layer->enclosingCompositingLayerForRepaint()) {
526             frameView()->setCannotBlitToWindow();
527             break;
528         }
529     }
530 
531     if (document().ownerElement() || !view())
532         return;
533 
534     if (paintInfo.skipRootBackground())
535         return;
536 
537     bool rootFillsViewport = false;
538     bool rootObscuresBackground = false;
539     Node* documentElement = document().documentElement();
540     if (RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0) {
541         // The document element's renderer is currently forced to be a block, but may not always be.
542         RenderBox* rootBox = rootRenderer->isBox() ? toRenderBox(rootRenderer) : 0;
543         rootFillsViewport = rootBox && !rootBox->x() && !rootBox->y() && rootBox->width() >= width() && rootBox->height() >= height();
544         rootObscuresBackground = rendererObscuresBackground(rootRenderer);
545     }
546 
547     Page* page = document().page();
548     float pageScaleFactor = page ? page->pageScaleFactor() : 1;
549 
550     // If painting will entirely fill the view, no need to fill the background.
551     if (rootFillsViewport && rootObscuresBackground && pageScaleFactor >= 1)
552         return;
553 
554     // This code typically only executes if the root element's visibility has been set to hidden,
555     // if there is a transform on the <html>, or if there is a page scale factor less than 1.
556     // Only fill with the base background color (typically white) if we're the root document,
557     // since iframes/frames with no background in the child document should show the parent's background.
558     if (frameView()->isTransparent()) // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being transparent.
559         frameView()->setCannotBlitToWindow(); // The parent must show behind the child.
560     else {
561         Color baseColor = frameView()->baseBackgroundColor();
562         if (baseColor.alpha()) {
563             CompositeOperator previousOperator = paintInfo.context->compositeOperation();
564             paintInfo.context->setCompositeOperation(CompositeCopy);
565             paintInfo.context->fillRect(paintInfo.rect, baseColor);
566             paintInfo.context->setCompositeOperation(previousOperator);
567         } else {
568             paintInfo.context->clearRect(paintInfo.rect);
569         }
570     }
571 }
572 
shouldRepaint(const LayoutRect & rect) const573 bool RenderView::shouldRepaint(const LayoutRect& rect) const
574 {
575     if (document().printing())
576         return false;
577     return m_frameView && !rect.isEmpty();
578 }
579 
repaintViewRectangle(const LayoutRect & ur) const580 void RenderView::repaintViewRectangle(const LayoutRect& ur) const
581 {
582     if (!shouldRepaint(ur))
583         return;
584 
585     // We always just invalidate the root view, since we could be an iframe that is clipped out
586     // or even invisible.
587     Element* elt = document().ownerElement();
588     if (!elt)
589         m_frameView->repaintContentRectangle(pixelSnappedIntRect(ur));
590     else if (RenderBox* obj = elt->renderBox()) {
591         LayoutRect vr = viewRect();
592         LayoutRect r = intersection(ur, vr);
593 
594         // Subtract out the contentsX and contentsY offsets to get our coords within the viewing
595         // rectangle.
596         r.moveBy(-vr.location());
597 
598         // FIXME: Hardcoded offsets here are not good.
599         r.moveBy(obj->contentBoxRect().location());
600         obj->repaintRectangle(r);
601     }
602 }
603 
repaintRectangleInViewAndCompositedLayers(const LayoutRect & ur)604 void RenderView::repaintRectangleInViewAndCompositedLayers(const LayoutRect& ur)
605 {
606     if (!shouldRepaint(ur))
607         return;
608 
609     repaintViewRectangle(ur);
610 
611     if (compositor()->inCompositingMode()) {
612         IntRect repaintRect = pixelSnappedIntRect(ur);
613         compositor()->repaintCompositedLayers(&repaintRect);
614     }
615 }
616 
repaintViewAndCompositedLayers()617 void RenderView::repaintViewAndCompositedLayers()
618 {
619     repaint();
620 
621     if (compositor()->inCompositingMode())
622         compositor()->repaintCompositedLayers();
623 }
624 
computeRectForRepaint(const RenderLayerModelObject * repaintContainer,LayoutRect & rect,bool fixed) const625 void RenderView::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
626 {
627     // If a container was specified, and was not 0 or the RenderView,
628     // then we should have found it by now.
629     ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
630 
631     if (document().printing())
632         return;
633 
634     if (style()->isFlippedBlocksWritingMode()) {
635         // We have to flip by hand since the view's logical height has not been determined.  We
636         // can use the viewport width and height.
637         if (style()->isHorizontalWritingMode())
638             rect.setY(viewHeight() - rect.maxY());
639         else
640             rect.setX(viewWidth() - rect.maxX());
641     }
642 
643     if (fixed && m_frameView)
644         rect.move(m_frameView->scrollOffsetForFixedPosition());
645 
646     // Apply our transform if we have one (because of full page zooming).
647     if (!repaintContainer && layer() && layer()->transform())
648         rect = layer()->transform()->mapRect(rect);
649 }
650 
absoluteRects(Vector<IntRect> & rects,const LayoutPoint & accumulatedOffset) const651 void RenderView::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
652 {
653     rects.append(pixelSnappedIntRect(accumulatedOffset, layer()->size()));
654 }
655 
absoluteQuads(Vector<FloatQuad> & quads,bool * wasFixed) const656 void RenderView::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
657 {
658     if (wasFixed)
659         *wasFixed = false;
660     quads.append(FloatRect(FloatPoint(), layer()->size()));
661 }
662 
rendererAfterPosition(RenderObject * object,unsigned offset)663 static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
664 {
665     if (!object)
666         return 0;
667 
668     RenderObject* child = object->childAt(offset);
669     return child ? child : object->nextInPreOrderAfterChildren();
670 }
671 
selectionBounds(bool clipToVisibleContent) const672 IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
673 {
674     typedef HashMap<RenderObject*, OwnPtr<RenderSelectionInfo> > SelectionMap;
675     SelectionMap selectedObjects;
676 
677     RenderObject* os = m_selectionStart;
678     RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
679     while (os && os != stop) {
680         if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
681             // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
682             selectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, clipToVisibleContent)));
683             RenderBlock* cb = os->containingBlock();
684             while (cb && !cb->isRenderView()) {
685                 OwnPtr<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).iterator->value;
686                 if (blockInfo)
687                     break;
688                 blockInfo = adoptPtr(new RenderSelectionInfo(cb, clipToVisibleContent));
689                 cb = cb->containingBlock();
690             }
691         }
692 
693         os = os->nextInPreOrder();
694     }
695 
696     // Now create a single bounding box rect that encloses the whole selection.
697     LayoutRect selRect;
698     SelectionMap::iterator end = selectedObjects.end();
699     for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
700         RenderSelectionInfo* info = i->value.get();
701         // RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
702         LayoutRect currRect = info->rect();
703         if (RenderLayerModelObject* repaintContainer = info->repaintContainer()) {
704             FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currRect));
705             currRect = absQuad.enclosingBoundingBox();
706         }
707         selRect.unite(currRect);
708     }
709     return pixelSnappedIntRect(selRect);
710 }
711 
repaintSelection() const712 void RenderView::repaintSelection() const
713 {
714     HashSet<RenderBlock*> processedBlocks;
715 
716     RenderObject* end = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
717     for (RenderObject* o = m_selectionStart; o && o != end; o = o->nextInPreOrder()) {
718         if (!o->canBeSelectionLeaf() && o != m_selectionStart && o != m_selectionEnd)
719             continue;
720         if (o->selectionState() == SelectionNone)
721             continue;
722 
723         RenderSelectionInfo(o, true).repaint();
724 
725         // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
726         for (RenderBlock* block = o->containingBlock(); block && !block->isRenderView(); block = block->containingBlock()) {
727             if (!processedBlocks.add(block).isNewEntry)
728                 break;
729             RenderSelectionInfo(block, true).repaint();
730         }
731     }
732 }
733 
734 // Compositing layer dimensions take outline size into account, so we have to recompute layer
735 // bounds when it changes.
736 // FIXME: This is ugly; it would be nice to have a better way to do this.
setMaximalOutlineSize(int o)737 void RenderView::setMaximalOutlineSize(int o)
738 {
739     if (o != m_maximalOutlineSize) {
740         m_maximalOutlineSize = o;
741 
742         // maximalOutlineSize affects compositing layer dimensions.
743         compositor()->setCompositingLayersNeedRebuild();    // FIXME: this really just needs to be a geometry update.
744     }
745 }
746 
747 // When exploring the RenderTree looking for the nodes involved in the Selection, sometimes it's
748 // required to change the traversing direction because the "start" position is below the "end" one.
getNextOrPrevRenderObjectBasedOnDirection(const RenderObject * o,const RenderObject * stop,bool & continueExploring,bool & exploringBackwards)749 static inline RenderObject* getNextOrPrevRenderObjectBasedOnDirection(const RenderObject* o, const RenderObject* stop, bool& continueExploring, bool& exploringBackwards)
750 {
751     RenderObject* next;
752     if (exploringBackwards) {
753         next = o->previousInPreOrder();
754         continueExploring = next && !(next)->isRenderView();
755     } else {
756         next = o->nextInPreOrder();
757         continueExploring = next && next != stop;
758         exploringBackwards = !next && (next != stop);
759         if (exploringBackwards) {
760             next = stop->previousInPreOrder();
761             continueExploring = next && !next->isRenderView();
762         }
763     }
764 
765     return next;
766 }
767 
setSelection(RenderObject * start,int startPos,RenderObject * end,int endPos,SelectionRepaintMode blockRepaintMode)768 void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
769 {
770     // This code makes no assumptions as to if the rendering tree is up to date or not
771     // and will not try to update it. Currently clearSelection calls this
772     // (intentionally) without updating the rendering tree as it doesn't care.
773     // Other callers may want to force recalc style before calling this.
774 
775     // Make sure both our start and end objects are defined.
776     // Check www.msnbc.com and try clicking around to find the case where this happened.
777     if ((start && !end) || (end && !start))
778         return;
779 
780     // Just return if the selection hasn't changed.
781     if (m_selectionStart == start && m_selectionStartPos == startPos &&
782         m_selectionEnd == end && m_selectionEndPos == endPos)
783         return;
784 
785     // Record the old selected objects.  These will be used later
786     // when we compare against the new selected objects.
787     int oldStartPos = m_selectionStartPos;
788     int oldEndPos = m_selectionEndPos;
789 
790     // Objects each have a single selection rect to examine.
791     typedef HashMap<RenderObject*, OwnPtr<RenderSelectionInfo> > SelectedObjectMap;
792     SelectedObjectMap oldSelectedObjects;
793     SelectedObjectMap newSelectedObjects;
794 
795     // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
796     // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
797     // the union of those rects might remain the same even when changes have occurred.
798     typedef HashMap<RenderBlock*, OwnPtr<RenderBlockSelectionInfo> > SelectedBlockMap;
799     SelectedBlockMap oldSelectedBlocks;
800     SelectedBlockMap newSelectedBlocks;
801 
802     RenderObject* os = m_selectionStart;
803     RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
804     bool exploringBackwards = false;
805     bool continueExploring = os && (os != stop);
806     while (continueExploring) {
807         if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
808             // Blocks are responsible for painting line gaps and margin gaps.  They must be examined as well.
809             oldSelectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, true)));
810             if (blockRepaintMode == RepaintNewXOROld) {
811                 RenderBlock* cb = os->containingBlock();
812                 while (cb && !cb->isRenderView()) {
813                     OwnPtr<RenderBlockSelectionInfo>& blockInfo = oldSelectedBlocks.add(cb, nullptr).iterator->value;
814                     if (blockInfo)
815                         break;
816                     blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb));
817                     cb = cb->containingBlock();
818                 }
819             }
820         }
821 
822         os = getNextOrPrevRenderObjectBasedOnDirection(os, stop, continueExploring, exploringBackwards);
823     }
824 
825     // Now clear the selection.
826     SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
827     for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
828         i->key->setSelectionStateIfNeeded(SelectionNone);
829 
830     // set selection start and end
831     m_selectionStart = start;
832     m_selectionStartPos = startPos;
833     m_selectionEnd = end;
834     m_selectionEndPos = endPos;
835 
836     // Update the selection status of all objects between m_selectionStart and m_selectionEnd
837     if (start && start == end)
838         start->setSelectionStateIfNeeded(SelectionBoth);
839     else {
840         if (start)
841             start->setSelectionStateIfNeeded(SelectionStart);
842         if (end)
843             end->setSelectionStateIfNeeded(SelectionEnd);
844     }
845 
846     RenderObject* o = start;
847     stop = rendererAfterPosition(end, endPos);
848 
849     while (o && o != stop) {
850         if (o != start && o != end && o->canBeSelectionLeaf())
851             o->setSelectionStateIfNeeded(SelectionInside);
852         o = o->nextInPreOrder();
853     }
854 
855     if (blockRepaintMode != RepaintNothing)
856         layer()->clearBlockSelectionGapsBounds();
857 
858     // Now that the selection state has been updated for the new objects, walk them again and
859     // put them in the new objects list.
860     o = start;
861     exploringBackwards = false;
862     continueExploring = o && (o != stop);
863     while (continueExploring) {
864         if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
865             newSelectedObjects.set(o, adoptPtr(new RenderSelectionInfo(o, true)));
866             RenderBlock* cb = o->containingBlock();
867             while (cb && !cb->isRenderView()) {
868                 OwnPtr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(cb, nullptr).iterator->value;
869                 if (blockInfo)
870                     break;
871                 blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb));
872                 cb = cb->containingBlock();
873             }
874         }
875 
876         o = getNextOrPrevRenderObjectBasedOnDirection(o, stop, continueExploring, exploringBackwards);
877     }
878 
879     if (!m_frameView || blockRepaintMode == RepaintNothing)
880         return;
881 
882     FrameView::DeferredRepaintScope deferRepaints(*m_frameView);
883 
884     // Have any of the old selected objects changed compared to the new selection?
885     for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
886         RenderObject* obj = i->key;
887         RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
888         RenderSelectionInfo* oldInfo = i->value.get();
889         if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
890             (m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
891             (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
892             oldInfo->repaint();
893             if (newInfo) {
894                 newInfo->repaint();
895                 newSelectedObjects.remove(obj);
896             }
897         }
898     }
899 
900     // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
901     SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
902     for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i)
903         i->value->repaint();
904 
905     // Have any of the old blocks changed?
906     SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
907     for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
908         RenderBlock* block = i->key;
909         RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
910         RenderBlockSelectionInfo* oldInfo = i->value.get();
911         if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
912             oldInfo->repaint();
913             if (newInfo) {
914                 newInfo->repaint();
915                 newSelectedBlocks.remove(block);
916             }
917         }
918     }
919 
920     // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
921     SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
922     for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i)
923         i->value->repaint();
924 }
925 
getSelection(RenderObject * & startRenderer,int & startOffset,RenderObject * & endRenderer,int & endOffset) const926 void RenderView::getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const
927 {
928     startRenderer = m_selectionStart;
929     startOffset = m_selectionStartPos;
930     endRenderer = m_selectionEnd;
931     endOffset = m_selectionEndPos;
932 }
933 
clearSelection()934 void RenderView::clearSelection()
935 {
936     layer()->repaintBlockSelectionGaps();
937     setSelection(0, -1, 0, -1, RepaintNewMinusOld);
938 }
939 
selectionStartEnd(int & startPos,int & endPos) const940 void RenderView::selectionStartEnd(int& startPos, int& endPos) const
941 {
942     startPos = m_selectionStartPos;
943     endPos = m_selectionEndPos;
944 }
945 
shouldUsePrintingLayout() const946 bool RenderView::shouldUsePrintingLayout() const
947 {
948     if (!document().printing() || !m_frameView)
949         return false;
950     return m_frameView->frame().shouldUsePrintingLayout();
951 }
952 
getRetainedWidgets(Vector<RenderWidget * > & renderWidgets)953 size_t RenderView::getRetainedWidgets(Vector<RenderWidget*>& renderWidgets)
954 {
955     size_t size = m_widgets.size();
956 
957     renderWidgets.reserveCapacity(size);
958 
959     RenderWidgetSet::const_iterator end = m_widgets.end();
960     for (RenderWidgetSet::const_iterator it = m_widgets.begin(); it != end; ++it) {
961         renderWidgets.uncheckedAppend(*it);
962         (*it)->ref();
963     }
964 
965     return size;
966 }
967 
releaseWidgets(Vector<RenderWidget * > & renderWidgets)968 void RenderView::releaseWidgets(Vector<RenderWidget*>& renderWidgets)
969 {
970     size_t size = renderWidgets.size();
971 
972     for (size_t i = 0; i < size; ++i)
973         renderWidgets[i]->deref();
974 }
975 
updateWidgetPositions()976 void RenderView::updateWidgetPositions()
977 {
978     // updateWidgetPosition() can possibly cause layout to be re-entered (via plug-ins running
979     // scripts in response to NPP_SetWindow, for example), so we need to keep the Widgets
980     // alive during enumeration.
981 
982     Vector<RenderWidget*> renderWidgets;
983     size_t size = getRetainedWidgets(renderWidgets);
984 
985     for (size_t i = 0; i < size; ++i)
986         renderWidgets[i]->updateWidgetPosition();
987 
988     for (size_t i = 0; i < size; ++i)
989         renderWidgets[i]->widgetPositionsUpdated();
990 
991     releaseWidgets(renderWidgets);
992 }
993 
addWidget(RenderWidget * o)994 void RenderView::addWidget(RenderWidget* o)
995 {
996     m_widgets.add(o);
997 }
998 
removeWidget(RenderWidget * o)999 void RenderView::removeWidget(RenderWidget* o)
1000 {
1001     m_widgets.remove(o);
1002 }
1003 
viewRect() const1004 LayoutRect RenderView::viewRect() const
1005 {
1006     if (shouldUsePrintingLayout())
1007         return LayoutRect(LayoutPoint(), size());
1008     if (m_frameView)
1009         return m_frameView->visibleContentRect();
1010     return LayoutRect();
1011 }
1012 
unscaledDocumentRect() const1013 IntRect RenderView::unscaledDocumentRect() const
1014 {
1015     LayoutRect overflowRect(layoutOverflowRect());
1016     flipForWritingMode(overflowRect);
1017     return pixelSnappedIntRect(overflowRect);
1018 }
1019 
rootBackgroundIsEntirelyFixed() const1020 bool RenderView::rootBackgroundIsEntirelyFixed() const
1021 {
1022     RenderObject* rootObject = document().documentElement() ? document().documentElement()->renderer() : 0;
1023     if (!rootObject)
1024         return false;
1025 
1026     RenderObject* rootRenderer = rootObject->rendererForRootBackground();
1027     return rootRenderer->hasEntirelyFixedBackground();
1028 }
1029 
backgroundRect(RenderBox * backgroundRenderer) const1030 LayoutRect RenderView::backgroundRect(RenderBox* backgroundRenderer) const
1031 {
1032     if (!hasColumns())
1033         return unscaledDocumentRect();
1034 
1035     ColumnInfo* columnInfo = this->columnInfo();
1036     LayoutRect backgroundRect(0, 0, columnInfo->desiredColumnWidth(), columnInfo->columnHeight() * columnInfo->columnCount());
1037     if (!isHorizontalWritingMode())
1038         backgroundRect = backgroundRect.transposedRect();
1039     backgroundRenderer->flipForWritingMode(backgroundRect);
1040 
1041     return backgroundRect;
1042 }
1043 
documentRect() const1044 IntRect RenderView::documentRect() const
1045 {
1046     FloatRect overflowRect(unscaledDocumentRect());
1047     if (hasTransform())
1048         overflowRect = layer()->currentTransform().mapRect(overflowRect);
1049     return IntRect(overflowRect);
1050 }
1051 
viewHeight(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion) const1052 int RenderView::viewHeight(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion) const
1053 {
1054     int height = 0;
1055     if (!shouldUsePrintingLayout() && m_frameView)
1056         height = m_frameView->layoutSize(scrollbarInclusion).height();
1057 
1058     return height;
1059 }
1060 
viewWidth(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion) const1061 int RenderView::viewWidth(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion) const
1062 {
1063     int width = 0;
1064     if (!shouldUsePrintingLayout() && m_frameView)
1065         width = m_frameView->layoutSize(scrollbarInclusion).width();
1066 
1067     return width;
1068 }
1069 
viewLogicalHeight(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion) const1070 int RenderView::viewLogicalHeight(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion) const
1071 {
1072     int height = style()->isHorizontalWritingMode() ? viewHeight(scrollbarInclusion) : viewWidth(scrollbarInclusion);
1073 
1074     if (hasColumns() && !style()->hasInlineColumnAxis()) {
1075         if (int pageLength = m_frameView->pagination().pageLength)
1076             height = pageLength;
1077     }
1078 
1079     return height;
1080 }
1081 
zoomFactor() const1082 float RenderView::zoomFactor() const
1083 {
1084     return m_frameView->frame().pageZoomFactor();
1085 }
1086 
pushLayoutState(RenderObject * root)1087 void RenderView::pushLayoutState(RenderObject* root)
1088 {
1089     ASSERT(m_layoutStateDisableCount == 0);
1090     ASSERT(m_layoutState == 0);
1091 
1092     pushLayoutStateForCurrentFlowThread(root);
1093     m_layoutState = new LayoutState(root);
1094 }
1095 
shouldDisableLayoutStateForSubtree(RenderObject * renderer) const1096 bool RenderView::shouldDisableLayoutStateForSubtree(RenderObject* renderer) const
1097 {
1098     RenderObject* o = renderer;
1099     while (o) {
1100         if (o->hasColumns() || o->hasTransform() || o->hasReflection())
1101             return true;
1102         o = o->container();
1103     }
1104     return false;
1105 }
1106 
updateHitTestResult(HitTestResult & result,const LayoutPoint & point)1107 void RenderView::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
1108 {
1109     if (result.innerNode())
1110         return;
1111 
1112     Node* node = document().documentElement();
1113     if (node) {
1114         result.setInnerNode(node);
1115         if (!result.innerNonSharedNode())
1116             result.setInnerNonSharedNode(node);
1117 
1118         LayoutPoint adjustedPoint = point;
1119         offsetForContents(adjustedPoint);
1120 
1121         result.setLocalPoint(adjustedPoint);
1122     }
1123 }
1124 
usesCompositing() const1125 bool RenderView::usesCompositing() const
1126 {
1127     return m_compositor && m_compositor->inCompositingMode();
1128 }
1129 
compositor()1130 RenderLayerCompositor* RenderView::compositor()
1131 {
1132     if (!m_compositor)
1133         m_compositor = adoptPtr(new RenderLayerCompositor(this));
1134 
1135     return m_compositor.get();
1136 }
1137 
setIsInWindow(bool isInWindow)1138 void RenderView::setIsInWindow(bool isInWindow)
1139 {
1140     if (m_compositor)
1141         m_compositor->setIsInWindow(isInWindow);
1142 }
1143 
customFilterGlobalContext()1144 CustomFilterGlobalContext* RenderView::customFilterGlobalContext()
1145 {
1146     if (!m_customFilterGlobalContext)
1147         m_customFilterGlobalContext = adoptPtr(new CustomFilterGlobalContext());
1148     return m_customFilterGlobalContext.get();
1149 }
1150 
styleDidChange(StyleDifference diff,const RenderStyle * oldStyle)1151 void RenderView::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
1152 {
1153     RenderBlock::styleDidChange(diff, oldStyle);
1154     if (hasRenderNamedFlowThreads())
1155         flowThreadController()->styleDidChange();
1156 }
1157 
hasRenderNamedFlowThreads() const1158 bool RenderView::hasRenderNamedFlowThreads() const
1159 {
1160     return m_flowThreadController && m_flowThreadController->hasRenderNamedFlowThreads();
1161 }
1162 
checkTwoPassLayoutForAutoHeightRegions() const1163 bool RenderView::checkTwoPassLayoutForAutoHeightRegions() const
1164 {
1165     return hasRenderNamedFlowThreads() && m_flowThreadController->hasFlowThreadsWithAutoLogicalHeightRegions();
1166 }
1167 
flowThreadController()1168 FlowThreadController* RenderView::flowThreadController()
1169 {
1170     if (!m_flowThreadController)
1171         m_flowThreadController = FlowThreadController::create(this);
1172 
1173     return m_flowThreadController.get();
1174 }
1175 
pushLayoutStateForCurrentFlowThread(const RenderObject * object)1176 void RenderView::pushLayoutStateForCurrentFlowThread(const RenderObject* object)
1177 {
1178     if (!m_flowThreadController)
1179         return;
1180 
1181     RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
1182     if (!currentFlowThread)
1183         return;
1184 
1185     currentFlowThread->pushFlowThreadLayoutState(object);
1186 }
1187 
popLayoutStateForCurrentFlowThread()1188 void RenderView::popLayoutStateForCurrentFlowThread()
1189 {
1190     if (!m_flowThreadController)
1191         return;
1192 
1193     RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
1194     if (!currentFlowThread)
1195         return;
1196 
1197     currentFlowThread->popFlowThreadLayoutState();
1198 }
1199 
intervalArena()1200 IntervalArena* RenderView::intervalArena()
1201 {
1202     if (!m_intervalArena)
1203         m_intervalArena = IntervalArena::create();
1204     return m_intervalArena.get();
1205 }
1206 
backgroundIsKnownToBeOpaqueInRect(const LayoutRect &) const1207 bool RenderView::backgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const
1208 {
1209     // FIXME: Remove this main frame check. Same concept applies to subframes too.
1210     if (!m_frameView || !m_frameView->isMainFrame())
1211         return false;
1212 
1213     return m_frameView->hasOpaqueBackground();
1214 }
1215 
viewportPercentageWidth(float percentage) const1216 LayoutUnit RenderView::viewportPercentageWidth(float percentage) const
1217 {
1218     return viewLogicalWidth(ScrollableArea::IncludeScrollbars) * percentage / 100.f;
1219 }
1220 
viewportPercentageHeight(float percentage) const1221 LayoutUnit RenderView::viewportPercentageHeight(float percentage) const
1222 {
1223     return viewLogicalHeight(ScrollableArea::IncludeScrollbars) * percentage / 100.f;
1224 }
1225 
viewportPercentageMin(float percentage) const1226 LayoutUnit RenderView::viewportPercentageMin(float percentage) const
1227 {
1228     return std::min(viewLogicalWidth(ScrollableArea::IncludeScrollbars), viewLogicalHeight(ScrollableArea::IncludeScrollbars))
1229         * percentage / 100.f;
1230 }
1231 
viewportPercentageMax(float percentage) const1232 LayoutUnit RenderView::viewportPercentageMax(float percentage) const
1233 {
1234     return std::max(viewLogicalWidth(ScrollableArea::IncludeScrollbars), viewLogicalHeight(ScrollableArea::IncludeScrollbars))
1235         * percentage / 100.f;
1236 }
1237 
FragmentationDisabler(RenderObject * root)1238 FragmentationDisabler::FragmentationDisabler(RenderObject* root)
1239 {
1240     RenderView* renderView = root->view();
1241     ASSERT(renderView);
1242 
1243     LayoutState* layoutState = renderView->layoutState();
1244 
1245     m_root = root;
1246     m_fragmenting = layoutState && layoutState->isPaginated();
1247     m_flowThreadState = m_root->flowThreadState();
1248 #ifndef NDEBUG
1249     m_layoutState = layoutState;
1250 #endif
1251 
1252     if (layoutState)
1253         layoutState->m_isPaginated = false;
1254 
1255     if (m_flowThreadState != RenderObject::NotInsideFlowThread)
1256         m_root->setFlowThreadStateIncludingDescendants(RenderObject::NotInsideFlowThread);
1257 }
1258 
~FragmentationDisabler()1259 FragmentationDisabler::~FragmentationDisabler()
1260 {
1261     RenderView* renderView = m_root->view();
1262     ASSERT(renderView);
1263 
1264     LayoutState* layoutState = renderView->layoutState();
1265 #ifndef NDEBUG
1266     ASSERT(m_layoutState == layoutState);
1267 #endif
1268 
1269     if (layoutState)
1270         layoutState->m_isPaginated = m_fragmenting;
1271 
1272     if (m_flowThreadState != RenderObject::NotInsideFlowThread)
1273         m_root->setFlowThreadStateIncludingDescendants(m_flowThreadState);
1274 }
1275 
1276 } // namespace WebCore
1277