Unreviewed, rolling out r167478.
[WebKit-https.git] / Source / WebCore / rendering / RenderView.cpp
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 "ColumnInfo.h"
25 #include "Document.h"
26 #include "Element.h"
27 #include "FloatQuad.h"
28 #include "FloatingObjects.h"
29 #include "FlowThreadController.h"
30 #include "Frame.h"
31 #include "FrameSelection.h"
32 #include "FrameView.h"
33 #include "GraphicsContext.h"
34 #include "HTMLFrameOwnerElement.h"
35 #include "HTMLIFrameElement.h"
36 #include "HitTestResult.h"
37 #include "ImageQualityController.h"
38 #include "Page.h"
39 #include "RenderGeometryMap.h"
40 #include "RenderIterator.h"
41 #include "RenderLayer.h"
42 #include "RenderLayerBacking.h"
43 #include "RenderLayerCompositor.h"
44 #include "RenderMultiColumnFlowThread.h"
45 #include "RenderNamedFlowThread.h"
46 #include "RenderSelectionInfo.h"
47 #include "RenderWidget.h"
48 #include "Settings.h"
49 #include "StyleInheritedData.h"
50 #include "TransformState.h"
51 #include <wtf/StackStats.h>
52
53 namespace WebCore {
54
55 RenderView::RenderView(Document& document, PassRef<RenderStyle> style)
56     : RenderBlockFlow(document, std::move(style))
57     , m_frameView(*document.view())
58     , m_selectionStart(0)
59     , m_selectionEnd(0)
60     , m_selectionStartPos(-1)
61     , m_selectionEndPos(-1)
62     , m_rendererCount(0)
63     , m_maximalOutlineSize(0)
64     , m_pageLogicalHeight(0)
65     , m_pageLogicalHeightChanged(false)
66     , m_layoutState(nullptr)
67     , m_layoutStateDisableCount(0)
68     , m_renderQuoteHead(0)
69     , m_renderCounterCount(0)
70     , m_selectionWasCaret(false)
71 #if ENABLE(CSS_FILTERS)
72     , m_hasSoftwareFilters(false)
73 #endif
74 {
75     setIsRenderView();
76
77     // FIXME: We should find a way to enforce this at compile time.
78     ASSERT(document.view());
79
80     // init RenderObject attributes
81     setInline(false);
82     
83     m_minPreferredLogicalWidth = 0;
84     m_maxPreferredLogicalWidth = 0;
85
86     setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
87     
88     setPositionState(AbsolutePosition); // to 0,0 :)
89 }
90
91 RenderView::~RenderView()
92 {
93 }
94
95 bool RenderView::hitTest(const HitTestRequest& request, HitTestResult& result)
96 {
97     return hitTest(request, result.hitTestLocation(), result);
98 }
99
100 bool RenderView::hitTest(const HitTestRequest& request, const HitTestLocation& location, HitTestResult& result)
101 {
102     if (layer()->hitTest(request, location, result))
103         return true;
104
105     // FIXME: Consider if this test should be done unconditionally.
106     if (request.allowsFrameScrollbars()) {
107         // ScrollView scrollbars are not the same as RenderLayer scrollbars tested by RenderLayer::hitTestOverflowControls,
108         // so we need to test ScrollView scrollbars separately here.
109         Scrollbar* frameScrollbar = frameView().scrollbarAtPoint(location.roundedPoint());
110         if (frameScrollbar) {
111             result.setScrollbar(frameScrollbar);
112             return true;
113         }
114     }
115
116     return false;
117 }
118
119 void RenderView::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit, LogicalExtentComputedValues& computedValues) const
120 {
121     computedValues.m_extent = !shouldUsePrintingLayout() ? LayoutUnit(viewLogicalHeight()) : logicalHeight;
122 }
123
124 void RenderView::updateLogicalWidth()
125 {
126     if (!shouldUsePrintingLayout())
127         setLogicalWidth(viewLogicalWidth());
128 }
129
130 LayoutUnit RenderView::availableLogicalHeight(AvailableLogicalHeightType) const
131 {
132     // If we have columns, then the available logical height is reduced to the column height.
133     if (hasColumns())
134         return columnInfo()->columnHeight();
135 #if PLATFORM(IOS)
136     // Workaround for <rdar://problem/7166808>.
137     if (document().isPluginDocument() && frameView().useFixedLayout())
138         return frameView().fixedLayoutSize().height();
139 #endif
140     return isHorizontalWritingMode() ? frameView().visibleHeight() : frameView().visibleWidth();
141 }
142
143 bool RenderView::isChildAllowed(const RenderObject& child, const RenderStyle&) const
144 {
145     return child.isBox();
146 }
147
148 void RenderView::layoutContent(const LayoutState& state)
149 {
150     UNUSED_PARAM(state);
151     ASSERT(needsLayout());
152
153     RenderBlockFlow::layout();
154     if (hasRenderNamedFlowThreads())
155         flowThreadController().layoutRenderNamedFlowThreads();
156 #ifndef NDEBUG
157     checkLayoutState(state);
158 #endif
159 }
160
161 #ifndef NDEBUG
162 void RenderView::checkLayoutState(const LayoutState& state)
163 {
164     ASSERT(layoutDeltaMatches(LayoutSize()));
165     ASSERT(!m_layoutStateDisableCount);
166     ASSERT(m_layoutState.get() == &state);
167 }
168 #endif
169
170 void RenderView::initializeLayoutState(LayoutState& state)
171 {
172     // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
173     state.m_clipped = false;
174
175     state.m_pageLogicalHeight = m_pageLogicalHeight;
176     state.m_pageLogicalHeightChanged = m_pageLogicalHeightChanged;
177     state.m_isPaginated = state.m_pageLogicalHeight;
178 }
179
180 // The algorithm below assumes this is a full layout. In case there are previously computed values for regions, supplemental steps are taken
181 // 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
182 // layout).
183 // 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 
184 // inner flows have the necessary information to correctly fragment the content.
185 // 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
186 // 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
187 // belonging to inner flows. This step will correctly set the computedAutoHeight for the auto-height regions. It's possible for non-auto-height
188 // regions to relayout if they depend on auto-height regions. This will invalidate the inner flow threads and mark them as needing layout.
189 // 3. The last step is to do one last layout if there are pathological dependencies between non-auto-height regions and auto-height regions
190 // as detected in the previous step.
191 void RenderView::layoutContentInAutoLogicalHeightRegions(const LayoutState& state)
192 {
193     // We need to invalidate all the flows with auto-height regions if one such flow needs layout.
194     // If none is found we do a layout a check back again afterwards.
195     if (!flowThreadController().updateFlowThreadsNeedingLayout()) {
196         // 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).
197         layoutContent(state);
198
199         // If we find no named flow needing a two step layout after the first layout, exit early.
200         // Otherwise, initiate the two step layout algorithm and recompute all the flows.
201         if (!flowThreadController().updateFlowThreadsNeedingTwoStepLayout())
202             return;
203     }
204
205     // Layout to recompute all the named flows with auto-height regions.
206     layoutContent(state);
207
208     // Propagate the computed auto-height values upwards.
209     // Non-auto-height regions may invalidate the flow thread because they depended on auto-height regions, but that's ok.
210     flowThreadController().updateFlowThreadsIntoConstrainedPhase();
211
212     // Do one last layout that should update the auto-height regions found in the main flow
213     // and solve pathological dependencies between regions (e.g. a non-auto-height region depending
214     // on an auto-height one).
215     if (needsLayout())
216         layoutContent(state);
217 }
218
219 void RenderView::layoutContentToComputeOverflowInRegions(const LayoutState& state)
220 {
221     if (!hasRenderNamedFlowThreads())
222         return;
223
224     // First pass through the flow threads and mark the regions as needing a simple layout.
225     // The regions extract the overflow from the flow thread and pass it to their containg
226     // block chain.
227     flowThreadController().updateFlowThreadsIntoOverflowPhase();
228     if (needsLayout())
229         layoutContent(state);
230
231     // In case scrollbars resized the regions a new pass is necessary to update the flow threads
232     // and recompute the overflow on regions. This is the final state of the flow threads.
233     flowThreadController().updateFlowThreadsIntoFinalPhase();
234     if (needsLayout())
235         layoutContent(state);
236
237     // Finally reset the layout state of the flow threads.
238     flowThreadController().updateFlowThreadsIntoMeasureContentPhase();
239 }
240
241 void RenderView::layout()
242 {
243     StackStats::LayoutCheckPoint layoutCheckPoint;
244     if (!document().paginated())
245         setPageLogicalHeight(0);
246
247     if (shouldUsePrintingLayout())
248         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = logicalWidth();
249
250     // Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
251     bool relayoutChildren = !shouldUsePrintingLayout() && (width() != viewWidth() || height() != viewHeight());
252     if (relayoutChildren) {
253         setChildNeedsLayout(MarkOnlyThis);
254
255         for (auto& box : childrenOfType<RenderBox>(*this)) {
256             if (box.hasRelativeLogicalHeight()
257                 || box.hasViewportPercentageLogicalHeight()
258                 || box.style().logicalHeight().isPercent()
259                 || box.style().logicalMinHeight().isPercent()
260                 || box.style().logicalMaxHeight().isPercent()
261                 || box.style().logicalHeight().isViewportPercentage()
262                 || box.style().logicalMinHeight().isViewportPercentage()
263                 || box.style().logicalMaxHeight().isViewportPercentage()
264                 || box.isSVGRoot()
265                 )
266                 box.setChildNeedsLayout(MarkOnlyThis);
267         }
268     }
269
270     ASSERT(!m_layoutState);
271     if (!needsLayout())
272         return;
273
274     m_layoutState = std::make_unique<LayoutState>();
275     initializeLayoutState(*m_layoutState);
276
277     m_pageLogicalHeightChanged = false;
278
279     if (checkTwoPassLayoutForAutoHeightRegions())
280         layoutContentInAutoLogicalHeightRegions(*m_layoutState);
281     else
282         layoutContent(*m_layoutState);
283
284     layoutContentToComputeOverflowInRegions(*m_layoutState);
285
286 #ifndef NDEBUG
287     checkLayoutState(*m_layoutState);
288 #endif
289     m_layoutState = nullptr;
290     clearNeedsLayout();
291 }
292
293 LayoutUnit RenderView::pageOrViewLogicalHeight() const
294 {
295     if (document().printing())
296         return pageLogicalHeight();
297     
298     if (hasColumns() && !style().hasInlineColumnAxis()) {
299         if (int pageLength = frameView().pagination().pageLength)
300             return pageLength;
301     }
302
303     return viewLogicalHeight();
304 }
305
306 LayoutUnit RenderView::clientLogicalWidthForFixedPosition() const
307 {
308     // FIXME: If the FrameView's fixedVisibleContentRect() is not empty, perhaps it should be consulted here too?
309     if (frameView().fixedElementsLayoutRelativeToFrame())
310         return (isHorizontalWritingMode() ? frameView().visibleWidth() : frameView().visibleHeight()) / frameView().frame().frameScaleFactor();
311
312 #if PLATFORM(IOS)
313     if (frameView().useCustomFixedPositionLayoutRect())
314         return isHorizontalWritingMode() ? frameView().customFixedPositionLayoutRect().width() : frameView().customFixedPositionLayoutRect().height();
315 #endif
316
317     return clientLogicalWidth();
318 }
319
320 LayoutUnit RenderView::clientLogicalHeightForFixedPosition() const
321 {
322     // FIXME: If the FrameView's fixedVisibleContentRect() is not empty, perhaps it should be consulted here too?
323     if (frameView().fixedElementsLayoutRelativeToFrame())
324         return (isHorizontalWritingMode() ? frameView().visibleHeight() : frameView().visibleWidth()) / frameView().frame().frameScaleFactor();
325
326 #if PLATFORM(IOS)
327     if (frameView().useCustomFixedPositionLayoutRect())
328         return isHorizontalWritingMode() ? frameView().customFixedPositionLayoutRect().height() : frameView().customFixedPositionLayoutRect().width();
329 #endif
330
331     return clientLogicalHeight();
332 }
333
334 #if PLATFORM(IOS)
335 static inline LayoutSize fixedPositionOffset(const FrameView& frameView)
336 {
337     return frameView.useCustomFixedPositionLayoutRect() ? (frameView.customFixedPositionLayoutRect().location() - LayoutPoint()) : frameView.scrollOffset();
338 }
339 #endif
340
341 void RenderView::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
342 {
343     // If a container was specified, and was not 0 or the RenderView,
344     // then we should have found it by now.
345     ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
346     ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == (mode & IsFixed));
347
348     if (!repaintContainer && mode & UseTransforms && shouldUseTransformFromContainer(0)) {
349         TransformationMatrix t;
350         getTransformFromContainer(0, LayoutSize(), t);
351         transformState.applyTransform(t);
352     }
353     
354     if (mode & IsFixed)
355 #if PLATFORM(IOS)
356         transformState.move(fixedPositionOffset(m_frameView));
357 #else
358         transformState.move(frameView().scrollOffsetForFixedPosition());
359 #endif
360 }
361
362 const RenderObject* RenderView::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
363 {
364     // If a container was specified, and was not 0 or the RenderView,
365     // then we should have found it by now.
366     ASSERT_ARG(ancestorToStopAt, !ancestorToStopAt || ancestorToStopAt == this);
367
368 #if PLATFORM(IOS)
369     LayoutSize scrollOffset = fixedPositionOffset(frameView());
370 #else
371     LayoutSize scrollOffset = frameView().scrollOffsetForFixedPosition();
372 #endif
373
374     if (!ancestorToStopAt && shouldUseTransformFromContainer(0)) {
375         TransformationMatrix t;
376         getTransformFromContainer(0, LayoutSize(), t);
377         geometryMap.pushView(this, scrollOffset, &t);
378     } else
379         geometryMap.pushView(this, scrollOffset);
380
381     return 0;
382 }
383
384 void RenderView::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
385 {
386     if (mode & IsFixed)
387 #if PLATFORM(IOS)
388         transformState.move(fixedPositionOffset(frameView()));
389 #else
390         transformState.move(frameView().scrollOffsetForFixedPosition());
391 #endif
392
393     if (mode & UseTransforms && shouldUseTransformFromContainer(0)) {
394         TransformationMatrix t;
395         getTransformFromContainer(0, LayoutSize(), t);
396         transformState.applyTransform(t);
397     }
398 }
399
400 bool RenderView::requiresColumns(int) const
401 {
402     return frameView().pagination().mode != Pagination::Unpaginated;
403 }
404
405 void RenderView::computeColumnCountAndWidth()
406 {
407     int columnWidth = contentLogicalWidth();
408     if (style().hasInlineColumnAxis()) {
409         if (int pageLength = frameView().pagination().pageLength)
410             columnWidth = pageLength;
411     }
412     setComputedColumnCountAndWidth(1, columnWidth);
413 }
414
415 ColumnInfo::PaginationUnit RenderView::paginationUnit() const
416 {
417     return frameView().pagination().behavesLikeColumns ? ColumnInfo::Column : ColumnInfo::Page;
418 }
419
420 void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
421 {
422     // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
423     ASSERT(!needsLayout());
424     // RenderViews should never be called to paint with an offset not on device pixels.
425     ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);
426
427     // This avoids painting garbage between columns if there is a column gap.
428     if (frameView().pagination().mode != Pagination::Unpaginated && paintInfo.shouldPaintWithinRoot(*this))
429         paintInfo.context->fillRect(paintInfo.rect, frameView().baseBackgroundColor(), ColorSpaceDeviceRGB);
430
431     paintObject(paintInfo, paintOffset);
432 }
433
434 static inline bool isComposited(RenderElement* object)
435 {
436     return object->hasLayer() && toRenderLayerModelObject(object)->layer()->isComposited();
437 }
438
439 static inline bool rendererObscuresBackground(RenderElement* rootObject)
440 {
441     if (!rootObject)
442         return false;
443     
444     const RenderStyle& style = rootObject->style();
445     if (style.visibility() != VISIBLE
446         || style.opacity() != 1
447         || style.hasTransform())
448         return false;
449     
450     if (isComposited(rootObject))
451         return false;
452
453     if (rootObject->rendererForRootBackground().style().backgroundClip() == TextFillBox)
454         return false;
455
456     return true;
457 }
458
459 void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
460 {
461     if (!paintInfo.shouldPaintWithinRoot(*this))
462         return;
463
464     // Check to see if we are enclosed by a layer that requires complex painting rules.  If so, we cannot blit
465     // when scrolling, and we need to use slow repaints.  Examples of layers that require this are transparent layers,
466     // layers with reflections, or transformed layers.
467     // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being inside
468     // a transform, transparency layer, etc.
469     Element* elt;
470     for (elt = document().ownerElement(); elt && elt->renderer(); elt = elt->document().ownerElement()) {
471         RenderLayer* layer = elt->renderer()->enclosingLayer();
472         if (layer->cannotBlitToWindow()) {
473             frameView().setCannotBlitToWindow();
474             break;
475         }
476
477         if (RenderLayer* compositingLayer = layer->enclosingCompositingLayerForRepaint()) {
478             if (!compositingLayer->backing()->paintsIntoWindow()) {
479                 frameView().setCannotBlitToWindow();
480                 break;
481             }
482         }
483     }
484
485     if (document().ownerElement())
486         return;
487
488     if (paintInfo.skipRootBackground())
489         return;
490
491     bool rootFillsViewport = false;
492     bool rootObscuresBackground = false;
493     Element* documentElement = document().documentElement();
494     if (RenderElement* rootRenderer = documentElement ? documentElement->renderer() : 0) {
495         // The document element's renderer is currently forced to be a block, but may not always be.
496         RenderBox* rootBox = rootRenderer->isBox() ? toRenderBox(rootRenderer) : 0;
497         rootFillsViewport = rootBox && !rootBox->x() && !rootBox->y() && rootBox->width() >= width() && rootBox->height() >= height();
498         rootObscuresBackground = rendererObscuresBackground(rootRenderer);
499     }
500
501     compositor().setRootExtendedBackgroundColor(frameView().frame().settings().backgroundShouldExtendBeyondPage()
502         ? frameView().documentBackgroundColor() : Color());
503
504     Page* page = document().page();
505     float pageScaleFactor = page ? page->pageScaleFactor() : 1;
506
507     // If painting will entirely fill the view, no need to fill the background.
508     if (rootFillsViewport && rootObscuresBackground && pageScaleFactor >= 1)
509         return;
510
511     // This code typically only executes if the root element's visibility has been set to hidden,
512     // if there is a transform on the <html>, or if there is a page scale factor less than 1.
513     // Only fill with the base background color (typically white) if we're the root document, 
514     // since iframes/frames with no background in the child document should show the parent's background.
515     if (frameView().isTransparent()) // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being transparent.
516         frameView().setCannotBlitToWindow(); // The parent must show behind the child.
517     else {
518         Color backgroundColor = frameView().baseBackgroundColor();
519         if (backgroundColor.alpha()) {
520             CompositeOperator previousOperator = paintInfo.context->compositeOperation();
521             paintInfo.context->setCompositeOperation(CompositeCopy);
522             paintInfo.context->fillRect(paintInfo.rect, backgroundColor, style().colorSpace());
523             paintInfo.context->setCompositeOperation(previousOperator);
524         } else
525             paintInfo.context->clearRect(paintInfo.rect);
526     }
527 }
528
529 bool RenderView::shouldRepaint(const LayoutRect& rect) const
530 {
531     return !printing() && !rect.isEmpty();
532 }
533
534 void RenderView::repaintRootContents()
535 {
536     if (layer()->isComposited()) {
537         layer()->setBackingNeedsRepaint(GraphicsLayer::DoNotClipToLayer);
538         return;
539     }
540     repaint();
541 }
542
543 void RenderView::repaintViewRectangle(const LayoutRect& repaintRect) const
544 {
545     if (!shouldRepaint(repaintRect))
546         return;
547
548     if (auto ownerElement = document().ownerElement()) {
549         RenderBox* ownerBox = ownerElement->renderBox();
550         if (!ownerBox)
551             return;
552         LayoutRect viewRect = this->viewRect();
553 #if PLATFORM(IOS)
554         // Don't clip using the visible rect since clipping is handled at a higher level on iPhone.
555         LayoutRect adjustedRect = repaintRect;
556 #else
557         LayoutRect adjustedRect = intersection(repaintRect, viewRect);
558 #endif
559         adjustedRect.moveBy(-viewRect.location());
560         adjustedRect.moveBy(ownerBox->contentBoxRect().location());
561         ownerBox->repaintRectangle(adjustedRect);
562         return;
563     }
564
565     frameView().addTrackedRepaintRect(pixelSnappedForPainting(repaintRect, document().deviceScaleFactor()));
566
567     // FIXME: convert all repaint rect dependencies to FloatRect.
568     IntRect enclosingRect = enclosingIntRect(repaintRect);
569     if (!m_accumulatedRepaintRegion) {
570         frameView().repaintContentRectangle(enclosingRect);
571         return;
572     }
573     m_accumulatedRepaintRegion->unite(enclosingRect);
574
575     // Region will get slow if it gets too complex. Merge all rects so far to bounds if this happens.
576     // FIXME: Maybe there should be a region type that does this automatically.
577     static const unsigned maximumRepaintRegionGridSize = 16 * 16;
578     if (m_accumulatedRepaintRegion->gridSize() > maximumRepaintRegionGridSize)
579         m_accumulatedRepaintRegion = std::make_unique<Region>(m_accumulatedRepaintRegion->bounds());
580 }
581
582 void RenderView::flushAccumulatedRepaintRegion() const
583 {
584     ASSERT(!document().ownerElement());
585     ASSERT(m_accumulatedRepaintRegion);
586     auto repaintRects = m_accumulatedRepaintRegion->rects();
587     for (auto& rect : repaintRects)
588         frameView().repaintContentRectangle(rect);
589     m_accumulatedRepaintRegion = nullptr;
590 }
591
592 void RenderView::repaintViewAndCompositedLayers()
593 {
594     repaintRootContents();
595
596     RenderLayerCompositor& compositor = this->compositor();
597     if (compositor.inCompositingMode())
598         compositor.repaintCompositedLayers();
599 }
600
601 LayoutRect RenderView::visualOverflowRect() const
602 {
603     if (frameView().paintsEntireContents())
604         return layoutOverflowRect();
605
606     return RenderBlockFlow::visualOverflowRect();
607 }
608
609 void RenderView::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
610 {
611     // If a container was specified, and was not 0 or the RenderView,
612     // then we should have found it by now.
613     ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
614
615     if (printing())
616         return;
617
618     if (style().isFlippedBlocksWritingMode()) {
619         // We have to flip by hand since the view's logical height has not been determined.  We
620         // can use the viewport width and height.
621         if (style().isHorizontalWritingMode())
622             rect.setY(viewHeight() - rect.maxY());
623         else
624             rect.setX(viewWidth() - rect.maxX());
625     }
626
627     if (fixed) {
628 #if PLATFORM(IOS)
629         rect.move(fixedPositionOffset(frameView()));
630 #else
631         rect.move(frameView().scrollOffsetForFixedPosition());
632 #endif
633     }
634         
635     // Apply our transform if we have one (because of full page zooming).
636     if (!repaintContainer && layer() && layer()->transform())
637         rect = layer()->transform()->mapRect(rect);
638 }
639
640 void RenderView::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
641 {
642     rects.append(pixelSnappedIntRect(accumulatedOffset, layer()->size()));
643 }
644
645 void RenderView::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
646 {
647     if (wasFixed)
648         *wasFixed = false;
649     quads.append(FloatRect(FloatPoint(), layer()->size()));
650 }
651
652 static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
653 {
654     if (!object)
655         return 0;
656
657     RenderObject* child = object->childAt(offset);
658     return child ? child : object->nextInPreOrderAfterChildren();
659 }
660
661 IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
662 {
663     typedef HashMap<RenderObject*, std::unique_ptr<RenderSelectionInfo>> SelectionMap;
664     SelectionMap selectedObjects;
665
666     RenderObject* os = m_selectionStart;
667     RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
668     while (os && os != stop) {
669         if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
670             // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
671             selectedObjects.set(os, std::make_unique<RenderSelectionInfo>(os, clipToVisibleContent));
672             RenderBlock* cb = os->containingBlock();
673             while (cb && !cb->isRenderView()) {
674                 std::unique_ptr<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).iterator->value;
675                 if (blockInfo)
676                     break;
677                 blockInfo = std::make_unique<RenderSelectionInfo>(cb, clipToVisibleContent);
678                 cb = cb->containingBlock();
679             }
680         }
681
682         os = os->nextInPreOrder();
683     }
684
685     // Now create a single bounding box rect that encloses the whole selection.
686     LayoutRect selRect;
687     SelectionMap::iterator end = selectedObjects.end();
688     for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
689         RenderSelectionInfo* info = i->value.get();
690         // RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
691         LayoutRect currRect = info->rect();
692         if (RenderLayerModelObject* repaintContainer = info->repaintContainer()) {
693             FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currRect));
694             currRect = absQuad.enclosingBoundingBox(); 
695         }
696         selRect.unite(currRect);
697     }
698     return pixelSnappedIntRect(selRect);
699 }
700
701 void RenderView::repaintSelection() const
702 {
703     HashSet<RenderBlock*> processedBlocks;
704
705     RenderObject* end = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
706     for (RenderObject* o = m_selectionStart; o && o != end; o = o->nextInPreOrder()) {
707         if (!o->canBeSelectionLeaf() && o != m_selectionStart && o != m_selectionEnd)
708             continue;
709         if (o->selectionState() == SelectionNone)
710             continue;
711
712         RenderSelectionInfo(o, true).repaint();
713
714         // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
715         for (RenderBlock* block = o->containingBlock(); block && !block->isRenderView(); block = block->containingBlock()) {
716             if (!processedBlocks.add(block).isNewEntry)
717                 break;
718             RenderSelectionInfo(block, true).repaint();
719         }
720     }
721 }
722
723 // Compositing layer dimensions take outline size into account, so we have to recompute layer
724 // bounds when it changes.
725 // FIXME: This is ugly; it would be nice to have a better way to do this.
726 void RenderView::setMaximalOutlineSize(int o)
727 {
728     if (o != m_maximalOutlineSize) {
729         m_maximalOutlineSize = o;
730
731         // maximalOutlineSize affects compositing layer dimensions.
732         compositor().setCompositingLayersNeedRebuild();    // FIXME: this really just needs to be a geometry update.
733     }
734 }
735
736 // When exploring the RenderTree looking for the nodes involved in the Selection, sometimes it's
737 // required to change the traversing direction because the "start" position is below the "end" one.
738 static inline RenderObject* getNextOrPrevRenderObjectBasedOnDirection(const RenderObject* o, const RenderObject* stop, bool& continueExploring, bool& exploringBackwards)
739 {
740     RenderObject* next;
741     if (exploringBackwards) {
742         next = o->previousInPreOrder();
743         continueExploring = next && !(next)->isRenderView();
744     } else {
745         next = o->nextInPreOrder();
746         continueExploring = next && next != stop;
747         exploringBackwards = !next && (next != stop);
748         if (exploringBackwards) {
749             next = stop->previousInPreOrder();
750             continueExploring = next && !next->isRenderView();
751         }
752     }
753
754     return next;
755 }
756
757 void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
758 {
759     // Make sure both our start and end objects are defined.
760     // Check www.msnbc.com and try clicking around to find the case where this happened.
761     if ((start && !end) || (end && !start))
762         return;
763
764     bool caretChanged = m_selectionWasCaret != view().frame().selection().isCaret();
765     m_selectionWasCaret = view().frame().selection().isCaret();
766     // Just return if the selection hasn't changed.
767     if (m_selectionStart == start && m_selectionStartPos == startPos &&
768         m_selectionEnd == end && m_selectionEndPos == endPos && !caretChanged)
769         return;
770
771     // Record the old selected objects.  These will be used later
772     // when we compare against the new selected objects.
773     int oldStartPos = m_selectionStartPos;
774     int oldEndPos = m_selectionEndPos;
775
776     // Objects each have a single selection rect to examine.
777     typedef HashMap<RenderObject*, std::unique_ptr<RenderSelectionInfo>> SelectedObjectMap;
778     SelectedObjectMap oldSelectedObjects;
779     SelectedObjectMap newSelectedObjects;
780
781     // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
782     // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
783     // the union of those rects might remain the same even when changes have occurred.
784     typedef HashMap<RenderBlock*, std::unique_ptr<RenderBlockSelectionInfo>> SelectedBlockMap;
785     SelectedBlockMap oldSelectedBlocks;
786     SelectedBlockMap newSelectedBlocks;
787
788     RenderObject* os = m_selectionStart;
789     RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
790     bool exploringBackwards = false;
791     bool continueExploring = os && (os != stop);
792     while (continueExploring) {
793         if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
794             // Blocks are responsible for painting line gaps and margin gaps.  They must be examined as well.
795             oldSelectedObjects.set(os, std::make_unique<RenderSelectionInfo>(os, true));
796             if (blockRepaintMode == RepaintNewXOROld) {
797                 RenderBlock* cb = os->containingBlock();
798                 while (cb && !cb->isRenderView()) {
799                     std::unique_ptr<RenderBlockSelectionInfo>& blockInfo = oldSelectedBlocks.add(cb, nullptr).iterator->value;
800                     if (blockInfo)
801                         break;
802                     blockInfo = std::make_unique<RenderBlockSelectionInfo>(cb);
803                     cb = cb->containingBlock();
804                 }
805             }
806         }
807
808         os = getNextOrPrevRenderObjectBasedOnDirection(os, stop, continueExploring, exploringBackwards);
809     }
810
811     // Now clear the selection.
812     SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
813     for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
814         i->key->setSelectionStateIfNeeded(SelectionNone);
815
816     // set selection start and end
817     m_selectionStart = start;
818     m_selectionStartPos = startPos;
819     m_selectionEnd = end;
820     m_selectionEndPos = endPos;
821
822     // Update the selection status of all objects between m_selectionStart and m_selectionEnd
823     if (start && start == end)
824         start->setSelectionStateIfNeeded(SelectionBoth);
825     else {
826         if (start)
827             start->setSelectionStateIfNeeded(SelectionStart);
828         if (end)
829             end->setSelectionStateIfNeeded(SelectionEnd);
830     }
831
832     RenderObject* o = start;
833     stop = rendererAfterPosition(end, endPos);
834
835     while (o && o != stop) {
836         if (o != start && o != end && o->canBeSelectionLeaf())
837             o->setSelectionStateIfNeeded(SelectionInside);
838         o = o->nextInPreOrder();
839     }
840
841     if (blockRepaintMode != RepaintNothing)
842         layer()->clearBlockSelectionGapsBounds();
843
844     // Now that the selection state has been updated for the new objects, walk them again and
845     // put them in the new objects list.
846     o = start;
847     exploringBackwards = false;
848     continueExploring = o && (o != stop);
849     while (continueExploring) {
850         if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
851             newSelectedObjects.set(o, std::make_unique<RenderSelectionInfo>(o, true));
852             RenderBlock* cb = o->containingBlock();
853             while (cb && !cb->isRenderView()) {
854                 std::unique_ptr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(cb, nullptr).iterator->value;
855                 if (blockInfo)
856                     break;
857                 blockInfo = std::make_unique<RenderBlockSelectionInfo>(cb);
858                 cb = cb->containingBlock();
859             }
860         }
861
862         o = getNextOrPrevRenderObjectBasedOnDirection(o, stop, continueExploring, exploringBackwards);
863     }
864
865     if (blockRepaintMode == RepaintNothing)
866         return;
867
868     // Have any of the old selected objects changed compared to the new selection?
869     for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
870         RenderObject* obj = i->key;
871         RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
872         RenderSelectionInfo* oldInfo = i->value.get();
873         if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
874             (m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
875             (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
876             oldInfo->repaint();
877             if (newInfo) {
878                 newInfo->repaint();
879                 newSelectedObjects.remove(obj);
880             }
881         }
882     }
883
884     // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
885     SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
886     for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i)
887         i->value->repaint();
888
889     // Have any of the old blocks changed?
890     SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
891     for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
892         RenderBlock* block = i->key;
893         RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
894         RenderBlockSelectionInfo* oldInfo = i->value.get();
895         if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
896             oldInfo->repaint();
897             if (newInfo) {
898                 newInfo->repaint();
899                 newSelectedBlocks.remove(block);
900             }
901         }
902     }
903
904     // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
905     SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
906     for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i)
907         i->value->repaint();
908 }
909
910 void RenderView::getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const
911 {
912     startRenderer = m_selectionStart;
913     startOffset = m_selectionStartPos;
914     endRenderer = m_selectionEnd;
915     endOffset = m_selectionEndPos;
916 }
917
918 void RenderView::clearSelection()
919 {
920     layer()->repaintBlockSelectionGaps();
921     setSelection(0, -1, 0, -1, RepaintNewMinusOld);
922 }
923
924 void RenderView::selectionStartEnd(int& startPos, int& endPos) const
925 {
926     startPos = m_selectionStartPos;
927     endPos = m_selectionEndPos;
928 }
929
930 bool RenderView::printing() const
931 {
932     return document().printing();
933 }
934
935 bool RenderView::shouldUsePrintingLayout() const
936 {
937     if (!printing())
938         return false;
939     return frameView().frame().shouldUsePrintingLayout();
940 }
941
942 LayoutRect RenderView::viewRect() const
943 {
944     if (shouldUsePrintingLayout())
945         return LayoutRect(LayoutPoint(), size());
946     return frameView().visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
947 }
948
949 IntRect RenderView::unscaledDocumentRect() const
950 {
951     LayoutRect overflowRect(layoutOverflowRect());
952     flipForWritingMode(overflowRect);
953     return pixelSnappedIntRect(overflowRect);
954 }
955
956 bool RenderView::rootBackgroundIsEntirelyFixed() const
957 {
958     RenderElement* rootObject = document().documentElement() ? document().documentElement()->renderer() : 0;
959     if (!rootObject)
960         return false;
961
962     return rootObject->rendererForRootBackground().hasEntirelyFixedBackground();
963 }
964     
965 LayoutRect RenderView::unextendedBackgroundRect(RenderBox* backgroundRenderer) const
966 {
967     if (!hasColumns())
968         return unscaledDocumentRect();
969
970     ColumnInfo* columnInfo = this->columnInfo();
971     LayoutRect backgroundRect(0, 0, columnInfo->desiredColumnWidth(), columnInfo->columnHeight() * columnInfo->columnCount());
972     if (!isHorizontalWritingMode())
973         backgroundRect = backgroundRect.transposedRect();
974     backgroundRenderer->flipForWritingMode(backgroundRect);
975
976     return backgroundRect;
977 }
978     
979 LayoutRect RenderView::backgroundRect(RenderBox* backgroundRenderer) const
980 {
981     if (!hasColumns() && frameView().hasExtendedBackgroundRectForPainting())
982         return frameView().extendedBackgroundRectForPainting();
983
984     return unextendedBackgroundRect(backgroundRenderer);
985 }
986
987 IntRect RenderView::documentRect() const
988 {
989     FloatRect overflowRect(unscaledDocumentRect());
990     if (hasTransform())
991         overflowRect = layer()->currentTransform().mapRect(overflowRect);
992     return IntRect(overflowRect);
993 }
994
995 int RenderView::viewHeight() const
996 {
997     int height = 0;
998     if (!shouldUsePrintingLayout()) {
999         height = frameView().layoutHeight();
1000         height = frameView().useFixedLayout() ? ceilf(style().effectiveZoom() * float(height)) : height;
1001     }
1002     return height;
1003 }
1004
1005 int RenderView::viewWidth() const
1006 {
1007     int width = 0;
1008     if (!shouldUsePrintingLayout()) {
1009         width = frameView().layoutWidth();
1010         width = frameView().useFixedLayout() ? ceilf(style().effectiveZoom() * float(width)) : width;
1011     }
1012     return width;
1013 }
1014
1015 int RenderView::viewLogicalHeight() const
1016 {
1017     int height = style().isHorizontalWritingMode() ? viewHeight() : viewWidth();
1018     return height;
1019 }
1020
1021 float RenderView::zoomFactor() const
1022 {
1023     return frameView().frame().pageZoomFactor();
1024 }
1025
1026 void RenderView::pushLayoutState(RenderObject& root)
1027 {
1028     ASSERT(m_layoutStateDisableCount == 0);
1029     ASSERT(m_layoutState == 0);
1030
1031     m_layoutState = std::make_unique<LayoutState>(root);
1032     pushLayoutStateForCurrentFlowThread(root);
1033 }
1034
1035 bool RenderView::shouldDisableLayoutStateForSubtree(RenderObject* renderer) const
1036 {
1037     RenderObject* o = renderer;
1038     while (o) {
1039         if (o->hasColumns() || o->hasTransform() || o->hasReflection())
1040             return true;
1041         o = o->container();
1042     }
1043     return false;
1044 }
1045
1046 IntSize RenderView::viewportSize() const
1047 {
1048     // FIXME: viewportSize() is used to layout content from viewport units. On iOS, it should use the last stable
1049     // unobscured rect. See <rdar://problem/16279088>.
1050     return frameView().visibleContentRectIncludingScrollbars(ScrollableArea::LegacyIOSDocumentVisibleRect).size();
1051 }
1052
1053 void RenderView::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
1054 {
1055     if (result.innerNode())
1056         return;
1057
1058     Node* node = document().documentElement();
1059     if (node) {
1060         result.setInnerNode(node);
1061         if (!result.innerNonSharedNode())
1062             result.setInnerNonSharedNode(node);
1063
1064         LayoutPoint adjustedPoint = point;
1065         offsetForContents(adjustedPoint);
1066
1067         result.setLocalPoint(adjustedPoint);
1068     }
1069 }
1070
1071 // FIXME: This function is obsolete and only used by embedded WebViews inside AppKit NSViews.
1072 // Do not add callers of this function!
1073 // The idea here is to take into account what object is moving the pagination point, and
1074 // thus choose the best place to chop it.
1075 void RenderView::setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak)
1076 {
1077     // Nobody else can set a page break once we have a forced break.
1078     if (m_legacyPrinting.m_forcedPageBreak)
1079         return;
1080
1081     // Forced breaks always win over unforced breaks.
1082     if (forcedBreak) {
1083         m_legacyPrinting.m_forcedPageBreak = true;
1084         m_legacyPrinting.m_bestTruncatedAt = y;
1085         return;
1086     }
1087
1088     // Prefer the widest object that tries to move the pagination point
1089     IntRect boundingBox = forRenderer->borderBoundingBox();
1090     if (boundingBox.width() > m_legacyPrinting.m_truncatorWidth) {
1091         m_legacyPrinting.m_truncatorWidth = boundingBox.width();
1092         m_legacyPrinting.m_bestTruncatedAt = y;
1093     }
1094 }
1095
1096 bool RenderView::usesCompositing() const
1097 {
1098     return m_compositor && m_compositor->inCompositingMode();
1099 }
1100
1101 RenderLayerCompositor& RenderView::compositor()
1102 {
1103     if (!m_compositor)
1104         m_compositor = std::make_unique<RenderLayerCompositor>(*this);
1105
1106     return *m_compositor;
1107 }
1108
1109 void RenderView::setIsInWindow(bool isInWindow)
1110 {
1111     if (m_compositor)
1112         m_compositor->setIsInWindow(isInWindow);
1113 }
1114
1115 void RenderView::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
1116 {
1117     RenderBlockFlow::styleDidChange(diff, oldStyle);
1118     if (hasRenderNamedFlowThreads())
1119         flowThreadController().styleDidChange();
1120 }
1121
1122 bool RenderView::hasRenderNamedFlowThreads() const
1123 {
1124     return m_flowThreadController && m_flowThreadController->hasRenderNamedFlowThreads();
1125 }
1126
1127 bool RenderView::checkTwoPassLayoutForAutoHeightRegions() const
1128 {
1129     return hasRenderNamedFlowThreads() && m_flowThreadController->hasFlowThreadsWithAutoLogicalHeightRegions();
1130 }
1131
1132 FlowThreadController& RenderView::flowThreadController()
1133 {
1134     if (!m_flowThreadController)
1135         m_flowThreadController = std::make_unique<FlowThreadController>(this);
1136
1137     return *m_flowThreadController;
1138 }
1139
1140 void RenderView::pushLayoutStateForCurrentFlowThread(const RenderObject& object)
1141 {
1142     if (!m_flowThreadController)
1143         return;
1144
1145     RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
1146     if (!currentFlowThread)
1147         return;
1148
1149     currentFlowThread->pushFlowThreadLayoutState(object);
1150 }
1151
1152 void RenderView::popLayoutStateForCurrentFlowThread()
1153 {
1154     if (!m_flowThreadController)
1155         return;
1156
1157     RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
1158     if (!currentFlowThread)
1159         return;
1160
1161     currentFlowThread->popFlowThreadLayoutState();
1162 }
1163
1164 IntervalArena* RenderView::intervalArena()
1165 {
1166     if (!m_intervalArena)
1167         m_intervalArena = IntervalArena::create();
1168     return m_intervalArena.get();
1169 }
1170
1171 ImageQualityController& RenderView::imageQualityController()
1172 {
1173     if (!m_imageQualityController)
1174         m_imageQualityController = std::make_unique<ImageQualityController>(*this);
1175     return *m_imageQualityController;
1176 }
1177
1178 void RenderView::addRendererWithPausedImageAnimations(RenderElement& renderer)
1179 {
1180     if (renderer.hasPausedImageAnimations()) {
1181         ASSERT(m_renderersWithPausedImageAnimation.contains(&renderer));
1182         return;
1183     }
1184     renderer.setHasPausedImageAnimations(true);
1185     m_renderersWithPausedImageAnimation.add(&renderer);
1186 }
1187
1188 void RenderView::removeRendererWithPausedImageAnimations(RenderElement& renderer)
1189 {
1190     ASSERT(renderer.hasPausedImageAnimations());
1191     ASSERT(m_renderersWithPausedImageAnimation.contains(&renderer));
1192
1193     renderer.setHasPausedImageAnimations(false);
1194     m_renderersWithPausedImageAnimation.remove(&renderer);
1195 }
1196
1197 void RenderView::resumePausedImageAnimationsIfNeeded()
1198 {
1199     auto visibleRect = frameView().visibleContentRect();
1200     Vector<RenderElement*, 10> toRemove;
1201     for (auto* renderer : m_renderersWithPausedImageAnimation) {
1202         if (renderer->repaintForPausedImageAnimationsIfNeeded(visibleRect))
1203             toRemove.append(renderer);
1204     }
1205     for (auto& renderer : toRemove)
1206         removeRendererWithPausedImageAnimations(*renderer);
1207 }
1208
1209 RenderView::RepaintRegionAccumulator::RepaintRegionAccumulator(RenderView* view)
1210     : m_rootView(view ? view->document().topDocument().renderView() : nullptr)
1211 {
1212     if (!m_rootView)
1213         return;
1214     m_wasAccumulatingRepaintRegion = !!m_rootView->m_accumulatedRepaintRegion;
1215     if (!m_wasAccumulatingRepaintRegion)
1216         m_rootView->m_accumulatedRepaintRegion = std::make_unique<Region>();
1217 }
1218
1219 RenderView::RepaintRegionAccumulator::~RepaintRegionAccumulator()
1220 {
1221     if (!m_rootView)
1222         return;
1223     if (m_wasAccumulatingRepaintRegion)
1224         return;
1225     m_rootView->flushAccumulatedRepaintRegion();
1226 }
1227
1228 unsigned RenderView::pageNumberForBlockProgressionOffset(int offset) const
1229 {
1230     int columnNumber = 0;
1231     const Pagination& pagination = frameView().frame().page()->pagination();
1232     if (pagination.mode == Pagination::Unpaginated)
1233         return columnNumber;
1234     
1235     bool progressionIsInline = false;
1236     bool progressionIsReversed = false;
1237     
1238     if (hasColumns()) {
1239         ColumnInfo* colInfo = columnInfo();
1240         if (!colInfo)
1241             return columnNumber;
1242         progressionIsInline = colInfo->progressionIsInline();
1243         progressionIsReversed = colInfo->progressionIsReversed();
1244     } else if (multiColumnFlowThread()) {
1245         progressionIsInline = multiColumnFlowThread()->progressionIsInline();
1246         progressionIsReversed = multiColumnFlowThread()->progressionIsReversed();
1247     } else
1248         return columnNumber;
1249     
1250     if (!progressionIsInline) {
1251         if (!progressionIsReversed)
1252             columnNumber = (pagination.pageLength + pagination.gap - offset) / (pagination.pageLength + pagination.gap);
1253         else
1254             columnNumber = offset / (pagination.pageLength + pagination.gap);
1255     }
1256
1257     return columnNumber;
1258 }
1259
1260 } // namespace WebCore