WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch, v3
bug-234524-20211222103420.patch (text/plain), 38.62 KB, created by
Nikolas Zimmermann
on 2021-12-22 10:34:21 PST
(
hide
)
Description:
Patch, v3
Filename:
MIME Type:
Creator:
Nikolas Zimmermann
Created:
2021-12-22 10:34:21 PST
Size:
38.62 KB
patch
obsolete
>Subversion Revision: 287361 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 5a6d105eca3c26dfd7cfc406d70fbe833f2a23d8..f73cad997caaca59c54e2bdde707dc54272f84c6 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,133 @@ >+2021-12-22 Nikolas Zimmermann <nzimmermann@igalia.com> >+ >+ [LBSE] Begin layer-aware RenderSVGModelObject implementation >+ https://bugs.webkit.org/show_bug.cgi?id=234524 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Begin implementing RenderSVGModelObject - the base class for most graphics >+ primitives in SVG (path / rect / circle / image / ...) for the LBSE. >+ >+ In the legacy engine, RenderSVGImage / RenderSVGShape / RenderSVGContainer inherit >+ from LegacyRenderSVGModelObject, which in turn inherits from RenderElement. The SVG >+ <text> / <foreignObject> renderers inherit from their existing "HTML counterparts" >+ e.g. RenderSVGBlock from RenderBlockFlow, or RenderSVGInline from RenderInline. >+ >+ This has historical reasons: When SVG text rendering was prototyped in WebCore, a goal was to >+ re-use the existing HTML/CSS text rendering code whenever possible. Therefore the SVG text >+ renderers were modelled in the terminology of HTML/CSS: A natural choice is to treat a SVG >+ <text> element as a CSS "block-level element" and <tspan> / <textPath> / <tref> / ... >+ elements as CSS "inline elements". These design choices from almost two decades ago, are >+ the reason for the unnecessary confusing SVG inheritance structure. Furthermore we explicitly >+ disable layer support in all SVG classes that indirectly inherit from RenderLayerModelObject. >+ >+ However for LBSE we do want SVG to participate in the layer tree. >+ Therefore let RenderSVGModelObject inherit from RenderLayerModelObject. This turns >+ RenderLayerModelObject into the common base-class for all SVG renderers in LBSE. >+ >+ The price for the layer support is that all SVG renderers need to be able to answer questions >+ in HTML/CSS language (what's your 'border box rect'? do you have visual overflow? etc.). >+ Finding consistent definitions/mappings was a tedious job, that is fully solved in LBSE and >+ will be upstreamed in pieces. This patch is one main piece of the work. >+ >+ If we forget about the legacy engine, the inheritance structure now looks like the following: >+ >+ + RenderObject >+ + RenderElement >+ | + RenderLayerModelObject >+ | + RenderBoxModelObject >+ | | + RenderBox >+ | | | + RenderReplaced (CSS "replaced" elements) >+ | | | | + RenderSVGRoot (outermost <svg> element) >+ | | | | >+ | | | + RenderBlock (CSS "block-level" elements) >+ | | | + RenderBlockFlow >+ | | | + RenderSVGBlock (HTML/SVG glue code) >+ | | | + RenderSVGForeignObject (<foreignObject> element) >+ | | | + RenderSVGText (<text> element) >+ | | | >+ | | + RenderInline (CSS "inline" elements) >+ | | + RenderSVGInline (HTML/SVG glue code) >+ | | + RenderSVGTSpan (<tspan> element) >+ | | + RenderSVGTextPath (<textPath> element) >+ | | >+ | + RenderSVGModelObject >+ | + RenderSVGContainer >+ | | + RenderSVGHiddenContainer (<defs> / <g> with 'display: none' / <symbol> elements) >+ | | | + RenderSVGResourceContainer >+ | | | + RenderSVGResourceClipper (<clipPath> element) >+ | | | + RenderSVGResourceFilter (<filter> element) >+ | | | + RenderSVGResourceFilterPrimitive >+ | | | + RenderSVGResourceGradient >+ | | | | + RenderSVGResourceLinearGradient (<linearGradient> element) >+ | | | | + RenderSVGResourceRadialGradient (<radialGradient> element) >+ | | | | >+ | | | + RenderSVGResourceMarker (<marker> element) >+ | | | + RenderSVGResourceMasker (<masker> element) >+ | | | + RenderSVGResourcePattern (<pattern> element) >+ | | | + RenderSVGResourceSolidColor >+ | | | >+ | | + RenderSVGTransformableContainer (<a> / <g> / <switch> / <use> elements) >+ | | >+ | + RenderSVGImage (<image> element) >+ | + RenderSVGShape (<rect> / <circle> / <path> ... elements) >+ | + RenderSVGEllipse >+ | + RenderSVGPath >+ | + RenderSVGRect >+ | >+ + RenderText (#text nodes in HTML) >+ + RenderSVGInlineText (#text nodes in SVG) >+ >+ This is way less confusing then the previous version of the SVG render tree. >+ Covered by existing tests, no change in behaviour. >+ >+ * Sources.txt: >+ * WebCore.xcodeproj/project.pbxproj: >+ * rendering/RenderLayerModelObject.cpp: >+ (WebCore::RenderLayerModelObject::computeVisibleRectInSVGContainer const): >+ (WebCore::RenderLayerModelObject::mapLocalToSVGContainer const): >+ * rendering/RenderLayerModelObject.h: >+ * rendering/svg/RenderSVGModelObject.cpp: Added. >+ (WebCore::RenderSVGModelObject::RenderSVGModelObject): >+ (WebCore::RenderSVGModelObject::updateFromStyle): >+ (WebCore::RenderSVGModelObject::borderBoxRectInFragmentEquivalent const): >+ (WebCore::RenderSVGModelObject::overflowClipRect const): >+ (WebCore::RenderSVGModelObject::clippedOverflowRect const): >+ (WebCore::RenderSVGModelObject::computeVisibleRectInContainer const): >+ (WebCore::RenderSVGModelObject::pushMappingToContainer const): >+ (WebCore::RenderSVGModelObject::outlineBoundsForRepaint const): >+ (WebCore::RenderSVGModelObject::absoluteRects const): >+ (WebCore::RenderSVGModelObject::absoluteQuads const): >+ (WebCore::RenderSVGModelObject::willBeDestroyed): >+ (WebCore::RenderSVGModelObject::styleDidChange): >+ (WebCore::RenderSVGModelObject::mapAbsoluteToLocalPoint const): >+ (WebCore::RenderSVGModelObject::mapLocalToContainer const): >+ (WebCore::RenderSVGModelObject::offsetFromContainer const): >+ (WebCore::RenderSVGModelObject::addFocusRingRects): >+ (WebCore::RenderSVGModelObject::shouldPaintSVGRenderer const): >+ (WebCore::intersectsAllowingEmpty): >+ (WebCore::isGraphicsElement): >+ (WebCore::RenderSVGModelObject::checkIntersection): >+ (WebCore::RenderSVGModelObject::checkEnclosure): >+ (WebCore::RenderSVGModelObject::computeClipPath const): >+ (WebCore::RenderSVGModelObject::applyTransform const): >+ (WebCore::RenderSVGModelObject::paintSVGOutline): >+ * rendering/svg/RenderSVGModelObject.h: Added. >+ (WebCore::RenderSVGModelObject::element const): >+ (WebCore::RenderSVGModelObject::borderBoxRectEquivalent const): >+ (WebCore::RenderSVGModelObject::contentBoxRectEquivalent const): >+ (WebCore::RenderSVGModelObject::frameRectEquivalent const): >+ (WebCore::RenderSVGModelObject::visualOverflowRectEquivalent const): >+ (WebCore::RenderSVGModelObject::applyTopLeftLocationOffsetEquivalent const): >+ (WebCore::RenderSVGModelObject::layoutRect const): >+ (WebCore::RenderSVGModelObject::setLayoutRect): >+ (WebCore::RenderSVGModelObject::setLayoutLocation): >+ (WebCore::RenderSVGModelObject::paintingLocation const): >+ (WebCore::RenderSVGModelObject::layoutLocation const): >+ (WebCore::RenderSVGModelObject::layoutLocationOffset const): >+ (WebCore::RenderSVGModelObject::layoutSize const): >+ (WebCore::RenderSVGModelObject::overflowClipRectForChildLayers): >+ > 2021-12-22 Michael Saboff <msaboff@apple.com> > > Fix WebCore install headers with alternate build >diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt >index bd5a7479cb39e46cc910400f4ee3849324c7531f..61e2b9dec6e327ffbab3836d12cb947102de8612 100644 >--- a/Source/WebCore/Sources.txt >+++ b/Source/WebCore/Sources.txt >@@ -2477,6 +2477,7 @@ rendering/svg/RenderSVGHiddenContainer.cpp > rendering/svg/RenderSVGImage.cpp > rendering/svg/RenderSVGInline.cpp > rendering/svg/RenderSVGInlineText.cpp >+rendering/svg/RenderSVGModelObject.cpp > rendering/svg/RenderSVGPath.cpp > rendering/svg/RenderSVGRect.cpp > rendering/svg/RenderSVGResource.cpp >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index 823fd6743985d6337b5c97b7d5c9f47baffd61f2..00e224ba28b9ee73c9887b0dd7c56f159282741a 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -1243,6 +1243,7 @@ > 436708C712D9CA4B00044234 /* RenderSVGHiddenContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367088812D9CA4A00044234 /* RenderSVGHiddenContainer.h */; }; > 436708C912D9CA4B00044234 /* RenderSVGImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367088A12D9CA4A00044234 /* RenderSVGImage.h */; }; > 436708CB12D9CA4B00044234 /* LegacyRenderSVGModelObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367088C12D9CA4A00044234 /* LegacyRenderSVGModelObject.h */; }; >+ 43670C9342D9BC4B00044234 /* RenderSVGModelObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 436708FD12D9CA4A00032114 /* RenderSVGModelObject.h */; }; > 436708CD12D9CA4B00044234 /* RenderSVGResource.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367088E12D9CA4A00044234 /* RenderSVGResource.h */; }; > 436708CF12D9CA4B00044234 /* RenderSVGResourceClipper.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367089012D9CA4A00044234 /* RenderSVGResourceClipper.h */; }; > 436708D112D9CA4B00044234 /* RenderSVGResourceContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367089212D9CA4A00044234 /* RenderSVGResourceContainer.h */; }; >@@ -8978,6 +8979,8 @@ > 4367088812D9CA4A00044234 /* RenderSVGHiddenContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGHiddenContainer.h; sourceTree = "<group>"; }; > 4367088912D9CA4A00044234 /* RenderSVGImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGImage.cpp; sourceTree = "<group>"; }; > 4367088A12D9CA4A00044234 /* RenderSVGImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGImage.h; sourceTree = "<group>"; }; >+ 4367088D34E9CA4A00044234 /* RenderSVGModelObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGModelObject.cpp; sourceTree = "<group>"; }; >+ 436708FD12D9CA4A00032114 /* RenderSVGModelObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGModelObject.h; sourceTree = "<group>"; }; > 4367088B12D9CA4A00044234 /* LegacyRenderSVGModelObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LegacyRenderSVGModelObject.cpp; sourceTree = "<group>"; }; > 4367088C12D9CA4A00044234 /* LegacyRenderSVGModelObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LegacyRenderSVGModelObject.h; sourceTree = "<group>"; }; > 4367088D12D9CA4A00044234 /* RenderSVGResource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGResource.cpp; sourceTree = "<group>"; }; >@@ -18920,6 +18923,8 @@ > CDF747E8270F6CAE008FEEEC /* RenderSVGInlineInlines.h */, > 0854B0041255E4E600B9CDD0 /* RenderSVGInlineText.cpp */, > 0854B0051255E4E600B9CDD0 /* RenderSVGInlineText.h */, >+ 4367088D34E9CA4A00044234 /* RenderSVGModelObject.cpp */, >+ 436708FD12D9CA4A00032114 /* RenderSVGModelObject.h */, > ADDF1AD41257CD9A0003A759 /* RenderSVGPath.cpp */, > ADDF1AD51257CD9A0003A759 /* RenderSVGPath.h */, > A10BB5821484E3A700B2E87A /* RenderSVGRect.cpp */, >@@ -36703,6 +36708,7 @@ > 0854B0151255E4E600B9CDD0 /* RenderSVGInline.h in Headers */, > CDF747E9270F6CAE008FEEEC /* RenderSVGInlineInlines.h in Headers */, > 0854B0171255E4E600B9CDD0 /* RenderSVGInlineText.h in Headers */, >+ 43670C9342D9BC4B00044234 /* RenderSVGModelObject.h in Headers */, > ADDF1AD71257CD9A0003A759 /* RenderSVGPath.h in Headers */, > A10BB5851484E3A700B2E87A /* RenderSVGRect.h in Headers */, > 436708CD12D9CA4B00044234 /* RenderSVGResource.h in Headers */, >diff --git a/Source/WebCore/rendering/RenderLayerModelObject.cpp b/Source/WebCore/rendering/RenderLayerModelObject.cpp >index f29504a2f32e85ad58327f66a34b19128b6d6878..8d990f1d531be63f2b25d06145fb131c4100726c 100644 >--- a/Source/WebCore/rendering/RenderLayerModelObject.cpp >+++ b/Source/WebCore/rendering/RenderLayerModelObject.cpp >@@ -29,9 +29,11 @@ > #include "RenderLayerBacking.h" > #include "RenderLayerCompositor.h" > #include "RenderLayerScrollableArea.h" >+#include "RenderSVGModelObject.h" > #include "RenderView.h" > #include "Settings.h" > #include "StyleScrollSnapPoints.h" >+#include "TransformState.h" > #include <wtf/IsoMallocInlines.h> > > namespace WebCore { >@@ -229,5 +231,92 @@ void RenderLayerModelObject::suspendAnimations(MonotonicTime time) > layer()->backing()->suspendAnimations(time); > } > >+#if ENABLE(LAYER_BASED_SVG_ENGINE) >+std::optional<LayoutRect> RenderLayerModelObject::computeVisibleRectInSVGContainer(const LayoutRect& rect, const RenderLayerModelObject* container, RenderObject::VisibleRectContext context) const >+{ >+ // FIXME: [LBSE] Upstream RenderSVGBlock changes >+ // ASSERT(is<RenderSVGModelObject>(this) || is<RenderSVGBlock>(this)); >+ ASSERT(is<RenderSVGModelObject>(this)); >+ >+ ASSERT(!style().hasInFlowPosition()); >+ ASSERT(!view().frameView().layoutContext().isPaintOffsetCacheEnabled()); >+ >+ if (container == this) >+ return rect; >+ >+ bool containerIsSkipped; >+ auto* localContainer = this->container(container, containerIsSkipped); >+ if (!localContainer) >+ return rect; >+ >+ ASSERT_UNUSED(containerIsSkipped, !containerIsSkipped); >+ >+ LayoutRect adjustedRect = rect; >+ >+ // FIXME: [LBSE] Upstream RenderSVGForeignObject changes >+ // Move to origin of local coordinate system, if this is the first call to computeVisibleRectInContainer() originating >+ // from a SVG renderer (RenderSVGModelObject / RenderSVGBlock) or if we cross the boundary from HTML -> SVG via RenderSVGForeignObject. >+ // bool moveToOrigin = is<RenderSVGForeignObject>(renderer); >+ bool moveToOrigin = false; >+ >+ /* FIXME: [LBSE] Upstream RenderObject changes >+ if (context.options.contains(RenderObject::VisibleRectContextOption::TranslateToSVGRendererOrigin)) { >+ context.options.remove(RenderObject::VisibleRectContextOption::TranslateToSVGRendererOrigin); >+ moveToOrigin = true; >+ } >+ */ >+ >+ if (moveToOrigin) >+ adjustedRect.moveBy(flooredLayoutPoint(objectBoundingBox().minXMinYCorner())); >+ >+ if (auto* transform = layer()->transform()) >+ adjustedRect = transform->mapRect(adjustedRect); >+ >+ return localContainer->computeVisibleRectInContainer(adjustedRect, container, context); >+} >+ >+void RenderLayerModelObject::mapLocalToSVGContainer(const RenderLayerModelObject* ancestorContainer, TransformState& transformState, OptionSet<MapCoordinatesMode> mode, bool* wasFixed) const >+{ >+ // FIXME: [LBSE] Upstream RenderSVGBlock changes >+ // ASSERT(is<RenderSVGModelObject>(this) || is<RenderSVGBlock>(this)); >+ ASSERT(is<RenderSVGModelObject>(this)); >+ ASSERT(style().position() == PositionType::Static); >+ >+ if (ancestorContainer == this) >+ return; >+ >+ ASSERT(!view().frameView().layoutContext().isPaintOffsetCacheEnabled()); >+ >+ bool ancestorSkipped; >+ auto* container = this->container(ancestorContainer, ancestorSkipped); >+ if (!container) >+ return; >+ >+ ASSERT_UNUSED(ancestorSkipped, !ancestorSkipped); >+ >+ // If this box has a transform, it acts as a fixed position container for fixed descendants, >+ // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position. >+ if (hasTransform()) >+ mode.remove(IsFixed); >+ >+ if (wasFixed) >+ *wasFixed = mode.contains(IsFixed); >+ >+ auto containerOffset = offsetFromContainer(*container, LayoutPoint(transformState.mappedPoint())); >+ >+ bool preserve3D = mode & UseTransforms && (container->style().preserves3D() || style().preserves3D()); >+ if (mode & UseTransforms && shouldUseTransformFromContainer(container)) { >+ TransformationMatrix t; >+ getTransformFromContainer(container, containerOffset, t); >+ transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); >+ } else >+ transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); >+ >+ mode.remove(ApplyContainerFlip); >+ >+ container->mapLocalToContainer(ancestorContainer, transformState, mode, wasFixed); >+} >+#endif >+ > } // namespace WebCore > >diff --git a/Source/WebCore/rendering/RenderLayerModelObject.h b/Source/WebCore/rendering/RenderLayerModelObject.h >index d118dc81a6a7c60bb43b271c735b21d6698c871e..9c314afb10d8c5a702afe202653fda704bdf68bb 100644 >--- a/Source/WebCore/rendering/RenderLayerModelObject.h >+++ b/Source/WebCore/rendering/RenderLayerModelObject.h >@@ -67,6 +67,16 @@ public: > > void suspendAnimations(MonotonicTime = MonotonicTime()) override; > >+#if ENABLE(LAYER_BASED_SVG_ENGINE) >+ // Provides the SVG implementation for computeVisibleRectInContainer(). >+ // This lives in RenderLayerModelObject, which is the common base-class for all SVG renderers. >+ std::optional<LayoutRect> computeVisibleRectInSVGContainer(const LayoutRect&, const RenderLayerModelObject* container, VisibleRectContext) const; >+ >+ // Provides the SVG implementation for mapLocalToContainer(). >+ // This lives in RenderLayerModelObject, which is the common base-class for all SVG renderers. >+ void mapLocalToSVGContainer(const RenderLayerModelObject* ancestorContainer, TransformState&, OptionSet<MapCoordinatesMode>, bool* wasFixed) const; >+#endif >+ > protected: > RenderLayerModelObject(Element&, RenderStyle&&, BaseTypeFlags); > RenderLayerModelObject(Document&, RenderStyle&&, BaseTypeFlags); >diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..21ff7c4b4a72614fc1eaca32845316f37044486b >--- /dev/null >+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp >@@ -0,0 +1,303 @@ >+/* >+ * Copyright (c) 2009, Google Inc. All rights reserved. >+ * Copyright (C) 2020, 2021 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions are >+ * met: >+ * >+ * * Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * * Redistributions in binary form must reproduce the above >+ * copyright notice, this list of conditions and the following disclaimer >+ * in the documentation and/or other materials provided with the >+ * distribution. >+ * * Neither the name of Google Inc. nor the names of its >+ * contributors may be used to endorse or promote products derived from >+ * this software without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS >+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT >+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR >+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT >+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, >+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT >+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "RenderSVGModelObject.h" >+ >+#if ENABLE(LAYER_BASED_SVG_ENGINE) >+#include "RenderGeometryMap.h" >+#include "RenderLayer.h" >+#include "RenderLayerModelObject.h" >+#include "RenderSVGResource.h" >+#include "RenderView.h" >+#include "SVGGraphicsElement.h" >+#include "SVGLocatable.h" >+#include "SVGNames.h" >+#include "SVGPathData.h" >+#include "SVGResourcesCache.h" >+#include "TransformState.h" >+#include <wtf/IsoMallocInlines.h> >+ >+namespace WebCore { >+ >+WTF_MAKE_ISO_ALLOCATED_IMPL(RenderSVGModelObject); >+ >+RenderSVGModelObject::RenderSVGModelObject(SVGElement& element, RenderStyle&& style) >+ : RenderLayerModelObject(element, WTFMove(style), 0) >+{ >+} >+ >+void RenderSVGModelObject::updateFromStyle() >+{ >+ RenderLayerModelObject::updateFromStyle(); >+ setHasTransformRelatedProperty(style().hasTransformRelatedProperty()); >+ >+ AffineTransform transform; >+ if (RenderObject::node() && is<SVGGraphicsElement>(nodeForNonAnonymous())) >+ transform = downcast<SVGGraphicsElement>(nodeForNonAnonymous()).animatedLocalTransform(); >+ >+ // FIXME: [LBSE] Upstream RenderObject changes >+ // if (!transform.isIdentity()) >+ // setHasSVGTransform(); >+} >+ >+FloatRect RenderSVGModelObject::borderBoxRectInFragmentEquivalent(RenderFragmentContainer*, RenderBox::RenderBoxFragmentInfoFlags) const >+{ >+ return borderBoxRectEquivalent(); >+} >+ >+LayoutRect RenderSVGModelObject::overflowClipRect(const LayoutPoint&, RenderFragmentContainer*, OverlayScrollbarSizeRelevancy, PaintPhase) const >+{ >+ ASSERT_NOT_REACHED(); >+ return LayoutRect(); >+} >+ >+LayoutRect RenderSVGModelObject::clippedOverflowRect(const RenderLayerModelObject* repaintContainer, VisibleRectContext context) const >+{ >+ if (style().visibility() != Visibility::Visible && !enclosingLayer()->hasVisibleContent()) >+ return LayoutRect(); >+ >+ ASSERT(!view().frameView().layoutContext().isPaintOffsetCacheEnabled()); >+ return computeRect(visualOverflowRectEquivalent(), repaintContainer, context); >+} >+ >+std::optional<LayoutRect> RenderSVGModelObject::computeVisibleRectInContainer(const LayoutRect& rect, const RenderLayerModelObject* container, VisibleRectContext context) const >+{ >+ return computeVisibleRectInSVGContainer(rect, container, context); >+} >+ >+const RenderObject* RenderSVGModelObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const >+{ >+ ASSERT(ancestorToStopAt != this); >+ ASSERT(style().position() == PositionType::Static); >+ >+ bool ancestorSkipped; >+ RenderElement* container = this->container(ancestorToStopAt, ancestorSkipped); >+ if (!container) >+ return nullptr; >+ >+ ASSERT_UNUSED(ancestorSkipped, !ancestorSkipped); >+ >+ bool offsetDependsOnPoint = false; >+ LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(), &offsetDependsOnPoint); >+ >+ bool preserve3D = container->style().preserves3D() || style().preserves3D(); >+ if (shouldUseTransformFromContainer(container) && (geometryMap.mapCoordinatesFlags() & UseTransforms)) { >+ TransformationMatrix t; >+ getTransformFromContainer(container, containerOffset, t); >+ geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, false /* isFixedPos */, hasTransform()); >+ } else >+ geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint, false /* isFixedPos */, hasTransform()); >+ >+ return container; >+} >+ >+LayoutRect RenderSVGModelObject::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap) const >+{ >+ ASSERT(!view().frameView().layoutContext().isPaintOffsetCacheEnabled()); >+ >+ auto outlineBounds = visualOverflowRectEquivalent(); >+ >+ if (repaintContainer != this) { >+ FloatQuad containerRelativeQuad; >+ if (geometryMap) >+ containerRelativeQuad = geometryMap->mapToContainer(outlineBounds, repaintContainer); >+ else >+ containerRelativeQuad = localToContainerQuad(FloatRect(outlineBounds), repaintContainer); >+ >+ outlineBounds = LayoutRect(containerRelativeQuad.boundingBox()); >+ } >+ >+ return outlineBounds; >+} >+ >+void RenderSVGModelObject::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const >+{ >+ rects.append(snappedIntRect(LayoutRect(accumulatedOffset + layoutLocation(), layoutSize()))); >+} >+ >+void RenderSVGModelObject::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const >+{ >+ quads.append(localToAbsoluteQuad(objectBoundingBox(), UseTransforms, wasFixed)); >+} >+ >+void RenderSVGModelObject::willBeDestroyed() >+{ >+ SVGResourcesCache::clientDestroyed(*this); >+ RenderLayerModelObject::willBeDestroyed(); >+} >+ >+void RenderSVGModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) >+{ >+ RenderLayerModelObject::styleDidChange(diff, oldStyle); >+ >+ // SVG masks are painted independent of the target renderers visibility. >+ // FIXME: [LBSE] Upstream RenderElement changes >+ // bool hasSVGMask = hasSVGMask(); >+ bool hasSVGMask = false; >+ if (hasSVGMask && hasLayer() && style().visibility() != Visibility::Visible) >+ layer()->setHasVisibleContent(); >+ >+ SVGResourcesCache::clientStyleChanged(*this, diff, style()); >+} >+ >+void RenderSVGModelObject::mapAbsoluteToLocalPoint(OptionSet<MapCoordinatesMode> mode, TransformState& transformState) const >+{ >+ ASSERT(style().position() == PositionType::Static); >+ >+ if (hasTransform()) >+ mode.remove(IsFixed); >+ >+ auto* container = this->parent(); >+ if (!container) >+ return; >+ >+ container->mapAbsoluteToLocalPoint(mode, transformState); >+ >+ LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint()); >+ >+ bool preserve3D = mode & UseTransforms && (container->style().preserves3D() || style().preserves3D()); >+ if (mode & UseTransforms && shouldUseTransformFromContainer(container)) { >+ TransformationMatrix t; >+ getTransformFromContainer(container, containerOffset, t); >+ transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); >+ } else >+ transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); >+} >+ >+void RenderSVGModelObject::mapLocalToContainer(const RenderLayerModelObject* ancestorContainer, TransformState& transformState, OptionSet<MapCoordinatesMode> mode, bool* wasFixed) const >+{ >+ mapLocalToSVGContainer(ancestorContainer, transformState, mode, wasFixed); >+} >+ >+LayoutSize RenderSVGModelObject::offsetFromContainer(RenderElement& container, const LayoutPoint&, bool*) const >+{ >+ ASSERT_UNUSED(container, &container == this->container()); >+ ASSERT(!isInFlowPositioned()); >+ ASSERT(!isAbsolutelyPositioned()); >+ ASSERT(isInline()); >+ return LayoutSize(); >+} >+ >+void RenderSVGModelObject::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*) >+{ >+ auto repaintBoundingBox = enclosingLayoutRect(this->repaintRectInLocalCoordinates()); >+ if (repaintBoundingBox.size().isEmpty()) >+ return; >+ rects.append(LayoutRect(additionalOffset, repaintBoundingBox.size())); >+} >+ >+bool RenderSVGModelObject::shouldPaintSVGRenderer(const PaintInfo& paintInfo) const >+{ >+ ASSERT(!paintInfo.context().paintingDisabled()); >+ >+ if ((paintInfo.phase != PaintPhase::Foreground && paintInfo.phase != PaintPhase::ClippingMask && paintInfo.phase != PaintPhase::Mask && paintInfo.phase != PaintPhase::Outline && paintInfo.phase != PaintPhase::SelfOutline)) >+ return false; >+ >+ if (!paintInfo.shouldPaintWithinRoot(*this)) >+ return false; >+ >+ if (style().visibility() == Visibility::Hidden || style().display() == DisplayType::None) >+ return false; >+ >+ return true; >+} >+ >+// FloatRect::intersects does not consider horizontal or vertical lines (because of isEmpty()). >+// So special-case handling of such lines. >+static bool intersectsAllowingEmpty(const FloatRect& r, const FloatRect& other) >+{ >+ if (r.isEmpty() && other.isEmpty()) >+ return false; >+ if (r.isEmpty() && !other.isEmpty()) >+ return (other.contains(r.x(), r.y()) && !other.contains(r.maxX(), r.maxY())) || (!other.contains(r.x(), r.y()) && other.contains(r.maxX(), r.maxY())); >+ if (other.isEmpty() && !r.isEmpty()) >+ return intersectsAllowingEmpty(other, r); >+ return r.intersects(other); >+} >+ >+// One of the element types that can cause graphics to be drawn onto the target canvas. Specifically: circle, ellipse, >+// image, line, path, polygon, polyline, rect, text and use. >+static bool isGraphicsElement(const RenderElement& renderer) >+{ >+ return renderer.isSVGShape() || renderer.isSVGText() || renderer.isSVGImage() || renderer.element()->hasTagName(SVGNames::useTag); >+} >+ >+bool RenderSVGModelObject::checkIntersection(RenderElement* renderer, const FloatRect& rect) >+{ >+ if (!renderer || renderer->style().pointerEvents() == PointerEvents::None) >+ return false; >+ if (!isGraphicsElement(*renderer)) >+ return false; >+ SVGElement* svgElement = downcast<SVGElement>(renderer->element()); >+ ASSERT(is<SVGGraphicsElement>(svgElement)); >+ auto ctm = downcast<SVGGraphicsElement>(*svgElement).getCTM(SVGLocatable::DisallowStyleUpdate); >+ return intersectsAllowingEmpty(rect, ctm.mapRect(renderer->repaintRectInLocalCoordinates())); >+} >+ >+bool RenderSVGModelObject::checkEnclosure(RenderElement* renderer, const FloatRect& rect) >+{ >+ if (!renderer || renderer->style().pointerEvents() == PointerEvents::None) >+ return false; >+ if (!isGraphicsElement(*renderer)) >+ return false; >+ SVGElement* svgElement = downcast<SVGElement>(renderer->element()); >+ ASSERT(is<SVGGraphicsElement>(svgElement)); >+ auto ctm = downcast<SVGGraphicsElement>(*svgElement).getCTM(SVGLocatable::DisallowStyleUpdate); >+ return rect.contains(ctm.mapRect(renderer->repaintRectInLocalCoordinates())); >+} >+ >+Path RenderSVGModelObject::computeClipPath(AffineTransform& transform) const >+{ >+ if (layer()->hasTransform()) >+ transform.multiply(layer()->currentTransform(RenderStyle::individualTransformOperations).toAffineTransform()); >+ >+ return pathFromGraphicsElement(&downcast<SVGGraphicsElement>(element())); >+} >+ >+void RenderSVGModelObject::applyTransform(TransformationMatrix& transform, const RenderStyle& style, const FloatRect& boundingBox, OptionSet<RenderStyle::TransformOperationOption> options) const >+{ >+ UNUSED_PARAM(transform); >+ UNUSED_PARAM(style); >+ UNUSED_PARAM(boundingBox); >+ UNUSED_PARAM(options); >+ // FIXME: [LBSE] Upstream SVGRenderSupport changes >+ // SVGRenderSupport::applyTransform(*this, transform, style, boundingBox, std::nullopt, std::nullopt, options); >+} >+ >+void RenderSVGModelObject::paintSVGOutline(PaintInfo& paintInfo, const LayoutPoint& adjustedPaintOffset) >+{ >+ paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, repaintRectInLocalCoordinates().size())); >+} >+ >+} // namespace WebCore >+ >+#endif // ENABLE(LAYER_BASED_SVG_ENGINE) >diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.h b/Source/WebCore/rendering/svg/RenderSVGModelObject.h >new file mode 100644 >index 0000000000000000000000000000000000000000..7c188b3f070304b813b34784b37d6f28d902fbfc >--- /dev/null >+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.h >@@ -0,0 +1,128 @@ >+/* >+ * Copyright (c) 2009, Google Inc. All rights reserved. >+ * Copyright (C) 2020, 2021 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions are >+ * met: >+ * >+ * * Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * * Redistributions in binary form must reproduce the above >+ * copyright notice, this list of conditions and the following disclaimer >+ * in the documentation and/or other materials provided with the >+ * distribution. >+ * * Neither the name of Google Inc. nor the names of its >+ * contributors may be used to endorse or promote products derived from >+ * this software without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS >+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT >+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR >+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT >+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, >+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT >+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#if ENABLE(LAYER_BASED_SVG_ENGINE) >+#include "RenderLayer.h" >+#include "RenderLayerModelObject.h" >+// FIXME: [LBSE] Upstream SVGBoundingBoxComputation >+// #include "SVGBoundingBoxComputation.h" >+#include "SVGElement.h" >+#include "SVGRenderSupport.h" >+ >+namespace WebCore { >+ >+// Most renderers in the SVG rendering tree will inherit from this class >+// but not all. RenderSVGForeignObject, RenderSVGBlock, etc. inherit from >+// existing RenderBlock classes, that all inherit from RenderLayerModelObject >+// directly, without RenderSVGModelObject inbetween. Therefore code which >+// needs to be shared between all SVG renderers goes to RenderLayerModelObject. >+class SVGElement; >+ >+class RenderSVGModelObject : public RenderLayerModelObject { >+ WTF_MAKE_ISO_ALLOCATED(RenderSVGModelObject); >+public: >+ bool requiresLayer() const override { return true; } >+ >+ void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override; >+ >+ static bool checkIntersection(RenderElement*, const FloatRect&); >+ static bool checkEnclosure(RenderElement*, const FloatRect&); >+ >+ SVGElement& element() const { return downcast<SVGElement>(nodeForNonAnonymous()); } >+ >+ // FIXME: [LBSE] Mark final, add applyTransform to RenderLayerModelObject >+ void applyTransform(TransformationMatrix&, const RenderStyle&, const FloatRect& boundingBox, OptionSet<RenderStyle::TransformOperationOption>) const; >+ >+ // Mimic the RenderBox accessors - by sharing the same terminology the painting / hit testing / layout logic is >+ // similar to read compared to non-SVG renderers such as RenderBox & friends. >+ LayoutRect borderBoxRectEquivalent() const { return { LayoutPoint(), m_layoutRect.size() }; } >+ LayoutRect contentBoxRectEquivalent() const { return borderBoxRectEquivalent(); } >+ LayoutRect frameRectEquivalent() const { return m_layoutRect; } >+ >+ LayoutRect visualOverflowRectEquivalent() const >+ { >+ // FIXME: [LBSE] Upstream SVGBoundingBoxComputation >+ // return SVGBoundingBoxComputation::computeVisualOverflowRect(*this); >+ return LayoutRect(); >+ } >+ >+ void applyTopLeftLocationOffsetEquivalent(LayoutPoint& point) const { point.moveBy(layoutLocation()); } >+ >+ LayoutRect layoutRect() const { return m_layoutRect; } >+ void setLayoutRect(const LayoutRect& layoutRect) { m_layoutRect = layoutRect; } >+ void setLayoutLocation(const LayoutPoint& layoutLocation) { m_layoutRect.setLocation(layoutLocation); } >+ >+ LayoutPoint paintingLocation() const { return toLayoutPoint(layoutLocation() - flooredLayoutPoint(objectBoundingBox().minXMinYCorner())); } >+ LayoutPoint layoutLocation() const { return m_layoutRect.location(); } >+ LayoutSize layoutLocationOffset() const { return toLayoutSize(m_layoutRect.location()); } >+ LayoutSize layoutSize() const { return m_layoutRect.size(); } >+ >+ // For RenderLayer only >+ FloatRect borderBoxRectInFragmentEquivalent(RenderFragmentContainer*, RenderBox::RenderBoxFragmentInfoFlags = RenderBox::CacheRenderBoxFragmentInfo) const; >+ virtual LayoutRect overflowClipRect(const LayoutPoint& location, RenderFragmentContainer* = nullptr, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, PaintPhase = PaintPhase::BlockBackground) const; >+ LayoutRect overflowClipRectForChildLayers(const LayoutPoint& location, RenderFragmentContainer* fragment, OverlayScrollbarSizeRelevancy relevancy) { return overflowClipRect(location, fragment, relevancy); } >+ >+ virtual Path computeClipPath(AffineTransform&) const; >+ >+protected: >+ RenderSVGModelObject(SVGElement&, RenderStyle&&); >+ >+ void willBeDestroyed() override; >+ void updateFromStyle() override; >+ bool shouldPaintSVGRenderer(const PaintInfo&) const; >+ >+ LayoutRect clippedOverflowRect(const RenderLayerModelObject* repaintContainer, VisibleRectContext) const override; >+ std::optional<LayoutRect> computeVisibleRectInContainer(const LayoutRect&, const RenderLayerModelObject* container, VisibleRectContext) const; >+ void mapAbsoluteToLocalPoint(OptionSet<MapCoordinatesMode>, TransformState&) const override; >+ void mapLocalToContainer(const RenderLayerModelObject* ancestorContainer, TransformState&, OptionSet<MapCoordinatesMode>, bool* wasFixed) const; >+ LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const final; >+ const RenderObject* pushMappingToContainer(const RenderLayerModelObject*, RenderGeometryMap&) const override; >+ LayoutSize offsetFromContainer(RenderElement&, const LayoutPoint&, bool* offsetDependsOnPoint = nullptr) const override; >+ >+ void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const override; >+ void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override; >+ >+ void addFocusRingRects(Vector<LayoutRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) override; >+ void paintSVGOutline(PaintInfo&, const LayoutPoint& adjustedPaintOffset); >+ >+private: >+ bool isRenderSVGModelObject() const final { return true; } >+ >+ LayoutRect m_layoutRect; >+}; >+ >+} // namespace WebCore >+ >+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGModelObject, isRenderSVGModelObject()) >+ >+#endif // ENABLE(LAYER_BASED_SVG_ENGINE)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
ews-feeder
:
commit-queue-
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 234524
:
447652
|
447745
|
447817
|
447819
|
447866
|
447887
|
448214
|
448222