Use "= default" to denote default constructor or destructor
[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 "FrameView.h"
30 #include "GraphicsContext.h"
31 #include "HTMLBodyElement.h"
32 #include "HTMLFrameOwnerElement.h"
33 #include "HTMLHtmlElement.h"
34 #include "HTMLIFrameElement.h"
35 #include "HitTestResult.h"
36 #include "ImageQualityController.h"
37 #include "NodeTraversal.h"
38 #include "Page.h"
39 #include "RenderDescendantIterator.h"
40 #include "RenderGeometryMap.h"
41 #include "RenderIterator.h"
42 #include "RenderLayer.h"
43 #include "RenderLayerBacking.h"
44 #include "RenderLayerCompositor.h"
45 #include "RenderMultiColumnFlow.h"
46 #include "RenderMultiColumnSet.h"
47 #include "RenderMultiColumnSpannerPlaceholder.h"
48 #include "RenderQuote.h"
49 #include "RenderWidget.h"
50 #include "ScrollbarTheme.h"
51 #include "Settings.h"
52 #include "StyleInheritedData.h"
53 #include "TransformState.h"
54 #include <wtf/SetForScope.h>
55 #include <wtf/StackStats.h>
56
57 namespace WebCore {
58
59 struct FrameFlatteningLayoutDisallower {
60     FrameFlatteningLayoutDisallower(FrameView& frameView)
61         : m_frameView(frameView)
62         , m_disallowLayout(frameView.effectiveFrameFlattening() != FrameFlattening::Disabled)
63     {
64         if (m_disallowLayout)
65             m_frameView.startDisallowingLayout();
66     }
67
68     ~FrameFlatteningLayoutDisallower()
69     {
70         if (m_disallowLayout)
71             m_frameView.endDisallowingLayout();
72     }
73
74 private:
75     FrameView& m_frameView;
76     bool m_disallowLayout { false };
77 };
78
79 RenderView::RenderView(Document& document, RenderStyle&& style)
80     : RenderBlockFlow(document, WTFMove(style))
81     , m_frameView(*document.view())
82     , m_selection(*this)
83     , m_lazyRepaintTimer(*this, &RenderView::lazyRepaintTimerFired)
84 {
85     setIsRenderView();
86
87     // FIXME: We should find a way to enforce this at compile time.
88     ASSERT(document.view());
89
90     // init RenderObject attributes
91     setInline(false);
92     
93     m_minPreferredLogicalWidth = 0;
94     m_maxPreferredLogicalWidth = 0;
95
96     setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
97     
98     setPositionState(AbsolutePosition); // to 0,0 :)
99 }
100
101 RenderView::~RenderView() = default;
102
103 void RenderView::scheduleLazyRepaint(RenderBox& renderer)
104 {
105     if (renderer.renderBoxNeedsLazyRepaint())
106         return;
107     renderer.setRenderBoxNeedsLazyRepaint(true);
108     m_renderersNeedingLazyRepaint.add(&renderer);
109     if (!m_lazyRepaintTimer.isActive())
110         m_lazyRepaintTimer.startOneShot(0_s);
111 }
112
113 void RenderView::unscheduleLazyRepaint(RenderBox& renderer)
114 {
115     if (!renderer.renderBoxNeedsLazyRepaint())
116         return;
117     renderer.setRenderBoxNeedsLazyRepaint(false);
118     m_renderersNeedingLazyRepaint.remove(&renderer);
119     if (m_renderersNeedingLazyRepaint.isEmpty())
120         m_lazyRepaintTimer.stop();
121 }
122
123 void RenderView::lazyRepaintTimerFired()
124 {
125     for (auto& renderer : m_renderersNeedingLazyRepaint) {
126         renderer->repaint();
127         renderer->setRenderBoxNeedsLazyRepaint(false);
128     }
129     m_renderersNeedingLazyRepaint.clear();
130 }
131
132 bool RenderView::hitTest(const HitTestRequest& request, HitTestResult& result)
133 {
134     return hitTest(request, result.hitTestLocation(), result);
135 }
136
137 bool RenderView::hitTest(const HitTestRequest& request, const HitTestLocation& location, HitTestResult& result)
138 {
139     document().updateLayout();
140     
141 #if !ASSERT_DISABLED
142     SetForScope<bool> hitTestRestorer { m_inHitTesting, true };
143 #endif
144
145     FrameFlatteningLayoutDisallower disallower(frameView());
146
147     bool resultLayer = layer()->hitTest(request, location, result);
148
149     // ScrollView scrollbars are not the same as RenderLayer scrollbars tested by RenderLayer::hitTestOverflowControls,
150     // so we need to test ScrollView scrollbars separately here. In case of using overlay scrollbars, the layer hit test
151     // will always work so we need to check the ScrollView scrollbars in that case too.
152     if (!resultLayer || ScrollbarTheme::theme().usesOverlayScrollbars()) {
153         // FIXME: Consider if this test should be done unconditionally.
154         if (request.allowsFrameScrollbars()) {
155             IntPoint windowPoint = frameView().contentsToWindow(location.roundedPoint());
156             if (Scrollbar* frameScrollbar = frameView().scrollbarAtPoint(windowPoint)) {
157                 result.setScrollbar(frameScrollbar);
158                 return true;
159             }
160         }
161     }
162
163     return resultLayer;
164 }
165
166 RenderBox::LogicalExtentComputedValues RenderView::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit) const
167 {
168     return { !shouldUsePrintingLayout() ? LayoutUnit(viewLogicalHeight()) : logicalHeight, LayoutUnit(), ComputedMarginValues() };
169 }
170
171 void RenderView::updateLogicalWidth()
172 {
173     setLogicalWidth(shouldUsePrintingLayout() ? m_pageLogicalSize->width() : LayoutUnit(viewLogicalWidth()));
174 }
175
176 LayoutUnit RenderView::availableLogicalHeight(AvailableLogicalHeightType) const
177 {
178     // Make sure block progression pagination for percentages uses the column extent and
179     // not the view's extent. See https://bugs.webkit.org/show_bug.cgi?id=135204.
180     if (multiColumnFlow() && multiColumnFlow()->firstMultiColumnSet())
181         return multiColumnFlow()->firstMultiColumnSet()->computedColumnHeight();
182
183 #if PLATFORM(IOS)
184     // Workaround for <rdar://problem/7166808>.
185     if (document().isPluginDocument() && frameView().useFixedLayout())
186         return frameView().fixedLayoutSize().height();
187 #endif
188     return isHorizontalWritingMode() ? frameView().visibleHeight() : frameView().visibleWidth();
189 }
190
191 bool RenderView::isChildAllowed(const RenderObject& child, const RenderStyle&) const
192 {
193     return child.isBox();
194 }
195
196 void RenderView::layoutContent(const LayoutState& state)
197 {
198     UNUSED_PARAM(state);
199     ASSERT(needsLayout());
200
201     RenderBlockFlow::layout();
202 #ifndef NDEBUG
203     checkLayoutState(state);
204 #endif
205 }
206
207 #ifndef NDEBUG
208 void RenderView::checkLayoutState(const LayoutState& state)
209 {
210     ASSERT(layoutDeltaMatches(LayoutSize()));
211     ASSERT(!m_layoutStateDisableCount);
212     ASSERT(m_layoutState.get() == &state);
213 }
214 #endif
215
216 void RenderView::initializeLayoutState(LayoutState& state)
217 {
218     // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
219     state.m_clipped = false;
220
221     state.m_pageLogicalHeight = m_pageLogicalSize ? m_pageLogicalSize->height() : LayoutUnit(0);
222     state.m_pageLogicalHeightChanged = m_pageLogicalHeightChanged;
223     ASSERT(state.m_pageLogicalHeight >= 0);
224     state.m_isPaginated = state.m_pageLogicalHeight > 0;
225 }
226
227 void RenderView::layout()
228 {
229     StackStats::LayoutCheckPoint layoutCheckPoint;
230     if (!document().paginated())
231         m_pageLogicalSize = { };
232
233     if (shouldUsePrintingLayout()) {
234         if (!m_pageLogicalSize)
235             m_pageLogicalSize = LayoutSize(logicalWidth(), 0);
236         m_minPreferredLogicalWidth = m_pageLogicalSize->width();
237         m_maxPreferredLogicalWidth = m_minPreferredLogicalWidth;
238     }
239
240     // Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
241     bool relayoutChildren = !shouldUsePrintingLayout() && (width() != viewWidth() || height() != viewHeight());
242     if (relayoutChildren) {
243         setChildNeedsLayout(MarkOnlyThis);
244
245         for (auto& box : childrenOfType<RenderBox>(*this)) {
246             if (box.hasRelativeLogicalHeight()
247                 || box.style().logicalHeight().isPercentOrCalculated()
248                 || box.style().logicalMinHeight().isPercentOrCalculated()
249                 || box.style().logicalMaxHeight().isPercentOrCalculated()
250                 || box.isSVGRoot()
251                 )
252                 box.setChildNeedsLayout(MarkOnlyThis);
253         }
254     }
255
256     ASSERT(!m_layoutState);
257     if (!needsLayout())
258         return;
259
260     m_layoutState = std::make_unique<LayoutState>();
261     initializeLayoutState(*m_layoutState);
262
263     m_pageLogicalHeightChanged = false;
264
265     layoutContent(*m_layoutState);
266
267 #ifndef NDEBUG
268     checkLayoutState(*m_layoutState);
269 #endif
270     m_layoutState = nullptr;
271     clearNeedsLayout();
272 }
273
274 LayoutUnit RenderView::pageOrViewLogicalHeight() const
275 {
276     if (document().printing())
277         return m_pageLogicalSize->height();
278     
279     if (multiColumnFlow() && !style().hasInlineColumnAxis()) {
280         if (int pageLength = frameView().pagination().pageLength)
281             return pageLength;
282     }
283
284     return viewLogicalHeight();
285 }
286
287 LayoutUnit RenderView::clientLogicalWidthForFixedPosition() const
288 {
289     // FIXME: If the FrameView's fixedVisibleContentRect() is not empty, perhaps it should be consulted here too?
290     if (frameView().fixedElementsLayoutRelativeToFrame())
291         return (isHorizontalWritingMode() ? frameView().visibleWidth() : frameView().visibleHeight()) / frameView().frame().frameScaleFactor();
292
293 #if PLATFORM(IOS)
294     if (frameView().useCustomFixedPositionLayoutRect())
295         return isHorizontalWritingMode() ? frameView().customFixedPositionLayoutRect().width() : frameView().customFixedPositionLayoutRect().height();
296 #endif
297
298     if (settings().visualViewportEnabled())
299         return isHorizontalWritingMode() ? frameView().layoutViewportRect().width() : frameView().layoutViewportRect().height();
300
301     return clientLogicalWidth();
302 }
303
304 LayoutUnit RenderView::clientLogicalHeightForFixedPosition() const
305 {
306     // FIXME: If the FrameView's fixedVisibleContentRect() is not empty, perhaps it should be consulted here too?
307     if (frameView().fixedElementsLayoutRelativeToFrame())
308         return (isHorizontalWritingMode() ? frameView().visibleHeight() : frameView().visibleWidth()) / frameView().frame().frameScaleFactor();
309
310 #if PLATFORM(IOS)
311     if (frameView().useCustomFixedPositionLayoutRect())
312         return isHorizontalWritingMode() ? frameView().customFixedPositionLayoutRect().height() : frameView().customFixedPositionLayoutRect().width();
313 #endif
314
315     if (settings().visualViewportEnabled())
316         return isHorizontalWritingMode() ? frameView().layoutViewportRect().height() : frameView().layoutViewportRect().width();
317
318     return clientLogicalHeight();
319 }
320
321 void RenderView::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
322 {
323     // If a container was specified, and was not nullptr or the RenderView,
324     // then we should have found it by now.
325     ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
326     ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == (mode & IsFixed));
327
328     if (mode & IsFixed)
329         transformState.move(toLayoutSize(frameView().scrollPositionRespectingCustomFixedPosition()));
330
331     if (!repaintContainer && mode & UseTransforms && shouldUseTransformFromContainer(nullptr)) {
332         TransformationMatrix t;
333         getTransformFromContainer(nullptr, LayoutSize(), t);
334         transformState.applyTransform(t);
335     }
336 }
337
338 const RenderObject* RenderView::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
339 {
340     // If a container was specified, and was not nullptr or the RenderView,
341     // then we should have found it by now.
342     ASSERT_ARG(ancestorToStopAt, !ancestorToStopAt || ancestorToStopAt == this);
343
344     LayoutPoint scrollPosition = frameView().scrollPositionRespectingCustomFixedPosition();
345
346     if (!ancestorToStopAt && shouldUseTransformFromContainer(nullptr)) {
347         TransformationMatrix t;
348         getTransformFromContainer(nullptr, LayoutSize(), t);
349         geometryMap.pushView(this, toLayoutSize(scrollPosition), &t);
350     } else
351         geometryMap.pushView(this, toLayoutSize(scrollPosition));
352
353     return nullptr;
354 }
355
356 void RenderView::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
357 {
358     if (mode & UseTransforms && shouldUseTransformFromContainer(nullptr)) {
359         TransformationMatrix t;
360         getTransformFromContainer(nullptr, LayoutSize(), t);
361         transformState.applyTransform(t);
362     }
363
364     if (mode & IsFixed)
365         transformState.move(toLayoutSize(frameView().scrollPositionRespectingCustomFixedPosition()));
366 }
367
368 bool RenderView::requiresColumns(int) const
369 {
370     return frameView().pagination().mode != Pagination::Unpaginated;
371 }
372
373 void RenderView::computeColumnCountAndWidth()
374 {
375     int columnWidth = contentLogicalWidth();
376     if (style().hasInlineColumnAxis()) {
377         if (int pageLength = frameView().pagination().pageLength)
378             columnWidth = pageLength;
379     }
380     setComputedColumnCountAndWidth(1, columnWidth);
381 }
382
383 void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
384 {
385     // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
386     ASSERT(!needsLayout());
387     // RenderViews should never be called to paint with an offset not on device pixels.
388     ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);
389
390     // This avoids painting garbage between columns if there is a column gap.
391     if (frameView().pagination().mode != Pagination::Unpaginated && paintInfo.shouldPaintWithinRoot(*this))
392         paintInfo.context().fillRect(paintInfo.rect, frameView().baseBackgroundColor());
393
394     paintObject(paintInfo, paintOffset);
395 }
396
397 RenderElement* RenderView::rendererForRootBackground() const
398 {
399     auto* firstChild = this->firstChild();
400     if (!firstChild)
401         return nullptr;
402     ASSERT(is<RenderElement>(*firstChild));
403     auto& documentRenderer = downcast<RenderElement>(*firstChild);
404
405     if (documentRenderer.hasBackground())
406         return &documentRenderer;
407
408     // We propagate the background only for HTML content.
409     if (!is<HTMLHtmlElement>(documentRenderer.element()))
410         return &documentRenderer;
411
412     if (auto* body = document().body()) {
413         if (auto* renderer = body->renderer())
414             return renderer;
415     }
416     return &documentRenderer;
417 }
418
419 static inline bool rendererObscuresBackground(const RenderElement& rootElement)
420 {
421     auto& style = rootElement.style();
422     if (style.visibility() != VISIBLE || style.opacity() != 1 || style.hasTransform())
423         return false;
424
425     if (style.hasBorderRadius())
426         return false;
427
428     if (rootElement.isComposited())
429         return false;
430
431     auto* rendererForBackground = rootElement.view().rendererForRootBackground();
432     if (!rendererForBackground)
433         return false;
434
435     if (rendererForBackground->style().backgroundClip() == TextFillBox)
436         return false;
437
438     return true;
439 }
440
441 void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
442 {
443     if (!paintInfo.shouldPaintWithinRoot(*this))
444         return;
445
446     // Check to see if we are enclosed by a layer that requires complex painting rules.  If so, we cannot blit
447     // when scrolling, and we need to use slow repaints.  Examples of layers that require this are transparent layers,
448     // layers with reflections, or transformed layers.
449     // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being inside
450     // a transform, transparency layer, etc.
451     for (HTMLFrameOwnerElement* element = document().ownerElement(); element && element->renderer(); element = element->document().ownerElement()) {
452         RenderLayer* layer = element->renderer()->enclosingLayer();
453         if (layer->cannotBlitToWindow()) {
454             frameView().setCannotBlitToWindow();
455             break;
456         }
457
458         if (RenderLayer* compositingLayer = layer->enclosingCompositingLayerForRepaint()) {
459             if (!compositingLayer->backing()->paintsIntoWindow()) {
460                 frameView().setCannotBlitToWindow();
461                 break;
462             }
463         }
464     }
465
466     if (document().ownerElement())
467         return;
468
469     if (paintInfo.skipRootBackground())
470         return;
471
472     bool rootFillsViewport = false;
473     bool rootObscuresBackground = false;
474     Element* documentElement = document().documentElement();
475     if (RenderElement* rootRenderer = documentElement ? documentElement->renderer() : nullptr) {
476         // The document element's renderer is currently forced to be a block, but may not always be.
477         RenderBox* rootBox = is<RenderBox>(*rootRenderer) ? downcast<RenderBox>(rootRenderer) : nullptr;
478         rootFillsViewport = rootBox && !rootBox->x() && !rootBox->y() && rootBox->width() >= width() && rootBox->height() >= height();
479         rootObscuresBackground = rendererObscuresBackground(*rootRenderer);
480     }
481
482     bool backgroundShouldExtendBeyondPage = settings().backgroundShouldExtendBeyondPage();
483     compositor().setRootExtendedBackgroundColor(backgroundShouldExtendBeyondPage ? frameView().documentBackgroundColor() : Color());
484
485     Page* page = document().page();
486     float pageScaleFactor = page ? page->pageScaleFactor() : 1;
487
488     // If painting will entirely fill the view, no need to fill the background.
489     if (rootFillsViewport && rootObscuresBackground && pageScaleFactor >= 1)
490         return;
491
492     // This code typically only executes if the root element's visibility has been set to hidden,
493     // if there is a transform on the <html>, or if there is a page scale factor less than 1.
494     // Only fill with a background color (typically white) if we're the root document, 
495     // since iframes/frames with no background in the child document should show the parent's background.
496     // We use the base background color unless the backgroundShouldExtendBeyondPage setting is set,
497     // in which case we use the document's background color.
498     if (frameView().isTransparent()) // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being transparent.
499         frameView().setCannotBlitToWindow(); // The parent must show behind the child.
500     else {
501         const Color& documentBackgroundColor = frameView().documentBackgroundColor();
502         const Color& backgroundColor = (backgroundShouldExtendBeyondPage && documentBackgroundColor.isValid()) ? documentBackgroundColor : frameView().baseBackgroundColor();
503         if (backgroundColor.isVisible()) {
504             CompositeOperator previousOperator = paintInfo.context().compositeOperation();
505             paintInfo.context().setCompositeOperation(CompositeCopy);
506             paintInfo.context().fillRect(paintInfo.rect, backgroundColor);
507             paintInfo.context().setCompositeOperation(previousOperator);
508         } else
509             paintInfo.context().clearRect(paintInfo.rect);
510     }
511 }
512
513 bool RenderView::shouldRepaint(const LayoutRect& rect) const
514 {
515     return !printing() && !rect.isEmpty();
516 }
517
518 void RenderView::repaintRootContents()
519 {
520     if (layer()->isComposited()) {
521         layer()->setBackingNeedsRepaint(GraphicsLayer::DoNotClipToLayer);
522         return;
523     }
524
525     // Always use layoutOverflowRect() to fix rdar://problem/27182267.
526     // This should be cleaned up via webkit.org/b/159913 and webkit.org/b/159914.
527     RenderLayerModelObject* repaintContainer = containerForRepaint();
528     repaintUsingContainer(repaintContainer, computeRectForRepaint(layoutOverflowRect(), repaintContainer));
529 }
530
531 void RenderView::repaintViewRectangle(const LayoutRect& repaintRect) const
532 {
533     if (!shouldRepaint(repaintRect))
534         return;
535
536     // FIXME: enclosingRect is needed as long as we integral snap ScrollView/FrameView/RenderWidget size/position.
537     IntRect enclosingRect = enclosingIntRect(repaintRect);
538     if (auto ownerElement = document().ownerElement()) {
539         RenderBox* ownerBox = ownerElement->renderBox();
540         if (!ownerBox)
541             return;
542         LayoutRect viewRect = this->viewRect();
543 #if PLATFORM(IOS)
544         // Don't clip using the visible rect since clipping is handled at a higher level on iPhone.
545         LayoutRect adjustedRect = enclosingRect;
546 #else
547         LayoutRect adjustedRect = intersection(enclosingRect, viewRect);
548 #endif
549         adjustedRect.moveBy(-viewRect.location());
550         adjustedRect.moveBy(ownerBox->contentBoxRect().location());
551
552         // A dirty rect in an iframe is relative to the contents of that iframe.
553         // When we traverse between parent frames and child frames, we need to make sure
554         // that the coordinate system is mapped appropriately between the iframe's contents
555         // and the Renderer that contains the iframe. This transformation must account for a
556         // left scrollbar (if one exists).
557         FrameView& frameView = this->frameView();
558         if (frameView.shouldPlaceBlockDirectionScrollbarOnLeft() && frameView.verticalScrollbar())
559             adjustedRect.move(LayoutSize(frameView.verticalScrollbar()->occupiedWidth(), 0));
560
561         ownerBox->repaintRectangle(adjustedRect);
562         return;
563     }
564
565     frameView().addTrackedRepaintRect(snapRectToDevicePixels(repaintRect, document().deviceScaleFactor()));
566     if (!m_accumulatedRepaintRegion) {
567         frameView().repaintContentRectangle(enclosingRect);
568         return;
569     }
570     m_accumulatedRepaintRegion->unite(enclosingRect);
571
572     // Region will get slow if it gets too complex. Merge all rects so far to bounds if this happens.
573     // FIXME: Maybe there should be a region type that does this automatically.
574     static const unsigned maximumRepaintRegionGridSize = 16 * 16;
575     if (m_accumulatedRepaintRegion->gridSize() > maximumRepaintRegionGridSize)
576         m_accumulatedRepaintRegion = std::make_unique<Region>(m_accumulatedRepaintRegion->bounds());
577 }
578
579 void RenderView::flushAccumulatedRepaintRegion() const
580 {
581     ASSERT(!document().ownerElement());
582     ASSERT(m_accumulatedRepaintRegion);
583     auto repaintRects = m_accumulatedRepaintRegion->rects();
584     for (auto& rect : repaintRects)
585         frameView().repaintContentRectangle(rect);
586     m_accumulatedRepaintRegion = nullptr;
587 }
588
589 void RenderView::repaintViewAndCompositedLayers()
590 {
591     repaintRootContents();
592
593     RenderLayerCompositor& compositor = this->compositor();
594     if (compositor.inCompositingMode())
595         compositor.repaintCompositedLayers();
596 }
597
598 LayoutRect RenderView::visualOverflowRect() const
599 {
600     if (frameView().paintsEntireContents())
601         return layoutOverflowRect();
602
603     return RenderBlockFlow::visualOverflowRect();
604 }
605
606 LayoutRect RenderView::computeRectForRepaint(const LayoutRect& rect, const RenderLayerModelObject* repaintContainer, RepaintContext context) const
607 {
608     // If a container was specified, and was not nullptr or the RenderView,
609     // then we should have found it by now.
610     ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
611
612     if (printing())
613         return rect;
614     
615     LayoutRect adjustedRect = rect;
616     if (style().isFlippedBlocksWritingMode()) {
617         // We have to flip by hand since the view's logical height has not been determined.  We
618         // can use the viewport width and height.
619         if (style().isHorizontalWritingMode())
620             adjustedRect.setY(viewHeight() - adjustedRect.maxY());
621         else
622             adjustedRect.setX(viewWidth() - adjustedRect.maxX());
623     }
624
625     if (context.m_hasPositionFixedDescendant)
626         adjustedRect.moveBy(frameView().scrollPositionRespectingCustomFixedPosition());
627     
628     // Apply our transform if we have one (because of full page zooming).
629     if (!repaintContainer && layer() && layer()->transform())
630         adjustedRect = LayoutRect(layer()->transform()->mapRect(snapRectToDevicePixels(adjustedRect, document().deviceScaleFactor())));
631     return adjustedRect;
632 }
633
634 bool RenderView::isScrollableOrRubberbandableBox() const
635 {
636     // The main frame might be allowed to rubber-band even if there is no content to scroll to. This is unique to
637     // the main frame; subframes and overflow areas have to have content that can be scrolled to in order to rubber-band.
638     FrameView::Scrollability defineScrollable = frame().ownerElement() ? FrameView::Scrollability::Scrollable : FrameView::Scrollability::ScrollableOrRubberbandable;
639     return frameView().isScrollable(defineScrollable);
640 }
641
642 void RenderView::willBeDestroyed()
643 {
644     RenderBlockFlow::willBeDestroyed();
645
646     ASSERT_WITH_MESSAGE(m_rendererCount == 1, "All other renderers in this render tree should have been destroyed");
647 }
648
649 void RenderView::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
650 {
651     rects.append(snappedIntRect(accumulatedOffset, layer()->size()));
652 }
653
654 void RenderView::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
655 {
656     if (wasFixed)
657         *wasFixed = false;
658     quads.append(FloatRect(FloatPoint(), layer()->size()));
659 }
660
661 bool RenderView::printing() const
662 {
663     return document().printing();
664 }
665
666 bool RenderView::shouldUsePrintingLayout() const
667 {
668     if (!printing())
669         return false;
670     return frameView().frame().shouldUsePrintingLayout();
671 }
672
673 LayoutRect RenderView::viewRect() const
674 {
675     if (shouldUsePrintingLayout())
676         return LayoutRect(LayoutPoint(), size());
677     return frameView().visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
678 }
679
680 IntRect RenderView::unscaledDocumentRect() const
681 {
682     LayoutRect overflowRect(layoutOverflowRect());
683     flipForWritingMode(overflowRect);
684     return snappedIntRect(overflowRect);
685 }
686
687 bool RenderView::rootBackgroundIsEntirelyFixed() const
688 {
689     if (auto* rootBackgroundRenderer = rendererForRootBackground())
690         return rootBackgroundRenderer->style().hasEntirelyFixedBackground();
691     return false;
692 }
693     
694 LayoutRect RenderView::unextendedBackgroundRect() const
695 {
696     // FIXME: What is this? Need to patch for new columns?
697     return unscaledDocumentRect();
698 }
699     
700 LayoutRect RenderView::backgroundRect() const
701 {
702     // FIXME: New columns care about this?
703     if (frameView().hasExtendedBackgroundRectForPainting())
704         return frameView().extendedBackgroundRectForPainting();
705
706     return unextendedBackgroundRect();
707 }
708
709 IntRect RenderView::documentRect() const
710 {
711     FloatRect overflowRect(unscaledDocumentRect());
712     if (hasTransform())
713         overflowRect = layer()->currentTransform().mapRect(overflowRect);
714     return IntRect(overflowRect);
715 }
716
717 int RenderView::viewHeight() const
718 {
719     int height = 0;
720     if (!shouldUsePrintingLayout()) {
721         height = frameView().layoutHeight();
722         height = frameView().useFixedLayout() ? ceilf(style().effectiveZoom() * float(height)) : height;
723     }
724     return height;
725 }
726
727 int RenderView::viewWidth() const
728 {
729     int width = 0;
730     if (!shouldUsePrintingLayout()) {
731         width = frameView().layoutWidth();
732         width = frameView().useFixedLayout() ? ceilf(style().effectiveZoom() * float(width)) : width;
733     }
734     return width;
735 }
736
737 int RenderView::viewLogicalHeight() const
738 {
739     int height = style().isHorizontalWritingMode() ? viewHeight() : viewWidth();
740     return height;
741 }
742
743 void RenderView::setPageLogicalSize(LayoutSize size)
744 {
745     if (!m_pageLogicalSize || m_pageLogicalSize->height() != size.height())
746         m_pageLogicalHeightChanged = true;
747
748     m_pageLogicalSize = size;
749 }
750
751 float RenderView::zoomFactor() const
752 {
753     return frameView().frame().pageZoomFactor();
754 }
755
756 void RenderView::pushLayoutState(RenderObject& root)
757 {
758     ASSERT(m_layoutStateDisableCount == 0);
759     ASSERT(m_layoutState == 0);
760
761     m_layoutState = std::make_unique<LayoutState>(root);
762 }
763
764 bool RenderView::pushLayoutStateForPaginationIfNeeded(RenderBlockFlow& layoutRoot)
765 {
766     if (m_layoutState)
767         return false;
768     m_layoutState = std::make_unique<LayoutState>(layoutRoot);
769     m_layoutState->m_isPaginated = true;
770     // This is just a flag for known page height (see RenderBlockFlow::checkForPaginationLogicalHeightChange).
771     m_layoutState->m_pageLogicalHeight = 1;
772     return true;
773 }
774
775 IntSize RenderView::viewportSizeForCSSViewportUnits() const
776 {
777     return frameView().viewportSizeForCSSViewportUnits();
778 }
779
780 void RenderView::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
781 {
782     if (result.innerNode())
783         return;
784
785     if (multiColumnFlow() && multiColumnFlow()->firstMultiColumnSet())
786         return multiColumnFlow()->firstMultiColumnSet()->updateHitTestResult(result, point);
787
788     Node* node = document().documentElement();
789     if (node) {
790         result.setInnerNode(node);
791         if (!result.innerNonSharedNode())
792             result.setInnerNonSharedNode(node);
793
794         LayoutPoint adjustedPoint = point;
795         offsetForContents(adjustedPoint);
796
797         result.setLocalPoint(adjustedPoint);
798     }
799 }
800
801 // FIXME: This function is obsolete and only used by embedded WebViews inside AppKit NSViews.
802 // Do not add callers of this function!
803 // The idea here is to take into account what object is moving the pagination point, and
804 // thus choose the best place to chop it.
805 void RenderView::setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak)
806 {
807     // Nobody else can set a page break once we have a forced break.
808     if (m_legacyPrinting.m_forcedPageBreak)
809         return;
810
811     // Forced breaks always win over unforced breaks.
812     if (forcedBreak) {
813         m_legacyPrinting.m_forcedPageBreak = true;
814         m_legacyPrinting.m_bestTruncatedAt = y;
815         return;
816     }
817
818     // Prefer the widest object that tries to move the pagination point
819     LayoutRect boundingBox = forRenderer->borderBoundingBox();
820     if (boundingBox.width() > m_legacyPrinting.m_truncatorWidth) {
821         m_legacyPrinting.m_truncatorWidth = boundingBox.width();
822         m_legacyPrinting.m_bestTruncatedAt = y;
823     }
824 }
825
826 bool RenderView::usesCompositing() const
827 {
828     return m_compositor && m_compositor->inCompositingMode();
829 }
830
831 RenderLayerCompositor& RenderView::compositor()
832 {
833     if (!m_compositor)
834         m_compositor = std::make_unique<RenderLayerCompositor>(*this);
835
836     return *m_compositor;
837 }
838
839 void RenderView::setIsInWindow(bool isInWindow)
840 {
841     if (m_compositor)
842         m_compositor->setIsInWindow(isInWindow);
843 }
844
845 void RenderView::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
846 {
847     RenderBlockFlow::styleDidChange(diff, oldStyle);
848
849     frameView().styleDidChange();
850 }
851
852 ImageQualityController& RenderView::imageQualityController()
853 {
854     if (!m_imageQualityController)
855         m_imageQualityController = std::make_unique<ImageQualityController>(*this);
856     return *m_imageQualityController;
857 }
858
859 void RenderView::registerForVisibleInViewportCallback(RenderElement& renderer)
860 {
861     ASSERT(!m_visibleInViewportRenderers.contains(&renderer));
862     m_visibleInViewportRenderers.add(&renderer);
863 }
864
865 void RenderView::unregisterForVisibleInViewportCallback(RenderElement& renderer)
866 {
867     ASSERT(m_visibleInViewportRenderers.contains(&renderer));
868     m_visibleInViewportRenderers.remove(&renderer);
869 }
870
871 void RenderView::updateVisibleViewportRect(const IntRect& visibleRect)
872 {
873     resumePausedImageAnimationsIfNeeded(visibleRect);
874
875     for (auto* renderer : m_visibleInViewportRenderers) {
876         auto state = visibleRect.intersects(enclosingIntRect(renderer->absoluteClippedOverflowRect())) ? VisibleInViewportState::Yes : VisibleInViewportState::No;
877         renderer->setVisibleInViewportState(state);
878     }
879 }
880
881 void RenderView::addRendererWithPausedImageAnimations(RenderElement& renderer, CachedImage& image)
882 {
883     ASSERT(!renderer.hasPausedImageAnimations() || m_renderersWithPausedImageAnimation.contains(&renderer));
884
885     renderer.setHasPausedImageAnimations(true);
886     auto& images = m_renderersWithPausedImageAnimation.ensure(&renderer, [] {
887         return Vector<CachedImage*>();
888     }).iterator->value;
889     if (!images.contains(&image))
890         images.append(&image);
891 }
892
893 void RenderView::removeRendererWithPausedImageAnimations(RenderElement& renderer)
894 {
895     ASSERT(renderer.hasPausedImageAnimations());
896     ASSERT(m_renderersWithPausedImageAnimation.contains(&renderer));
897
898     renderer.setHasPausedImageAnimations(false);
899     m_renderersWithPausedImageAnimation.remove(&renderer);
900 }
901
902 void RenderView::removeRendererWithPausedImageAnimations(RenderElement& renderer, CachedImage& image)
903 {
904     ASSERT(renderer.hasPausedImageAnimations());
905
906     auto it = m_renderersWithPausedImageAnimation.find(&renderer);
907     ASSERT(it != m_renderersWithPausedImageAnimation.end());
908
909     auto& images = it->value;
910     if (!images.contains(&image))
911         return;
912
913     if (images.size() == 1)
914         removeRendererWithPausedImageAnimations(renderer);
915     else
916         images.removeFirst(&image);
917 }
918
919 void RenderView::resumePausedImageAnimationsIfNeeded(IntRect visibleRect)
920 {
921     Vector<std::pair<RenderElement*, CachedImage*>, 10> toRemove;
922     for (auto& it : m_renderersWithPausedImageAnimation) {
923         auto* renderer = it.key;
924         for (auto* image : it.value) {
925             if (renderer->repaintForPausedImageAnimationsIfNeeded(visibleRect, *image))
926                 toRemove.append(std::make_pair(renderer, image));
927         }
928     }
929     for (auto& pair : toRemove)
930         removeRendererWithPausedImageAnimations(*pair.first, *pair.second);
931 }
932
933 RenderView::RepaintRegionAccumulator::RepaintRegionAccumulator(RenderView* view)
934 {
935     if (!view)
936         return;
937
938     auto* rootRenderView = view->document().topDocument().renderView();
939     if (!rootRenderView)
940         return;
941
942     m_wasAccumulatingRepaintRegion = !!rootRenderView->m_accumulatedRepaintRegion;
943     if (!m_wasAccumulatingRepaintRegion)
944         rootRenderView->m_accumulatedRepaintRegion = std::make_unique<Region>();
945     m_rootView = makeWeakPtr(*rootRenderView);
946 }
947
948 RenderView::RepaintRegionAccumulator::~RepaintRegionAccumulator()
949 {
950     if (m_wasAccumulatingRepaintRegion)
951         return;
952     if (!m_rootView)
953         return;
954     m_rootView.get()->flushAccumulatedRepaintRegion();
955 }
956
957 unsigned RenderView::pageNumberForBlockProgressionOffset(int offset) const
958 {
959     int columnNumber = 0;
960     const Pagination& pagination = page().pagination();
961     if (pagination.mode == Pagination::Unpaginated)
962         return columnNumber;
963     
964     bool progressionIsInline = false;
965     bool progressionIsReversed = false;
966     
967     if (multiColumnFlow()) {
968         progressionIsInline = multiColumnFlow()->progressionIsInline();
969         progressionIsReversed = multiColumnFlow()->progressionIsReversed();
970     } else
971         return columnNumber;
972     
973     if (!progressionIsInline) {
974         if (!progressionIsReversed)
975             columnNumber = (pagination.pageLength + pagination.gap - offset) / (pagination.pageLength + pagination.gap);
976         else
977             columnNumber = offset / (pagination.pageLength + pagination.gap);
978     }
979
980     return columnNumber;
981 }
982
983 unsigned RenderView::pageCount() const
984 {
985     const Pagination& pagination = page().pagination();
986     if (pagination.mode == Pagination::Unpaginated)
987         return 0;
988     
989     if (multiColumnFlow() && multiColumnFlow()->firstMultiColumnSet())
990         return multiColumnFlow()->firstMultiColumnSet()->columnCount();
991
992     return 0;
993 }
994
995 #if ENABLE(CSS_SCROLL_SNAP)
996 void RenderView::registerBoxWithScrollSnapPositions(const RenderBox& box)
997 {
998     m_boxesWithScrollSnapPositions.add(&box);
999 }
1000
1001 void RenderView::unregisterBoxWithScrollSnapPositions(const RenderBox& box)
1002 {
1003     m_boxesWithScrollSnapPositions.remove(&box);
1004 }
1005 #endif
1006
1007 } // namespace WebCore