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