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