Diff
Modified: trunk/Source/WebCore/ChangeLog (287831 => 287832)
--- trunk/Source/WebCore/ChangeLog 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/ChangeLog 2022-01-10 09:47:29 UTC (rev 287832)
@@ -1,3 +1,106 @@
+2022-01-10 Nikolas Zimmermann <[email protected]>
+
+ [LBSE] Begin layer-aware RenderSVGShape implementation
+ https://bugs.webkit.org/show_bug.cgi?id=234954
+
+ Reviewed by Rob Buis.
+
+ Begin implementing RenderSVGShape, based on the downstream version in the
+ LBSE branch. Many parts are 1:1 copies from LegacyRenderSVGShape, although
+ the core methods for layout / paint / hit-testing looks quite different in
+ RenderSVGShape -- the code is mostly adapted from layer-aware CSS renderers
+ such as RenderBox / RenderBlock taking SVG specifics into account.
+
+ This patch hooks in RenderSVGShape in all places that used to handle
+ LegacyRenderSVGShape, e.g. in AccessibilityRenderObject. However no
+ renderer inherits from RenderSVGShape yet -- a follow-up patch will
+ introduce RenderSVGRect.
+
+ Covered by existing tests, no change in behaviour.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * accessibility/AccessibilityRenderObject.cpp:
+ (WebCore::AccessibilityRenderObject::supportsPath const):
+ (WebCore::AccessibilityRenderObject::elementPath const):
+ * rendering/RenderTreeAsText.cpp:
+ (WebCore::write):
+ * rendering/svg/RenderSVGResource.cpp:
+ (WebCore::RenderSVGResource::fillAndStrokePathOrShape const):
+ * rendering/svg/RenderSVGResource.h:
+ (WebCore::RenderSVGResource::postApplyResource):
+ * rendering/svg/RenderSVGResourceFilter.cpp:
+ (WebCore::RenderSVGResourceFilter::postApplyResource):
+ * rendering/svg/RenderSVGResourceFilter.h:
+ * rendering/svg/RenderSVGResourceGradient.cpp:
+ (WebCore::RenderSVGResourceGradient::postApplyResource):
+ * rendering/svg/RenderSVGResourceGradient.h:
+ * rendering/svg/RenderSVGResourcePattern.cpp:
+ (WebCore::RenderSVGResourcePattern::postApplyResource):
+ * rendering/svg/RenderSVGResourcePattern.h:
+ * rendering/svg/RenderSVGResourceSolidColor.cpp:
+ (WebCore::RenderSVGResourceSolidColor::postApplyResource):
+ * rendering/svg/RenderSVGResourceSolidColor.h:
+ * rendering/svg/RenderSVGShape.cpp: Added.
+ (WebCore::RenderSVGShape::RenderSVGShape):
+ (WebCore::RenderSVGShape::updateShapeFromElement):
+ (WebCore::RenderSVGShape::isEmpty const):
+ (WebCore::RenderSVGShape::fillShape const):
+ (WebCore::RenderSVGShape::strokeShape const):
+ (WebCore::RenderSVGShape::shapeDependentStrokeContains):
+ (WebCore::RenderSVGShape::shapeDependentFillContains const):
+ (WebCore::RenderSVGShape::fillContains):
+ (WebCore::RenderSVGShape::strokeContains):
+ (WebCore::RenderSVGShape::layout):
+ (WebCore::RenderSVGShape::nonScalingStrokePath const):
+ (WebCore::RenderSVGShape::setupNonScalingStrokeContext):
+ (WebCore::RenderSVGShape::nonScalingStrokeTransform const):
+ (WebCore::RenderSVGShape::shouldGenerateMarkerPositions const):
+ (WebCore::RenderSVGShape::fillShape):
+ (WebCore::RenderSVGShape::strokeShape):
+ (WebCore::RenderSVGShape::fillStrokeMarkers):
+ (WebCore::RenderSVGShape::paint):
+ (WebCore::RenderSVGShape::isPointInFill):
+ (WebCore::RenderSVGShape::isPointInStroke):
+ (WebCore::RenderSVGShape::getTotalLength const):
+ (WebCore::RenderSVGShape::getPointAtLength const):
+ (WebCore::RenderSVGShape::nodeAtPoint):
+ (WebCore::markerForType):
+ (WebCore::RenderSVGShape::computeMarkerBoundingBox const):
+ (WebCore::RenderSVGShape::calculateObjectBoundingBox const):
+ (WebCore::RenderSVGShape::calculateStrokeBoundingBox const):
+ (WebCore::RenderSVGShape::strokeWidth const):
+ (WebCore::RenderSVGShape::hasSmoothStroke const):
+ (WebCore::RenderSVGShape::drawMarkers):
+ (WebCore::RenderSVGShape::createPath const):
+ (WebCore::RenderSVGShape::processMarkerPositions):
+ (WebCore::RenderSVGShape::styleWillChange):
+ * rendering/svg/RenderSVGShape.h: Added.
+ (WebCore::RenderSVGShape::setNeedsShapeUpdate):
+ (WebCore::RenderSVGShape::hasPath const):
+ (WebCore::RenderSVGShape::path const):
+ (WebCore::RenderSVGShape::clearPath):
+ (WebCore::RenderSVGShape::hasNonScalingStroke const):
+ * rendering/svg/RenderSVGShapeInlines.h: Added.
+ (WebCore::RenderSVGShape::graphicsElement const):
+ * rendering/svg/SVGRenderSupport.cpp:
+ * rendering/svg/SVGRenderTreeAsText.cpp:
+ (WebCore::writeSVGPaintingResource):
+ (WebCore::writeSVGFillPaintingResource):
+ (WebCore::writeSVGStrokePaintingResource):
+ (WebCore::writeStyle):
+ (WebCore::writeSVGGraphicsElement):
+ (WebCore::operator<<):
+ (WebCore::write):
+ * rendering/svg/SVGRenderTreeAsText.h:
+ * svg/SVGAnimateMotionElement.cpp:
+ * svg/SVGGeometryElement.cpp:
+ (WebCore::SVGGeometryElement::getTotalLength const):
+ (WebCore::SVGGeometryElement::getPointAtLength const):
+ (WebCore::SVGGeometryElement::isPointInFill):
+ (WebCore::SVGGeometryElement::isPointInStroke):
+ * svg/SVGLineElement.cpp:
+
2022-01-09 Sam Weinig <[email protected]>
Remove support for Direct2D / FTW
Modified: trunk/Source/WebCore/Sources.txt (287831 => 287832)
--- trunk/Source/WebCore/Sources.txt 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/Sources.txt 2022-01-10 09:47:29 UTC (rev 287832)
@@ -2494,6 +2494,7 @@
rendering/svg/RenderSVGResourceRadialGradient.cpp
rendering/svg/RenderSVGResourceSolidColor.cpp
rendering/svg/RenderSVGRoot.cpp
+rendering/svg/RenderSVGShape.cpp
rendering/svg/RenderSVGTSpan.cpp
rendering/svg/RenderSVGText.cpp
rendering/svg/RenderSVGTextPath.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (287831 => 287832)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2022-01-10 09:47:29 UTC (rev 287832)
@@ -3273,6 +3273,7 @@
A104F24414C71F7A009E2C23 /* CachedSVGDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = A104F24214C71F7A009E2C23 /* CachedSVGDocument.h */; settings = {ATTRIBUTES = (Private, ); }; };
A10BB5851484E3A700B2E87A /* LegacyRenderSVGRect.h in Headers */ = {isa = PBXBuildFile; fileRef = A10BB5831484E3A700B2E87A /* LegacyRenderSVGRect.h */; };
A10BB58B1484E3B300B2E87A /* LegacyRenderSVGShape.h in Headers */ = {isa = PBXBuildFile; fileRef = A10BB5891484E3B300B2E87A /* LegacyRenderSVGShape.h */; };
+ A10BB58B1484E3B300C3F77B /* RenderSVGShape.h in Headers */ = {isa = PBXBuildFile; fileRef = A10BB5891484E3B300C3F77B /* RenderSVGShape.h */; };
A10DBF4718F92317000D70C6 /* LegacyPreviewLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = A10DBF4618F92317000D70C6 /* LegacyPreviewLoaderClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
A10DC76B14747BAB005E2471 /* StyleGridData.h in Headers */ = {isa = PBXBuildFile; fileRef = A10DC76914747BAB005E2471 /* StyleGridData.h */; settings = {ATTRIBUTES = (Private, ); }; };
A10F7C73273100D0008FA9AF /* ModalContainerObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = A10F7C7027310073008FA9AF /* ModalContainerObserver.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -4632,6 +4633,7 @@
CDF747F3270F76CF008FEEEC /* RenderSVGResourceLinearGradientInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF747F2270F76CF008FEEEC /* RenderSVGResourceLinearGradientInlines.h */; };
CDF747F5270F83B1008FEEEC /* RenderSVGGradientStopInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF747F4270F83B1008FEEEC /* RenderSVGGradientStopInlines.h */; };
CDF747F7270F86A4008FEEEC /* LegacyRenderSVGShapeInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF747F6270F86A4008FEEEC /* LegacyRenderSVGShapeInlines.h */; };
+ CDF747F7270F83B4107DEEEC /* RenderSVGShapeInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF747F6270F83B4107DEEEC /* RenderSVGShapeInlines.h */; };
CDF747F9270F87CB008FEEEC /* RenderSVGResourceRadialGradientInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF747F8270F87CB008FEEEC /* RenderSVGResourceRadialGradientInlines.h */; };
CDF747FB270F891A008FEEEC /* RenderSVGResourceMaskerInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF747FA270F891A008FEEEC /* RenderSVGResourceMaskerInlines.h */; };
CDF7483F18FEBCEC0006ECC0 /* GridPositionsResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF7483D18FEBCEC0006ECC0 /* GridPositionsResolver.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -13379,7 +13381,9 @@
A10BB5821484E3A700B2E87A /* LegacyRenderSVGRect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LegacyRenderSVGRect.cpp; sourceTree = "<group>"; };
A10BB5831484E3A700B2E87A /* LegacyRenderSVGRect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LegacyRenderSVGRect.h; sourceTree = "<group>"; };
A10BB5881484E3B300B2E87A /* LegacyRenderSVGShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LegacyRenderSVGShape.cpp; sourceTree = "<group>"; };
+ A10CC5881473E3B300B2A8BF /* RenderSVGShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGShape.cpp; sourceTree = "<group>"; };
A10BB5891484E3B300B2E87A /* LegacyRenderSVGShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LegacyRenderSVGShape.h; sourceTree = "<group>"; };
+ A10BB5891484E3B300C3F77B /* RenderSVGShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGShape.h; sourceTree = "<group>"; };
A10D6E942144C99800FDD14D /* JSPaymentResponseCustom.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSPaymentResponseCustom.cpp; sourceTree = "<group>"; };
A10DBF4618F92317000D70C6 /* LegacyPreviewLoaderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LegacyPreviewLoaderClient.h; sourceTree = "<group>"; };
A10DC76814747BAB005E2471 /* StyleGridData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleGridData.cpp; sourceTree = "<group>"; };
@@ -16280,6 +16284,7 @@
CDF747F2270F76CF008FEEEC /* RenderSVGResourceLinearGradientInlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderSVGResourceLinearGradientInlines.h; sourceTree = "<group>"; };
CDF747F4270F83B1008FEEEC /* RenderSVGGradientStopInlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderSVGGradientStopInlines.h; sourceTree = "<group>"; };
CDF747F6270F86A4008FEEEC /* LegacyRenderSVGShapeInlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LegacyRenderSVGShapeInlines.h; sourceTree = "<group>"; };
+ CDF747F6270F83B4107DEEEC /* RenderSVGShapeInlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderSVGShapeInlines.h; sourceTree = "<group>"; };
CDF747F8270F87CB008FEEEC /* RenderSVGResourceRadialGradientInlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderSVGResourceRadialGradientInlines.h; sourceTree = "<group>"; };
CDF747FA270F891A008FEEEC /* RenderSVGResourceMaskerInlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderSVGResourceMaskerInlines.h; sourceTree = "<group>"; };
CDF7483C18FEBCEC0006ECC0 /* GridPositionsResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GridPositionsResolver.cpp; sourceTree = "<group>"; };
@@ -18972,6 +18977,9 @@
436708A412D9CA4B00044234 /* RenderSVGResourceSolidColor.h */,
436708A512D9CA5C00044234 /* RenderSVGRoot.cpp */,
436708A612D9DB4B00044234 /* RenderSVGRoot.h */,
+ A10CC5881473E3B300B2A8BF /* RenderSVGShape.cpp */,
+ A10BB5891484E3B300C3F77B /* RenderSVGShape.h */,
+ CDF747F6270F83B4107DEEEC /* RenderSVGShapeInlines.h */,
0854B0061255E4E600B9CDD0 /* RenderSVGText.cpp */,
0854B0071255E4E600B9CDD0 /* RenderSVGText.h */,
0854B0081255E4E600B9CDD0 /* RenderSVGTextPath.cpp */,
@@ -36750,6 +36758,8 @@
CDF747F9270F87CB008FEEEC /* RenderSVGResourceRadialGradientInlines.h in Headers */,
436708E312D9CA4B00044234 /* RenderSVGResourceSolidColor.h in Headers */,
436708E512D9DB4B00044234 /* RenderSVGRoot.h in Headers */,
+ A10BB58B1484E3B300C3F77B /* RenderSVGShape.h in Headers */,
+ CDF747F7270F83B4107DEEEC /* RenderSVGShapeInlines.h in Headers */,
0854B0191255E4E600B9CDD0 /* RenderSVGText.h in Headers */,
0854B01B1255E4E600B9CDD0 /* RenderSVGTextPath.h in Headers */,
436708E912D9CA4B00044234 /* RenderSVGTransformableContainer.h in Headers */,
Modified: trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp (287831 => 287832)
--- trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -96,6 +96,7 @@
#include "RenderMathMLBlock.h"
#include "RenderMenuList.h"
#include "RenderSVGRoot.h"
+#include "RenderSVGShape.h"
#include "RenderTableCell.h"
#include "RenderText.h"
#include "RenderTextControl.h"
@@ -910,7 +911,7 @@
bool AccessibilityRenderObject::supportsPath() const
{
- return is<RenderText>(renderer()) || is<LegacyRenderSVGShape>(renderer());
+ return is<RenderText>(renderer()) || (renderer() && renderer()->isSVGShapeOrLegacySVGShape());
}
Path AccessibilityRenderObject::elementPath() const
@@ -960,15 +961,24 @@
if (auto svgRoot = ancestorsOfType<LegacyRenderSVGRoot>(*m_renderer).first()) {
LayoutPoint parentOffset = axObjectCache()->getOrCreate(&*svgRoot)->elementRect().location();
path.transform(AffineTransform().translate(parentOffset.x(), parentOffset.y()));
+ }
+
+ return path;
+ }
+
#if ENABLE(LAYER_BASED_SVG_ENGINE)
- } else if (auto svgRoot = ancestorsOfType<RenderSVGRoot>(*m_renderer).first()) {
+ if (is<RenderSVGShape>(renderer()) && downcast<RenderSVGShape>(*m_renderer).hasPath()) {
+ Path path = downcast<RenderSVGShape>(*m_renderer).path();
+
+ // The SVG path is in terms of the parent's bounding box. The path needs to be offset to frame coordinates.
+ if (auto svgRoot = ancestorsOfType<RenderSVGRoot>(*m_renderer).first()) {
LayoutPoint parentOffset = axObjectCache()->getOrCreate(&*svgRoot)->elementRect().location();
path.transform(AffineTransform().translate(parentOffset.x(), parentOffset.y()));
-#endif
}
return path;
}
+#endif
return Path();
}
Modified: trunk/Source/WebCore/rendering/RenderTreeAsText.cpp (287831 => 287832)
--- trunk/Source/WebCore/rendering/RenderTreeAsText.cpp 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/RenderTreeAsText.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -39,6 +39,7 @@
#include "InlineIteratorTextBox.h"
#include "LegacyInlineTextBox.h"
#include "LegacyRenderSVGRoot.h"
+#include "LegacyRenderSVGShape.h"
#include "Logging.h"
#include "PrintContext.h"
#include "PseudoElement.h"
@@ -64,6 +65,7 @@
#include "RenderSVGPath.h"
#include "RenderSVGResourceContainer.h"
#include "RenderSVGRoot.h"
+#include "RenderSVGShape.h"
#include "RenderSVGText.h"
#include "RenderTableCell.h"
#include "RenderView.h"
@@ -558,6 +560,12 @@
ts << "\n";
};
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ if (is<RenderSVGShape>(o)) {
+ write(ts, downcast<RenderSVGShape>(o), behavior);
+ return;
+ }
+#endif
if (is<LegacyRenderSVGShape>(o)) {
write(ts, downcast<LegacyRenderSVGShape>(o), behavior);
return;
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResource.cpp (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResource.cpp 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResource.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -26,11 +26,13 @@
#include "Frame.h"
#include "FrameView.h"
#include "LegacyRenderSVGRoot.h"
+#include "LegacyRenderSVGShape.h"
#include "RenderSVGResourceClipper.h"
#include "RenderSVGResourceFilter.h"
#include "RenderSVGResourceMasker.h"
#include "RenderSVGResourceSolidColor.h"
#include "RenderSVGRoot.h"
+#include "RenderSVGShape.h"
#include "RenderView.h"
#include "SVGResourceElementClient.h"
#include "SVGResources.h"
@@ -243,4 +245,39 @@
}
}
+void RenderSVGResource::fillAndStrokePathOrShape(GraphicsContext& context, OptionSet<RenderSVGResourceMode> resourceMode, const Path* path, const RenderElement* shape) const
+{
+ if (shape) {
+ ASSERT(shape->isSVGShapeOrLegacySVGShape());
+
+ if (resourceMode.contains(RenderSVGResourceMode::ApplyToFill)) {
+ if (is<LegacyRenderSVGShape>(shape))
+ downcast<LegacyRenderSVGShape>(shape)->fillShape(context);
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ else if (is<RenderSVGShape>(shape))
+ downcast<RenderSVGShape>(shape)->fillShape(context);
+#endif
+ }
+
+ if (resourceMode.contains(RenderSVGResourceMode::ApplyToStroke)) {
+ if (is<LegacyRenderSVGShape>(shape))
+ downcast<LegacyRenderSVGShape>(shape)->strokeShape(context);
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ else if (is<RenderSVGShape>(shape))
+ downcast<RenderSVGShape>(shape)->strokeShape(context);
+#endif
+ }
+
+ return;
+ }
+
+ if (!path)
+ return;
+
+ if (resourceMode.contains(RenderSVGResourceMode::ApplyToFill))
+ context.fillPath(*path);
+ if (resourceMode.contains(RenderSVGResourceMode::ApplyToStroke))
+ context.strokePath(*path);
}
+
+}
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResource.h (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResource.h 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResource.h 2022-01-10 09:47:29 UTC (rev 287832)
@@ -19,8 +19,8 @@
#pragma once
-#include "LegacyRenderSVGShape.h"
#include "RenderStyleConstants.h"
+#include <wtf/OptionSet.h>
#include <wtf/TypeCasts.h>
namespace WebCore {
@@ -47,9 +47,10 @@
class FloatRect;
class GraphicsContext;
class Path;
+class RenderElement;
class RenderObject;
+class RenderSVGResourceSolidColor;
class RenderStyle;
-class RenderSVGResourceSolidColor;
class RenderSVGResource {
public:
@@ -60,7 +61,7 @@
virtual void removeClientFromCache(RenderElement&, bool markForInvalidation = true) = 0;
virtual bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>) = 0;
- virtual void postApplyResource(RenderElement&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>, const Path*, const LegacyRenderSVGShape*) { }
+ virtual void postApplyResource(RenderElement&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>, const Path*, const RenderElement* /* shape */) { }
virtual FloatRect resourceBoundingBox(const RenderObject&) = 0;
virtual RenderSVGResourceType resourceType() const = 0;
@@ -71,6 +72,9 @@
static RenderSVGResourceSolidColor* sharedSolidPaintingResource();
static void markForLayoutAndParentResourceInvalidation(RenderObject&, bool needsLayout = true);
+
+protected:
+ void fillAndStrokePathOrShape(GraphicsContext&, OptionSet<RenderSVGResourceMode>, const Path*, const RenderElement* shape) const;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -172,7 +172,7 @@
return true;
}
-void RenderSVGResourceFilter::postApplyResource(RenderElement& renderer, GraphicsContext*& context, OptionSet<RenderSVGResourceMode> resourceMode, const Path*, const LegacyRenderSVGShape*)
+void RenderSVGResourceFilter::postApplyResource(RenderElement& renderer, GraphicsContext*& context, OptionSet<RenderSVGResourceMode> resourceMode, const Path*, const RenderElement*)
{
ASSERT(context);
ASSERT_UNUSED(resourceMode, !resourceMode);
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h 2022-01-10 09:47:29 UTC (rev 287832)
@@ -69,7 +69,7 @@
void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override;
bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>) override;
- void postApplyResource(RenderElement&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>, const Path*, const LegacyRenderSVGShape*) override;
+ void postApplyResource(RenderElement&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>, const Path*, const RenderElement*) override;
FloatRect resourceBoundingBox(const RenderObject&) override;
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -179,7 +179,7 @@
return true;
}
-void RenderSVGResourceGradient::postApplyResource(RenderElement& renderer, GraphicsContext*& context, OptionSet<RenderSVGResourceMode> resourceMode, const Path* path, const LegacyRenderSVGShape* shape)
+void RenderSVGResourceGradient::postApplyResource(RenderElement& renderer, GraphicsContext*& context, OptionSet<RenderSVGResourceMode> resourceMode, const Path* path, const RenderElement* shape)
{
ASSERT(context);
ASSERT(!resourceMode.isEmpty());
@@ -207,20 +207,8 @@
#else
UNUSED_PARAM(renderer);
#endif
- } else {
- if (resourceMode.contains(RenderSVGResourceMode::ApplyToFill)) {
- if (path)
- context->fillPath(*path);
- else if (shape)
- shape->fillShape(*context);
- }
- if (resourceMode.contains(RenderSVGResourceMode::ApplyToStroke)) {
- if (path)
- context->strokePath(*path);
- else if (shape)
- shape->strokeShape(*context);
- }
- }
+ } else
+ fillAndStrokePathOrShape(*context, resourceMode, path, shape);
context->restore();
}
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h 2022-01-10 09:47:29 UTC (rev 287832)
@@ -40,7 +40,7 @@
void removeClientFromCache(RenderElement&, bool markForInvalidation = true) final;
bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>) final;
- void postApplyResource(RenderElement&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>, const Path*, const LegacyRenderSVGShape*) final;
+ void postApplyResource(RenderElement&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>, const Path*, const RenderElement*) final;
FloatRect resourceBoundingBox(const RenderObject&) final { return FloatRect(); }
protected:
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -201,24 +201,11 @@
return true;
}
-void RenderSVGResourcePattern::postApplyResource(RenderElement&, GraphicsContext*& context, OptionSet<RenderSVGResourceMode> resourceMode, const Path* path, const LegacyRenderSVGShape* shape)
+void RenderSVGResourcePattern::postApplyResource(RenderElement&, GraphicsContext*& context, OptionSet<RenderSVGResourceMode> resourceMode, const Path* path, const RenderElement* shape)
{
ASSERT(context);
ASSERT(!resourceMode.isEmpty());
-
- if (resourceMode.contains(RenderSVGResourceMode::ApplyToFill)) {
- if (path)
- context->fillPath(*path);
- else if (shape)
- shape->fillShape(*context);
- }
- if (resourceMode.contains(RenderSVGResourceMode::ApplyToStroke)) {
- if (path)
- context->strokePath(*path);
- else if (shape)
- shape->strokeShape(*context);
- }
-
+ fillAndStrokePathOrShape(*context, resourceMode, path, shape);
context->restore();
}
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h 2022-01-10 09:47:29 UTC (rev 287832)
@@ -48,7 +48,7 @@
void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override;
bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>) override;
- void postApplyResource(RenderElement&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>, const Path*, const LegacyRenderSVGShape*) override;
+ void postApplyResource(RenderElement&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>, const Path*, const RenderElement*) override;
FloatRect resourceBoundingBox(const RenderObject&) override { return FloatRect(); }
RenderSVGResourceType resourceType() const override { return PatternResourceType; }
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -23,8 +23,10 @@
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
+#include "RenderElement.h"
#include "RenderStyle.h"
#include "RenderView.h"
+#include "SVGRenderSupport.h"
namespace WebCore {
@@ -67,23 +69,11 @@
return true;
}
-void RenderSVGResourceSolidColor::postApplyResource(RenderElement&, GraphicsContext*& context, OptionSet<RenderSVGResourceMode> resourceMode, const Path* path, const LegacyRenderSVGShape* shape)
+void RenderSVGResourceSolidColor::postApplyResource(RenderElement&, GraphicsContext*& context, OptionSet<RenderSVGResourceMode> resourceMode, const Path* path, const RenderElement* shape)
{
ASSERT(context);
ASSERT(!resourceMode.isEmpty());
-
- if (resourceMode.contains(RenderSVGResourceMode::ApplyToFill)) {
- if (path)
- context->fillPath(*path);
- else if (shape)
- shape->fillShape(*context);
- }
- if (resourceMode.contains(RenderSVGResourceMode::ApplyToStroke)) {
- if (path)
- context->strokePath(*path);
- else if (shape)
- shape->strokeShape(*context);
- }
+ fillAndStrokePathOrShape(*context, resourceMode, path, shape);
}
}
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h 2022-01-10 09:47:29 UTC (rev 287832)
@@ -20,10 +20,13 @@
#pragma once
#include "Color.h"
+#include "FloatRect.h"
#include "RenderSVGResource.h"
namespace WebCore {
+class RenderObject;
+
class RenderSVGResourceSolidColor final : public RenderSVGResource {
WTF_MAKE_FAST_ALLOCATED;
public:
@@ -34,7 +37,7 @@
void removeClientFromCache(RenderElement&, bool = true) override { }
bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>) override;
- void postApplyResource(RenderElement&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>, const Path*, const LegacyRenderSVGShape*) override;
+ void postApplyResource(RenderElement&, GraphicsContext*&, OptionSet<RenderSVGResourceMode>, const Path*, const RenderElement*) override;
FloatRect resourceBoundingBox(const RenderObject&) override { return FloatRect(); }
RenderSVGResourceType resourceType() const override { return SolidColorResourceType; }
Added: trunk/Source/WebCore/rendering/svg/RenderSVGShape.cpp (0 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGShape.cpp (rev 0)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGShape.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+ * Copyright (C) 2004, 2005, 2008 Rob Buis <[email protected]>
+ * Copyright (C) 2005, 2007 Eric Seidel <[email protected]>
+ * Copyright (C) 2009 Google, Inc.
+ * Copyright (C) 2009 Dirk Schulze <[email protected]>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) 2009 Jeff Schiller <[email protected]>
+ * Copyright (C) 2011 Renata Hodovan <[email protected]>
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2018 Adobe Systems Incorporated. All rights reserved.
+ * Copyright (C) 2020, 2021, 2022 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "RenderSVGShape.h"
+
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+#include "FloatPoint.h"
+#include "FloatQuad.h"
+#include "GraphicsContext.h"
+#include "HitTestRequest.h"
+#include "HitTestResult.h"
+#include "LayoutRepainter.h"
+#include "PointerEventsHitRules.h"
+#include "RenderSVGResourceMarker.h"
+#include "RenderSVGResourceSolidColor.h"
+#include "RenderSVGShapeInlines.h"
+#include "SVGPathData.h"
+#include "SVGRenderingContext.h"
+#include "SVGResources.h"
+#include "SVGResourcesCache.h"
+#include "SVGURIReference.h"
+#include <wtf/IsoMallocInlines.h>
+#include <wtf/StackStats.h>
+
+namespace WebCore {
+
+WTF_MAKE_ISO_ALLOCATED_IMPL(RenderSVGShape);
+
+RenderSVGShape::RenderSVGShape(SVGGraphicsElement& element, RenderStyle&& style)
+ : RenderSVGModelObject(element, WTFMove(style))
+{
+}
+
+RenderSVGShape::~RenderSVGShape() = default;
+
+void RenderSVGShape::updateShapeFromElement()
+{
+ m_path = createPath();
+ processMarkerPositions();
+
+ m_fillBoundingBox = calculateObjectBoundingBox();
+ m_strokeBoundingBox = calculateStrokeBoundingBox();
+}
+
+bool RenderSVGShape::isEmpty() const
+{
+ // This function should never be called before assigning a new Path to m_path.
+ // But this bug can happen if this renderer was created and its layout was not
+ // done before painting. Assert this did not happen but do not crash.
+ ASSERT(hasPath());
+ return !hasPath() || path().isEmpty();
+}
+
+void RenderSVGShape::fillShape(GraphicsContext& context) const
+{
+ context.fillPath(path());
+}
+
+void RenderSVGShape::strokeShape(GraphicsContext& context) const
+{
+ ASSERT(m_path);
+ Path* usePath = m_path.get();
+
+ if (hasNonScalingStroke())
+ usePath = nonScalingStrokePath(usePath, nonScalingStrokeTransform());
+
+ context.strokePath(*usePath);
+}
+
+bool RenderSVGShape::shapeDependentStrokeContains(const FloatPoint& point, PointCoordinateSpace pointCoordinateSpace)
+{
+ ASSERT(m_path);
+
+ if (hasNonScalingStroke() && pointCoordinateSpace != LocalCoordinateSpace) {
+ AffineTransform nonScalingTransform = nonScalingStrokeTransform();
+ Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform);
+ return usePath->strokeContains(nonScalingTransform.mapPoint(point), [this] (GraphicsContext& context) {
+ SVGRenderSupport::applyStrokeStyleToContext(context, style(), *this);
+ });
+ }
+
+ return m_path->strokeContains(point, [this] (GraphicsContext& context) {
+ SVGRenderSupport::applyStrokeStyleToContext(context, style(), *this);
+ });
+}
+
+bool RenderSVGShape::shapeDependentFillContains(const FloatPoint& point, const WindRule fillRule) const
+{
+ return path().contains(point, fillRule);
+}
+
+bool RenderSVGShape::fillContains(const FloatPoint& point, bool requiresFill, const WindRule fillRule)
+{
+ if (m_fillBoundingBox.isEmpty() || !m_fillBoundingBox.contains(point))
+ return false;
+
+ Color fallbackColor;
+ if (requiresFill && !RenderSVGResource::fillPaintingResource(*this, style(), fallbackColor))
+ return false;
+
+ return shapeDependentFillContains(point, fillRule);
+}
+
+bool RenderSVGShape::strokeContains(const FloatPoint& point, bool requiresStroke)
+{
+ if (strokeBoundingBox().isEmpty() || !strokeBoundingBox().contains(point))
+ return false;
+
+ Color fallbackColor;
+ if (requiresStroke && !RenderSVGResource::strokePaintingResource(*this, style(), fallbackColor))
+ return false;
+
+ return shapeDependentStrokeContains(point);
+}
+
+void RenderSVGShape::layout()
+{
+ StackStats::LayoutCheckPoint layoutCheckPoint;
+
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+ if (m_needsShapeUpdate) {
+ // FIXME: [LBSE] Upstream SVGLengthContext changes
+ // graphicsElement().updateLengthContext();
+ updateShapeFromElement();
+
+ m_needsShapeUpdate = false;
+ setLayoutRect(enclosingLayoutRect(m_fillBoundingBox));
+ }
+
+ // FIXME: [LBSE] Upstream SVGLayerTransformUpdater
+ // SVGRenderSupport::updateLayerTransform(*this);
+
+ // Invalidate all resources of this client if our layout changed.
+ if (everHadLayout() && selfNeedsLayout())
+ SVGResourcesCache::clientLayoutChanged(*this);
+
+ repainter.repaintAfterLayout();
+ clearNeedsLayout();
+}
+
+Path* RenderSVGShape::nonScalingStrokePath(const Path* path, const AffineTransform& strokeTransform) const
+{
+ static NeverDestroyed<Path> tempPath;
+
+ tempPath.get() = *path;
+ tempPath.get().transform(strokeTransform);
+
+ return &tempPath.get();
+}
+
+bool RenderSVGShape::setupNonScalingStrokeContext(AffineTransform& strokeTransform, GraphicsContextStateSaver& stateSaver)
+{
+ std::optional<AffineTransform> inverse = strokeTransform.inverse();
+ if (!inverse)
+ return false;
+
+ stateSaver.save();
+ stateSaver.context()->concatCTM(inverse.value());
+ return true;
+}
+
+AffineTransform RenderSVGShape::nonScalingStrokeTransform() const
+{
+ return graphicsElement().getScreenCTM(SVGLocatable::DisallowStyleUpdate);
+}
+
+bool RenderSVGShape::shouldGenerateMarkerPositions() const
+{
+ if (!style().svgStyle().hasMarkers())
+ return false;
+
+ if (!graphicsElement().supportsMarkers())
+ return false;
+
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this);
+ if (!resources)
+ return false;
+
+ return resources->markerStart() || resources->markerMid() || resources->markerEnd();
+}
+
+void RenderSVGShape::fillShape(const RenderStyle& style, GraphicsContext& originalContext)
+{
+ GraphicsContext* context = &originalContext;
+ Color fallbackColor;
+ if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(*this, style, fallbackColor)) {
+ if (fillPaintingResource->applyResource(*this, style, context, RenderSVGResourceMode::ApplyToFill))
+ fillPaintingResource->postApplyResource(*this, context, RenderSVGResourceMode::ApplyToFill, nullptr, this);
+ else if (fallbackColor.isValid()) {
+ RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
+ fallbackResource->setColor(fallbackColor);
+ if (fallbackResource->applyResource(*this, style, context, RenderSVGResourceMode::ApplyToFill))
+ fallbackResource->postApplyResource(*this, context, RenderSVGResourceMode::ApplyToFill, nullptr, this);
+ }
+ }
+}
+
+void RenderSVGShape::strokeShape(const RenderStyle& style, GraphicsContext& originalContext)
+{
+ GraphicsContext* context = &originalContext;
+ Color fallbackColor;
+ if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(*this, style, fallbackColor)) {
+ if (strokePaintingResource->applyResource(*this, style, context, RenderSVGResourceMode::ApplyToStroke))
+ strokePaintingResource->postApplyResource(*this, context, RenderSVGResourceMode::ApplyToStroke, nullptr, this);
+ else if (fallbackColor.isValid()) {
+ RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
+ fallbackResource->setColor(fallbackColor);
+ if (fallbackResource->applyResource(*this, style, context, RenderSVGResourceMode::ApplyToStroke))
+ fallbackResource->postApplyResource(*this, context, RenderSVGResourceMode::ApplyToStroke, nullptr, this);
+ }
+ }
+}
+
+void RenderSVGShape::strokeShape(GraphicsContext& context)
+{
+ if (!style().hasVisibleStroke())
+ return;
+
+ GraphicsContextStateSaver stateSaver(context, false);
+ if (hasNonScalingStroke()) {
+ AffineTransform nonScalingTransform = nonScalingStrokeTransform();
+ if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
+ return;
+ }
+ strokeShape(style(), context);
+}
+
+void RenderSVGShape::fillStrokeMarkers(PaintInfo& childPaintInfo)
+{
+ auto paintOrder = RenderStyle::paintTypesForPaintOrder(style().paintOrder());
+ for (unsigned i = 0; i < paintOrder.size(); ++i) {
+ switch (paintOrder.at(i)) {
+ case PaintType::Fill:
+ fillShape(style(), childPaintInfo.context());
+ break;
+ case PaintType::Stroke:
+ strokeShape(childPaintInfo.context());
+ break;
+ case PaintType::Markers:
+ if (!m_markerPositions.isEmpty())
+ drawMarkers(childPaintInfo);
+ break;
+ }
+ }
+}
+
+void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+ if (paintInfo.context().paintingDisabled())
+ return;
+
+ // FIXME: [LBSE] Upstream SVGRenderSupport changes
+ // if (!SVGRenderSupport::shouldPaintHiddenRenderer(*this))
+ // return;
+
+ if (!shouldPaintSVGRenderer(paintInfo) || isEmpty())
+ return;
+
+ if (paintInfo.phase == PaintPhase::ClippingMask) {
+ // FIXME: [LBSE] Upstream SVGRenderSupport changes
+ // SVGRenderSupport::paintSVGClippingMask(*this, paintInfo);
+ return;
+ }
+
+ auto adjustedPaintOffset = paintOffset + layoutLocation();
+ if (paintInfo.phase == PaintPhase::Mask) {
+ // FIXME: [LBSE] Upstream SVGRenderSupport changes
+ // SVGRenderSupport::paintSVGMask(*this, paintInfo, adjustedPaintOffset);
+ return;
+ }
+
+ auto visualOverflowRect = visualOverflowRectEquivalent();
+ visualOverflowRect.moveBy(adjustedPaintOffset);
+ if (!visualOverflowRect.intersects(paintInfo.rect))
+ return;
+
+ if (paintInfo.phase == PaintPhase::Outline || paintInfo.phase == PaintPhase::SelfOutline) {
+ // FIXME: [LBSE] Upstream outline painting
+ // paintSVGOutline(paintInfo, adjustedPaintOffset);
+ return;
+ }
+
+ GraphicsContextStateSaver stateSaver(paintInfo.context());
+
+ auto coordinateSystemOriginTranslation = adjustedPaintOffset - flooredLayoutPoint(objectBoundingBox().location());
+ paintInfo.context().translate(coordinateSystemOriginTranslation.width(), coordinateSystemOriginTranslation.height());
+
+ if (style().svgStyle().shapeRendering() == ShapeRendering::CrispEdges)
+ paintInfo.context().setShouldAntialias(false);
+
+ fillStrokeMarkers(paintInfo);
+}
+
+bool RenderSVGShape::isPointInFill(const FloatPoint& point)
+{
+ return shapeDependentFillContains(point, style().svgStyle().fillRule());
+}
+
+bool RenderSVGShape::isPointInStroke(const FloatPoint& point)
+{
+ if (!style().svgStyle().hasStroke())
+ return false;
+
+ return shapeDependentStrokeContains(point, LocalCoordinateSpace);
+}
+
+float RenderSVGShape::getTotalLength() const
+{
+ return hasPath() ? path().length() : createPath()->length();
+}
+
+FloatPoint RenderSVGShape::getPointAtLength(float distance) const
+{
+ return hasPath() ? path().pointAtLength(distance) : createPath()->pointAtLength(distance);
+}
+
+bool RenderSVGShape::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+{
+ if (hitTestAction != HitTestForeground)
+ return false;
+
+ auto adjustedLocation = accumulatedOffset + layoutLocation();
+
+ auto localPoint = locationInContainer.point();
+ auto boundingBoxTopLeftCorner = flooredLayoutPoint(objectBoundingBox().minXMinYCorner());
+ auto coordinateSystemOriginTranslation = boundingBoxTopLeftCorner - adjustedLocation;
+ localPoint.move(coordinateSystemOriginTranslation);
+
+ if (!SVGRenderSupport::pointInClippingArea(*this, localPoint))
+ return false;
+
+ SVGHitTestCycleDetectionScope hitTestScope(*this);
+
+ PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, request, style().pointerEvents());
+ bool isVisible = (style().visibility() == Visibility::Visible);
+ if (isVisible || !hitRules.requireVisible) {
+ const SVGRenderStyle& svgStyle = style().svgStyle();
+ WindRule fillRule = svgStyle.fillRule();
+ if (request.svgClipContent())
+ fillRule = svgStyle.clipRule();
+
+ if (hitRules.canHitStroke && (svgStyle.hasStroke() || !hitRules.requireStroke) && strokeContains(localPoint, hitRules.requireStroke)) {
+ updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
+ if (result.addNodeToListBasedTestResult(nodeForHitTest(), request, locationInContainer, m_strokeBoundingBox) == HitTestProgress::Stop)
+ return true;
+ return false;
+ }
+
+ if ((hitRules.canHitFill && (svgStyle.hasFill() || !hitRules.requireFill) && fillContains(localPoint, hitRules.requireFill, fillRule))
+ || (hitRules.canHitBoundingBox && m_fillBoundingBox.contains(localPoint))) {
+ updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
+ if (result.addNodeToListBasedTestResult(nodeForHitTest(), request, locationInContainer, m_fillBoundingBox) == HitTestProgress::Stop)
+ return true;
+ return false;
+ }
+ }
+
+ return false;
+}
+
+static inline RenderSVGResourceMarker* markerForType(SVGMarkerType type, RenderSVGResourceMarker* markerStart, RenderSVGResourceMarker* markerMid, RenderSVGResourceMarker* markerEnd)
+{
+ switch (type) {
+ case StartMarker:
+ return markerStart;
+ case MidMarker:
+ return markerMid;
+ case EndMarker:
+ return markerEnd;
+ }
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+FloatRect RenderSVGShape::computeMarkerBoundingBox() const
+{
+ if (m_markerPositions.isEmpty())
+ return FloatRect();
+
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this);
+ ASSERT(resources);
+
+ auto* markerStart = resources->markerStart();
+ auto* markerMid = resources->markerMid();
+ auto* markerEnd = resources->markerEnd();
+ if (!markerStart && !markerMid && !markerEnd)
+ return FloatRect();
+
+ FloatRect boundaries;
+ unsigned size = m_markerPositions.size();
+ for (unsigned i = 0; i < size; ++i) {
+ if (RenderSVGResourceMarker* marker = markerForType(m_markerPositions[i].type, markerStart, markerMid, markerEnd))
+ boundaries.unite(marker->markerBoundaries(marker->markerTransformation(m_markerPositions[i].origin, m_markerPositions[i].angle, strokeWidth())));
+ }
+ return boundaries;
+}
+
+FloatRect RenderSVGShape::calculateObjectBoundingBox() const
+{
+ return path().boundingRect();
+}
+
+FloatRect RenderSVGShape::calculateStrokeBoundingBox() const
+{
+ ASSERT(m_path);
+ FloatRect strokeBoundingBox = m_fillBoundingBox;
+
+ if (style().svgStyle().hasStroke()) {
+ if (hasNonScalingStroke()) {
+ AffineTransform nonScalingTransform = nonScalingStrokeTransform();
+ if (std::optional<AffineTransform> inverse = nonScalingTransform.inverse()) {
+ Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform);
+ FloatRect strokeBoundingRect = usePath->strokeBoundingRect(Function<void(GraphicsContext&)> { [this] (GraphicsContext& context) {
+ SVGRenderSupport::applyStrokeStyleToContext(context, style(), *this);
+ } });
+ strokeBoundingRect = inverse.value().mapRect(strokeBoundingRect);
+ strokeBoundingBox.unite(strokeBoundingRect);
+ }
+ } else {
+ strokeBoundingBox.unite(path().strokeBoundingRect(Function<void(GraphicsContext&)> { [this] (GraphicsContext& context) {
+ SVGRenderSupport::applyStrokeStyleToContext(context, style(), *this);
+ } }));
+ }
+ }
+
+ return strokeBoundingBox;
+}
+
+float RenderSVGShape::strokeWidth() const
+{
+ SVGLengthContext lengthContext(&graphicsElement());
+ return lengthContext.valueForLength(style().strokeWidth());
+}
+
+bool RenderSVGShape::hasSmoothStroke() const
+{
+ const SVGRenderStyle& svgStyle = style().svgStyle();
+ return svgStyle.strokeDashArray().isEmpty()
+ && style().strokeMiterLimit() == style().initialStrokeMiterLimit()
+ && style().joinStyle() == style().initialJoinStyle()
+ && style().capStyle() == style().initialCapStyle();
+}
+
+void RenderSVGShape::drawMarkers(PaintInfo&)
+{
+ ASSERT(!m_markerPositions.isEmpty());
+
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this);
+ if (!resources)
+ return;
+
+ auto* markerStart = resources->markerStart();
+ auto* markerMid = resources->markerMid();
+ auto* markerEnd = resources->markerEnd();
+ if (!markerStart && !markerMid && !markerEnd)
+ return;
+
+ float strokeWidth = this->strokeWidth();
+ unsigned size = m_markerPositions.size();
+ for (unsigned i = 0; i < size; ++i) {
+ if (auto* marker = markerForType(m_markerPositions[i].type, markerStart, markerMid, markerEnd)) {
+ UNUSED_PARAM(marker);
+ UNUSED_PARAM(strokeWidth);
+
+ // FIXME: [LBSE] Upstream RenderLayer changes
+ // ASSERT(marker->hasLayer());
+ // GraphicsContextStateSaver stateSaver(paintInfo.context());
+ // auto contentTransform = marker->markerTransformation(m_markerPositions[i].origin, m_markerPositions[i].angle, strokeWidth);
+ // marker->layer()->paintSVGResourceLayer(paintInfo.context(), LayoutRect::infiniteRect(), contentTransform);
+ }
+ }
+}
+
+std::unique_ptr<Path> RenderSVGShape::createPath() const
+{
+ return makeUnique<Path>(pathFromGraphicsElement(&graphicsElement()));
+}
+
+void RenderSVGShape::processMarkerPositions()
+{
+ m_markerPositions.clear();
+
+ if (!shouldGenerateMarkerPositions())
+ return;
+
+ ASSERT(m_path);
+
+ SVGMarkerData markerData(m_markerPositions, SVGResourcesCache::cachedResourcesForRenderer(*this)->markerReverseStart());
+ m_path->apply([&markerData](const PathElement& pathElement) {
+ SVGMarkerData::updateFromPathElement(markerData, pathElement);
+ });
+ markerData.pathIsDone();
+}
+
+void RenderSVGShape::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
+{
+ auto* oldStyle = hasInitializedStyle() ? &style() : nullptr;
+ if (oldStyle) {
+ if (diff == StyleDifference::Layout)
+ setNeedsShapeUpdate();
+ }
+
+ RenderSVGModelObject::styleWillChange(diff, newStyle);
+}
+
+}
+
+#endif // ENABLE(LAYER_BASED_SVG_ENGINE)
Added: trunk/Source/WebCore/rendering/svg/RenderSVGShape.h (0 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGShape.h (rev 0)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGShape.h 2022-01-10 09:47:29 UTC (rev 287832)
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
+ * Copyright (C) 2004, 2005 Rob Buis <[email protected]>
+ * Copyright (C) 2005 Eric Seidel <[email protected]>
+ * Copyright (C) 2006 Apple Inc.
+ * Copyright (C) 2009 Google, Inc.
+ * Copyright (C) 2011 Renata Hodovan <[email protected]>
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2020, 2021, 2022 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+#include "AffineTransform.h"
+#include "FloatRect.h"
+#include "RenderSVGModelObject.h"
+// FIXME: [LBSE] Upstream SVGBoundingBoxComputation
+// #include "SVGBoundingBoxComputation.h"
+#include "SVGGraphicsElement.h"
+#include "SVGMarkerData.h"
+#include <memory>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FloatPoint;
+class GraphicsContextStateSaver;
+class RenderSVGContainer;
+class RenderSVGPath;
+class RenderSVGResource;
+class SVGGraphicsElement;
+
+class RenderSVGShape : public RenderSVGModelObject {
+ WTF_MAKE_ISO_ALLOCATED(RenderSVGShape);
+public:
+ enum PointCoordinateSpace {
+ GlobalCoordinateSpace,
+ LocalCoordinateSpace
+ };
+ RenderSVGShape(SVGGraphicsElement&, RenderStyle&&);
+ virtual ~RenderSVGShape();
+
+ inline SVGGraphicsElement& graphicsElement() const;
+
+ void setNeedsShapeUpdate() { m_needsShapeUpdate = true; }
+
+ virtual void fillShape(GraphicsContext&) const;
+ virtual void strokeShape(GraphicsContext&) const;
+ virtual bool isRenderingDisabled() const = 0;
+
+ bool isPointInFill(const FloatPoint&);
+ bool isPointInStroke(const FloatPoint&);
+
+ float getTotalLength() const;
+ FloatPoint getPointAtLength(float distance) const;
+
+ bool hasPath() const { return m_path.get(); }
+ Path& path() const
+ {
+ ASSERT(m_path);
+ return *m_path;
+ }
+ void clearPath() { m_path = nullptr; }
+
+ FloatRect objectBoundingBox() const final { return m_fillBoundingBox; }
+ FloatRect strokeBoundingBox() const final { return m_strokeBoundingBox; }
+
+ FloatRect repaintRectInLocalCoordinates() const final
+ {
+ // FIXME: [LBSE] Upstream SVGBoundingBoxComputation
+ // return SVGBoundingBoxComputation::computeRepaintBoundingBox(*this); }
+ return FloatRect();
+ }
+
+ FloatRect computeMarkerBoundingBox() const;
+
+protected:
+ void element() const = delete;
+
+ virtual void updateShapeFromElement();
+ virtual bool isEmpty() const;
+ virtual bool shapeDependentStrokeContains(const FloatPoint&, PointCoordinateSpace = GlobalCoordinateSpace);
+ virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
+ float strokeWidth() const;
+ bool hasSmoothStroke() const;
+
+ bool hasNonScalingStroke() const { return style().svgStyle().vectorEffect() == VectorEffect::NonScalingStroke; }
+ AffineTransform nonScalingStrokeTransform() const;
+ Path* nonScalingStrokePath(const Path*, const AffineTransform&) const;
+
+ FloatRect m_fillBoundingBox;
+ FloatRect m_strokeBoundingBox;
+
+private:
+ // Hit-detection separated for the fill and the stroke
+ bool fillContains(const FloatPoint&, bool requiresFill = true, const WindRule fillRule = WindRule::NonZero);
+ bool strokeContains(const FloatPoint&, bool requiresStroke = true);
+
+ bool isSVGShape() const final { return true; }
+ bool canHaveChildren() const final { return false; }
+ const char* renderName() const override { return "RenderSVGShape"; }
+
+ void layout() final;
+ void paint(PaintInfo&, const LayoutPoint&) final;
+
+ bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
+
+ FloatRect calculateObjectBoundingBox() const;
+ FloatRect calculateStrokeBoundingBox() const;
+
+ bool setupNonScalingStrokeContext(AffineTransform&, GraphicsContextStateSaver&);
+
+ bool shouldGenerateMarkerPositions() const;
+
+ std::unique_ptr<Path> createPath() const;
+ void processMarkerPositions();
+
+ void fillShape(const RenderStyle&, GraphicsContext&);
+ void strokeShape(const RenderStyle&, GraphicsContext&);
+ void strokeShape(GraphicsContext&);
+ void fillStrokeMarkers(PaintInfo&);
+ void drawMarkers(PaintInfo&);
+
+ void styleWillChange(StyleDifference, const RenderStyle& newStyle) override;
+
+private:
+ bool m_needsShapeUpdate { true };
+
+ std::unique_ptr<Path> m_path;
+ Vector<MarkerPosition> m_markerPositions;
+};
+
+} // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGShape, isSVGShape())
+
+#endif // ENABLE(LAYER_BASED_SVG_ENGINE)
Added: trunk/Source/WebCore/rendering/svg/RenderSVGShapeInlines.h (0 => 287832)
--- trunk/Source/WebCore/rendering/svg/RenderSVGShapeInlines.h (rev 0)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGShapeInlines.h 2022-01-10 09:47:29 UTC (rev 287832)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "RenderSVGShape.h"
+#include "SVGGraphicsElement.h"
+
+namespace WebCore {
+
+inline SVGGraphicsElement& RenderSVGShape::graphicsElement() const
+{
+ return downcast<SVGGraphicsElement>(RenderSVGModelObject::element());
+}
+
+} // namespace WebCore
+
+#endif // LAYER_BASED_SVG_ENGINE
Modified: trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -29,6 +29,7 @@
#include "ElementAncestorIterator.h"
#include "LegacyRenderSVGRoot.h"
+#include "LegacyRenderSVGShape.h"
#include "NodeRenderStyle.h"
#include "RenderChildIterator.h"
#include "RenderElement.h"
Modified: trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -49,6 +49,7 @@
#include "RenderSVGResourceRadialGradientInlines.h"
#include "RenderSVGResourceSolidColor.h"
#include "RenderSVGRoot.h"
+#include "RenderSVGShapeInlines.h"
#include "RenderSVGText.h"
#include "SVGCircleElement.h"
#include "SVGElementTypeHelpers.h"
@@ -151,27 +152,73 @@
return ts;
}
-static void writeSVGPaintingResource(TextStream& ts, RenderSVGResource* resource)
+static void writeSVGPaintingResource(TextStream& ts, const RenderSVGResource& resource)
{
- if (resource->resourceType() == SolidColorResourceType) {
- ts << "[type=SOLID] [color=" << static_cast<RenderSVGResourceSolidColor*>(resource)->color() << "]";
+ auto resourceType = resource.resourceType();
+ if (resourceType == SolidColorResourceType) {
+ ts << "[type=SOLID] [color=" << downcast<RenderSVGResourceSolidColor>(resource).color() << "]";
return;
}
- // All other resources derive from RenderSVGResourceContainer
- RenderSVGResourceContainer* container = static_cast<RenderSVGResourceContainer*>(resource);
- SVGElement& element = container->element();
-
- if (resource->resourceType() == PatternResourceType)
+ if (resourceType == PatternResourceType)
ts << "[type=PATTERN]";
- else if (resource->resourceType() == LinearGradientResourceType)
+ else if (resourceType == LinearGradientResourceType)
ts << "[type=LINEAR-GRADIENT]";
- else if (resource->resourceType() == RadialGradientResourceType)
+ else if (resourceType == RadialGradientResourceType)
ts << "[type=RADIAL-GRADIENT]";
- ts << " [id=\"" << element.getIdAttribute() << "\"]";
+ // All other resources derive from RenderSVGResourceContainer
+ const auto& container = static_cast<const RenderSVGResourceContainer&>(resource);
+ ts << " [id=\"" << container.element().getIdAttribute() << "\"]";
}
+static void writeSVGFillPaintingResource(TextStream& ts, const RenderElement& renderer, const RenderSVGResource& fillPaintingResource)
+{
+ TextStreamSeparator s(" ");
+ ts << " [fill={" << s;
+ writeSVGPaintingResource(ts, fillPaintingResource);
+
+ const auto& svgStyle = renderer.style().svgStyle();
+ writeIfNotDefault(ts, "opacity", svgStyle.fillOpacity(), 1.0f);
+ writeIfNotDefault(ts, "fill rule", svgStyle.fillRule(), WindRule::NonZero);
+ ts << "}]";
+}
+
+static void writeSVGStrokePaintingResource(TextStream& ts, const RenderElement& renderer, const RenderSVGResource& strokePaintingResource, const SVGGraphicsElement& shape)
+{
+ TextStreamSeparator s(" ");
+ ts << " [stroke={" << s;
+ writeSVGPaintingResource(ts, strokePaintingResource);
+
+ const auto& style = renderer.style();
+ const auto& svgStyle = style.svgStyle();
+
+ SVGLengthContext lengthContext(&shape);
+ double dashOffset = lengthContext.valueForLength(svgStyle.strokeDashOffset());
+ double strokeWidth = lengthContext.valueForLength(style.strokeWidth());
+ const auto& dashes = svgStyle.strokeDashArray();
+
+ DashArray dashArray;
+ for (auto& length : dashes)
+ dashArray.append(length.value(lengthContext));
+
+ writeIfNotDefault(ts, "opacity", svgStyle.strokeOpacity(), 1.0f);
+ writeIfNotDefault(ts, "stroke width", strokeWidth, 1.0);
+ writeIfNotDefault(ts, "miter limit", style.strokeMiterLimit(), 4.0f);
+ writeIfNotDefault(ts, "line cap", style.capStyle(), LineCap::Butt);
+ writeIfNotDefault(ts, "line join", style.joinStyle(), LineJoin::Miter);
+ writeIfNotDefault(ts, "dash offset", dashOffset, 0.0);
+ if (!dashArray.isEmpty())
+ writeNameValuePair(ts, "dash array", dashArray);
+
+ if (is<SVGGeometryElement>(shape)) {
+ double pathLength = downcast<SVGGeometryElement>(shape).pathLength();
+ writeIfNotDefault(ts, "path length", pathLength, 0.0);
+ }
+
+ ts << "}]";
+}
+
static void writeStyle(TextStream& ts, const RenderElement& renderer)
{
const RenderStyle& style = renderer.style();
@@ -181,52 +228,34 @@
writeNameValuePair(ts, "transform", renderer.localTransform());
writeIfNotDefault(ts, "image rendering", style.imageRendering(), RenderStyle::initialImageRendering());
writeIfNotDefault(ts, "opacity", style.opacity(), RenderStyle::initialOpacity());
+
if (is<LegacyRenderSVGShape>(renderer)) {
const auto& shape = downcast<LegacyRenderSVGShape>(renderer);
Color fallbackColor;
- if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<LegacyRenderSVGShape&>(shape), shape.style(), fallbackColor)) {
- TextStreamSeparator s(" ");
- ts << " [stroke={" << s;
- writeSVGPaintingResource(ts, strokePaintingResource);
+ if (auto* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<LegacyRenderSVGShape&>(shape), shape.style(), fallbackColor))
+ writeSVGStrokePaintingResource(ts, renderer, *strokePaintingResource, shape.graphicsElement());
- SVGLengthContext lengthContext(&shape.graphicsElement());
- double dashOffset = lengthContext.valueForLength(svgStyle.strokeDashOffset());
- double strokeWidth = lengthContext.valueForLength(style.strokeWidth());
- const auto& dashes = svgStyle.strokeDashArray();
+ if (auto* fillPaintingResource = RenderSVGResource::fillPaintingResource(const_cast<LegacyRenderSVGShape&>(shape), shape.style(), fallbackColor))
+ writeSVGFillPaintingResource(ts, renderer, *fillPaintingResource);
- DashArray dashArray;
- for (auto& length : dashes)
- dashArray.append(length.value(lengthContext));
+ writeIfNotDefault(ts, "clip rule", svgStyle.clipRule(), WindRule::NonZero);
+ }
- writeIfNotDefault(ts, "opacity", svgStyle.strokeOpacity(), 1.0f);
- writeIfNotDefault(ts, "stroke width", strokeWidth, 1.0);
- writeIfNotDefault(ts, "miter limit", style.strokeMiterLimit(), 4.0f);
- writeIfNotDefault(ts, "line cap", style.capStyle(), LineCap::Butt);
- writeIfNotDefault(ts, "line join", style.joinStyle(), LineJoin::Miter);
- writeIfNotDefault(ts, "dash offset", dashOffset, 0.0);
- if (!dashArray.isEmpty())
- writeNameValuePair(ts, "dash array", dashArray);
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ else if (is<LegacyRenderSVGShape>(renderer)) {
+ const auto& shape = downcast<RenderSVGShape>(renderer);
- if (is<SVGGeometryElement>(shape.graphicsElement())) {
- double pathLength = downcast<SVGGeometryElement>(shape.graphicsElement()).pathLength();
- writeIfNotDefault(ts, "path length", pathLength, 0.0);
- }
+ Color fallbackColor;
+ if (auto* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<RenderSVGShape&>(shape), shape.style(), fallbackColor))
+ writeSVGStrokePaintingResource(ts, renderer, *strokePaintingResource, shape.graphicsElement());
- ts << "}]";
- }
+ if (auto* fillPaintingResource = RenderSVGResource::fillPaintingResource(const_cast<RenderSVGShape&>(shape), shape.style(), fallbackColor))
+ writeSVGFillPaintingResource(ts, renderer, *fillPaintingResource);
- if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(const_cast<LegacyRenderSVGShape&>(shape), shape.style(), fallbackColor)) {
- TextStreamSeparator s(" ");
- ts << " [fill={" << s;
- writeSVGPaintingResource(ts, fillPaintingResource);
-
- writeIfNotDefault(ts, "opacity", svgStyle.fillOpacity(), 1.0f);
- writeIfNotDefault(ts, "fill rule", svgStyle.fillRule(), WindRule::NonZero);
- ts << "}]";
- }
writeIfNotDefault(ts, "clip rule", svgStyle.clipRule(), WindRule::NonZero);
}
+#endif
writeIfNotEmpty(ts, "start marker", svgStyle.markerStartResource());
writeIfNotEmpty(ts, "middle marker", svgStyle.markerMidResource());
@@ -250,11 +279,8 @@
return ts;
}
-static TextStream& operator<<(TextStream& ts, const LegacyRenderSVGShape& shape)
+static void writeSVGGraphicsElement(TextStream& ts, SVGGraphicsElement& svgElement)
{
- writePositionAndStyle(ts, shape);
-
- SVGGraphicsElement& svgElement = shape.graphicsElement();
SVGLengthContext lengthContext(&svgElement);
if (is<SVGRectElement>(svgElement)) {
@@ -291,9 +317,24 @@
writeNameAndQuotedValue(ts, "data", pathString);
} else
ASSERT_NOT_REACHED();
+}
+
+static TextStream& operator<<(TextStream& ts, const LegacyRenderSVGShape& shape)
+{
+ writePositionAndStyle(ts, shape);
+ writeSVGGraphicsElement(ts, shape.graphicsElement());
return ts;
}
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape)
+{
+ writePositionAndStyle(ts, shape);
+ writeSVGGraphicsElement(ts, shape.graphicsElement());
+ return ts;
+}
+#endif
+
static void writeRenderSVGTextBox(TextStream& ts, const RenderSVGText& text)
{
auto* box = downcast<SVGRootInlineBox>(text.firstRootBox());
@@ -551,6 +592,15 @@
writeResources(ts, image, behavior);
}
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+void write(TextStream& ts, const RenderSVGShape& shape, OptionSet<RenderAsTextFlag> behavior)
+{
+ writeStandardPrefix(ts, shape, behavior);
+ ts << shape << "\n";
+ writeResources(ts, shape, behavior);
+}
+#endif
+
void write(TextStream& ts, const LegacyRenderSVGShape& shape, OptionSet<RenderAsTextFlag> behavior)
{
writeStandardPrefix(ts, shape, behavior);
Modified: trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.h (287831 => 287832)
--- trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.h 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.h 2022-01-10 09:47:29 UTC (rev 287832)
@@ -45,15 +45,17 @@
class RenderSVGInlineText;
class RenderSVGResourceContainer;
class RenderSVGRoot;
+class RenderSVGShape;
class RenderSVGText;
class SVGUnitTypes;
// functions used by the main RenderTreeAsText code
void write(WTF::TextStream&, const LegacyRenderSVGRoot&, OptionSet<RenderAsTextFlag>);
+void write(WTF::TextStream&, const LegacyRenderSVGShape&, OptionSet<RenderAsTextFlag>);
#if ENABLE(LAYER_BASED_SVG_ENGINE)
void write(WTF::TextStream&, const RenderSVGRoot&, OptionSet<RenderAsTextFlag>);
+void write(WTF::TextStream&, const RenderSVGShape&, OptionSet<RenderAsTextFlag>);
#endif
-void write(WTF::TextStream&, const LegacyRenderSVGShape&, OptionSet<RenderAsTextFlag>);
void writeSVGGradientStop(WTF::TextStream&, const RenderSVGGradientStop&, OptionSet<RenderAsTextFlag>);
void writeSVGResourceContainer(WTF::TextStream&, const RenderSVGResourceContainer&, OptionSet<RenderAsTextFlag>);
void writeSVGContainer(WTF::TextStream&, const RenderSVGContainer&, OptionSet<RenderAsTextFlag>);
Modified: trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp (287831 => 287832)
--- trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -25,6 +25,7 @@
#include "AffineTransform.h"
#include "ElementIterator.h"
#include "PathTraversalState.h"
+#include "RenderElement.h"
#include "RenderSVGResource.h"
#include "SVGElementTypeHelpers.h"
#include "SVGImageElement.h"
Modified: trunk/Source/WebCore/svg/SVGGeometryElement.cpp (287831 => 287832)
--- trunk/Source/WebCore/svg/SVGGeometryElement.cpp 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/svg/SVGGeometryElement.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -26,6 +26,7 @@
#include "DOMPoint.h"
#include "LegacyRenderSVGShape.h"
#include "RenderSVGResource.h"
+#include "RenderSVGShape.h"
#include "SVGDocumentExtensions.h"
#include "SVGPathUtilities.h"
#include "SVGPoint.h"
@@ -48,11 +49,20 @@
{
document().updateLayoutIgnorePendingStylesheets();
- auto* renderer = downcast<LegacyRenderSVGShape>(this->renderer());
+ auto* renderer = this->renderer();
if (!renderer)
return 0;
- return renderer->getTotalLength();
+ if (is<LegacyRenderSVGShape>(renderer))
+ return downcast<LegacyRenderSVGShape>(renderer)->getTotalLength();
+
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ if (is<RenderSVGShape>(renderer))
+ return downcast<RenderSVGShape>(renderer)->getTotalLength();
+#endif
+
+ ASSERT_NOT_REACHED();
+ return 0;
}
ExceptionOr<Ref<SVGPoint>> SVGGeometryElement::getPointAtLength(float distance) const
@@ -59,17 +69,26 @@
{
document().updateLayoutIgnorePendingStylesheets();
- auto* renderer = downcast<LegacyRenderSVGShape>(this->renderer());
-
+ auto* renderer = this->renderer();
+
// Spec: If current element is a non-rendered element, throw an InvalidStateError.
if (!renderer)
return Exception { InvalidStateError };
-
+
// Spec: Clamp distance to [0, length].
distance = clampTo<float>(distance, 0, getTotalLength());
// Spec: Return a newly created, detached SVGPoint object.
- return SVGPoint::create(renderer->getPointAtLength(distance));
+ if (is<LegacyRenderSVGShape>(renderer))
+ return SVGPoint::create(downcast<LegacyRenderSVGShape>(renderer)->getPointAtLength(distance));
+
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ if (is<RenderSVGShape>(renderer))
+ return SVGPoint::create(downcast<RenderSVGShape>(renderer)->getPointAtLength(distance));
+#endif
+
+ ASSERT_NOT_REACHED();
+ return Exception { InvalidStateError };
}
bool SVGGeometryElement::isPointInFill(DOMPointInit&& pointInit)
@@ -76,12 +95,21 @@
{
document().updateLayoutIgnorePendingStylesheets();
- auto* renderer = downcast<LegacyRenderSVGShape>(this->renderer());
+ auto* renderer = this->renderer();
if (!renderer)
return false;
FloatPoint point {static_cast<float>(pointInit.x), static_cast<float>(pointInit.y)};
- return renderer->isPointInFill(point);
+ if (is<LegacyRenderSVGShape>(renderer))
+ return downcast<LegacyRenderSVGShape>(renderer)->isPointInFill(point);
+
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ if (is<RenderSVGShape>(renderer))
+ return downcast<RenderSVGShape>(renderer)->isPointInFill(point);
+#endif
+
+ ASSERT_NOT_REACHED();
+ return false;
}
bool SVGGeometryElement::isPointInStroke(DOMPointInit&& pointInit)
@@ -88,12 +116,21 @@
{
document().updateLayoutIgnorePendingStylesheets();
- auto* renderer = downcast<LegacyRenderSVGShape>(this->renderer());
+ auto* renderer = this->renderer();
if (!renderer)
return false;
FloatPoint point {static_cast<float>(pointInit.x), static_cast<float>(pointInit.y)};
- return renderer->isPointInStroke(point);
+ if (is<LegacyRenderSVGShape>(renderer))
+ return downcast<LegacyRenderSVGShape>(renderer)->isPointInStroke(point);
+
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ if (is<RenderSVGShape>(renderer))
+ return downcast<RenderSVGShape>(renderer)->isPointInStroke(point);
+#endif
+
+ ASSERT_NOT_REACHED();
+ return false;
}
void SVGGeometryElement::parseAttribute(const QualifiedName& name, const AtomString& value)
Modified: trunk/Source/WebCore/svg/SVGLineElement.cpp (287831 => 287832)
--- trunk/Source/WebCore/svg/SVGLineElement.cpp 2022-01-10 08:45:56 UTC (rev 287831)
+++ trunk/Source/WebCore/svg/SVGLineElement.cpp 2022-01-10 09:47:29 UTC (rev 287832)
@@ -22,6 +22,7 @@
#include "config.h"
#include "SVGLineElement.h"
+#include "LegacyRenderSVGShape.h"
#include "RenderSVGResource.h"
#include "SVGLengthValue.h"
#include <wtf/IsoMallocInlines.h>