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