1 | /*
|
---|
2 | * Copyright (C) 1999 Lars Knoll ([email protected])
|
---|
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 "Frame.h"
|
---|
28 | #include "FrameView.h"
|
---|
29 | #include "GraphicsContext.h"
|
---|
30 | #include "HTMLBodyElement.h"
|
---|
31 | #include "HTMLFrameOwnerElement.h"
|
---|
32 | #include "HTMLFrameSetElement.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().layoutSize().height() : frameView().layoutSize().width();
|
---|
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.isSVGRootOrLegacySVGRoot()
|
---|
173 | )
|
---|
174 | box.setChildNeedsLayout(MarkOnlyThis);
|
---|
175 | }
|
---|
176 | }
|
---|
177 |
|
---|
178 | ASSERT(!frameView().layoutContext().layoutState());
|
---|
179 | if (!needsLayout())
|
---|
180 | return;
|
---|
181 |
|
---|
182 | LayoutStateMaintainer statePusher(*this, { }, false, valueOrDefault(m_pageLogicalSize).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* ancestorContainer, TransformState& transformState, OptionSet<MapCoordinatesMode> 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(ancestorContainer, !ancestorContainer || ancestorContainer == this);
|
---|
246 | ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == (mode.contains(IsFixed)));
|
---|
247 |
|
---|
248 | if (mode.contains(IsFixed))
|
---|
249 | transformState.move(toLayoutSize(frameView().scrollPositionRespectingCustomFixedPosition()));
|
---|
250 |
|
---|
251 | if (!ancestorContainer && mode.contains(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(OptionSet<MapCoordinatesMode> 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 (documentRenderer.shouldApplyAnyContainment())
|
---|
333 | return nullptr;
|
---|
334 |
|
---|
335 | if (auto* body = document().body()) {
|
---|
336 | if (auto* renderer = body->renderer()) {
|
---|
337 | if (!renderer->shouldApplyAnyContainment())
|
---|
338 | return renderer;
|
---|
339 | }
|
---|
340 | }
|
---|
341 | return &documentRenderer;
|
---|
342 | }
|
---|
343 |
|
---|
344 | static inline bool rendererObscuresBackground(const RenderElement& rootElement)
|
---|
345 | {
|
---|
346 | auto& style = rootElement.style();
|
---|
347 | if (style.visibility() != Visibility::Visible || style.opacity() != 1 || style.hasTransform())
|
---|
348 | return false;
|
---|
349 |
|
---|
350 | if (style.hasBorderRadius())
|
---|
351 | return false;
|
---|
352 |
|
---|
353 | if (rootElement.isComposited())
|
---|
354 | return false;
|
---|
355 |
|
---|
356 | auto* rendererForBackground = rootElement.view().rendererForRootBackground();
|
---|
357 | if (!rendererForBackground)
|
---|
358 | return false;
|
---|
359 |
|
---|
360 | if (rendererForBackground->style().backgroundClip() == FillBox::Text)
|
---|
361 | return false;
|
---|
362 |
|
---|
363 | return true;
|
---|
364 | }
|
---|
365 |
|
---|
366 | void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
|
---|
367 | {
|
---|
368 | if (!paintInfo.shouldPaintWithinRoot(*this))
|
---|
369 | return;
|
---|
370 |
|
---|
371 | // Check to see if we are enclosed by a layer that requires complex painting rules. If so, we cannot blit
|
---|
372 | // when scrolling, and we need to use slow repaints. Examples of layers that require this are transparent layers,
|
---|
373 | // layers with reflections, or transformed layers.
|
---|
374 | // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being inside
|
---|
375 | // a transform, transparency layer, etc.
|
---|
376 | for (HTMLFrameOwnerElement* element = document().ownerElement(); element && element->renderer(); element = element->document().ownerElement()) {
|
---|
377 | RenderLayer* layer = element->renderer()->enclosingLayer();
|
---|
378 | if (layer->cannotBlitToWindow()) {
|
---|
379 | frameView().setCannotBlitToWindow();
|
---|
380 | break;
|
---|
381 | }
|
---|
382 |
|
---|
383 | if (auto* compositingLayer = layer->enclosingCompositingLayerForRepaint().layer) {
|
---|
384 | if (!compositingLayer->backing()->paintsIntoWindow()) {
|
---|
385 | frameView().setCannotBlitToWindow();
|
---|
386 | break;
|
---|
387 | }
|
---|
388 | }
|
---|
389 | }
|
---|
390 |
|
---|
391 | if (document().ownerElement())
|
---|
392 | return;
|
---|
393 |
|
---|
394 | if (paintInfo.skipRootBackground())
|
---|
395 | return;
|
---|
396 |
|
---|
397 | bool rootFillsViewport = false;
|
---|
398 | bool rootObscuresBackground = false;
|
---|
399 | Element* documentElement = document().documentElement();
|
---|
400 | if (RenderElement* rootRenderer = documentElement ? documentElement->renderer() : nullptr) {
|
---|
401 | // The document element's renderer is currently forced to be a block, but may not always be.
|
---|
402 | auto* rootBox = dynamicDowncast<RenderBox>(*rootRenderer);
|
---|
403 | rootFillsViewport = rootBox && !rootBox->x() && !rootBox->y() && rootBox->width() >= width() && rootBox->height() >= height();
|
---|
404 | rootObscuresBackground = rendererObscuresBackground(*rootRenderer);
|
---|
405 | }
|
---|
406 |
|
---|
407 | compositor().rootBackgroundColorOrTransparencyChanged();
|
---|
408 |
|
---|
409 | Page* page = document().page();
|
---|
410 | float pageScaleFactor = page ? page->pageScaleFactor() : 1;
|
---|
411 |
|
---|
412 | // If painting will entirely fill the view, no need to fill the background.
|
---|
413 | if (rootFillsViewport && rootObscuresBackground && pageScaleFactor >= 1)
|
---|
414 | return;
|
---|
415 |
|
---|
416 | // This code typically only executes if the root element's visibility has been set to hidden,
|
---|
417 | // if there is a transform on the <html>, or if there is a page scale factor less than 1.
|
---|
418 | // Only fill with a background color (typically white) if we're the root document,
|
---|
419 | // since iframes/frames with no background in the child document should show the parent's background.
|
---|
420 | // We use the base background color unless the backgroundShouldExtendBeyondPage setting is set,
|
---|
421 | // in which case we use the document's background color.
|
---|
422 | if (frameView().isTransparent()) // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being transparent.
|
---|
423 | frameView().setCannotBlitToWindow(); // The parent must show behind the child.
|
---|
424 | else {
|
---|
425 | const Color& documentBackgroundColor = frameView().documentBackgroundColor();
|
---|
426 | const Color& backgroundColor = (settings().backgroundShouldExtendBeyondPage() && documentBackgroundColor.isValid()) ? documentBackgroundColor : frameView().baseBackgroundColor();
|
---|
427 | if (backgroundColor.isVisible()) {
|
---|
428 | CompositeOperator previousOperator = paintInfo.context().compositeOperation();
|
---|
429 | paintInfo.context().setCompositeOperation(CompositeOperator::Copy);
|
---|
430 | paintInfo.context().fillRect(paintInfo.rect, backgroundColor);
|
---|
431 | paintInfo.context().setCompositeOperation(previousOperator);
|
---|
432 | } else
|
---|
433 | paintInfo.context().clearRect(paintInfo.rect);
|
---|
434 | }
|
---|
435 | }
|
---|
436 |
|
---|
437 | bool RenderView::shouldRepaint(const LayoutRect& rect) const
|
---|
438 | {
|
---|
439 | return !printing() && !rect.isEmpty();
|
---|
440 | }
|
---|
441 |
|
---|
442 | void RenderView::repaintRootContents()
|
---|
443 | {
|
---|
444 | if (layer()->isComposited()) {
|
---|
445 | layer()->setBackingNeedsRepaint(GraphicsLayer::DoNotClipToLayer);
|
---|
446 | return;
|
---|
447 | }
|
---|
448 |
|
---|
449 | // Always use layoutOverflowRect() to fix rdar://problem/27182267.
|
---|
450 | // This should be cleaned up via webkit.org/b/159913 and webkit.org/b/159914.
|
---|
451 | auto* repaintContainer = containerForRepaint().renderer;
|
---|
452 | repaintUsingContainer(repaintContainer, computeRectForRepaint(layoutOverflowRect(), repaintContainer));
|
---|
453 | }
|
---|
454 |
|
---|
455 | void RenderView::repaintViewRectangle(const LayoutRect& repaintRect) const
|
---|
456 | {
|
---|
457 | if (!shouldRepaint(repaintRect))
|
---|
458 | return;
|
---|
459 |
|
---|
460 | // FIXME: enclosingRect is needed as long as we integral snap ScrollView/FrameView/RenderWidget size/position.
|
---|
461 | IntRect enclosingRect = enclosingIntRect(repaintRect);
|
---|
462 | if (auto ownerElement = document().ownerElement()) {
|
---|
463 | RenderBox* ownerBox = ownerElement->renderBox();
|
---|
464 | if (!ownerBox)
|
---|
465 | return;
|
---|
466 | LayoutRect viewRect = this->viewRect();
|
---|
467 | #if PLATFORM(IOS_FAMILY)
|
---|
468 | // Don't clip using the visible rect since clipping is handled at a higher level on iPhone.
|
---|
469 | LayoutRect adjustedRect = enclosingRect;
|
---|
470 | #else
|
---|
471 | LayoutRect adjustedRect = intersection(enclosingRect, viewRect);
|
---|
472 | #endif
|
---|
473 | adjustedRect.moveBy(-viewRect.location());
|
---|
474 | adjustedRect.moveBy(ownerBox->contentBoxRect().location());
|
---|
475 |
|
---|
476 | // A dirty rect in an iframe is relative to the contents of that iframe.
|
---|
477 | // When we traverse between parent frames and child frames, we need to make sure
|
---|
478 | // that the coordinate system is mapped appropriately between the iframe's contents
|
---|
479 | // and the Renderer that contains the iframe. This transformation must account for a
|
---|
480 | // left scrollbar (if one exists).
|
---|
481 | FrameView& frameView = this->frameView();
|
---|
482 | if (frameView.shouldPlaceVerticalScrollbarOnLeft() && frameView.verticalScrollbar())
|
---|
483 | adjustedRect.move(LayoutSize(frameView.verticalScrollbar()->occupiedWidth(), 0));
|
---|
484 |
|
---|
485 | ownerBox->repaintRectangle(adjustedRect);
|
---|
486 | return;
|
---|
487 | }
|
---|
488 |
|
---|
489 | frameView().addTrackedRepaintRect(snapRectToDevicePixels(repaintRect, document().deviceScaleFactor()));
|
---|
490 | if (!m_accumulatedRepaintRegion) {
|
---|
491 | frameView().repaintContentRectangle(enclosingRect);
|
---|
492 | return;
|
---|
493 | }
|
---|
494 | m_accumulatedRepaintRegion->unite(enclosingRect);
|
---|
495 |
|
---|
496 | // Region will get slow if it gets too complex. Merge all rects so far to bounds if this happens.
|
---|
497 | // FIXME: Maybe there should be a region type that does this automatically.
|
---|
498 | static const unsigned maximumRepaintRegionGridSize = 16 * 16;
|
---|
499 | if (m_accumulatedRepaintRegion->gridSize() > maximumRepaintRegionGridSize)
|
---|
500 | m_accumulatedRepaintRegion = makeUnique<Region>(m_accumulatedRepaintRegion->bounds());
|
---|
501 | }
|
---|
502 |
|
---|
503 | void RenderView::flushAccumulatedRepaintRegion() const
|
---|
504 | {
|
---|
505 | ASSERT(!document().ownerElement());
|
---|
506 | ASSERT(m_accumulatedRepaintRegion);
|
---|
507 | auto repaintRects = m_accumulatedRepaintRegion->rects();
|
---|
508 | for (auto& rect : repaintRects)
|
---|
509 | frameView().repaintContentRectangle(rect);
|
---|
510 | m_accumulatedRepaintRegion = nullptr;
|
---|
511 | }
|
---|
512 |
|
---|
513 | void RenderView::repaintViewAndCompositedLayers()
|
---|
514 | {
|
---|
515 | repaintRootContents();
|
---|
516 |
|
---|
517 | RenderLayerCompositor& compositor = this->compositor();
|
---|
518 | if (compositor.usesCompositing())
|
---|
519 | compositor.repaintCompositedLayers();
|
---|
520 | }
|
---|
521 |
|
---|
522 | std::optional<LayoutRect> RenderView::computeVisibleRectInContainer(const LayoutRect& rect, const RenderLayerModelObject* container, VisibleRectContext context) const
|
---|
523 | {
|
---|
524 | // If a container was specified, and was not nullptr or the RenderView,
|
---|
525 | // then we should have found it by now.
|
---|
526 | ASSERT_ARG(container, !container || container == this);
|
---|
527 |
|
---|
528 | if (printing())
|
---|
529 | return rect;
|
---|
530 |
|
---|
531 | LayoutRect adjustedRect = rect;
|
---|
532 | if (style().isFlippedBlocksWritingMode()) {
|
---|
533 | // We have to flip by hand since the view's logical height has not been determined. We
|
---|
534 | // can use the viewport width and height.
|
---|
535 | if (style().isHorizontalWritingMode())
|
---|
536 | adjustedRect.setY(viewHeight() - adjustedRect.maxY());
|
---|
537 | else
|
---|
538 | adjustedRect.setX(viewWidth() - adjustedRect.maxX());
|
---|
539 | }
|
---|
540 |
|
---|
541 | if (context.hasPositionFixedDescendant)
|
---|
542 | adjustedRect.moveBy(frameView().scrollPositionRespectingCustomFixedPosition());
|
---|
543 |
|
---|
544 | // Apply our transform if we have one (because of full page zooming).
|
---|
545 | if (!container && layer() && layer()->transform())
|
---|
546 | adjustedRect = LayoutRect(layer()->transform()->mapRect(snapRectToDevicePixels(adjustedRect, document().deviceScaleFactor())));
|
---|
547 | return adjustedRect;
|
---|
548 | }
|
---|
549 |
|
---|
550 | bool RenderView::isScrollableOrRubberbandableBox() const
|
---|
551 | {
|
---|
552 | // The main frame might be allowed to rubber-band even if there is no content to scroll to. This is unique to
|
---|
553 | // the main frame; subframes and overflow areas have to have content that can be scrolled to in order to rubber-band.
|
---|
554 | FrameView::Scrollability defineScrollable = frame().ownerElement() ? FrameView::Scrollability::Scrollable : FrameView::Scrollability::ScrollableOrRubberbandable;
|
---|
555 | return frameView().isScrollable(defineScrollable);
|
---|
556 | }
|
---|
557 |
|
---|
558 | void RenderView::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
|
---|
559 | {
|
---|
560 | rects.append(snappedIntRect(accumulatedOffset, layer()->size()));
|
---|
561 | }
|
---|
562 |
|
---|
563 | void RenderView::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
|
---|
564 | {
|
---|
565 | if (wasFixed)
|
---|
566 | *wasFixed = false;
|
---|
567 | quads.append(FloatRect(FloatPoint(), layer()->size()));
|
---|
568 | }
|
---|
569 |
|
---|
570 | bool RenderView::printing() const
|
---|
571 | {
|
---|
572 | return document().printing();
|
---|
573 | }
|
---|
574 |
|
---|
575 | bool RenderView::shouldUsePrintingLayout() const
|
---|
576 | {
|
---|
577 | if (!printing())
|
---|
578 | return false;
|
---|
579 | return frameView().frame().shouldUsePrintingLayout();
|
---|
580 | }
|
---|
581 |
|
---|
582 | LayoutRect RenderView::viewRect() const
|
---|
583 | {
|
---|
584 | if (shouldUsePrintingLayout())
|
---|
585 | return LayoutRect(LayoutPoint(), size());
|
---|
586 | return frameView().visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
|
---|
587 | }
|
---|
588 |
|
---|
589 | IntRect RenderView::unscaledDocumentRect() const
|
---|
590 | {
|
---|
591 | LayoutRect overflowRect(layoutOverflowRect());
|
---|
592 | flipForWritingMode(overflowRect);
|
---|
593 | return snappedIntRect(overflowRect);
|
---|
594 | }
|
---|
595 |
|
---|
596 | bool RenderView::rootBackgroundIsEntirelyFixed() const
|
---|
597 | {
|
---|
598 | if (auto* rootBackgroundRenderer = rendererForRootBackground())
|
---|
599 | return rootBackgroundRenderer->style().hasEntirelyFixedBackground();
|
---|
600 | return false;
|
---|
601 | }
|
---|
602 |
|
---|
603 | bool RenderView::shouldPaintBaseBackground() const
|
---|
604 | {
|
---|
605 | auto& document = this->document();
|
---|
606 | auto& frameView = this->frameView();
|
---|
607 | auto* ownerElement = document.ownerElement();
|
---|
608 |
|
---|
609 | // Fill with a base color if we're the root document.
|
---|
610 | if (!ownerElement)
|
---|
611 | return !frameView.isTransparent();
|
---|
612 |
|
---|
613 | if (ownerElement->hasTagName(HTMLNames::frameTag))
|
---|
614 | return true;
|
---|
615 |
|
---|
616 | // Locate the <body> element using the DOM. This is easier than trying
|
---|
617 | // to crawl around a render tree with potential :before/:after content and
|
---|
618 | // anonymous blocks created by inline <body> tags etc. We can locate the <body>
|
---|
619 | // render object very easily via the DOM.
|
---|
620 | auto* body = document.bodyOrFrameset();
|
---|
621 |
|
---|
622 | // SVG documents and XML documents with SVG root nodes are transparent.
|
---|
623 | if (!body)
|
---|
624 | return !document.hasSVGRootNode();
|
---|
625 |
|
---|
626 | // Can't scroll a frameset document anyway.
|
---|
627 | if (is<HTMLFrameSetElement>(*body))
|
---|
628 | return true;
|
---|
629 |
|
---|
630 | auto* frameRenderer = ownerElement->renderer();
|
---|
631 | if (!frameRenderer)
|
---|
632 | return false;
|
---|
633 |
|
---|
634 | // iframes should fill with a base color if the used color scheme of the
|
---|
635 | // element and the used color scheme of the embedded document’s root
|
---|
636 | // element do not match.
|
---|
637 | if (frameView.useDarkAppearance() != frameRenderer->useDarkAppearance())
|
---|
638 | return !frameView.isTransparent();
|
---|
639 |
|
---|
640 | return false;
|
---|
641 | }
|
---|
642 |
|
---|
643 | LayoutRect RenderView::unextendedBackgroundRect() const
|
---|
644 | {
|
---|
645 | // FIXME: What is this? Need to patch for new columns?
|
---|
646 | return unscaledDocumentRect();
|
---|
647 | }
|
---|
648 |
|
---|
649 | LayoutRect RenderView::backgroundRect() const
|
---|
650 | {
|
---|
651 | // FIXME: New columns care about this?
|
---|
652 | if (frameView().hasExtendedBackgroundRectForPainting())
|
---|
653 | return frameView().extendedBackgroundRectForPainting();
|
---|
654 |
|
---|
655 | return unextendedBackgroundRect();
|
---|
656 | }
|
---|
657 |
|
---|
658 | IntRect RenderView::documentRect() const
|
---|
659 | {
|
---|
660 | FloatRect overflowRect(unscaledDocumentRect());
|
---|
661 | if (hasTransform())
|
---|
662 | overflowRect = layer()->currentTransform().mapRect(overflowRect);
|
---|
663 | return IntRect(overflowRect);
|
---|
664 | }
|
---|
665 |
|
---|
666 | int RenderView::viewHeight() const
|
---|
667 | {
|
---|
668 | int height = 0;
|
---|
669 | if (!shouldUsePrintingLayout()) {
|
---|
670 | height = frameView().layoutHeight();
|
---|
671 | height = frameView().useFixedLayout() ? ceilf(style().effectiveZoom() * float(height)) : height;
|
---|
672 | }
|
---|
673 | return height;
|
---|
674 | }
|
---|
675 |
|
---|
676 | int RenderView::viewWidth() const
|
---|
677 | {
|
---|
678 | int width = 0;
|
---|
679 | if (!shouldUsePrintingLayout()) {
|
---|
680 | width = frameView().layoutWidth();
|
---|
681 | width = frameView().useFixedLayout() ? ceilf(style().effectiveZoom() * float(width)) : width;
|
---|
682 | }
|
---|
683 | return width;
|
---|
684 | }
|
---|
685 |
|
---|
686 | int RenderView::viewLogicalHeight() const
|
---|
687 | {
|
---|
688 | int height = style().isHorizontalWritingMode() ? viewHeight() : viewWidth();
|
---|
689 | return height;
|
---|
690 | }
|
---|
691 |
|
---|
692 | void RenderView::setPageLogicalSize(LayoutSize size)
|
---|
693 | {
|
---|
694 | if (!m_pageLogicalSize || m_pageLogicalSize->height() != size.height())
|
---|
695 | m_pageLogicalHeightChanged = true;
|
---|
696 |
|
---|
697 | m_pageLogicalSize = size;
|
---|
698 | }
|
---|
699 |
|
---|
700 | float RenderView::zoomFactor() const
|
---|
701 | {
|
---|
702 | return frameView().frame().pageZoomFactor();
|
---|
703 | }
|
---|
704 |
|
---|
705 | FloatSize RenderView::sizeForCSSSmallViewportUnits() const
|
---|
706 | {
|
---|
707 | return frameView().sizeForCSSSmallViewportUnits();
|
---|
708 | }
|
---|
709 |
|
---|
710 | FloatSize RenderView::sizeForCSSLargeViewportUnits() const
|
---|
711 | {
|
---|
712 | return frameView().sizeForCSSLargeViewportUnits();
|
---|
713 | }
|
---|
714 |
|
---|
715 | FloatSize RenderView::sizeForCSSDynamicViewportUnits() const
|
---|
716 | {
|
---|
717 | return frameView().sizeForCSSDynamicViewportUnits();
|
---|
718 | }
|
---|
719 |
|
---|
720 | FloatSize RenderView::sizeForCSSDefaultViewportUnits() const
|
---|
721 | {
|
---|
722 | return frameView().sizeForCSSDefaultViewportUnits();
|
---|
723 | }
|
---|
724 |
|
---|
725 | Node* RenderView::nodeForHitTest() const
|
---|
726 | {
|
---|
727 | return document().documentElement();
|
---|
728 | }
|
---|
729 |
|
---|
730 | void RenderView::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
|
---|
731 | {
|
---|
732 | if (result.innerNode())
|
---|
733 | return;
|
---|
734 |
|
---|
735 | if (multiColumnFlow() && multiColumnFlow()->firstMultiColumnSet())
|
---|
736 | return multiColumnFlow()->firstMultiColumnSet()->updateHitTestResult(result, point);
|
---|
737 |
|
---|
738 | if (auto* node = nodeForHitTest()) {
|
---|
739 | result.setInnerNode(node);
|
---|
740 | if (!result.innerNonSharedNode())
|
---|
741 | result.setInnerNonSharedNode(node);
|
---|
742 |
|
---|
743 | LayoutPoint adjustedPoint = point;
|
---|
744 | offsetForContents(adjustedPoint);
|
---|
745 |
|
---|
746 | result.setLocalPoint(adjustedPoint);
|
---|
747 | }
|
---|
748 | }
|
---|
749 |
|
---|
750 | // FIXME: This function is obsolete and only used by embedded WebViews inside AppKit NSViews.
|
---|
751 | // Do not add callers of this function!
|
---|
752 | // The idea here is to take into account what object is moving the pagination point, and
|
---|
753 | // thus choose the best place to chop it.
|
---|
754 | void RenderView::setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak)
|
---|
755 | {
|
---|
756 | // Nobody else can set a page break once we have a forced break.
|
---|
757 | if (m_legacyPrinting.m_forcedPageBreak)
|
---|
758 | return;
|
---|
759 |
|
---|
760 | // Forced breaks always win over unforced breaks.
|
---|
761 | if (forcedBreak) {
|
---|
762 | m_legacyPrinting.m_forcedPageBreak = true;
|
---|
763 | m_legacyPrinting.m_bestTruncatedAt = y;
|
---|
764 | return;
|
---|
765 | }
|
---|
766 |
|
---|
767 | // Prefer the widest object that tries to move the pagination point
|
---|
768 | LayoutRect boundingBox = forRenderer->borderBoundingBox();
|
---|
769 | if (boundingBox.width() > m_legacyPrinting.m_truncatorWidth) {
|
---|
770 | m_legacyPrinting.m_truncatorWidth = boundingBox.width();
|
---|
771 | m_legacyPrinting.m_bestTruncatedAt = y;
|
---|
772 | }
|
---|
773 | }
|
---|
774 |
|
---|
775 | bool RenderView::usesCompositing() const
|
---|
776 | {
|
---|
777 | return m_compositor && m_compositor->usesCompositing();
|
---|
778 | }
|
---|
779 |
|
---|
780 | RenderLayerCompositor& RenderView::compositor()
|
---|
781 | {
|
---|
782 | if (!m_compositor)
|
---|
783 | m_compositor = makeUnique<RenderLayerCompositor>(*this);
|
---|
784 |
|
---|
785 | return *m_compositor;
|
---|
786 | }
|
---|
787 |
|
---|
788 | void RenderView::setIsInWindow(bool isInWindow)
|
---|
789 | {
|
---|
790 | if (m_compositor)
|
---|
791 | m_compositor->setIsInWindow(isInWindow);
|
---|
792 | }
|
---|
793 |
|
---|
794 | ImageQualityController& RenderView::imageQualityController()
|
---|
795 | {
|
---|
796 | if (!m_imageQualityController)
|
---|
797 | m_imageQualityController = makeUnique<ImageQualityController>(*this);
|
---|
798 | return *m_imageQualityController;
|
---|
799 | }
|
---|
800 |
|
---|
801 | void RenderView::registerForVisibleInViewportCallback(RenderElement& renderer)
|
---|
802 | {
|
---|
803 | ASSERT(!m_visibleInViewportRenderers.contains(&renderer));
|
---|
804 | m_visibleInViewportRenderers.add(&renderer);
|
---|
805 | }
|
---|
806 |
|
---|
807 | void RenderView::unregisterForVisibleInViewportCallback(RenderElement& renderer)
|
---|
808 | {
|
---|
809 | ASSERT(m_visibleInViewportRenderers.contains(&renderer));
|
---|
810 | m_visibleInViewportRenderers.remove(&renderer);
|
---|
811 | }
|
---|
812 |
|
---|
813 | void RenderView::updateVisibleViewportRect(const IntRect& visibleRect)
|
---|
814 | {
|
---|
815 | resumePausedImageAnimationsIfNeeded(visibleRect);
|
---|
816 |
|
---|
817 | for (auto* renderer : m_visibleInViewportRenderers) {
|
---|
818 | auto state = visibleRect.intersects(enclosingIntRect(renderer->absoluteClippedOverflowRectForRepaint())) ? VisibleInViewportState::Yes : VisibleInViewportState::No;
|
---|
819 | renderer->setVisibleInViewportState(state);
|
---|
820 | }
|
---|
821 | }
|
---|
822 |
|
---|
823 | void RenderView::addRendererWithPausedImageAnimations(RenderElement& renderer, CachedImage& image)
|
---|
824 | {
|
---|
825 | ASSERT(!renderer.hasPausedImageAnimations() || m_renderersWithPausedImageAnimation.contains(&renderer));
|
---|
826 |
|
---|
827 | renderer.setHasPausedImageAnimations(true);
|
---|
828 | auto& images = m_renderersWithPausedImageAnimation.ensure(&renderer, [] {
|
---|
829 | return Vector<CachedImage*>();
|
---|
830 | }).iterator->value;
|
---|
831 | if (!images.contains(&image))
|
---|
832 | images.append(&image);
|
---|
833 | }
|
---|
834 |
|
---|
835 | void RenderView::removeRendererWithPausedImageAnimations(RenderElement& renderer)
|
---|
836 | {
|
---|
837 | ASSERT(renderer.hasPausedImageAnimations());
|
---|
838 | ASSERT(m_renderersWithPausedImageAnimation.contains(&renderer));
|
---|
839 |
|
---|
840 | renderer.setHasPausedImageAnimations(false);
|
---|
841 | m_renderersWithPausedImageAnimation.remove(&renderer);
|
---|
842 | }
|
---|
843 |
|
---|
844 | void RenderView::removeRendererWithPausedImageAnimations(RenderElement& renderer, CachedImage& image)
|
---|
845 | {
|
---|
846 | ASSERT(renderer.hasPausedImageAnimations());
|
---|
847 |
|
---|
848 | auto it = m_renderersWithPausedImageAnimation.find(&renderer);
|
---|
849 | ASSERT(it != m_renderersWithPausedImageAnimation.end());
|
---|
850 |
|
---|
851 | auto& images = it->value;
|
---|
852 | if (!images.contains(&image))
|
---|
853 | return;
|
---|
854 |
|
---|
855 | if (images.size() == 1)
|
---|
856 | removeRendererWithPausedImageAnimations(renderer);
|
---|
857 | else
|
---|
858 | images.removeFirst(&image);
|
---|
859 | }
|
---|
860 |
|
---|
861 | void RenderView::resumePausedImageAnimationsIfNeeded(const IntRect& visibleRect)
|
---|
862 | {
|
---|
863 | Vector<std::pair<RenderElement*, CachedImage*>, 10> toRemove;
|
---|
864 | for (auto& it : m_renderersWithPausedImageAnimation) {
|
---|
865 | auto* renderer = it.key;
|
---|
866 | for (auto* image : it.value) {
|
---|
867 | if (renderer->repaintForPausedImageAnimationsIfNeeded(visibleRect, *image))
|
---|
868 | toRemove.append(std::make_pair(renderer, image));
|
---|
869 | }
|
---|
870 | }
|
---|
871 | for (auto& pair : toRemove)
|
---|
872 | removeRendererWithPausedImageAnimations(*pair.first, *pair.second);
|
---|
873 | }
|
---|
874 |
|
---|
875 | RenderView::RepaintRegionAccumulator::RepaintRegionAccumulator(RenderView* view)
|
---|
876 | {
|
---|
877 | if (!view)
|
---|
878 | return;
|
---|
879 |
|
---|
880 | auto* rootRenderView = view->document().topDocument().renderView();
|
---|
881 | if (!rootRenderView)
|
---|
882 | return;
|
---|
883 |
|
---|
884 | m_wasAccumulatingRepaintRegion = !!rootRenderView->m_accumulatedRepaintRegion;
|
---|
885 | if (!m_wasAccumulatingRepaintRegion)
|
---|
886 | rootRenderView->m_accumulatedRepaintRegion = makeUnique<Region>();
|
---|
887 | m_rootView = *rootRenderView;
|
---|
888 | }
|
---|
889 |
|
---|
890 | RenderView::RepaintRegionAccumulator::~RepaintRegionAccumulator()
|
---|
891 | {
|
---|
892 | if (m_wasAccumulatingRepaintRegion)
|
---|
893 | return;
|
---|
894 | if (!m_rootView)
|
---|
895 | return;
|
---|
896 | m_rootView.get()->flushAccumulatedRepaintRegion();
|
---|
897 | }
|
---|
898 |
|
---|
899 | unsigned RenderView::pageNumberForBlockProgressionOffset(int offset) const
|
---|
900 | {
|
---|
901 | int columnNumber = 0;
|
---|
902 | const Pagination& pagination = page().pagination();
|
---|
903 | if (pagination.mode == Pagination::Unpaginated)
|
---|
904 | return columnNumber;
|
---|
905 |
|
---|
906 | bool progressionIsInline = false;
|
---|
907 | bool progressionIsReversed = false;
|
---|
908 |
|
---|
909 | if (multiColumnFlow()) {
|
---|
910 | progressionIsInline = multiColumnFlow()->progressionIsInline();
|
---|
911 | progressionIsReversed = multiColumnFlow()->progressionIsReversed();
|
---|
912 | } else
|
---|
913 | return columnNumber;
|
---|
914 |
|
---|
915 | if (!progressionIsInline) {
|
---|
916 | if (!progressionIsReversed)
|
---|
917 | columnNumber = (pagination.pageLength + pagination.gap - offset) / (pagination.pageLength + pagination.gap);
|
---|
918 | else
|
---|
919 | columnNumber = offset / (pagination.pageLength + pagination.gap);
|
---|
920 | }
|
---|
921 |
|
---|
922 | return columnNumber;
|
---|
923 | }
|
---|
924 |
|
---|
925 | unsigned RenderView::pageCount() const
|
---|
926 | {
|
---|
927 | const Pagination& pagination = page().pagination();
|
---|
928 | if (pagination.mode == Pagination::Unpaginated)
|
---|
929 | return 0;
|
---|
930 |
|
---|
931 | if (multiColumnFlow() && multiColumnFlow()->firstMultiColumnSet())
|
---|
932 | return multiColumnFlow()->firstMultiColumnSet()->columnCount();
|
---|
933 |
|
---|
934 | return 0;
|
---|
935 | }
|
---|
936 |
|
---|
937 | void RenderView::layerChildrenChangedDuringStyleChange(RenderLayer& layer)
|
---|
938 | {
|
---|
939 | if (!m_styleChangeLayerMutationRoot) {
|
---|
940 | m_styleChangeLayerMutationRoot = layer;
|
---|
941 | return;
|
---|
942 | }
|
---|
943 |
|
---|
944 | RenderLayer* commonAncestor = m_styleChangeLayerMutationRoot->commonAncestorWithLayer(layer);
|
---|
945 | m_styleChangeLayerMutationRoot = commonAncestor;
|
---|
946 | }
|
---|
947 |
|
---|
948 | RenderLayer* RenderView::takeStyleChangeLayerTreeMutationRoot()
|
---|
949 | {
|
---|
950 | auto* result = m_styleChangeLayerMutationRoot.get();
|
---|
951 | m_styleChangeLayerMutationRoot.clear();
|
---|
952 | return result;
|
---|
953 | }
|
---|
954 |
|
---|
955 | void RenderView::registerBoxWithScrollSnapPositions(const RenderBox& box)
|
---|
956 | {
|
---|
957 | m_boxesWithScrollSnapPositions.add(&box);
|
---|
958 | }
|
---|
959 |
|
---|
960 | void RenderView::unregisterBoxWithScrollSnapPositions(const RenderBox& box)
|
---|
961 | {
|
---|
962 | m_boxesWithScrollSnapPositions.remove(&box);
|
---|
963 | }
|
---|
964 |
|
---|
965 | void RenderView::registerContainerQueryBox(const RenderBox& box)
|
---|
966 | {
|
---|
967 | m_containerQueryBoxes.add(box);
|
---|
968 | }
|
---|
969 |
|
---|
970 | void RenderView::unregisterContainerQueryBox(const RenderBox& box)
|
---|
971 | {
|
---|
972 | m_containerQueryBoxes.remove(box);
|
---|
973 | }
|
---|
974 |
|
---|
975 | } // namespace WebCore
|
---|