From 934f67a68da2054e526e13648c5452e2cf79c211 Mon Sep 17 00:00:00 2001 From: wangxianzhu Date: Fri, 25 Mar 2016 18:09:36 -0700 Subject: Move all fast-path paint invalidation mapping into PaintInvalidationState - Remove the optional const PaintInvalidationState* parameter from paint invalidation mapping methods and move fast-path mapping code into PaintInvalidationState. - PaintLayer::computePaintInvalidationRect() is now PaintInvalidationState::computePaintInvalidationRectInBacking(); PaintLayer::positionFromPaintInvalidationBacking() is now PaintInvalidationState::positionFromPaintInvalidationBacking(); PaintLayer::mapRectToPaintInvalidationBacking() is now PaintInvalidationState::mapLocalRectToPaintInvalidationBacking(). - Change LayoutObject::clippedOverflowRectForPaintInvalidationBacking() to: * Non-SVG objects and LayoutSVGRoot: LayoutObject::localOverflowRectForPaintInvalidation() which doesn't map the rect to paint invalidation backing; * SVG objects except LayoutSVGRoot: Using existing paintInvalidationRectInLocalSVGCoordinates() PaintInvalidationState::computePaintInvalidationRectInBacking(), calls the above functions to get the local paint invalidation rect, and map to paintInvalidationContainer using fast path if possible, or slow path by calling LayoutObject::mapToVisibleRectToAncestor(). - Let selection paint invalidation go through fast-path if possible. BUG=591199 Review URL: https://codereview.chromium.org/1813383002 Cr-Commit-Position: refs/heads/master@{#383430} --- third_party/WebKit/LayoutTests/TestExpectations | 2 + .../repaint-during-scroll-with-zoom-expected.txt | 3 +- ...-size-changes-no-layout-triggers-1-expected.txt | 6 +- ...-size-changes-no-layout-triggers-2-expected.txt | 6 +- .../Source/core/dom/IntersectionObservation.cpp | 2 +- third_party/WebKit/Source/core/frame/FrameView.cpp | 11 +- .../WebKit/Source/core/layout/LayoutBox.cpp | 26 +- third_party/WebKit/Source/core/layout/LayoutBox.h | 4 +- .../Source/core/layout/LayoutBoxModelObject.cpp | 8 +- .../WebKit/Source/core/layout/LayoutFlowThread.cpp | 4 +- .../WebKit/Source/core/layout/LayoutFlowThread.h | 4 +- .../WebKit/Source/core/layout/LayoutInline.cpp | 11 +- .../WebKit/Source/core/layout/LayoutInline.h | 4 +- .../layout/LayoutMultiColumnSpannerPlaceholder.cpp | 8 +- .../layout/LayoutMultiColumnSpannerPlaceholder.h | 2 +- .../WebKit/Source/core/layout/LayoutObject.cpp | 67 ++-- .../WebKit/Source/core/layout/LayoutObject.h | 30 +- .../WebKit/Source/core/layout/LayoutObjectTest.cpp | 12 +- .../WebKit/Source/core/layout/LayoutPart.cpp | 4 +- .../WebKit/Source/core/layout/LayoutReplaced.cpp | 2 +- .../WebKit/Source/core/layout/LayoutTableCell.cpp | 6 +- .../WebKit/Source/core/layout/LayoutTableCell.h | 2 +- .../WebKit/Source/core/layout/LayoutView.cpp | 34 ++- third_party/WebKit/Source/core/layout/LayoutView.h | 14 +- .../Source/core/layout/PaintInvalidationState.cpp | 336 ++++++++++++++------- .../Source/core/layout/PaintInvalidationState.h | 63 ++-- .../layout/compositing/CompositedLayerMapping.cpp | 2 +- .../Source/core/layout/svg/LayoutSVGBlock.cpp | 15 +- .../WebKit/Source/core/layout/svg/LayoutSVGBlock.h | 8 +- .../Source/core/layout/svg/LayoutSVGGradientStop.h | 2 +- .../core/layout/svg/LayoutSVGHiddenContainer.h | 3 +- .../Source/core/layout/svg/LayoutSVGInline.cpp | 11 +- .../Source/core/layout/svg/LayoutSVGInline.h | 4 +- .../Source/core/layout/svg/LayoutSVGInlineText.cpp | 12 +- .../Source/core/layout/svg/LayoutSVGInlineText.h | 3 +- .../core/layout/svg/LayoutSVGModelObject.cpp | 10 +- .../Source/core/layout/svg/LayoutSVGModelObject.h | 7 +- .../Source/core/layout/svg/LayoutSVGRoot.cpp | 22 +- .../WebKit/Source/core/layout/svg/LayoutSVGRoot.h | 6 +- .../Source/core/layout/svg/LayoutSVGShape.cpp | 9 - .../WebKit/Source/core/layout/svg/LayoutSVGShape.h | 2 - .../Source/core/layout/svg/LayoutSVGText.cpp | 3 +- .../Source/core/layout/svg/SVGLayoutSupport.cpp | 100 +++--- .../Source/core/layout/svg/SVGLayoutSupport.h | 11 +- .../core/page/scrolling/ScrollingCoordinator.cpp | 2 +- .../PaintInvalidationCapableScrollableArea.cpp | 2 +- .../WebKit/Source/core/paint/PaintLayer.cpp | 41 +-- third_party/WebKit/Source/core/paint/PaintLayer.h | 16 +- .../Source/core/paint/SVGContainerPainter.cpp | 4 +- .../WebKit/Source/core/testing/Internals.cpp | 4 +- .../WebKit/Source/web/LinkHighlightImpl.cpp | 2 +- .../WebKit/Source/web/WebPluginContainerImpl.cpp | 2 +- 52 files changed, 496 insertions(+), 478 deletions(-) diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 2ab26b2..b9d6580 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations @@ -366,6 +366,8 @@ crbug.com/552433 [ Linux Mac Win10 Win7 ] svg/dom/length-list-parser.html [ Fail crbug.com/552433 [ Linux Mac Win10 Win7 ] svg/transforms/text-with-pattern-with-svg-transform.svg [ Failure Pass ] crbug.com/552433 [ Linux Mac Win10 Win7 ] svg/hixie/perf/006.xml [ Failure Pass ] +crbug.com/591199 fast/repaint/repaint-during-scroll-with-zoom.html [ NeedsRebaseline ] + crbug.com/581661 svg/hixie/perf/002.xml [ NeedsManualRebaseline ] crbug.com/581661 svg/batik/text/textOnPath.svg [ NeedsManualRebaseline ] crbug.com/581661 svg/hixie/perf/001.xml [ NeedsManualRebaseline ] diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/repaint-during-scroll-with-zoom-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/repaint-during-scroll-with-zoom-expected.txt index a33b799..c6dbe03 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/repaint-during-scroll-with-zoom-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/repaint-during-scroll-with-zoom-expected.txt @@ -12,8 +12,7 @@ [2, 64, 235, 236], [2, 64, 235, 236], [2, 64, 235, 236], - [2, 64, 225, 226], - [2, 64, 135, 136], + [2, 64, 235, 236], [2, 64, 52, 18] ], "paintInvalidationClients": [ diff --git a/third_party/WebKit/LayoutTests/svg/as-object/nested-embedded-svg-size-changes-no-layout-triggers-1-expected.txt b/third_party/WebKit/LayoutTests/svg/as-object/nested-embedded-svg-size-changes-no-layout-triggers-1-expected.txt index 9f82134..ec7a5fd6 100644 --- a/third_party/WebKit/LayoutTests/svg/as-object/nested-embedded-svg-size-changes-no-layout-triggers-1-expected.txt +++ b/third_party/WebKit/LayoutTests/svg/as-object/nested-embedded-svg-size-changes-no-layout-triggers-1-expected.txt @@ -9,11 +9,11 @@ [285, 135, 15, 15], [285, 0, 15, 135], [211, 11, 180, 180], - [210, 10, 180, 180], + [210, 10, 75, 125], [11, 11, 380, 180], [11, 11, 180, 180], - [10, 10, 380, 180], - [10, 10, 180, 180], + [10, 10, 275, 125], + [10, 10, 180, 125], [1, 1, 400, 200], [1, 1, 400, 200], [1, 1, 400, 200], diff --git a/third_party/WebKit/LayoutTests/svg/as-object/nested-embedded-svg-size-changes-no-layout-triggers-2-expected.txt b/third_party/WebKit/LayoutTests/svg/as-object/nested-embedded-svg-size-changes-no-layout-triggers-2-expected.txt index 9f82134..ec7a5fd6 100644 --- a/third_party/WebKit/LayoutTests/svg/as-object/nested-embedded-svg-size-changes-no-layout-triggers-2-expected.txt +++ b/third_party/WebKit/LayoutTests/svg/as-object/nested-embedded-svg-size-changes-no-layout-triggers-2-expected.txt @@ -9,11 +9,11 @@ [285, 135, 15, 15], [285, 0, 15, 135], [211, 11, 180, 180], - [210, 10, 180, 180], + [210, 10, 75, 125], [11, 11, 380, 180], [11, 11, 180, 180], - [10, 10, 380, 180], - [10, 10, 180, 180], + [10, 10, 275, 125], + [10, 10, 180, 125], [1, 1, 400, 200], [1, 1, 400, 200], [1, 1, 400, 200], diff --git a/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp b/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp index 7b126fbe..06af503 100644 --- a/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp +++ b/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp @@ -71,7 +71,7 @@ void IntersectionObservation::clipToRoot(IntersectionGeometry& geometry) const LayoutObject* rootLayoutObject = m_observer->rootLayoutObject(); LayoutObject* targetLayoutObject = target()->layoutObject(); - geometry.doesIntersect = targetLayoutObject->mapToVisibleRectInAncestorSpace(toLayoutBoxModelObject(rootLayoutObject), geometry.intersectionRect, nullptr, EdgeInclusive); + geometry.doesIntersect = targetLayoutObject->mapToVisibleRectInAncestorSpace(toLayoutBoxModelObject(rootLayoutObject), geometry.intersectionRect, EdgeInclusive); if (!geometry.doesIntersect) return; LayoutRect rootClipRect(geometry.rootRect); diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp index c0226c98..663f5a1 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.cpp +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp @@ -1099,14 +1099,11 @@ void FrameView::invalidateTreeIfNeeded(PaintInvalidationState& paintInvalidation rootForPaintInvalidation.invalidateTreeIfNeeded(paintInvalidationState); - if (!m_frame->settings() || !m_frame->settings()->rootLayerScrolls()) { - paintInvalidationState.setViewClippingAndScrollOffsetDisabled(true); + if (!m_frame->settings() || !m_frame->settings()->rootLayerScrolls()) invalidatePaintOfScrollControlsIfNeeded(paintInvalidationState); - paintInvalidationState.setViewClippingAndScrollOffsetDisabled(false); - } #if ENABLE(ASSERT) - layoutView()->assertSubtreeClearedPaintInvalidationState(); + layoutView()->assertSubtreeClearedPaintInvalidationFlags(); #endif if (m_frame->selection().isCaretBoundsDirty()) @@ -2114,7 +2111,7 @@ IntRect FrameView::windowClipRect(IncludeScrollbarsInRect scrollbarInclusion) co ASSERT(m_frame->view() == this); LayoutRect clipRect(LayoutPoint(), LayoutSize(visibleContentSize(scrollbarInclusion))); - layoutView()->mapToVisibleRectInAncestorSpace(&layoutView()->containerForPaintInvalidation(), clipRect, nullptr); + layoutView()->mapToVisibleRectInAncestorSpace(&layoutView()->containerForPaintInvalidation(), clipRect); return enclosingIntRect(clipRect); } @@ -3972,7 +3969,7 @@ void FrameView::collectFrameTimingRequests(GraphicsLayerFrameTimingRequests& gra if (!graphicsLayer) return; - PaintLayer::mapRectToPaintInvalidationBacking(localFrame->contentLayoutObject(), &paintInvalidationContainer, viewRect); + PaintLayer::mapRectToPaintInvalidationBacking(*localFrame->contentLayoutObject(), paintInvalidationContainer, viewRect); graphicsLayerTimingRequests.add(graphicsLayer, Vector>()).storedValue->value.append(std::make_pair(m_frame->frameID(), enclosingIntRect(viewRect))); } diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp index 280a8ba..382501f 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp @@ -1482,7 +1482,7 @@ bool LayoutBox::intersectsVisibleViewport() LayoutView* layoutView = view(); while (layoutView->frame()->ownerLayoutObject()) layoutView = layoutView->frame()->ownerLayoutObject()->view(); - mapToVisibleRectInAncestorSpace(layoutView, rect, nullptr); + mapToVisibleRectInAncestorSpace(layoutView, rect); return rect.intersects(LayoutRect(layoutView->frameView()->getScrollableArea()->visibleContentRectDouble())); } @@ -1683,7 +1683,7 @@ LayoutUnit LayoutBox::perpendicularContainingBlockLogicalHeight() const return cb->adjustContentBoxLogicalHeightForBoxSizing(LayoutUnit(logicalHeightLength.value())); } -void LayoutBox::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const +void LayoutBox::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const { bool isFixedPos = style()->position() == FixedPosition; bool hasTransform = hasLayer() && layer()->transform(); @@ -1694,7 +1694,7 @@ void LayoutBox::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, Transfo else if (isFixedPos) mode |= IsFixed; - LayoutBoxModelObject::mapLocalToAncestor(ancestor, transformState, mode, wasFixed, paintInvalidationState); + LayoutBoxModelObject::mapLocalToAncestor(ancestor, transformState, mode, wasFixed); } void LayoutBox::mapAncestorToLocal(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags mode) const @@ -1935,7 +1935,7 @@ LayoutRect LayoutBox::localOverflowRectForPaintInvalidation() const return visualOverflowRect(); } -bool LayoutBox::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, const PaintInvalidationState* paintInvalidationState, VisibleRectFlags visibleRectFlags) const +bool LayoutBox::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, VisibleRectFlags visibleRectFlags) const { // The rect we compute at each step is shifted by our x/y offset in the parent container's coordinate space. // Only when we cross a writing mode boundary will we have to possibly flipForWritingMode (to convert into a more appropriate @@ -1943,21 +1943,17 @@ bool LayoutBox::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ance // properly even during layout, since the rect remains flipped all the way until the end. // // LayoutView::computeRectForPaintInvalidation then converts the rect to physical coordinates. We also convert to - // physical when we hit a paintInvalidationContainer boundary. Therefore the final rect returned is always in the - // physical coordinate space of the paintInvalidationContainer. + // physical when we hit the ancestor. Therefore the final rect returned is always in the + // physical coordinate space of the ancestor. const ComputedStyle& styleToUse = styleRef(); EPosition position = styleToUse.position(); // We need to inflate the paint invalidation rect before we use paintInvalidationState, // else we would forget to inflate it for the current layoutObject. FIXME: If these were - // included into the visual overflow for repaint, we wouldn't have this issue. + // included into the visual overflow for paint invalidation, we wouldn't have this issue. inflatePaintInvalidationRectForReflectionAndFilter(rect); - if (paintInvalidationState && paintInvalidationState->canMapToAncestor(ancestor) && position != FixedPosition) { - return paintInvalidationState->mapObjectRectToAncestor(*this, ancestor, rect, visibleRectFlags); - } - if (ancestor == this) { if (ancestor->style()->isFlippedBlocksWritingMode()) flipForWritingMode(rect); @@ -2008,15 +2004,15 @@ bool LayoutBox::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ance LayoutSize containerOffset = ancestor->offsetFromAncestorContainer(container); rect.move(-containerOffset); // If the paintInvalidationContainer is fixed, then the rect is already in its coordinates so doesn't need viewport-adjusting. - if (ancestor->style()->position() != FixedPosition && container->isLayoutView()) - toLayoutView(container)->adjustViewportConstrainedOffset(rect, LayoutView::toViewportConstrainedPosition(position)); + if (ancestor->style()->position() != FixedPosition && container->isLayoutView() && position == FixedPosition) + toLayoutView(container)->adjustOffsetForFixedPosition(rect); return true; } if (container->isLayoutView()) - return toLayoutView(container)->mapToVisibleRectInAncestorSpace(ancestor, rect, LayoutView::toViewportConstrainedPosition(position), nullptr, visibleRectFlags); + return toLayoutView(container)->mapToVisibleRectInAncestorSpace(ancestor, rect, position == FixedPosition ? IsFixed : 0, visibleRectFlags); else - return container->mapToVisibleRectInAncestorSpace(ancestor, rect, nullptr, visibleRectFlags); + return container->mapToVisibleRectInAncestorSpace(ancestor, rect, visibleRectFlags); } void LayoutBox::inflatePaintInvalidationRectForReflectionAndFilter(LayoutRect& paintInvalidationRect) const diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h index ebde1d5..9df0837 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.h +++ b/third_party/WebKit/Source/core/layout/LayoutBox.h @@ -639,7 +639,7 @@ public: bool hasForcedBreakAfter() const; LayoutRect localOverflowRectForPaintInvalidation() const override; - bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, const PaintInvalidationState*, VisibleRectFlags = DefaultVisibleRectFlags) const override; + bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, VisibleRectFlags = DefaultVisibleRectFlags) const override; virtual void invalidatePaintForOverhangingFloats(bool paintAllDescendants); LayoutUnit containingBlockLogicalHeightForGetComputedStyle() const; @@ -891,7 +891,7 @@ public: bool canRenderBorderImage() const; - void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr, const PaintInvalidationState* = nullptr) const override; + void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr) const override; void mapAncestorToLocal(const LayoutBoxModelObject*, TransformState&, MapCoordinatesFlags) const override; void clearPreviousPaintInvalidationRects() override; diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp index af2bed6..e5294b7 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp @@ -360,12 +360,12 @@ void LayoutBoxModelObject::invalidateTreeIfNeeded(const PaintInvalidationState& { ASSERT(!needsLayout()); - if (!shouldCheckForPaintInvalidation(paintInvalidationState)) + PaintInvalidationState newPaintInvalidationState(paintInvalidationState, *this); + if (!shouldCheckForPaintInvalidation(newPaintInvalidationState)) return; LayoutRect previousPaintInvalidationRect = this->previousPaintInvalidationRect(); - PaintInvalidationState newPaintInvalidationState(paintInvalidationState, *this); // TODO(wangxianzhu): Enable this assert after we fix all paintInvalidationContainer mismatch issues. crbug.com/360286 // ASSERT(&newPaintInvalidationState.paintInvalidationContainer() == &containerForPaintInvalidation()); @@ -378,6 +378,8 @@ void LayoutBoxModelObject::invalidateTreeIfNeeded(const PaintInvalidationState& if (reason == PaintInvalidationLocationChange) newPaintInvalidationState.setForceSubtreeInvalidationWithinContainer(); + // TODO(wangxianzhu): Combine this function into LayoutObject::invalidateTreeIfNeeded() when removing the following workarounds. + // TODO(wangxianzhu): This is a workaround for crbug.com/533277. Will remove when we enable paint offset caching. if (reason != PaintInvalidationNone && hasPercentageTransform(styleRef())) newPaintInvalidationState.setForceSubtreeInvalidationWithinContainer(); @@ -390,7 +392,7 @@ void LayoutBoxModelObject::invalidateTreeIfNeeded(const PaintInvalidationState& && hasOverflowClip()) newPaintInvalidationState.setForceSubtreeInvalidationRectUpdateWithinContainer(); - newPaintInvalidationState.updatePaintOffsetAndClipForChildren(); + newPaintInvalidationState.updateForChildren(); invalidatePaintOfSubtreesIfNeeded(newPaintInvalidationState); } diff --git a/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp b/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp index 61a4163..0304480 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp @@ -97,7 +97,7 @@ void LayoutFlowThread::validateColumnSets() generateColumnSetIntervalTree(); } -bool LayoutFlowThread::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, const PaintInvalidationState* paintInvalidationState, VisibleRectFlags visibleRectFlags) const +bool LayoutFlowThread::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, VisibleRectFlags visibleRectFlags) const { ASSERT(ancestor != this); // A flow thread should never be an invalidation container. // |rect| is a layout rectangle, where the block direction coordinate is flipped for writing @@ -106,7 +106,7 @@ bool LayoutFlowThread::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObjec flipForWritingMode(rect); rect = fragmentsBoundingBox(rect); flipForWritingMode(rect); - return LayoutBlockFlow::mapToVisibleRectInAncestorSpace(ancestor, rect, paintInvalidationState, visibleRectFlags); + return LayoutBlockFlow::mapToVisibleRectInAncestorSpace(ancestor, rect, visibleRectFlags); } void LayoutFlowThread::layout() diff --git a/third_party/WebKit/Source/core/layout/LayoutFlowThread.h b/third_party/WebKit/Source/core/layout/LayoutFlowThread.h index bac6c8b..d9a34dd 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFlowThread.h +++ b/third_party/WebKit/Source/core/layout/LayoutFlowThread.h @@ -54,8 +54,6 @@ public: virtual bool isLayoutMultiColumnFlowThread() const { return false; } virtual bool isLayoutPagedFlowThread() const { return false; } - bool supportsPaintInvalidationStateCachedOffsets() const override { return false; } - static LayoutFlowThread* locateFlowThreadContainingBlockOf(const LayoutObject&); void layout() override; @@ -82,7 +80,7 @@ public: void invalidateColumnSets(); bool hasValidColumnSetInfo() const { return !m_columnSetsInvalidated && !m_multiColumnSetList.isEmpty(); } - bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, const PaintInvalidationState*, VisibleRectFlags = DefaultVisibleRectFlags) const override; + bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, VisibleRectFlags = DefaultVisibleRectFlags) const override; LayoutUnit pageLogicalHeightForOffset(LayoutUnit); LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule); diff --git a/third_party/WebKit/Source/core/layout/LayoutInline.cpp b/third_party/WebKit/Source/core/layout/LayoutInline.cpp index c310452..4329025 100644 --- a/third_party/WebKit/Source/core/layout/LayoutInline.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutInline.cpp @@ -1023,7 +1023,7 @@ LayoutRect LayoutInline::absoluteClippedOverflowRect() const { if (!continuation()) { LayoutRect rect = visualOverflowRect(); - mapToVisibleRectInAncestorSpace(view(), rect, nullptr); + mapToVisibleRectInAncestorSpace(view(), rect); return rect; } @@ -1040,7 +1040,7 @@ LayoutRect LayoutInline::absoluteClippedOverflowRect() const context(FloatRect(rect)); if (curr == endContinuation) { LayoutRect rect(enclosingIntRect(floatResult)); - mapToVisibleRectInAncestorSpace(view(), rect, nullptr); + mapToVisibleRectInAncestorSpace(view(), rect); return rect; } } @@ -1078,11 +1078,8 @@ LayoutRect LayoutInline::visualOverflowRect() const return overflowRect; } -bool LayoutInline::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, const PaintInvalidationState* paintInvalidationState, VisibleRectFlags visibleRectFlags) const +bool LayoutInline::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, VisibleRectFlags visibleRectFlags) const { - if (paintInvalidationState && paintInvalidationState->canMapToAncestor(ancestor)) - return paintInvalidationState->mapObjectRectToAncestor(*this, ancestor, rect, visibleRectFlags); - if (ancestor == this) return true; @@ -1118,7 +1115,7 @@ bool LayoutInline::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* a return true; } - return container->mapToVisibleRectInAncestorSpace(ancestor, rect, nullptr, visibleRectFlags); + return container->mapToVisibleRectInAncestorSpace(ancestor, rect, visibleRectFlags); } LayoutSize LayoutInline::offsetFromContainer(const LayoutObject* container) const diff --git a/third_party/WebKit/Source/core/layout/LayoutInline.h b/third_party/WebKit/Source/core/layout/LayoutInline.h index 1a452d7..d0b2eb9 100644 --- a/third_party/WebKit/Source/core/layout/LayoutInline.h +++ b/third_party/WebKit/Source/core/layout/LayoutInline.h @@ -237,12 +237,12 @@ private: LayoutRect absoluteClippedOverflowRect() const override; - bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, const PaintInvalidationState*, VisibleRectFlags = DefaultVisibleRectFlags) const override; - // This method differs from visualOverflowRect in that it doesn't include the rects // for culled inline boxes, which aren't necessary for paint invalidation. LayoutRect localOverflowRectForPaintInvalidation() const override; + bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, VisibleRectFlags = DefaultVisibleRectFlags) const final; + PositionWithAffinity positionForPoint(const LayoutPoint&) final; IntRect borderBoundingBox() const final diff --git a/third_party/WebKit/Source/core/layout/LayoutMultiColumnSpannerPlaceholder.cpp b/third_party/WebKit/Source/core/layout/LayoutMultiColumnSpannerPlaceholder.cpp index 60aadea..b67e840 100644 --- a/third_party/WebKit/Source/core/layout/LayoutMultiColumnSpannerPlaceholder.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutMultiColumnSpannerPlaceholder.cpp @@ -119,12 +119,10 @@ void LayoutMultiColumnSpannerPlaceholder::computeLogicalHeight(LayoutUnit, Layou computedValues.m_margins.m_after = marginAfter(); } -void LayoutMultiColumnSpannerPlaceholder::invalidateTreeIfNeeded(const PaintInvalidationState& paintInvalidationState) +void LayoutMultiColumnSpannerPlaceholder::invalidatePaintOfSubtreesIfNeeded(const PaintInvalidationState& childPaintInvalidationState) { - PaintInvalidationState newPaintInvalidationState(paintInvalidationState, *this); - newPaintInvalidationState.updatePaintOffsetAndClipForChildren(); - m_layoutObjectInFlowThread->invalidateTreeIfNeeded(newPaintInvalidationState); - LayoutBox::invalidateTreeIfNeeded(paintInvalidationState); + m_layoutObjectInFlowThread->invalidateTreeIfNeeded(childPaintInvalidationState); + LayoutBox::invalidatePaintOfSubtreesIfNeeded(childPaintInvalidationState); } void LayoutMultiColumnSpannerPlaceholder::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) const diff --git a/third_party/WebKit/Source/core/layout/LayoutMultiColumnSpannerPlaceholder.h b/third_party/WebKit/Source/core/layout/LayoutMultiColumnSpannerPlaceholder.h index e7a576f..2749700 100644 --- a/third_party/WebKit/Source/core/layout/LayoutMultiColumnSpannerPlaceholder.h +++ b/third_party/WebKit/Source/core/layout/LayoutMultiColumnSpannerPlaceholder.h @@ -43,7 +43,7 @@ protected: LayoutUnit maxPreferredLogicalWidth() const override; void layout() override; void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const override; - void invalidateTreeIfNeeded(const PaintInvalidationState&) override; + void invalidatePaintOfSubtreesIfNeeded(const PaintInvalidationState&) override; void paint(const PaintInfo&, const LayoutPoint& paintOffset) const override; bool nodeAtPoint(HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override; diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp index ebd750e..c9bf739 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp @@ -1191,12 +1191,6 @@ static PassOwnPtr jsonObjectForPaintInvalidationInfo(const LayoutRe return value.release(); } -LayoutRect LayoutObject::computePaintInvalidationRect(const LayoutBoxModelObject& paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const -{ - return clippedOverflowRectForPaintInvalidation(&paintInvalidationContainer, paintInvalidationState); -} - - static void invalidatePaintRectangleOnWindow(const LayoutBoxModelObject& paintInvalidationContainer, const IntRect& dirtyRect) { FrameView* frameView = paintInvalidationContainer.frameView(); @@ -1294,11 +1288,6 @@ void LayoutObject::invalidateDisplayItemClientsWithPaintInvalidationState(const invalidateDisplayItemClients(paintInvalidationContainer, invalidationReason); } -LayoutRect LayoutObject::boundsRectForPaintInvalidation(const LayoutBoxModelObject& paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const -{ - return PaintLayer::computePaintInvalidationRect(*this, paintInvalidationContainer.layer(), paintInvalidationState); -} - const LayoutBoxModelObject* LayoutObject::invalidatePaintRectangleInternal(const LayoutRect& dirtyRect) const { RELEASE_ASSERT(isRooted()); @@ -1311,7 +1300,7 @@ const LayoutBoxModelObject* LayoutObject::invalidatePaintRectangleInternal(const const LayoutBoxModelObject& paintInvalidationContainer = containerForPaintInvalidation(); LayoutRect dirtyRectOnBacking = dirtyRect; - PaintLayer::mapRectToPaintInvalidationBacking(this, &paintInvalidationContainer, dirtyRectOnBacking); + PaintLayer::mapRectToPaintInvalidationBacking(*this, paintInvalidationContainer, dirtyRectOnBacking); invalidatePaintUsingContainer(paintInvalidationContainer, dirtyRectOnBacking, PaintInvalidationRectangle); return &paintInvalidationContainer; } @@ -1339,13 +1328,15 @@ void LayoutObject::invalidateTreeIfNeeded(const PaintInvalidationState& paintInv if (!shouldCheckForPaintInvalidation(paintInvalidationState)) return; - PaintInvalidationReason reason = invalidatePaintIfNeeded(paintInvalidationState); - clearPaintInvalidationFlags(paintInvalidationState); + PaintInvalidationState newPaintInvalidationState(paintInvalidationState, *this); + PaintInvalidationReason reason = invalidatePaintIfNeeded(newPaintInvalidationState); + clearPaintInvalidationFlags(newPaintInvalidationState); if (reason == PaintInvalidationDelayedFull) - paintInvalidationState.pushDelayedPaintInvalidationTarget(*this); + newPaintInvalidationState.pushDelayedPaintInvalidationTarget(*this); - invalidatePaintOfSubtreesIfNeeded(paintInvalidationState); + newPaintInvalidationState.updateForChildren(); + invalidatePaintOfSubtreesIfNeeded(newPaintInvalidationState); } void LayoutObject::invalidatePaintOfSubtreesIfNeeded(const PaintInvalidationState& childPaintInvalidationState) @@ -1370,7 +1361,7 @@ LayoutRect LayoutObject::selectionRectInViewCoordinates() const { LayoutRect selectionRect = localSelectionRect(); if (!selectionRect.isEmpty()) - mapToVisibleRectInAncestorSpace(view(), selectionRect, nullptr); + mapToVisibleRectInAncestorSpace(view(), selectionRect); return selectionRect; } @@ -1408,7 +1399,7 @@ inline void LayoutObject::invalidateSelectionIfNeeded(const LayoutBoxModelObject LayoutRect oldSelectionRect = previousSelectionRectForPaintInvalidation(); LayoutRect newSelectionRect = localSelectionRect(); if (!newSelectionRect.isEmpty()) { - PaintLayer::mapRectToPaintInvalidationBacking(this, &paintInvalidationContainer, newSelectionRect, &paintInvalidationState); + paintInvalidationState.mapLocalRectToPaintInvalidationBacking(newSelectionRect); // Composited scrolling should not be included in the bounds and position tracking, because the graphics layer backing the scroller // does not move on scroll. @@ -1431,6 +1422,8 @@ inline void LayoutObject::invalidateSelectionIfNeeded(const LayoutBoxModelObject PaintInvalidationReason LayoutObject::invalidatePaintIfNeeded(const PaintInvalidationState& paintInvalidationState) { + ASSERT(&paintInvalidationState.currentObject() == this); + if (styleRef().hasOutline()) { PaintLayer& layer = paintInvalidationState.enclosingSelfPaintingLayer(*this); if (layer.layoutObject() != this) @@ -1447,8 +1440,8 @@ PaintInvalidationReason LayoutObject::invalidatePaintIfNeeded(const PaintInvalid const LayoutRect oldBounds = previousPaintInvalidationRect(); const LayoutPoint oldLocation = RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() ? LayoutPoint() : previousPositionFromPaintInvalidationBacking(); - LayoutRect newBounds = boundsRectForPaintInvalidation(paintInvalidationContainer, &paintInvalidationState); - LayoutPoint newLocation = RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() ? LayoutPoint() : PaintLayer::positionFromPaintInvalidationBacking(this, &paintInvalidationContainer, &paintInvalidationState); + LayoutRect newBounds = paintInvalidationState.computePaintInvalidationRectInBacking(); + LayoutPoint newLocation = RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() ? LayoutPoint() : paintInvalidationState.computePositionFromPaintInvalidationBacking(); // Composited scrolling should not be included in the bounds and position tracking, because the graphics layer backing the scroller // does not move on scroll. @@ -1634,13 +1627,8 @@ void LayoutObject::invalidatePaintForOverflowIfNeeded() LayoutRect LayoutObject::absoluteClippedOverflowRect() const { - return clippedOverflowRectForPaintInvalidation(view()); -} - -LayoutRect LayoutObject::clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const -{ LayoutRect rect = localOverflowRectForPaintInvalidation(); - mapToVisibleRectInAncestorSpace(paintInvalidationContainer, rect, paintInvalidationState); + mapToVisibleRectInAncestorSpace(view(), rect); return rect; } @@ -1650,7 +1638,7 @@ LayoutRect LayoutObject::localOverflowRectForPaintInvalidation() const return LayoutRect(); } -bool LayoutObject::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, const PaintInvalidationState* paintInvalidationState, VisibleRectFlags visibleRectFlags) const +bool LayoutObject::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, VisibleRectFlags visibleRectFlags) const { // For any layout object that doesn't override this method (the main example is LayoutText), // the rect is assumed to be in the coordinate space of the object's parent. @@ -1658,9 +1646,6 @@ bool LayoutObject::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* a if (ancestor == this) return true; - if (paintInvalidationState && paintInvalidationState->canMapToAncestor(ancestor)) - return paintInvalidationState->mapObjectRectToAncestor(*this, ancestor, rect, visibleRectFlags); - if (LayoutObject* parent = this->parent()) { if (parent->hasOverflowClip()) { LayoutBox* parentBox = toLayoutBox(parent); @@ -1669,7 +1654,7 @@ bool LayoutObject::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* a return false; } - return parent->mapToVisibleRectInAncestorSpace(ancestor, rect, nullptr, visibleRectFlags); + return parent->mapToVisibleRectInAncestorSpace(ancestor, rect, visibleRectFlags); } return true; } @@ -2255,21 +2240,11 @@ FloatQuad LayoutObject::ancestorToLocalQuad(LayoutBoxModelObject* ancestor, cons return transformState.lastPlanarQuad(); } -void LayoutObject::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const +void LayoutObject::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const { if (ancestor == this) return; - if (paintInvalidationState && paintInvalidationState->canMapToAncestor(ancestor)) { - LayoutSize offset = paintInvalidationState->paintOffset(); - if (const LayoutBox* layoutBox = isBox() ? toLayoutBox(this) : nullptr) - offset += layoutBox->locationOffset(); - if (const PaintLayer* layer = style()->hasInFlowPosition() && hasLayer() ? toLayoutBoxModelObject(this)->layer() : nullptr) - offset += layer->offsetForInFlowPosition(); - transformState.move(offset); - return; - } - if (wasFixed) *wasFixed = mode & IsFixed; @@ -2316,7 +2291,7 @@ void LayoutObject::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, Tran return; } - o->mapLocalToAncestor(ancestor, transformState, mode, wasFixed, paintInvalidationState); + o->mapLocalToAncestor(ancestor, transformState, mode, wasFixed); } const LayoutObject* LayoutObject::pushMappingToContainer(const LayoutBoxModelObject* ancestorToStopAt, LayoutGeometryMap& geometryMap) const @@ -2415,10 +2390,10 @@ FloatQuad LayoutObject::localToAncestorQuad(const FloatQuad& localQuad, const La return transformState.lastPlanarQuad(); } -FloatPoint LayoutObject::localToAncestorPoint(const FloatPoint& localPoint, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const +FloatPoint LayoutObject::localToAncestorPoint(const FloatPoint& localPoint, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode, bool* wasFixed) const { TransformState transformState(TransformState::ApplyTransformDirection, localPoint); - mapLocalToAncestor(ancestor, transformState, mode | ApplyContainerFlip | UseTransforms, wasFixed, paintInvalidationState); + mapLocalToAncestor(ancestor, transformState, mode | ApplyContainerFlip | UseTransforms, wasFixed); transformState.flatten(); return transformState.lastPlanarPoint(); @@ -2461,7 +2436,7 @@ FloatPoint LayoutObject::localToInvalidationBackingPoint(const LayoutPoint& loca if (paintInvalidationContainer.layer()->compositingState() == NotComposited) return containerPoint; - PaintLayer::mapPointInPaintInvalidationContainerToBacking(&paintInvalidationContainer, containerPoint); + PaintLayer::mapPointInPaintInvalidationContainerToBacking(paintInvalidationContainer, containerPoint); return containerPoint; } diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h index 61d5f92..0e7df46 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.h +++ b/third_party/WebKit/Source/core/layout/LayoutObject.h @@ -95,6 +95,12 @@ enum MapCoordinatesMode { UseTransforms = 1 << 1, ApplyContainerFlip = 1 << 2, TraverseDocumentBoundaries = 1 << 3, + + // Applies to LayoutView::mapLocalToAncestor() and LayoutView::mapToVisibleRectInAncestorSpace() + // only, to indicate the input point or rect is in frame coordinates instead of frame contents + // coordinates. This disables view clipping and scroll offset adjustment. + // TODO(wangxianzhu): Remove this when root-layer-scrolls launches. + InputIsInFrameCoordinates = 1 << 4, }; typedef unsigned MapCoordinatesFlags; @@ -323,7 +329,7 @@ public: layoutObject->assertLaidOut(); } - void assertClearedPaintInvalidationState() const + void assertClearedPaintInvalidationFlags() const { #ifndef NDEBUG if (paintInvalidationStateIsDirty()) { @@ -333,10 +339,10 @@ public: #endif } - void assertSubtreeClearedPaintInvalidationState() const + void assertSubtreeClearedPaintInvalidationFlags() const { for (const LayoutObject* layoutObject = this; layoutObject; layoutObject = layoutObject->nextInPreOrder()) - layoutObject->assertClearedPaintInvalidationState(); + layoutObject->assertClearedPaintInvalidationFlags(); } #endif @@ -991,7 +997,7 @@ public: // If TraverseDocumentBoundaries is specified, the result will be in the space of the local root frame. // Otherwise, the result will be in the space of the containing frame. FloatQuad localToAncestorQuad(const FloatQuad&, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags = 0, bool* wasFixed = nullptr) const; - FloatPoint localToAncestorPoint(const FloatPoint&, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags = 0, bool* wasFixed = nullptr, const PaintInvalidationState* = nullptr) const; + FloatPoint localToAncestorPoint(const FloatPoint&, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags = 0, bool* wasFixed = nullptr) const; void localToAncestorRects(Vector&, const LayoutBoxModelObject* ancestor, const LayoutPoint& preOffset, const LayoutPoint& postOffset) const; // Return the transformation matrix to map points from local to the coordinate system of a container, taking transforms into account. @@ -1103,12 +1109,6 @@ public: bool isPaintInvalidationContainer() const; - // Returns the paint invalidation rect for this LayoutObject in the coordinate space of the paint backing (typically a GraphicsLayer) for |paintInvalidationContainer|. - LayoutRect computePaintInvalidationRect(const LayoutBoxModelObject& paintInvalidationContainer, const PaintInvalidationState* = nullptr) const; - - // Returns the rect bounds needed to invalidate the paint of this object, in the coordinate space of the layoutObject backing of |paintInvalidationContainer| - LayoutRect boundsRectForPaintInvalidation(const LayoutBoxModelObject& paintInvalidationContainer, const PaintInvalidationState* = nullptr) const; - // Actually do the paint invalidate of rect r for this object which has been computed in the coordinate space // of the GraphicsLayer backing of |paintInvalidationContainer|. Note that this coordinaten space is not the same // as the local coordinate space of |paintInvalidationContainer| in the presence of layer squashing. @@ -1135,10 +1135,10 @@ public: // Returns the rect that should have paint invalidated whenever this object changes. The rect is in the view's // coordinate space. This method deals with outlines and overflow. virtual LayoutRect absoluteClippedOverflowRect() const; - virtual LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* = nullptr) const; // Returns the rect that should have paint invalidated whenever this object changes. The rect is in the object's - // local coordinate space. + // local coordinate space. This is for non-SVG objects and LayoutSVGRoot only. SVG objects (except LayoutSVGRoot) + // should use paintInvalidationRectInLocalSVGCoordinates() and map with SVG transforms instead. virtual LayoutRect localOverflowRectForPaintInvalidation() const; // Given a rect in the object's coordinate space, compute a rect in the coordinate space of |ancestor|. If @@ -1150,7 +1150,7 @@ public: // to the return value of this method. Otherwise, clipping operations will use LayoutRect::intersect, // and the return value will be true only if the clipped rect has non-zero area. // See the documentation for LayoutRect::inclusiveIntersect for more information. - virtual bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, const PaintInvalidationState*, VisibleRectFlags = DefaultVisibleRectFlags) const; + virtual bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, VisibleRectFlags = DefaultVisibleRectFlags) const; // Return the offset to the column in which the specified point (in flow-thread coordinates) // lives. This is used to convert a flow-thread point to a visual point. @@ -1248,7 +1248,7 @@ public: // Map points and quads through elements, potentially via 3d transforms. You should never need to call these directly; use // localToAbsolute/absoluteToLocal methods instead. - virtual void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr, const PaintInvalidationState* = nullptr) const; + virtual void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr) const; // If the LayoutBoxModelObject ancestor is non-null, the input quad is in the space of the ancestor. // Otherwise: // If TraverseDocumentBoundaries is specified, the input quad is in the space of the local root frame. @@ -1365,8 +1365,6 @@ public: return mayNeedPaintInvalidation() || shouldDoFullPaintInvalidation() || shouldInvalidateSelection() || m_bitfields.childShouldCheckForPaintInvalidation(); } - virtual bool supportsPaintInvalidationStateCachedOffsets() const { return !hasTransformRelatedProperty() && !hasReflection() && !style()->isFlippedBlocksWritingMode(); } - virtual LayoutRect viewRect() const; void invalidateDisplayItemClient(const DisplayItemClient&) const; diff --git a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp index feca2db..8a8ff19 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp @@ -123,11 +123,11 @@ TEST_F(LayoutObjectTest, LayoutTextMapToVisibleRectInAncestorSpace) container->setScrollTop(LayoutUnit(50)); LayoutRect rect(0, 60, 20, 80); - EXPECT_TRUE(text->mapToVisibleRectInAncestorSpace(container, rect, nullptr)); + EXPECT_TRUE(text->mapToVisibleRectInAncestorSpace(container, rect)); EXPECT_EQ(rect, LayoutRect(0, 10, 20, 80)); rect = LayoutRect(0, 60, 80, 0); - EXPECT_TRUE(text->mapToVisibleRectInAncestorSpace(container, rect, nullptr, EdgeInclusive)); + EXPECT_TRUE(text->mapToVisibleRectInAncestorSpace(container, rect, EdgeInclusive)); EXPECT_EQ(rect, LayoutRect(0, 10, 80, 0)); } @@ -145,11 +145,11 @@ TEST_F(LayoutObjectTest, LayoutInlineMapToVisibleRectInAncestorSpace) container->setScrollTop(LayoutUnit(50)); LayoutRect rect(0, 60, 20, 80); - EXPECT_TRUE(leaf->mapToVisibleRectInAncestorSpace(container, rect, nullptr)); + EXPECT_TRUE(leaf->mapToVisibleRectInAncestorSpace(container, rect)); EXPECT_EQ(rect, LayoutRect(0, 10, 20, 80)); rect = LayoutRect(0, 60, 80, 0); - EXPECT_TRUE(leaf->mapToVisibleRectInAncestorSpace(container, rect, nullptr, EdgeInclusive)); + EXPECT_TRUE(leaf->mapToVisibleRectInAncestorSpace(container, rect, EdgeInclusive)); EXPECT_EQ(rect, LayoutRect(0, 10, 80, 0)); } @@ -173,11 +173,11 @@ TEST_F(LayoutObjectTest, LayoutViewMapToVisibleRectInAncestorSpace) // so height should be clipped to (50 - 13) == 37. frameDocument.view()->setScrollPosition(DoublePoint(0, 47), ProgrammaticScroll); LayoutRect rect(4, 60, 20, 80); - EXPECT_TRUE(frameText->mapToVisibleRectInAncestorSpace(frameContainer, rect, nullptr)); + EXPECT_TRUE(frameText->mapToVisibleRectInAncestorSpace(frameContainer, rect)); EXPECT_EQ(rect, LayoutRect(4, 13, 20, 37)); rect = LayoutRect(4, 60, 0, 80); - EXPECT_TRUE(frameText->mapToVisibleRectInAncestorSpace(frameContainer, rect, nullptr, EdgeInclusive)); + EXPECT_TRUE(frameText->mapToVisibleRectInAncestorSpace(frameContainer, rect, EdgeInclusive)); EXPECT_EQ(rect, LayoutRect(4, 13, 0, 37)); } diff --git a/third_party/WebKit/Source/core/layout/LayoutPart.cpp b/third_party/WebKit/Source/core/layout/LayoutPart.cpp index 0a83a68..def0bec 100644 --- a/third_party/WebKit/Source/core/layout/LayoutPart.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutPart.cpp @@ -349,13 +349,13 @@ bool LayoutPart::setWidgetGeometry(const LayoutRect& frame) void LayoutPart::invalidatePaintOfSubtreesIfNeeded(const PaintInvalidationState& paintInvalidationState) { - if (widget() && widget()->isFrameView()) { + if (widget() && widget()->isFrameView() && !isThrottledFrameView()) { FrameView* childFrameView = toFrameView(widget()); // |childFrameView| is in another document, which could be // missing its LayoutView. TODO(jchaffraix): Ideally we should // not need this code. if (LayoutView* childLayoutView = childFrameView->layoutView()) { - PaintInvalidationState childViewPaintInvalidationState(*childLayoutView, paintInvalidationState); + PaintInvalidationState childViewPaintInvalidationState(paintInvalidationState, *childLayoutView); childFrameView->invalidateTreeIfNeeded(childViewPaintInvalidationState); } } diff --git a/third_party/WebKit/Source/core/layout/LayoutReplaced.cpp b/third_party/WebKit/Source/core/layout/LayoutReplaced.cpp index 1e02150..bd27c59 100644 --- a/third_party/WebKit/Source/core/layout/LayoutReplaced.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutReplaced.cpp @@ -738,7 +738,7 @@ void LayoutReplaced::setSelectionState(SelectionState state) // image is selected. Since the selection state has changed update the rect. if (hasLayer()) { LayoutRect rect = localOverflowRectForPaintInvalidation(); - PaintLayer::mapRectToPaintInvalidationBacking(this, &containerForPaintInvalidation(), rect); + PaintLayer::mapRectToPaintInvalidationBacking(*this, containerForPaintInvalidation(), rect); setPreviousPaintInvalidationRect(rect); } diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp index e149e66..8c10281 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp @@ -358,13 +358,13 @@ LayoutRect LayoutTableCell::localOverflowRectForPaintInvalidation() const return LayoutRect(-location.x(), -location.y(), location.x() + std::max(size().width() + right, visualOverflowRect().maxX()), location.y() + std::max(size().height() + bottom, visualOverflowRect().maxY())); } -bool LayoutTableCell::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& r, const PaintInvalidationState* paintInvalidationState, VisibleRectFlags visibleRectFlags) const +bool LayoutTableCell::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& r, VisibleRectFlags visibleRectFlags) const { if (ancestor == this) return true; - if ((!paintInvalidationState || !paintInvalidationState->canMapToAncestor(ancestor)) && parent()) + if (parent()) r.moveBy(-parentBox()->location()); // Rows are in the same coordinate space, so don't add their offset in. - return LayoutBlockFlow::mapToVisibleRectInAncestorSpace(ancestor, r, paintInvalidationState, visibleRectFlags); + return LayoutBlockFlow::mapToVisibleRectInAncestorSpace(ancestor, r, visibleRectFlags); } int LayoutTableCell::cellBaselinePosition() const diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.h b/third_party/WebKit/Source/core/layout/LayoutTableCell.h index 61196d0..413ee8e 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableCell.h +++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.h @@ -292,7 +292,7 @@ private: LayoutSize offsetFromContainer(const LayoutObject*) const override; LayoutRect localOverflowRectForPaintInvalidation() const override; - bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, const PaintInvalidationState*, VisibleRectFlags = DefaultVisibleRectFlags) const override; + bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, VisibleRectFlags = DefaultVisibleRectFlags) const override; int borderHalfLeft(bool outer) const; int borderHalfRight(bool outer) const; diff --git a/third_party/WebKit/Source/core/layout/LayoutView.cpp b/third_party/WebKit/Source/core/layout/LayoutView.cpp index aa2ca02..b49d539 100644 --- a/third_party/WebKit/Source/core/layout/LayoutView.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutView.cpp @@ -323,7 +323,7 @@ LayoutRect LayoutView::visualOverflowRect() const return LayoutRect(documentRect()); } -void LayoutView::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const +void LayoutView::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const { ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == static_cast(mode & IsFixed)); @@ -346,10 +346,16 @@ void LayoutView::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, Transf if (mode & TraverseDocumentBoundaries) { if (LayoutPart* parentDocLayoutObject = frame()->ownerLayoutObject()) { - transformState.move(-frame()->view()->scrollOffset()); + if (!(mode & InputIsInFrameCoordinates)) { + transformState.move(-frame()->view()->scrollOffset()); + } else { + // The flag applies to immediate LayoutView only. + mode &= ~InputIsInFrameCoordinates; + } + transformState.move(parentDocLayoutObject->contentBoxOffset()); - parentDocLayoutObject->mapLocalToAncestor(ancestor, transformState, mode, wasFixed, paintInvalidationState); + parentDocLayoutObject->mapLocalToAncestor(ancestor, transformState, mode, wasFixed); } } } @@ -444,7 +450,7 @@ void LayoutView::invalidateTreeIfNeeded(const PaintInvalidationState& paintInval LayoutRect dirtyRect = viewRect(); if (doingFullPaintInvalidation() && !dirtyRect.isEmpty()) { const LayoutBoxModelObject& paintInvalidationContainer = paintInvalidationState.paintInvalidationContainer(); - PaintLayer::mapRectToPaintInvalidationBacking(this, &paintInvalidationContainer, dirtyRect, &paintInvalidationState); + paintInvalidationState.mapLocalRectToPaintInvalidationBacking(dirtyRect); invalidatePaintUsingContainer(paintInvalidationContainer, dirtyRect, PaintInvalidationFull); invalidateDisplayItemClientsWithPaintInvalidationState(paintInvalidationContainer, paintInvalidationState, PaintInvalidationFull); } @@ -475,18 +481,16 @@ void LayoutView::invalidatePaintForViewAndCompositedLayers() compositor()->fullyInvalidatePaint(); } -bool LayoutView::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, const PaintInvalidationState* invalidationState, VisibleRectFlags visibleRectFlags) const +bool LayoutView::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, VisibleRectFlags visibleRectFlags) const { - return mapToVisibleRectInAncestorSpace(ancestor, rect, IsNotFixedPosition, invalidationState, visibleRectFlags); + return mapToVisibleRectInAncestorSpace(ancestor, rect, 0, visibleRectFlags); } -bool LayoutView::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, ViewportConstrainedPosition viewportConstraint, const PaintInvalidationState* paintInvalidationState, VisibleRectFlags visibleRectFlags) const +bool LayoutView::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, MapCoordinatesFlags mode, VisibleRectFlags visibleRectFlags) const { if (document().printing()) return true; - // TODO(chrishtr): fix PaintInvalidationState offsets for LayoutViews. - if (style()->isFlippedBlocksWritingMode()) { // We have to flip by hand since the view's logical height has not been determined. We // can use the viewport width and height. @@ -496,7 +500,8 @@ bool LayoutView::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* anc rect.setX(viewWidth() - rect.maxX()); } - adjustViewportConstrainedOffset(rect, viewportConstraint); + if (mode & IsFixed) + adjustOffsetForFixedPosition(rect); // Apply our transform if we have one (because of full page zooming). if (!ancestor && layer() && layer()->transform()) @@ -511,7 +516,7 @@ bool LayoutView::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* anc return true; if (LayoutBox* obj = owner->layoutBox()) { - if (!paintInvalidationState || !paintInvalidationState->viewClippingAndScrollOffsetDisabled()) { + if (!(mode & InputIsInFrameCoordinates)) { // Intersect the viewport with the paint invalidation rect. LayoutRect viewRectangle = viewRect(); if (visibleRectFlags & EdgeInclusive) { @@ -527,17 +532,14 @@ bool LayoutView::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* anc // Adjust for frame border. rect.move(obj->contentBoxOffset()); - return obj->mapToVisibleRectInAncestorSpace(ancestor, rect, 0, visibleRectFlags); + return obj->mapToVisibleRectInAncestorSpace(ancestor, rect, visibleRectFlags); } return true; } -void LayoutView::adjustViewportConstrainedOffset(LayoutRect& rect, ViewportConstrainedPosition viewportConstraint) const +void LayoutView::adjustOffsetForFixedPosition(LayoutRect& rect) const { - if (viewportConstraint != IsFixedPosition) - return; - if (m_frameView) { rect.move(toIntSize(m_frameView->scrollPosition())); if (hasOverflowClip()) diff --git a/third_party/WebKit/Source/core/layout/LayoutView.h b/third_party/WebKit/Source/core/layout/LayoutView.h index e620f79..e6514d7 100644 --- a/third_party/WebKit/Source/core/layout/LayoutView.h +++ b/third_party/WebKit/Source/core/layout/LayoutView.h @@ -104,15 +104,9 @@ public: FrameView* frameView() const { return m_frameView; } - enum ViewportConstrainedPosition { - IsNotFixedPosition, - IsFixedPosition, - }; - - static ViewportConstrainedPosition toViewportConstrainedPosition(EPosition position) { return position == FixedPosition ? IsFixedPosition : IsNotFixedPosition; } - bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, ViewportConstrainedPosition, const PaintInvalidationState*, VisibleRectFlags = DefaultVisibleRectFlags) const; - bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, const PaintInvalidationState*, VisibleRectFlags = DefaultVisibleRectFlags) const override; - void adjustViewportConstrainedOffset(LayoutRect&, ViewportConstrainedPosition) const; + bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, MapCoordinatesFlags, VisibleRectFlags) const; + bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, VisibleRectFlags = DefaultVisibleRectFlags) const override; + void adjustOffsetForFixedPosition(LayoutRect&) const; void invalidatePaintForViewAndCompositedLayers(); @@ -215,7 +209,7 @@ public: ScrollResult scroll(ScrollGranularity, const FloatSize&) override; private: - void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr, const PaintInvalidationState* = nullptr) const override; + void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr) const override; const LayoutObject* pushMappingToContainer(const LayoutBoxModelObject* ancestorToStopAt, LayoutGeometryMap&) const override; void mapAncestorToLocal(const LayoutBoxModelObject*, TransformState&, MapCoordinatesFlags) const override; diff --git a/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp b/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp index 99a0553..c028923 100644 --- a/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp +++ b/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp @@ -4,45 +4,66 @@ #include "core/layout/PaintInvalidationState.h" +#include "core/frame/FrameView.h" +#include "core/frame/Settings.h" #include "core/layout/LayoutInline.h" +#include "core/layout/LayoutPart.h" #include "core/layout/LayoutView.h" #include "core/layout/svg/LayoutSVGModelObject.h" #include "core/layout/svg/LayoutSVGRoot.h" +#include "core/layout/svg/SVGLayoutSupport.h" #include "core/paint/PaintLayer.h" +// We can't enable this by default because saturated operations of LayoutUnit +// don't conform commutative law for overflowing results, preventing us from +// making fast-path and slow-path always return the same result. +#define ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH (0 && ENABLE(ASSERT)) + namespace blink { -PaintInvalidationState::PaintInvalidationState(const LayoutView& layoutView, Vector& pendingDelayedPaintInvalidations, const PaintInvalidationState* ownerPaintInvalidationState) +static bool isAbsolutePositionUnderRelativePositionInline(const LayoutObject& object) +{ + if (object.styleRef().position() != AbsolutePosition) + return false; + if (LayoutObject* container = object.container()) + return container->isAnonymousBlock() && container->styleRef().position() == RelativePosition; + return false; +} + +static bool supportsCachedOffsets(const LayoutObject& object) +{ + // TODO(wangxianzhu): Move some conditions to fast path if possible. + return !object.hasTransformRelatedProperty() + && !object.hasReflection() + && !object.hasFilter() + && !object.isLayoutFlowThread() + && !object.isLayoutMultiColumnSpannerPlaceholder() + && object.styleRef().position() != FixedPosition + && !object.styleRef().isFlippedBlocksWritingMode() + // TODO(crbug.com/598094): Handle this in fast path. + && !isAbsolutePositionUnderRelativePositionInline(object); +} + +PaintInvalidationState::PaintInvalidationState(const LayoutView& layoutView, Vector& pendingDelayedPaintInvalidations) : m_currentObject(layoutView) , m_clipped(false) , m_cachedOffsetsEnabled(true) , m_forcedSubtreeInvalidationWithinContainer(false) , m_forcedSubtreeInvalidationRectUpdateWithinContainer(false) - , m_viewClippingAndScrollOffsetDisabled(false) , m_paintInvalidationContainer(layoutView.containerForPaintInvalidation()) , m_pendingDelayedPaintInvalidations(pendingDelayedPaintInvalidations) , m_enclosingSelfPaintingLayer(*layoutView.layer()) #if ENABLE(ASSERT) - , m_didUpdatePaintOffsetAndClipForChildren(true) + , m_didUpdateForChildren(false) #endif { - ASSERT(!ownerPaintInvalidationState || ownerPaintInvalidationState->m_didUpdatePaintOffsetAndClipForChildren); - - bool establishesPaintInvalidationContainer = layoutView == m_paintInvalidationContainer; - if (!establishesPaintInvalidationContainer) { - if ((ownerPaintInvalidationState && !ownerPaintInvalidationState->m_cachedOffsetsEnabled) - || !layoutView.supportsPaintInvalidationStateCachedOffsets()) { - m_cachedOffsetsEnabled = false; - return; - } - if (ownerPaintInvalidationState && ownerPaintInvalidationState->m_forcedSubtreeInvalidationWithinContainer) - m_forcedSubtreeInvalidationWithinContainer = true; - FloatPoint point = layoutView.localToAncestorPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries); - m_paintOffset = LayoutSize(point.x(), point.y()); + if (!supportsCachedOffsets(layoutView)) { + m_cachedOffsetsEnabled = false; + return; } - m_clipRect = layoutView.viewRect(); - m_clipRect.move(m_paintOffset); - m_clipped = true; + + FloatPoint point = layoutView.localToAncestorPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries | InputIsInFrameCoordinates); + m_paintOffset = LayoutSize(point.x(), point.y()); } // TODO(wangxianzhu): This is temporary for positioned object whose paintInvalidationContainer is different from @@ -53,7 +74,6 @@ PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& par , m_cachedOffsetsEnabled(parentState.m_cachedOffsetsEnabled) , m_forcedSubtreeInvalidationWithinContainer(parentState.m_forcedSubtreeInvalidationWithinContainer) , m_forcedSubtreeInvalidationRectUpdateWithinContainer(parentState.m_forcedSubtreeInvalidationRectUpdateWithinContainer) - , m_viewClippingAndScrollOffsetDisabled(false) , m_clipRect(parentState.m_clipRect) , m_paintOffset(parentState.m_paintOffset) , m_paintInvalidationContainer(paintInvalidationContainer) @@ -61,10 +81,10 @@ PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& par , m_pendingDelayedPaintInvalidations(parentState.pendingDelayedPaintInvalidationTargets()) , m_enclosingSelfPaintingLayer(parentState.enclosingSelfPaintingLayer(currentObject)) #if ENABLE(ASSERT) - , m_didUpdatePaintOffsetAndClipForChildren(true) + , m_didUpdateForChildren(true) #endif { - ASSERT(parentState.m_didUpdatePaintOffsetAndClipForChildren); + ASSERT(parentState.m_didUpdateForChildren); ASSERT(!m_cachedOffsetsEnabled); } @@ -74,7 +94,6 @@ PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& par , m_cachedOffsetsEnabled(parentState.m_cachedOffsetsEnabled) , m_forcedSubtreeInvalidationWithinContainer(parentState.m_forcedSubtreeInvalidationWithinContainer) , m_forcedSubtreeInvalidationRectUpdateWithinContainer(parentState.m_forcedSubtreeInvalidationRectUpdateWithinContainer) - , m_viewClippingAndScrollOffsetDisabled(false) , m_clipRect(parentState.m_clipRect) , m_paintOffset(parentState.m_paintOffset) , m_paintInvalidationContainer(currentObject.isPaintInvalidationContainer() ? toLayoutBoxModelObject(currentObject) : parentState.m_paintInvalidationContainer) @@ -82,35 +101,40 @@ PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& par , m_pendingDelayedPaintInvalidations(parentState.pendingDelayedPaintInvalidationTargets()) , m_enclosingSelfPaintingLayer(parentState.enclosingSelfPaintingLayer(currentObject)) #if ENABLE(ASSERT) - , m_didUpdatePaintOffsetAndClipForChildren(false) + , m_didUpdateForChildren(false) #endif { - ASSERT(parentState.m_didUpdatePaintOffsetAndClipForChildren); -} - -void PaintInvalidationState::updatePaintOffsetAndClipForChildren() -{ + if (currentObject == parentState.m_currentObject) { + // Sometimes we create a new PaintInvalidationState from parentState on the same object + // (e.g. LayoutView, and the HorriblySlowRectMapping cases in LayoutBlock::invalidatePaintOfSubtreesIfNeeded()). + // TODO(wangxianzhu): Avoid this for RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled(). #if ENABLE(ASSERT) - ASSERT(!m_didUpdatePaintOffsetAndClipForChildren); - m_didUpdatePaintOffsetAndClipForChildren = true; + m_didUpdateForChildren = parentState.m_didUpdateForChildren; #endif - - bool establishesPaintInvalidationContainer = m_currentObject == m_paintInvalidationContainer; - - if (!m_currentObject.isBoxModelObject()) { - // TODO(wangxianzhu): SVG could probably benefit from a stack-based optimization like html does. crbug.com/391054. - ASSERT(m_currentObject.isSVG()); - ASSERT(!establishesPaintInvalidationContainer); - if (m_cachedOffsetsEnabled) - m_svgTransform = AffineTransform(m_svgTransform * m_currentObject.localToSVGParentTransform()); return; } - bool fixed = m_currentObject.style()->position() == FixedPosition; + ASSERT(parentState.m_didUpdateForChildren); + + if (!currentObject.isBoxModelObject() && !currentObject.isSVG()) + return; - if (!m_currentObject.supportsPaintInvalidationStateCachedOffsets()) + if (m_cachedOffsetsEnabled && !supportsCachedOffsets(currentObject)) m_cachedOffsetsEnabled = false; - if (establishesPaintInvalidationContainer) { + + if (currentObject.isSVG()) { + if (currentObject.isSVGRoot()) { + m_svgTransform = toLayoutSVGRoot(currentObject).localToBorderBoxTransform(); + // Don't early return here, because the SVGRoot object needs to execute the later code + // as a normal LayoutBox. + } else { + ASSERT(currentObject != m_paintInvalidationContainer); + m_svgTransform *= currentObject.localToSVGParentTransform(); + return; + } + } + + if (currentObject == m_paintInvalidationContainer) { // When we hit a new paint invalidation container, we don't need to // continue forcing a check for paint invalidation, since we're // descending into a different invalidation container. (For instance if @@ -118,102 +142,204 @@ void PaintInvalidationState::updatePaintOffsetAndClipForChildren() m_forcedSubtreeInvalidationWithinContainer = false; m_forcedSubtreeInvalidationRectUpdateWithinContainer = false; - m_clipped = false; // Will be updated in applyClipIfNeeded(). + m_clipped = false; // Will be updated in updateForChildren(). m_paintOffset = LayoutSize(); - } else { - if (m_cachedOffsetsEnabled) { - if (fixed) { - FloatPoint fixedOffset = m_currentObject.localToAncestorPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries); - m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()); - } else if (m_currentObject.isBox() && !m_currentObject.isTableRow()) { - // We don't add locationOffset of table row because the child cells' location offsets include the row's location offset. - m_paintOffset += toLayoutBox(m_currentObject).locationOffset(); - } - - if (m_currentObject.isOutOfFlowPositioned() && !fixed) { - if (LayoutObject* container = m_currentObject.container()) { - if (container->isInFlowPositioned() && container->isLayoutInline()) - m_paintOffset += toLayoutInline(container)->offsetForInFlowPositionedInline(toLayoutBox(m_currentObject)); - } - } + return; + } - if (m_currentObject.isInFlowPositioned() && m_currentObject.hasLayer()) - m_paintOffset += toLayoutBoxModelObject(m_currentObject).layer()->offsetForInFlowPosition(); - } + if (!m_cachedOffsetsEnabled) + return; - m_clipped = !fixed && m_clipped; + if (currentObject.isLayoutView()) { + ASSERT(&parentState.m_currentObject == toLayoutView(currentObject).frame()->ownerLayoutObject()); + m_paintOffset += toLayoutBox(parentState.m_currentObject).contentBoxOffset(); + return; } - if (m_cachedOffsetsEnabled && m_currentObject.isSVGRoot()) { + if (currentObject.isBox()) + m_paintOffset += toLayoutBox(currentObject).locationOffset(); + + if (currentObject.isInFlowPositioned() && currentObject.hasLayer()) + m_paintOffset += toLayoutBoxModelObject(currentObject).layer()->offsetForInFlowPosition(); +} + +void PaintInvalidationState::updateForChildren() +{ +#if ENABLE(ASSERT) + ASSERT(!m_didUpdateForChildren); + m_didUpdateForChildren = true; +#endif + + if (!m_cachedOffsetsEnabled) + return; + + if (!m_currentObject.isBoxModelObject() && !m_currentObject.isSVG()) + return; + + if (m_currentObject.isLayoutView()) { + if (!m_currentObject.document().settings() || !m_currentObject.document().settings()->rootLayerScrolls()) { + if (m_currentObject != m_paintInvalidationContainer) { + m_paintOffset -= toLayoutView(m_currentObject).frameView()->scrollOffset(); + addClipRectRelativeToPaintOffset(toLayoutView(m_currentObject).viewRect()); + } + return; + } + } else if (m_currentObject.isSVGRoot()) { const LayoutSVGRoot& svgRoot = toLayoutSVGRoot(m_currentObject); - m_svgTransform = AffineTransform(svgRoot.localToBorderBoxTransform()); if (svgRoot.shouldApplyViewportClip()) - addClipRectRelativeToPaintOffset(LayoutSize(svgRoot.pixelSnappedSize())); + addClipRectRelativeToPaintOffset(LayoutRect(LayoutPoint(), LayoutSize(svgRoot.pixelSnappedSize()))); + } else if (m_currentObject.isTableRow()) { + // Child table cell's locationOffset() includes its row's locationOffset(). + m_paintOffset -= toLayoutBox(m_currentObject).locationOffset(); } - applyClipIfNeeded(); + if (!m_currentObject.hasOverflowClip()) + return; + + const LayoutBox& box = toLayoutBox(m_currentObject); + + // Do not clip scroll layer contents because the compositor expects the whole layer + // to be always invalidated in-time. + if (box.usesCompositedScrolling()) + ASSERT(!m_clipped); // The box should establish paint invalidation container, so no m_clipped inherited. + else + addClipRectRelativeToPaintOffset(LayoutRect(LayoutPoint(), LayoutSize(box.layer()->size()))); + + m_paintOffset -= box.scrolledContentOffset(); // FIXME: Apply control clip if present. } -bool PaintInvalidationState::mapObjectRectToAncestor(const LayoutObject& object, const LayoutBoxModelObject* ancestor, LayoutRect& rect, VisibleRectFlags visibleRectFlags) const +static FloatPoint slowLocalToAncestorPoint(const LayoutObject& object, const LayoutBoxModelObject& ancestor, const FloatPoint& point) +{ + if (object.isLayoutView()) + return toLayoutView(object).localToAncestorPoint(point, &ancestor, TraverseDocumentBoundaries | InputIsInFrameCoordinates); + return object.localToAncestorPoint(point, &ancestor, TraverseDocumentBoundaries); +} + +LayoutPoint PaintInvalidationState::computePositionFromPaintInvalidationBacking() const { - ASSERT(canMapToAncestor(ancestor)); + ASSERT(!m_didUpdateForChildren); - if (ancestor == &object) { - if (object.isBox() && object.styleRef().isFlippedBlocksWritingMode()) - toLayoutBox(object).flipForWritingMode(rect); - return true; + FloatPoint point; + if (m_paintInvalidationContainer != m_currentObject) { + if (m_cachedOffsetsEnabled) { + if (m_currentObject.isSVG() && !m_currentObject.isSVGRoot()) + point = m_svgTransform.mapPoint(point); + point += FloatPoint(m_paintOffset); +#if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH + // TODO(wangxianzhu): We can't enable this ASSERT for now because of crbug.com/597745. + // ASSERT(point == slowLocalOriginToAncestorPoint(m_currentObject, m_paintInvalidationContainer, FloatPoint()); +#endif + } else { + point = slowLocalToAncestorPoint(m_currentObject, m_paintInvalidationContainer, FloatPoint()); + } } - if (object.hasLayer()) { - if (const TransformationMatrix* transform = toLayoutBoxModelObject(object).layer()->transform()) - rect = LayoutRect(transform->mapRect(pixelSnappedIntRect(rect))); + if (m_paintInvalidationContainer.layer()->groupedMapping()) + PaintLayer::mapPointInPaintInvalidationContainerToBacking(m_paintInvalidationContainer, point); - if (object.isInFlowPositioned()) - rect.move(toLayoutBoxModelObject(object).layer()->offsetForInFlowPosition()); - } + return LayoutPoint(point); +} + +LayoutRect PaintInvalidationState::computePaintInvalidationRectInBacking() const +{ + ASSERT(!m_didUpdateForChildren); - if (object.isBox()) - rect.moveBy(toLayoutBox(object).location()); + if (m_currentObject.isSVG() && !m_currentObject.isSVGRoot()) + return computePaintInvalidationRectInBackingForSVG(); - rect.move(m_paintOffset); + LayoutRect rect = m_currentObject.localOverflowRectForPaintInvalidation(); + mapLocalRectToPaintInvalidationBacking(rect); + return rect; +} - if (m_clipped) { - if (visibleRectFlags & EdgeInclusive) - return rect.inclusiveIntersect(m_clipRect); - rect.intersect(m_clipRect); +LayoutRect PaintInvalidationState::computePaintInvalidationRectInBackingForSVG() const +{ + LayoutRect rect; + if (m_cachedOffsetsEnabled) { + FloatRect svgRect = SVGLayoutSupport::localOverflowRectForPaintInvalidation(m_currentObject); + rect = SVGLayoutSupport::transformPaintInvalidationRect(m_currentObject, m_svgTransform, svgRect); + rect.move(m_paintOffset); + if (m_clipped) + rect.intersect(m_clipRect); +#if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH + LayoutRect slowPathRect = SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(m_currentObject, m_paintInvalidationContainer); + // TODO(crbug.com/597902): Slow path misses clipping of paintInvalidationContainer. + if (m_clipped) + slowPathRect.intersect(m_clipRect); + // TODO(crbug.com/597903): Fast path and slow path should generate equal empty rects. + ASSERT((rect.isEmpty() && slowPathRect.isEmpty()) || rect == slowPathRect); +#endif + } else { + // TODO(wangxianzhu): Sometimes m_cachedOffsetsEnabled==false doesn't mean we can't use cached + // m_svgTransform. We can use hybrid fast-path (for SVG) and slow-path (for things above the SVGRoot). + rect = SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(m_currentObject, m_paintInvalidationContainer); } - return !rect.isEmpty(); + if (m_paintInvalidationContainer.layer()->groupedMapping()) + PaintLayer::mapRectInPaintInvalidationContainerToBacking(m_paintInvalidationContainer, rect); + return rect; } -void PaintInvalidationState::addClipRectRelativeToPaintOffset(const LayoutSize& clipSize) +static void slowMapToVisibleRectInAncestorSpace(const LayoutObject& object, const LayoutBoxModelObject& ancestor, LayoutRect& rect) { - LayoutRect clipRect(toPoint(m_paintOffset), clipSize); - if (m_clipped) { - m_clipRect.intersect(clipRect); + // TODO(crbug.com/597965): LayoutBox::mapToVisibleRectInAncestorSpace() incorrectly flips a rect + // in its own space for writing mode. Here flip to workaround the flip. + if (object.isBox() && (toLayoutBox(object).isWritingModeRoot() || (ancestor == object && object.styleRef().isFlippedBlocksWritingMode()))) + toLayoutBox(object).flipForWritingMode(rect); + + if (object.isLayoutView()) { + toLayoutView(object).mapToVisibleRectInAncestorSpace(&ancestor, rect, InputIsInFrameCoordinates, DefaultVisibleRectFlags); + } else if (object.isSVGRoot()) { + // TODO(crbug.com/597813): This is to avoid the extra clip applied in LayoutSVGRoot::mapVisibleRectInAncestorSpace(). + toLayoutSVGRoot(object).LayoutReplaced::mapToVisibleRectInAncestorSpace(&ancestor, rect); } else { - m_clipRect = clipRect; - m_clipped = true; + object.mapToVisibleRectInAncestorSpace(&ancestor, rect); } } -void PaintInvalidationState::applyClipIfNeeded() +void PaintInvalidationState::mapLocalRectToPaintInvalidationBacking(LayoutRect& rect) const { - if (!m_currentObject.hasOverflowClip()) - return; + ASSERT(!m_didUpdateForChildren); - const LayoutBox& box = toLayoutBox(m_currentObject); + if (m_cachedOffsetsEnabled) { +#if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH + LayoutRect slowPathRect(rect); + slowMapToVisibleRectInAncestorSpace(m_currentObject, m_paintInvalidationContainer, slowPathRect); +#endif + rect.move(m_paintOffset); + if (m_clipped) + rect.intersect(m_clipRect); +#if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH + // Make sure that the fast path and the slow path generate the same rect. + // TODO(crbug.com/597902): Slow path misses clipping of paintInvalidationContainer. + if (m_clipped) + slowPathRect.intersect(m_clipRect); + // TODO(wangxianzhu): The isLayoutView() condition is for cases that a sub-frame creates a + // root PaintInvalidationState which doesn't inherit clip from ancestor frames. + // Remove the condition when we eliminate the latter case of PaintInvalidationState(const LayoutView&, ...). + // TODO(crbug.com/597903): Fast path and slow path should generate equal empty rects. + ASSERT(m_currentObject.isLayoutView() || (rect.isEmpty() && slowPathRect.isEmpty()) || rect == slowPathRect); +#endif + } else { + slowMapToVisibleRectInAncestorSpace(m_currentObject, m_paintInvalidationContainer, rect); + } - // Do not clip scroll layer contents because the compositor expects the whole layer - // to be always invalidated in-time. - if (box.usesCompositedScrolling()) - ASSERT(!m_clipped); // The box should establish paint invalidation container, so no m_clipped inherited. - else - addClipRectRelativeToPaintOffset(LayoutSize(box.layer()->size())); + if (m_paintInvalidationContainer.layer()->groupedMapping()) + PaintLayer::mapRectInPaintInvalidationContainerToBacking(m_paintInvalidationContainer, rect); +} - m_paintOffset -= box.scrolledContentOffset(); +void PaintInvalidationState::addClipRectRelativeToPaintOffset(const LayoutRect& localClipRect) +{ + LayoutRect clipRect = localClipRect; + clipRect.move(m_paintOffset); + if (m_clipped) { + m_clipRect.intersect(clipRect); + } else { + m_clipRect = clipRect; + m_clipped = true; + } } PaintLayer& PaintInvalidationState::enclosingSelfPaintingLayer(const LayoutObject& layoutObject) const diff --git a/third_party/WebKit/Source/core/layout/PaintInvalidationState.h b/third_party/WebKit/Source/core/layout/PaintInvalidationState.h index 94f9a8c..6bf530f 100644 --- a/third_party/WebKit/Source/core/layout/PaintInvalidationState.h +++ b/third_party/WebKit/Source/core/layout/PaintInvalidationState.h @@ -42,28 +42,16 @@ public: // the one we find during tree walk. Remove this after we fix the issue with tree walk in DOM-order. PaintInvalidationState(const PaintInvalidationState& parentState, const LayoutBoxModelObject&, const LayoutBoxModelObject& paintInvalidationContainer); - // For root LayoutView. - PaintInvalidationState(const LayoutView& layoutView, Vector& pendingDelayedPaintInvalidations) - : PaintInvalidationState(layoutView, pendingDelayedPaintInvalidations, nullptr) { } - // For LayoutView in a sub-frame. - PaintInvalidationState(const LayoutView& layoutView, const PaintInvalidationState& ownerPaintInvalidationState) - : PaintInvalidationState(layoutView, ownerPaintInvalidationState.m_pendingDelayedPaintInvalidations, &ownerPaintInvalidationState) { } - - // When a PaintInvalidationState is constructed, it just updates paintInvalidationContainer and - // copy cached paintOffset and clip from the parent PaintInvalidationContainer. - // This PaintInvalidationContainer can be used to invalidate the current object. - // - // After invalidation of the current object, before invalidation of the subtrees, - // this method must be called to make this PaintInvalidationState suitable for - // paint invalidation of children. - void updatePaintOffsetAndClipForChildren(); - - const LayoutRect& clipRect() const { return m_clipRect; } - const LayoutSize& paintOffset() const { return m_paintOffset; } - const AffineTransform& svgTransform() const { return m_svgTransform; } + // For root LayoutView, or when sub-frame LayoutView's invalidateTreeIfNeeded() is called directly from + // FrameView::invalidateTreeIfNeededRecursive() instead of the owner LayoutPart. + // TODO(wangxianzhu): Eliminate the latter case. + PaintInvalidationState(const LayoutView&, Vector& pendingDelayedPaintInvalidations); - bool cachedOffsetsEnabled() const { return m_cachedOffsetsEnabled; } - bool isClipped() const { return m_clipped; } + // When a PaintInvalidationState is constructed, it can be used to map points/rects in the object's + // local space (border box space for LayoutBoxes). After invalidation of the current object, + // before invalidation of the subtrees, this method must be called to apply clip and scroll offset + // etc. for creating child PaintInvalidationStates. + void updateForChildren(); bool forcedSubtreeInvalidationWithinContainer() const { return m_forcedSubtreeInvalidationWithinContainer; } void setForceSubtreeInvalidationWithinContainer() { m_forcedSubtreeInvalidationWithinContainer = true; } @@ -73,28 +61,30 @@ public: const LayoutBoxModelObject& paintInvalidationContainer() const { return m_paintInvalidationContainer; } - bool canMapToAncestor(const LayoutBoxModelObject* ancestor) const - { - return m_cachedOffsetsEnabled && ancestor == &m_paintInvalidationContainer; - } - bool mapObjectRectToAncestor(const LayoutObject&, const LayoutBoxModelObject* ancestor, LayoutRect&, VisibleRectFlags = DefaultVisibleRectFlags) const; + // Computes the position of the current object ((0,0) in the space of the object) + // in the space of paint invalidation backing. + LayoutPoint computePositionFromPaintInvalidationBacking() const; + + // Returns the rect bounds needed to invalidate paint of this object, + // in the space of paint invalidation backing. + LayoutRect computePaintInvalidationRectInBacking() const; + + void mapLocalRectToPaintInvalidationBacking(LayoutRect&) const; // Records |obj| as needing paint invalidation on the next frame. See the definition of PaintInvalidationDelayedFull for more details. void pushDelayedPaintInvalidationTarget(LayoutObject& obj) const { m_pendingDelayedPaintInvalidations.append(&obj); } Vector& pendingDelayedPaintInvalidationTargets() const { return m_pendingDelayedPaintInvalidations; } - // Disable view clipping and scroll offset adjustment for paint invalidation of FrameView scrollbars. - // TODO(wangxianzhu): Remove this when root-layer-scrolls launches. - bool viewClippingAndScrollOffsetDisabled() const { return m_viewClippingAndScrollOffsetDisabled; } - void setViewClippingAndScrollOffsetDisabled(bool b) { m_viewClippingAndScrollOffsetDisabled = b; } - PaintLayer& enclosingSelfPaintingLayer(const LayoutObject&) const; +#if ENABLE(ASSERT) + const LayoutObject& currentObject() const { return m_currentObject; } +#endif + private: - PaintInvalidationState(const LayoutView&, Vector& pendingDelayedPaintInvalidations, const PaintInvalidationState* ownerPaintInvalidationState); + LayoutRect computePaintInvalidationRectInBackingForSVG() const; - void applyClipIfNeeded(); - void addClipRectRelativeToPaintOffset(const LayoutSize& clipSize); + void addClipRectRelativeToPaintOffset(const LayoutRect& localClipRect); friend class ForceHorriblySlowRectMapping; @@ -104,7 +94,6 @@ private: mutable bool m_cachedOffsetsEnabled; bool m_forcedSubtreeInvalidationWithinContainer; bool m_forcedSubtreeInvalidationRectUpdateWithinContainer; - bool m_viewClippingAndScrollOffsetDisabled; LayoutRect m_clipRect; @@ -126,7 +115,7 @@ private: PaintLayer& m_enclosingSelfPaintingLayer; #if ENABLE(ASSERT) - bool m_didUpdatePaintOffsetAndClipForChildren; + bool m_didUpdateForChildren; #endif }; @@ -140,7 +129,7 @@ class ForceHorriblySlowRectMapping { public: ForceHorriblySlowRectMapping(const PaintInvalidationState* paintInvalidationState) : m_paintInvalidationState(paintInvalidationState) - , m_didDisable(m_paintInvalidationState && m_paintInvalidationState->cachedOffsetsEnabled()) + , m_didDisable(m_paintInvalidationState && m_paintInvalidationState->m_cachedOffsetsEnabled) { if (m_paintInvalidationState) m_paintInvalidationState->m_cachedOffsetsEnabled = false; diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp index 42c5d32..3a1c37e 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp @@ -2224,7 +2224,7 @@ IntRect CompositedLayerMapping::recomputeInterestRect(const GraphicsLayer* graph LayoutView* rootView = anchorLayoutObject->view(); while (rootView->frame()->ownerLayoutObject()) rootView = rootView->frame()->ownerLayoutObject()->view(); - anchorLayoutObject->mapToVisibleRectInAncestorSpace(rootView, visibleContentRect, 0); + anchorLayoutObject->mapToVisibleRectInAncestorSpace(rootView, visibleContentRect); visibleContentRect.intersect(LayoutRect(rootView->frameView()->visibleContentRect())); IntRect enclosingGraphicsLayerBounds(enclosingIntRect(graphicsLayerBounds)); diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGBlock.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGBlock.cpp index 7804493..0414f44 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGBlock.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGBlock.cpp @@ -82,9 +82,9 @@ void LayoutSVGBlock::styleDidChange(StyleDifference diff, const ComputedStyle* o SVGResourcesCache::clientStyleChanged(this, diff, styleRef()); } -void LayoutSVGBlock::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const +void LayoutSVGBlock::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const { - SVGLayoutSupport::mapLocalToAncestor(this, ancestor, transformState, wasFixed, paintInvalidationState); + SVGLayoutSupport::mapLocalToAncestor(this, ancestor, transformState, wasFixed); } void LayoutSVGBlock::mapAncestorToLocal(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags) const @@ -99,16 +99,14 @@ const LayoutObject* LayoutSVGBlock::pushMappingToContainer(const LayoutBoxModelO return SVGLayoutSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap); } -LayoutRect LayoutSVGBlock::clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const +LayoutRect LayoutSVGBlock::absoluteClippedOverflowRect() const { - return SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(*this, paintInvalidationContainer, paintInvalidationState); + return SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(*this, *view()); } -bool LayoutSVGBlock::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, const PaintInvalidationState* paintInvalidationState, VisibleRectFlags visibleRectFlags) const +bool LayoutSVGBlock::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, VisibleRectFlags visibleRectFlags) const { - FloatRect paintInvalidationRect(rect); - const LayoutSVGRoot& svgRoot = SVGLayoutSupport::mapRectToSVGRootForPaintInvalidation(*this, paintInvalidationRect, rect); - return svgRoot.mapToVisibleRectInAncestorSpace(ancestor, rect, paintInvalidationState, visibleRectFlags); + return SVGLayoutSupport::mapToVisibleRectInAncestorSpace(*this, ancestor, FloatRect(rect), rect); } bool LayoutSVGBlock::nodeAtPoint(HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction) @@ -122,6 +120,7 @@ void LayoutSVGBlock::invalidateTreeIfNeeded(const PaintInvalidationState& paintI if (!shouldCheckForPaintInvalidation(paintInvalidationState)) return; + // TODO(wangxianzhu): Move this to fast path if possible. crbug.com/391054. ForceHorriblySlowRectMapping slowRectMapping(&paintInvalidationState); LayoutBlockFlow::invalidateTreeIfNeeded(paintInvalidationState); } diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGBlock.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGBlock.h index ccbc362..1dcca09 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGBlock.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGBlock.h @@ -30,9 +30,7 @@ class LayoutSVGBlock : public LayoutBlockFlow { public: explicit LayoutSVGBlock(SVGElement*); - LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* = nullptr) const final; - - void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr, const PaintInvalidationState* = nullptr) const final; + void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr) const final; void mapAncestorToLocal(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip) const final; const LayoutObject* pushMappingToContainer(const LayoutBoxModelObject* ancestorToStopAt, LayoutGeometryMap&) const final; @@ -44,12 +42,14 @@ public: protected: void willBeDestroyed() override; - bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, const PaintInvalidationState*, VisibleRectFlags = DefaultVisibleRectFlags) const final; + bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, VisibleRectFlags = DefaultVisibleRectFlags) const final; AffineTransform m_localTransform; bool isOfType(LayoutObjectType type) const override { return type == LayoutObjectSVG || LayoutBlockFlow::isOfType(type); } private: + LayoutRect absoluteClippedOverflowRect() const final; + bool allowsOverflowClip() const final; void absoluteRects(Vector&, const LayoutPoint& accumulatedOffset) const final; diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGGradientStop.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGGradientStop.h index 739e1b5..51eed2e 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGGradientStop.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGGradientStop.h @@ -42,7 +42,7 @@ public: // This overrides are needed to prevent ASSERTs on // LayoutObject's default implementations ASSERT_NOT_REACHED() // https://bugs.webkit.org/show_bug.cgi?id=20400 - LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject*, const PaintInvalidationState* = nullptr) const override { return LayoutRect(); } + LayoutRect localOverflowRectForPaintInvalidation() const override { return LayoutRect(); } FloatRect objectBoundingBox() const override { return FloatRect(); } FloatRect strokeBoundingBox() const override { return FloatRect(); } FloatRect paintInvalidationRectInLocalSVGCoordinates() const override { return FloatRect(); } diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGHiddenContainer.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGHiddenContainer.h index 5f45a37..71dfc0b 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGHiddenContainer.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGHiddenContainer.h @@ -41,7 +41,8 @@ protected: private: void paint(const PaintInfo&, const LayoutPoint&) const final; - LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject*, const PaintInvalidationState* = nullptr) const final { return LayoutRect(); } + LayoutRect absoluteClippedOverflowRect() const final { return LayoutRect(); } + FloatRect paintInvalidationRectInLocalSVGCoordinates() const final { return FloatRect(); } void absoluteQuads(Vector&, bool* wasFixed) const final; bool nodeAtFloatPoint(HitTestResult&, const FloatPoint& pointInParent, HitTestAction) final; diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.cpp index 97ee97d..3606e44 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.cpp @@ -21,6 +21,7 @@ #include "core/layout/svg/LayoutSVGInline.h" +#include "core/layout/LayoutView.h" #include "core/layout/svg/LayoutSVGText.h" #include "core/layout/svg/SVGLayoutSupport.h" #include "core/layout/svg/SVGResourcesCache.h" @@ -83,14 +84,14 @@ FloatRect LayoutSVGInline::paintInvalidationRectInLocalSVGCoordinates() const return FloatRect(); } -LayoutRect LayoutSVGInline::clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const +LayoutRect LayoutSVGInline::absoluteClippedOverflowRect() const { - return SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(*this, paintInvalidationContainer, paintInvalidationState); + return SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(*this, *view()); } -void LayoutSVGInline::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const +void LayoutSVGInline::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const { - SVGLayoutSupport::mapLocalToAncestor(this, ancestor, transformState, wasFixed, paintInvalidationState); + SVGLayoutSupport::mapLocalToAncestor(this, ancestor, transformState, wasFixed); } const LayoutObject* LayoutSVGInline::pushMappingToContainer(const LayoutBoxModelObject* ancestorToStopAt, LayoutGeometryMap& geometryMap) const @@ -165,7 +166,7 @@ void LayoutSVGInline::invalidateTreeIfNeeded(const PaintInvalidationState& paint if (reason == PaintInvalidationSVGResourceChange) newPaintInvalidationState.setForceSubtreeInvalidationWithinContainer(); - newPaintInvalidationState.updatePaintOffsetAndClipForChildren(); + newPaintInvalidationState.updateForChildren(); invalidatePaintOfSubtreesIfNeeded(newPaintInvalidationState); } diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.h index 2d851b1..9680f57 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.h @@ -44,8 +44,8 @@ public: FloatRect strokeBoundingBox() const final; FloatRect paintInvalidationRectInLocalSVGCoordinates() const final; - LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* = nullptr) const final; - void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr, const PaintInvalidationState* = nullptr) const final; + LayoutRect absoluteClippedOverflowRect() const final; + void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr) const final; const LayoutObject* pushMappingToContainer(const LayoutBoxModelObject* ancestorToStopAt, LayoutGeometryMap&) const final; void absoluteQuads(Vector&, bool* wasFixed) const final; diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.cpp index 259d6f3..4ee1f83 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.cpp @@ -231,12 +231,14 @@ void LayoutSVGInlineText::computeNewScaledFontForStyle(LayoutObject* layoutObjec scaledFont.update(document.styleEngine().fontSelector()); } -LayoutRect LayoutSVGInlineText::clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const +LayoutRect LayoutSVGInlineText::absoluteClippedOverflowRect() const { - // FIXME: The following works because LayoutSVGBlock has forced slow rect mapping of the paintInvalidationState. - // Should let this really work with paintInvalidationState's fast mapping and remove the assert. - ASSERT(!paintInvalidationState || !paintInvalidationState->canMapToAncestor(paintInvalidationContainer)); - return parent()->clippedOverflowRectForPaintInvalidation(paintInvalidationContainer, nullptr); + return parent()->absoluteClippedOverflowRect(); +} + +FloatRect LayoutSVGInlineText::paintInvalidationRectInLocalSVGCoordinates() const +{ + return parent()->paintInvalidationRectInLocalSVGCoordinates(); } PassRefPtr LayoutSVGInlineText::originalText() const diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.h index b8ea64a..5084e1e 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.h @@ -60,7 +60,8 @@ private: IntRect linesBoundingBox() const override; InlineTextBox* createTextBox(int start, unsigned short length) override; - LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState*) const final; + LayoutRect absoluteClippedOverflowRect() const final; + FloatRect paintInvalidationRectInLocalSVGCoordinates() const final; float m_scalingFactor; Font m_scaledFont; diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGModelObject.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGModelObject.cpp index 76144fa..9681a52 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGModelObject.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGModelObject.cpp @@ -50,14 +50,14 @@ bool LayoutSVGModelObject::isChildAllowed(LayoutObject* child, const ComputedSty return child->isSVG() && !(child->isSVGInline() || child->isSVGInlineText() || child->isSVGGradientStop()); } -LayoutRect LayoutSVGModelObject::clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const +void LayoutSVGModelObject::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const { - return SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(*this, paintInvalidationContainer, paintInvalidationState); + SVGLayoutSupport::mapLocalToAncestor(this, ancestor, transformState, wasFixed); } -void LayoutSVGModelObject::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const +LayoutRect LayoutSVGModelObject::absoluteClippedOverflowRect() const { - SVGLayoutSupport::mapLocalToAncestor(this, ancestor, transformState, wasFixed, paintInvalidationState); + return SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(*this, *view()); } void LayoutSVGModelObject::mapAncestorToLocal(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags) const @@ -143,7 +143,7 @@ void LayoutSVGModelObject::invalidateTreeIfNeeded(const PaintInvalidationState& invalidatePaintIfNeeded(newPaintInvalidationState); clearPaintInvalidationFlags(newPaintInvalidationState); - newPaintInvalidationState.updatePaintOffsetAndClipForChildren(); + newPaintInvalidationState.updateForChildren(); invalidatePaintOfSubtreesIfNeeded(newPaintInvalidationState); } diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGModelObject.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGModelObject.h index a9a29a7..2552b13c 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGModelObject.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGModelObject.h @@ -47,14 +47,13 @@ public: bool isChildAllowed(LayoutObject*, const ComputedStyle&) const override; - LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* = nullptr) const override; - - FloatRect paintInvalidationRectInLocalSVGCoordinates() const final { return m_paintInvalidationBoundingBox; } + LayoutRect absoluteClippedOverflowRect() const override; + FloatRect paintInvalidationRectInLocalSVGCoordinates() const override { return m_paintInvalidationBoundingBox; } void absoluteRects(Vector&, const LayoutPoint& accumulatedOffset) const final; void absoluteQuads(Vector&, bool* wasFixed) const override; - void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr, const PaintInvalidationState* = nullptr) const final; + void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr) const final; void mapAncestorToLocal(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip) const final; const LayoutObject* pushMappingToContainer(const LayoutBoxModelObject* ancestorToStopAt, LayoutGeometryMap&) const final; void styleDidChange(StyleDifference, const ComputedStyle* oldStyle) override; diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.cpp index b2cb115..ed7548a 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.cpp @@ -318,12 +318,13 @@ const AffineTransform& LayoutSVGRoot::localToSVGParentTransform() const return m_localToParentTransform; } -LayoutRect LayoutSVGRoot::clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const +LayoutRect LayoutSVGRoot::localOverflowRectForPaintInvalidation() const { - // This is an open-coded aggregate of SVGLayoutSupport::clippedOverflowRectForPaintInvalidation, - // LayoutSVGRoot::mapToVisibleRectInAncestorSpace and LayoutReplaced::clippedOverflowRectForPaintInvalidation. + // This is an open-coded aggregate of SVGLayoutSupport::localOverflowRectForPaintInvalidation, + // and LayoutReplaced::localOverflowRectForPaintInvalidation. // The reason for this is to optimize/minimize the paint invalidation rect when the box is not "decorated" // (does not have background/border/etc.) + // TODO(wangxianzhu): Verify if the optimization is still needed. // Return early for any cases where we don't actually paint. if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) @@ -346,18 +347,17 @@ LayoutRect LayoutSVGRoot::clippedOverflowRectForPaintInvalidation(const LayoutBo paintInvalidationRect.unite(decoratedPaintInvalidationRect); } - // Compute the paint invalidation rect in the parent coordinate space. - LayoutRect rect(enclosingIntRect(paintInvalidationRect)); - LayoutReplaced::mapToVisibleRectInAncestorSpace(paintInvalidationContainer, rect, paintInvalidationState); - return rect; + return LayoutRect(enclosingIntRect(paintInvalidationRect)); } -bool LayoutSVGRoot::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, const PaintInvalidationState* paintInvalidationState, VisibleRectFlags visibleRectFlags) const +bool LayoutSVGRoot::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, VisibleRectFlags visibleRectFlags) const { // Note that we don't apply the border-box transform here - it's assumed // that whoever called us has done that already. // Apply initial viewport clip + // TODO(crbug.com/597813): We should not apply clip on LayoutSVGRoot's own rect. This clip should + // be applied in children's mapToVisibleRectInAncestorSpace(). if (shouldApplyViewportClip()) { if (visibleRectFlags & EdgeInclusive) { if (!rect.inclusiveIntersect(LayoutRect(pixelSnappedBorderBoxRect()))) @@ -367,17 +367,17 @@ bool LayoutSVGRoot::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* } } - return LayoutReplaced::mapToVisibleRectInAncestorSpace(ancestor, rect, paintInvalidationState, visibleRectFlags); + return LayoutReplaced::mapToVisibleRectInAncestorSpace(ancestor, rect, visibleRectFlags); } // This method expects local CSS box coordinates. // Callers with local SVG viewport coordinates should first apply the localToBorderBoxTransform // to convert from SVG viewport coordinates to local CSS box coordinates. -void LayoutSVGRoot::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const +void LayoutSVGRoot::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const { ASSERT(!(mode & IsFixed)); // We should have no fixed content in the SVG layout tree. - LayoutReplaced::mapLocalToAncestor(ancestor, transformState, mode | ApplyContainerFlip, wasFixed, paintInvalidationState); + LayoutReplaced::mapLocalToAncestor(ancestor, transformState, mode | ApplyContainerFlip, wasFixed); } const LayoutObject* LayoutSVGRoot::pushMappingToContainer(const LayoutBoxModelObject* ancestorToStopAt, LayoutGeometryMap& geometryMap) const diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.h index 27d8ebd..2474972 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.h @@ -38,7 +38,7 @@ public: bool isEmbeddedThroughFrameContainingSVGDocument() const; void computeIntrinsicSizingInfo(IntrinsicSizingInfo&) const override; - bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, const PaintInvalidationState*, VisibleRectFlags = DefaultVisibleRectFlags) const override; + bool mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, VisibleRectFlags = DefaultVisibleRectFlags) const override; // If you have a LayoutSVGRoot, use firstChild or lastChild instead. void slowFirstChild() const = delete; @@ -101,9 +101,9 @@ private: bool nodeAtPoint(HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override; - LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* = nullptr) const override; + LayoutRect localOverflowRectForPaintInvalidation() const override; - void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr, const PaintInvalidationState* = nullptr) const override; + void mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr) const override; const LayoutObject* pushMappingToContainer(const LayoutBoxModelObject* ancestorToStopAt, LayoutGeometryMap&) const override; bool canBeSelectionLeaf() const override { return false; } diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGShape.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGShape.cpp index abcd05e..b7671c4 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGShape.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGShape.cpp @@ -295,15 +295,6 @@ float LayoutSVGShape::strokeWidth() const return lengthContext.valueForLength(style()->svgStyle().strokeWidth()); } -LayoutRect LayoutSVGShape::clippedOverflowRectForPaintInvalidation( - const LayoutBoxModelObject* paintInvalidationContainer, - const PaintInvalidationState* paintInvalidationState) const -{ - const float strokeWidthForHairlinePadding = style()->svgStyle().hasStroke() ? strokeWidth() : 0; - return SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(*this, - paintInvalidationContainer, paintInvalidationState, strokeWidthForHairlinePadding); -} - LayoutSVGShapeRareData& LayoutSVGShape::ensureRareData() const { if (!m_rareData) diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGShape.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGShape.h index afe3667..55b53b8 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGShape.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGShape.h @@ -113,8 +113,6 @@ private: bool strokeContains(const FloatPoint&, bool requiresStroke = true); const AffineTransform& localToSVGParentTransform() const final { return m_localTransform; } - LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject*, - const PaintInvalidationState* = nullptr) const override; bool isOfType(LayoutObjectType type) const override { return type == LayoutObjectSVGShape || LayoutSVGModelObject::isOfType(type); } void layout() final; diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGText.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGText.cpp index a60f188f..8a66fd8 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGText.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGText.cpp @@ -516,11 +516,12 @@ void LayoutSVGText::invalidateTreeIfNeeded(const PaintInvalidationState& paintIn if (reason == PaintInvalidationDelayedFull) paintInvalidationState.pushDelayedPaintInvalidationTarget(*this); + // TODO(wangxianzhu): Move this to fast path if possible. crbug.com/391054. ForceHorriblySlowRectMapping slowRectMapping(&newPaintInvalidationState); if (reason == PaintInvalidationSVGResourceChange) newPaintInvalidationState.setForceSubtreeInvalidationWithinContainer(); - newPaintInvalidationState.updatePaintOffsetAndClipForChildren(); + newPaintInvalidationState.updateForChildren(); invalidatePaintOfSubtreesIfNeeded(newPaintInvalidationState); } diff --git a/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp b/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp index 5d69308..3ed6613 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp @@ -59,63 +59,53 @@ struct SearchCandidate { float candidateDistance; }; -static inline LayoutRect adjustedEnclosingIntRect(const FloatRect& rect, - const AffineTransform& rootTransform, float strokeWidthForHairlinePadding) -{ - FloatRect adjustedRect = rect; - - if (strokeWidthForHairlinePadding) { - // For hairline strokes (stroke-width < 1 in device space), Skia rasterizes up to 0.4(9) off - // the stroke center. That means enclosingIntRect is not enough - we must also pad to 0.5. - // This is still fragile as it misses out on CC/DSF CTM components. - const FloatSize strokeSize = rootTransform.mapSize( - FloatSize(strokeWidthForHairlinePadding, strokeWidthForHairlinePadding)); - if (strokeSize.width() < 1 || strokeSize.height() < 1) { - const float pad = 0.5f - std::min(strokeSize.width(), strokeSize.height()) / 2; - ASSERT(pad > 0); - adjustedRect.inflate(pad); - } - } - - if (adjustedRect.isEmpty()) - return LayoutRect(); - - return LayoutRect(enclosingIntRect(adjustedRect)); -} - -LayoutRect SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(const LayoutObject& object, - const LayoutBoxModelObject* paintInvalidationContainer, - const PaintInvalidationState* paintInvalidationState, float strokeWidthForHairlinePadding) +FloatRect SVGLayoutSupport::localOverflowRectForPaintInvalidation(const LayoutObject& object) { + // This doesn't apply to LayoutSVGRoot. Use LayoutSVGRoot::localOverflowRectForPaintInvalidation() instead. + ASSERT(!object.isSVGRoot()); + // Return early for any cases where we don't actually paint if (object.styleRef().visibility() != VISIBLE && !object.enclosingLayer()->hasVisibleContent()) - return LayoutRect(); + return FloatRect(); FloatRect paintInvalidationRect = object.paintInvalidationRectInLocalSVGCoordinates(); if (int outlineOutset = object.styleRef().outlineOutsetExtent()) paintInvalidationRect.inflate(outlineOutset); + return paintInvalidationRect; +} - if (paintInvalidationState && paintInvalidationState->canMapToAncestor(paintInvalidationContainer)) { - // Compute accumulated SVG transform and apply to local paint rect. - AffineTransform transform = paintInvalidationState->svgTransform() * object.localToSVGParentTransform(); - - // FIXME: These are quirks carried forward from the old paint invalidation infrastructure. - LayoutRect rect = adjustedEnclosingIntRect(transform.mapRect(paintInvalidationRect), - transform, strokeWidthForHairlinePadding); - // Offset by SVG root paint offset and apply clipping as needed. - rect.move(paintInvalidationState->paintOffset()); - if (paintInvalidationState->isClipped()) - rect.intersect(paintInvalidationState->clipRect()); - return rect; - } - +LayoutRect SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(const LayoutObject& object, const LayoutBoxModelObject& paintInvalidationContainer) +{ LayoutRect rect; - const LayoutSVGRoot& svgRoot = mapRectToSVGRootForPaintInvalidation(object, - paintInvalidationRect, rect, strokeWidthForHairlinePadding); - svgRoot.mapToVisibleRectInAncestorSpace(paintInvalidationContainer, rect, nullptr); + mapToVisibleRectInAncestorSpace(object, &paintInvalidationContainer, localOverflowRectForPaintInvalidation(object), rect); return rect; } +LayoutRect SVGLayoutSupport::transformPaintInvalidationRect(const LayoutObject& object, const AffineTransform& rootTransform, const FloatRect& localRect) +{ + FloatRect adjustedRect = rootTransform.mapRect(localRect); + + if (object.isSVGShape() && object.styleRef().svgStyle().hasStroke()) { + if (float strokeWidthForHairlinePadding = toLayoutSVGShape(object).strokeWidth()) { + // For hairline strokes (stroke-width < 1 in device space), Skia rasterizes up to 0.4(9) off + // the stroke center. That means enclosingIntRect is not enough - we must also pad to 0.5. + // This is still fragile as it misses out on CC/DSF CTM components. + const FloatSize strokeSize = rootTransform.mapSize( + FloatSize(strokeWidthForHairlinePadding, strokeWidthForHairlinePadding)); + if (strokeSize.width() < 1 || strokeSize.height() < 1) { + const float pad = 0.5f - std::min(strokeSize.width(), strokeSize.height()) / 2; + ASSERT(pad > 0); + adjustedRect.inflate(pad); + } + } + } + + if (adjustedRect.isEmpty()) + return LayoutRect(); + + return LayoutRect(enclosingIntRect(adjustedRect)); +} + static const LayoutSVGRoot& computeTransformToSVGRoot(const LayoutObject& object, AffineTransform& rootBorderBoxTransform) { ASSERT(object.isSVG() && !object.isSVGRoot()); @@ -129,28 +119,18 @@ static const LayoutSVGRoot& computeTransformToSVGRoot(const LayoutObject& object return svgRoot; } -const LayoutSVGRoot& SVGLayoutSupport::mapRectToSVGRootForPaintInvalidation(const LayoutObject& object, - const FloatRect& localPaintInvalidationRect, LayoutRect& rect, float strokeWidthForHairlinePadding) +bool SVGLayoutSupport::mapToVisibleRectInAncestorSpace(const LayoutObject& object, const LayoutBoxModelObject* ancestor, const FloatRect& localPaintInvalidationRect, LayoutRect& resultRect, VisibleRectFlags visibleRectFlags) { AffineTransform rootBorderBoxTransform; const LayoutSVGRoot& svgRoot = computeTransformToSVGRoot(object, rootBorderBoxTransform); - - rect = adjustedEnclosingIntRect(rootBorderBoxTransform.mapRect(localPaintInvalidationRect), - rootBorderBoxTransform, strokeWidthForHairlinePadding); - return svgRoot; + resultRect = transformPaintInvalidationRect(object, rootBorderBoxTransform, localPaintInvalidationRect); + return svgRoot.mapToVisibleRectInAncestorSpace(ancestor, resultRect, visibleRectFlags); } -void SVGLayoutSupport::mapLocalToAncestor(const LayoutObject* object, const LayoutBoxModelObject* ancestor, TransformState& transformState, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) +void SVGLayoutSupport::mapLocalToAncestor(const LayoutObject* object, const LayoutBoxModelObject* ancestor, TransformState& transformState, bool* wasFixed) { transformState.applyTransform(object->localToSVGParentTransform()); - if (paintInvalidationState && paintInvalidationState->canMapToAncestor(ancestor)) { - // |svgTransform| contains localToBorderBoxTransform mentioned below. - transformState.applyTransform(paintInvalidationState->svgTransform()); - transformState.move(paintInvalidationState->paintOffset()); - return; - } - LayoutObject* parent = object->parent(); // At the SVG/HTML boundary (aka LayoutSVGRoot), we apply the localToBorderBoxTransform @@ -160,7 +140,7 @@ void SVGLayoutSupport::mapLocalToAncestor(const LayoutObject* object, const Layo transformState.applyTransform(toLayoutSVGRoot(parent)->localToBorderBoxTransform()); MapCoordinatesFlags mode = UseTransforms; - parent->mapLocalToAncestor(ancestor, transformState, mode, wasFixed, paintInvalidationState); + parent->mapLocalToAncestor(ancestor, transformState, mode, wasFixed); } void SVGLayoutSupport::mapAncestorToLocal(const LayoutObject& object, const LayoutBoxModelObject* ancestor, TransformState& transformState) diff --git a/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.h b/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.h index f3c99a5..426e7f5 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.h +++ b/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.h @@ -75,12 +75,11 @@ public: static void computeContainerBoundingBoxes(const LayoutObject* container, FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& strokeBoundingBox, FloatRect& paintInvalidationBoundingBox); // Important functions used by nearly all SVG layoutObjects centralizing coordinate transformations / paint invalidation rect calculations - static LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutObject&, - const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState*, - float strokeWidthForHairlinePadding = 0); - static const LayoutSVGRoot& mapRectToSVGRootForPaintInvalidation(const LayoutObject&, - const FloatRect& localPaintInvalidationRect, LayoutRect&, float strokeWidthForHairlinePadding = 0); - static void mapLocalToAncestor(const LayoutObject*, const LayoutBoxModelObject* ancestor, TransformState&, bool* wasFixed = nullptr, const PaintInvalidationState* = nullptr); + static FloatRect localOverflowRectForPaintInvalidation(const LayoutObject&); + static LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutObject&, const LayoutBoxModelObject& paintInvalidationContainer); + static LayoutRect transformPaintInvalidationRect(const LayoutObject&, const AffineTransform&, const FloatRect&); + static bool mapToVisibleRectInAncestorSpace(const LayoutObject&, const LayoutBoxModelObject* ancestor, const FloatRect& localPaintInvalidationRect, LayoutRect& resultRect, VisibleRectFlags = DefaultVisibleRectFlags); + static void mapLocalToAncestor(const LayoutObject*, const LayoutBoxModelObject* ancestor, TransformState&, bool* wasFixed = nullptr); static void mapAncestorToLocal(const LayoutObject&, const LayoutBoxModelObject* ancestor, TransformState&); static const LayoutObject* pushMappingToContainer(const LayoutObject*, const LayoutBoxModelObject* ancestorToStopAt, LayoutGeometryMap&); diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp index a2c16fc..ab2d550 100644 --- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp +++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp @@ -474,7 +474,7 @@ static void projectRectsToGraphicsLayerSpaceRecursive( if (compositedLayer->layoutObject()->hasOverflowClip()) rect.move(compositedLayer->layoutBox()->scrolledContentOffset()); } - PaintLayer::mapRectInPaintInvalidationContainerToBacking(compositedLayer->layoutObject(), rect); + PaintLayer::mapRectInPaintInvalidationContainerToBacking(*compositedLayer->layoutObject(), rect); glRects->append(rect); } } diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp index 7ed559e..5175913 100644 --- a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp +++ b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp @@ -28,7 +28,7 @@ static LayoutRect scrollControlPaintInvalidationRect(const IntRect& scrollContro { LayoutRect paintInvalidationRect(scrollControlRect); if (!paintInvalidationRect.isEmpty()) - PaintLayer::mapRectToPaintInvalidationBacking(&box, &paintInvalidationState.paintInvalidationContainer(), paintInvalidationRect, &paintInvalidationState); + paintInvalidationState.mapLocalRectToPaintInvalidationBacking(paintInvalidationRect); return paintInvalidationRect; } diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp index 1657234..c96f42c 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp @@ -543,20 +543,9 @@ void PaintLayer::clearPaginationRecursive() child->clearPaginationRecursive(); } -LayoutPoint PaintLayer::positionFromPaintInvalidationBacking(const LayoutObject* layoutObject, const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) +void PaintLayer::mapPointInPaintInvalidationContainerToBacking(const LayoutBoxModelObject& paintInvalidationContainer, FloatPoint& point) { - FloatPoint point = layoutObject->localToAncestorPoint(FloatPoint(), paintInvalidationContainer, 0, 0, paintInvalidationState); - - // FIXME: Eventually we are going to unify coordinates in GraphicsLayer space. - if (paintInvalidationContainer && paintInvalidationContainer->layer()->groupedMapping()) - mapPointInPaintInvalidationContainerToBacking(paintInvalidationContainer, point); - - return LayoutPoint(point); -} - -void PaintLayer::mapPointInPaintInvalidationContainerToBacking(const LayoutBoxModelObject* paintInvalidationContainer, FloatPoint& point) -{ - PaintLayer* paintInvalidationLayer = paintInvalidationContainer->layer(); + PaintLayer* paintInvalidationLayer = paintInvalidationContainer.layer(); if (!paintInvalidationLayer->groupedMapping()) { point.move(paintInvalidationLayer->compositedLayerMapping()->contentOffsetInCompositingLayer()); return; @@ -568,14 +557,14 @@ void PaintLayer::mapPointInPaintInvalidationContainerToBacking(const LayoutBoxMo // |paintInvalidationContainer| may have a local 2D transform on it, so take that into account when mapping into the space of the // transformed ancestor. - point = paintInvalidationContainer->localToAncestorPoint(point, transformedAncestor); + point = paintInvalidationContainer.localToAncestorPoint(point, transformedAncestor); point.moveBy(-paintInvalidationLayer->groupedMapping()->squashingOffsetFromTransformedAncestor()); } -void PaintLayer::mapRectInPaintInvalidationContainerToBacking(const LayoutBoxModelObject* paintInvalidationContainer, LayoutRect& rect) +void PaintLayer::mapRectInPaintInvalidationContainerToBacking(const LayoutBoxModelObject& paintInvalidationContainer, LayoutRect& rect) { - PaintLayer* paintInvalidationLayer = paintInvalidationContainer->layer(); + PaintLayer* paintInvalidationLayer = paintInvalidationContainer.layer(); if (!paintInvalidationLayer->groupedMapping()) { rect.move(paintInvalidationLayer->compositedLayerMapping()->contentOffsetInCompositingLayer()); return; @@ -587,15 +576,15 @@ void PaintLayer::mapRectInPaintInvalidationContainerToBacking(const LayoutBoxMod // |paintInvalidationContainer| may have a local 2D transform on it, so take that into account when mapping into the space of the // transformed ancestor. - rect = LayoutRect(paintInvalidationContainer->localToAncestorQuad(FloatRect(rect), transformedAncestor).boundingBox()); + rect = LayoutRect(paintInvalidationContainer.localToAncestorQuad(FloatRect(rect), transformedAncestor).boundingBox()); rect.moveBy(-paintInvalidationLayer->groupedMapping()->squashingOffsetFromTransformedAncestor()); } -void PaintLayer::mapRectToPaintInvalidationBacking(const LayoutObject* layoutObject, const LayoutBoxModelObject* paintInvalidationContainer, LayoutRect& rect, const PaintInvalidationState* paintInvalidationState) +void PaintLayer::mapRectToPaintInvalidationBacking(const LayoutObject& layoutObject, const LayoutBoxModelObject& paintInvalidationContainer, LayoutRect& rect) { - if (!paintInvalidationContainer->layer()->groupedMapping()) { - layoutObject->mapToVisibleRectInAncestorSpace(paintInvalidationContainer, rect, paintInvalidationState); + if (!paintInvalidationContainer.layer()->groupedMapping()) { + layoutObject.mapToVisibleRectInAncestorSpace(&paintInvalidationContainer, rect); return; } @@ -603,21 +592,11 @@ void PaintLayer::mapRectToPaintInvalidationBacking(const LayoutObject* layoutObj // layer. This is because all layers that squash together need to issue paint invalidations w.r.t. a single container that is // an ancestor of all of them, in order to properly take into account any local transforms etc. // FIXME: remove this special-case code that works around the paint invalidation code structure. - layoutObject->mapToVisibleRectInAncestorSpace(paintInvalidationContainer, rect, paintInvalidationState); + layoutObject.mapToVisibleRectInAncestorSpace(&paintInvalidationContainer, rect); mapRectInPaintInvalidationContainerToBacking(paintInvalidationContainer, rect); } -LayoutRect PaintLayer::computePaintInvalidationRect(const LayoutObject& layoutObject, const PaintLayer* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) -{ - if (!paintInvalidationContainer->groupedMapping()) - return layoutObject.computePaintInvalidationRect(*paintInvalidationContainer->layoutObject(), paintInvalidationState); - - LayoutRect rect = layoutObject.clippedOverflowRectForPaintInvalidation(paintInvalidationContainer->layoutObject(), paintInvalidationState); - mapRectInPaintInvalidationContainerToBacking(paintInvalidationContainer->layoutObject(), rect); - return rect; -} - void PaintLayer::dirtyVisibleContentStatus() { compositor()->setNeedsUpdateDescendantDependentFlags(); diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.h b/third_party/WebKit/Source/core/paint/PaintLayer.h index 2cbff35..26d5c27 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayer.h +++ b/third_party/WebKit/Source/core/paint/PaintLayer.h @@ -438,20 +438,12 @@ public: bool hasCompositedClippingMask() const; bool needsCompositedScrolling() const { return m_scrollableArea && m_scrollableArea->needsCompositedScrolling(); } - // Computes the position of the given layout object in the space of |paintInvalidationContainer|. - // FIXME: invert the logic to have paint invalidation containers take care of painting objects into them, rather than the reverse. - // This will allow us to clean up this static method messiness. - static LayoutPoint positionFromPaintInvalidationBacking(const LayoutObject*, const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* = 0); - - static void mapPointInPaintInvalidationContainerToBacking(const LayoutBoxModelObject* paintInvalidationContainer, FloatPoint&); - static void mapRectInPaintInvalidationContainerToBacking(const LayoutBoxModelObject* paintInvalidationContainer, LayoutRect&); + static void mapPointInPaintInvalidationContainerToBacking(const LayoutBoxModelObject& paintInvalidationContainer, FloatPoint&); + static void mapRectInPaintInvalidationContainerToBacking(const LayoutBoxModelObject& paintInvalidationContainer, LayoutRect&); // Adjusts the given rect (in the coordinate space of the LayoutObject) to the coordinate space of |paintInvalidationContainer|'s GraphicsLayer backing. - static void mapRectToPaintInvalidationBacking(const LayoutObject*, const LayoutBoxModelObject* paintInvalidationContainer, LayoutRect&, const PaintInvalidationState* = 0); - - // Computes the bounding paint invalidation rect for |layoutObject|, in the coordinate space of |paintInvalidationContainer|'s GraphicsLayer backing. - // TODO(jchaffraix): |paintInvalidationContainer| should be a reference. - static LayoutRect computePaintInvalidationRect(const LayoutObject&, const PaintLayer* paintInvalidationContainer, const PaintInvalidationState* = 0); + // Should use PaintInvalidationState::mapRectToPaintInvalidationBacking() instead if PaintInvalidationState is available. + static void mapRectToPaintInvalidationBacking(const LayoutObject&, const LayoutBoxModelObject& paintInvalidationContainer, LayoutRect&); bool paintsWithTransparency(GlobalPaintFlags globalPaintFlags) const { diff --git a/third_party/WebKit/Source/core/paint/SVGContainerPainter.cpp b/third_party/WebKit/Source/core/paint/SVGContainerPainter.cpp index 94e198a..6ff1ca7 100644 --- a/third_party/WebKit/Source/core/paint/SVGContainerPainter.cpp +++ b/third_party/WebKit/Source/core/paint/SVGContainerPainter.cpp @@ -24,7 +24,9 @@ void SVGContainerPainter::paint(const PaintInfo& paintInfo) return; FloatRect boundingBox = m_layoutSVGContainer.paintInvalidationRectInLocalSVGCoordinates(); - if (!paintInfo.cullRect().intersectsCullRect(m_layoutSVGContainer.localToSVGParentTransform(), boundingBox)) + // LayoutSVGHiddenContainer's paint invalidation rect is always empty but we need to paint its descendants. + if (!m_layoutSVGContainer.isSVGHiddenContainer() + && !paintInfo.cullRect().intersectsCullRect(m_layoutSVGContainer.localToSVGParentTransform(), boundingBox)) return; // Spec: An empty viewBox on the element disables rendering. diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp index ee4cd0f..e80449e 100644 --- a/third_party/WebKit/Source/core/testing/Internals.cpp +++ b/third_party/WebKit/Source/core/testing/Internals.cpp @@ -1303,7 +1303,7 @@ static PaintLayer* findLayerForGraphicsLayer(PaintLayer* searchRoot, GraphicsLay } LayoutRect rect; - PaintLayer::mapRectInPaintInvalidationContainerToBacking(searchRoot->layoutObject(), rect); + PaintLayer::mapRectInPaintInvalidationContainerToBacking(*searchRoot->layoutObject(), rect); *layerOffset = IntSize(rect.x(), rect.y()); return searchRoot; } @@ -1321,7 +1321,7 @@ static PaintLayer* findLayerForGraphicsLayer(PaintLayer* searchRoot, GraphicsLay if (graphicsLayer == squashingLayer) { *layerType ="squashing"; LayoutRect rect; - PaintLayer::mapRectInPaintInvalidationContainerToBacking(searchRoot->layoutObject(), rect); + PaintLayer::mapRectInPaintInvalidationContainerToBacking(*searchRoot->layoutObject(), rect); *layerOffset = IntSize(rect.x(), rect.y()); return searchRoot; } diff --git a/third_party/WebKit/Source/web/LinkHighlightImpl.cpp b/third_party/WebKit/Source/web/LinkHighlightImpl.cpp index 93800a5..e5a6bdd 100644 --- a/third_party/WebKit/Source/web/LinkHighlightImpl.cpp +++ b/third_party/WebKit/Source/web/LinkHighlightImpl.cpp @@ -160,7 +160,7 @@ static void convertTargetSpaceQuadToCompositedLayer(const FloatQuad& targetSpace point = targetLayoutObject->frame()->view()->contentsToRootFrame(point); point = paintInvalidationContainer.frame()->view()->rootFrameToContents(point); FloatPoint floatPoint = paintInvalidationContainer.absoluteToLocal(point, UseTransforms); - PaintLayer::mapPointInPaintInvalidationContainerToBacking(&paintInvalidationContainer, floatPoint); + PaintLayer::mapPointInPaintInvalidationContainerToBacking(paintInvalidationContainer, floatPoint); switch (i) { case 0: compositedSpaceQuad.setP1(floatPoint); break; diff --git a/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp b/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp index 08a0799..0eeec22 100644 --- a/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp +++ b/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp @@ -943,7 +943,7 @@ void WebPluginContainerImpl::computeClipRectsForPlugin( FloatRect frameRectInOwnerElementSpace = box->absoluteToLocalQuad(FloatRect(frameRect()), UseTransforms).boundingBox(); LayoutRect unclippedAbsoluteRect(frameRectInOwnerElementSpace); - box->mapToVisibleRectInAncestorSpace(rootView, unclippedAbsoluteRect, nullptr); + box->mapToVisibleRectInAncestorSpace(rootView, unclippedAbsoluteRect); // The frameRect is already in absolute space of the local frame to the plugin. windowRect = frameRect(); -- cgit v1.1