Diff
Modified: trunk/Source/WebCore/ChangeLog (287537 => 287538)
--- trunk/Source/WebCore/ChangeLog 2022-01-03 13:51:08 UTC (rev 287537)
+++ trunk/Source/WebCore/ChangeLog 2022-01-03 14:01:22 UTC (rev 287538)
@@ -1,3 +1,131 @@
+2022-01-03 Nikolas Zimmermann <[email protected]>
+
+ [LBSE] Begin layer-aware RenderSVGModelObject implementation
+ https://bugs.webkit.org/show_bug.cgi?id=234524
+
+ Reviewed by Rob Buis.
+
+ 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::applyTransform const):
+ * 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):
+
2022-01-03 Antoine Quint <[email protected]>
Refactor code creating css values and lists for animation and transition properties
Modified: trunk/Source/WebCore/Sources.txt (287537 => 287538)
--- trunk/Source/WebCore/Sources.txt 2022-01-03 13:51:08 UTC (rev 287537)
+++ trunk/Source/WebCore/Sources.txt 2022-01-03 14:01:22 UTC (rev 287538)
@@ -2477,6 +2477,7 @@
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
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (287537 => 287538)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2022-01-03 13:51:08 UTC (rev 287537)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2022-01-03 14:01:22 UTC (rev 287538)
@@ -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 */; };
@@ -8980,6 +8981,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>"; };
@@ -18924,6 +18927,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 */,
@@ -36711,6 +36716,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 */,
Modified: trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp (287537 => 287538)
--- trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp 2022-01-03 13:51:08 UTC (rev 287537)
+++ trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp 2022-01-03 14:01:22 UTC (rev 287538)
@@ -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 @@
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
Modified: trunk/Source/WebCore/rendering/RenderLayerModelObject.h (287537 => 287538)
--- trunk/Source/WebCore/rendering/RenderLayerModelObject.h 2022-01-03 13:51:08 UTC (rev 287537)
+++ trunk/Source/WebCore/rendering/RenderLayerModelObject.h 2022-01-03 14:01:22 UTC (rev 287538)
@@ -67,6 +67,16 @@
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);
Added: trunk/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp (0 => 287538)
--- trunk/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp (rev 0)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp 2022-01-03 14:01:22 UTC (rev 287538)
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2009, Google Inc. All rights reserved.
+ * Copyright (C) 2020, 2021, 2022 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 (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 = 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(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())
+ 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()));
+}
+
+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);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(LAYER_BASED_SVG_ENGINE)
Added: trunk/Source/WebCore/rendering/svg/RenderSVGModelObject.h (0 => 287538)
--- trunk/Source/WebCore/rendering/svg/RenderSVGModelObject.h (rev 0)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGModelObject.h 2022-01-03 14:01:22 UTC (rev 287538)
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2009, Google Inc. All rights reserved.
+ * Copyright (C) 2020, 2021, 2022 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); }
+
+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 final;
+ void mapAbsoluteToLocalPoint(OptionSet<MapCoordinatesMode>, TransformState&) const override;
+ void mapLocalToContainer(const RenderLayerModelObject* ancestorContainer, TransformState&, OptionSet<MapCoordinatesMode>, bool* wasFixed) const final;
+ 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;
+ // FIXME: [LBSE] Upstream SVG outline painting functionality
+ // 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)