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