summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/svg
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/rendering/svg
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/rendering/svg')
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp78
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGBlock.cpp10
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGBlock.h28
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGContainer.cpp29
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGContainer.h41
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGEllipse.cpp67
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGEllipse.h28
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp79
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGForeignObject.h52
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp25
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGGradientStop.h47
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp8
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGHiddenContainer.h24
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGImage.cpp89
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGImage.h48
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInline.cpp55
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInline.h49
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInlineText.cpp77
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInlineText.h41
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGModelObject.cpp26
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGModelObject.h40
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGPath.cpp58
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGPath.h27
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRect.cpp61
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRect.h26
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResource.cpp74
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResource.h24
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp104
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceClipper.h52
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp69
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceContainer.h46
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp81
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceFilter.h40
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp61
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h19
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp54
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceGradient.h25
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp10
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h26
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp16
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceMarker.h35
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp33
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceMasker.h27
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp111
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourcePattern.h38
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp11
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h26
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp15
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h25
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRoot.cpp247
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRoot.h76
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGShape.cpp144
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGShape.h68
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGTSpan.h20
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGText.cpp155
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGText.h75
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGTextPath.cpp17
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGTextPath.h17
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp22
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h25
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp82
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGViewportContainer.h33
-rw-r--r--Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp89
-rw-r--r--Source/WebCore/rendering/svg/SVGInlineFlowBox.h21
-rw-r--r--Source/WebCore/rendering/svg/SVGInlineTextBox.cpp309
-rw-r--r--Source/WebCore/rendering/svg/SVGInlineTextBox.h55
-rw-r--r--Source/WebCore/rendering/svg/SVGMarkerData.h38
-rw-r--r--Source/WebCore/rendering/svg/SVGPathData.cpp77
-rw-r--r--Source/WebCore/rendering/svg/SVGPathData.h9
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderSupport.cpp285
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderSupport.h25
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp361
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderTreeAsText.h39
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderingContext.cpp232
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderingContext.h28
-rw-r--r--Source/WebCore/rendering/svg/SVGResources.cpp240
-rw-r--r--Source/WebCore/rendering/svg/SVGResources.h76
-rw-r--r--Source/WebCore/rendering/svg/SVGResourcesCache.cpp76
-rw-r--r--Source/WebCore/rendering/svg/SVGResourcesCache.h16
-rw-r--r--Source/WebCore/rendering/svg/SVGResourcesCycleSolver.cpp132
-rw-r--r--Source/WebCore/rendering/svg/SVGResourcesCycleSolver.h9
-rw-r--r--Source/WebCore/rendering/svg/SVGRootInlineBox.cpp126
-rw-r--r--Source/WebCore/rendering/svg/SVGRootInlineBox.h22
-rw-r--r--Source/WebCore/rendering/svg/SVGSubpathData.h67
-rw-r--r--Source/WebCore/rendering/svg/SVGTextChunk.cpp201
-rw-r--r--Source/WebCore/rendering/svg/SVGTextChunk.h32
-rw-r--r--Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp241
-rw-r--r--Source/WebCore/rendering/svg/SVGTextChunkBuilder.h25
-rw-r--r--Source/WebCore/rendering/svg/SVGTextFragment.h7
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp4
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h7
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp87
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h16
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp139
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutEngine.h18
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp40
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.h19
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.cpp54
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.h18
-rw-r--r--Source/WebCore/rendering/svg/SVGTextMetrics.cpp52
-rw-r--r--Source/WebCore/rendering/svg/SVGTextMetrics.h21
-rw-r--r--Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp78
-rw-r--r--Source/WebCore/rendering/svg/SVGTextMetricsBuilder.h17
-rw-r--r--Source/WebCore/rendering/svg/SVGTextQuery.cpp108
-rw-r--r--Source/WebCore/rendering/svg/SVGTextQuery.h20
-rw-r--r--Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp254
-rw-r--r--Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h71
107 files changed, 3055 insertions, 3922 deletions
diff --git a/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp b/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp
new file mode 100644
index 000000000..3cd5c4a3d
--- /dev/null
+++ b/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2009, 2010 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. ``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
+ * 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.
+ */
+
+// This all-in-one cpp file cuts down on template bloat to allow us to build our Windows release build.
+
+#include "RenderSVGBlock.cpp"
+#include "RenderSVGContainer.cpp"
+#include "RenderSVGEllipse.cpp"
+#include "RenderSVGForeignObject.cpp"
+#include "RenderSVGGradientStop.cpp"
+#include "RenderSVGHiddenContainer.cpp"
+#include "RenderSVGImage.cpp"
+#include "RenderSVGInline.cpp"
+#include "RenderSVGInlineText.cpp"
+#include "RenderSVGModelObject.cpp"
+#include "RenderSVGPath.cpp"
+#include "RenderSVGRect.cpp"
+#include "RenderSVGResource.cpp"
+#include "RenderSVGResourceClipper.cpp"
+#include "RenderSVGResourceContainer.cpp"
+#include "RenderSVGResourceFilter.cpp"
+#include "RenderSVGResourceFilterPrimitive.cpp"
+#include "RenderSVGResourceGradient.cpp"
+#include "RenderSVGResourceLinearGradient.cpp"
+#include "RenderSVGResourceMarker.cpp"
+#include "RenderSVGResourceMasker.cpp"
+#include "RenderSVGResourcePattern.cpp"
+#include "RenderSVGResourceRadialGradient.cpp"
+#include "RenderSVGResourceSolidColor.cpp"
+#include "RenderSVGRoot.cpp"
+#include "RenderSVGShape.cpp"
+#include "RenderSVGText.cpp"
+#include "RenderSVGTextPath.cpp"
+#include "RenderSVGTransformableContainer.cpp"
+#include "RenderSVGViewportContainer.cpp"
+#include "SVGInlineFlowBox.cpp"
+#include "SVGInlineTextBox.cpp"
+#include "SVGPathData.cpp"
+#include "SVGRenderSupport.cpp"
+#include "SVGRenderTreeAsText.cpp"
+#include "SVGRenderingContext.cpp"
+#include "SVGResources.cpp"
+#include "SVGResourcesCache.cpp"
+#include "SVGResourcesCycleSolver.cpp"
+#include "SVGRootInlineBox.cpp"
+#include "SVGTextChunk.cpp"
+#include "SVGTextChunkBuilder.cpp"
+#include "SVGTextLayoutAttributes.cpp"
+#include "SVGTextLayoutAttributesBuilder.cpp"
+#include "SVGTextLayoutEngine.cpp"
+#include "SVGTextLayoutEngineBaseline.cpp"
+#include "SVGTextLayoutEngineSpacing.cpp"
+#include "SVGTextMetrics.cpp"
+#include "SVGTextMetricsBuilder.cpp"
+#include "SVGTextQuery.cpp"
+
diff --git a/Source/WebCore/rendering/svg/RenderSVGBlock.cpp b/Source/WebCore/rendering/svg/RenderSVGBlock.cpp
index 953728b01..ab63ecf97 100644
--- a/Source/WebCore/rendering/svg/RenderSVGBlock.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGBlock.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
*
@@ -20,8 +20,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGBlock.h"
#include "RenderSVGResource.h"
@@ -30,8 +28,8 @@
namespace WebCore {
-RenderSVGBlock::RenderSVGBlock(SVGGraphicsElement& element, PassRef<RenderStyle> style)
- : RenderBlockFlow(element, std::move(style))
+RenderSVGBlock::RenderSVGBlock(SVGGraphicsElement& element, RenderStyle&& style)
+ : RenderBlockFlow(element, WTFMove(style))
{
}
@@ -85,5 +83,3 @@ void RenderSVGBlock::styleDidChange(StyleDifference diff, const RenderStyle* old
}
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGBlock.h b/Source/WebCore/rendering/svg/RenderSVGBlock.h
index 23efff55d..c231156ed 100644
--- a/Source/WebCore/rendering/svg/RenderSVGBlock.h
+++ b/Source/WebCore/rendering/svg/RenderSVGBlock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -17,10 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGBlock_h
-#define RenderSVGBlock_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderBlockFlow.h"
#include "SVGGraphicsElement.h"
#include "SVGRenderSupport.h"
@@ -31,26 +29,26 @@ class SVGElement;
class RenderSVGBlock : public RenderBlockFlow {
public:
- virtual LayoutRect visualOverflowRect() const override final;
+ LayoutRect visualOverflowRect() const final;
- SVGGraphicsElement& graphicsElement() const { return toSVGGraphicsElement(nodeForNonAnonymous()); }
+ SVGGraphicsElement& graphicsElement() const { return downcast<SVGGraphicsElement>(nodeForNonAnonymous()); }
protected:
- RenderSVGBlock(SVGGraphicsElement&, PassRef<RenderStyle>);
- virtual void willBeDestroyed() override;
+ RenderSVGBlock(SVGGraphicsElement&, RenderStyle&&);
+ void willBeDestroyed() override;
private:
void element() const = delete;
- virtual void updateFromStyle() override final;
+ void updateFromStyle() final;
- virtual bool isRenderSVGBlock() const override final { return true; };
+ bool isRenderSVGBlock() const final { return true; }
- virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
+ void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const override;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override final;
+ void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final;
};
-}
-#endif
-#endif
+} // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGBlock, isRenderSVGBlock())
diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp
index 71c7bcc00..ccdf24f9c 100644
--- a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp
@@ -22,11 +22,10 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGContainer.h"
#include "GraphicsContext.h"
+#include "HitTestRequest.h"
#include "LayoutRepainter.h"
#include "RenderIterator.h"
#include "RenderSVGResourceFilter.h"
@@ -38,8 +37,8 @@
namespace WebCore {
-RenderSVGContainer::RenderSVGContainer(SVGElement& element, PassRef<RenderStyle> style)
- : RenderSVGModelObject(element, std::move(style))
+RenderSVGContainer::RenderSVGContainer(SVGElement& element, RenderStyle&& style)
+ : RenderSVGModelObject(element, WTFMove(style))
, m_objectBoundingBoxValid(false)
, m_needsBoundariesUpdate(true)
{
@@ -103,13 +102,13 @@ void RenderSVGContainer::removeChild(RenderObject& child)
bool RenderSVGContainer::selfWillPaint()
{
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this);
return resources && resources->filter();
}
void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
- if (paintInfo.context->paintingDisabled())
+ if (paintInfo.context().paintingDisabled())
return;
// Spec: groups w/o children still may render filter content.
@@ -122,7 +121,7 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&)
PaintInfo childPaintInfo(paintInfo);
{
- GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
+ GraphicsContextStateSaver stateSaver(childPaintInfo.context());
// Let the RenderSVGViewportContainer subclass clip if necessary
applyViewportClip(childPaintInfo);
@@ -144,20 +143,20 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&)
}
// FIXME: This really should be drawn from local coordinates, but currently we hack it
- // to avoid our clip killing our outline rect. Thus we translate our
+ // to avoid our clip killing our outline rect. Thus we translate our
// outline rect into parent coords before drawing.
// FIXME: This means our focus ring won't share our rotation like it should.
// We should instead disable our clip during PaintPhaseOutline
- if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style().outlineWidth() && style().visibility() == VISIBLE) {
+ if (paintInfo.phase == PaintPhaseSelfOutline && style().outlineWidth() && style().visibility() == VISIBLE) {
IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRect));
paintOutline(paintInfo, paintRectInParent);
}
}
// addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call
-void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
+void RenderSVGContainer::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
{
- IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates()));
+ LayoutRect paintRectInParent = LayoutRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates()));
if (!paintRectInParent.isEmpty())
rects.append(paintRectInParent);
}
@@ -174,21 +173,21 @@ bool RenderSVGContainer::nodeAtFloatPoint(const HitTestRequest& request, HitTest
if (!pointIsInsideViewportClip(pointInParent))
return false;
- FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
+ FloatPoint localPoint = localToParentTransform().inverse().value_or(AffineTransform()).mapPoint(pointInParent);
if (!SVGRenderSupport::pointInClippingArea(*this, localPoint))
return false;
for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) {
- updateHitTestResult(result, roundedLayoutPoint(localPoint));
+ updateHitTestResult(result, LayoutPoint(localPoint));
return true;
}
}
// Accessibility wants to return SVG containers, if appropriate.
if (request.type() & HitTestRequest::AccessibilityHitTest && m_objectBoundingBox.contains(localPoint)) {
- updateHitTestResult(result, roundedLayoutPoint(localPoint));
+ updateHitTestResult(result, LayoutPoint(localPoint));
return true;
}
@@ -198,5 +197,3 @@ bool RenderSVGContainer::nodeAtFloatPoint(const HitTestRequest& request, HitTest
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.h b/Source/WebCore/rendering/svg/RenderSVGContainer.h
index 78d318e99..bffbfefc5 100644
--- a/Source/WebCore/rendering/svg/RenderSVGContainer.h
+++ b/Source/WebCore/rendering/svg/RenderSVGContainer.h
@@ -20,10 +20,7 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGContainer_h
-#define RenderSVGContainer_h
-
-#if ENABLE(SVG)
+#pragma once
#include "RenderSVGModelObject.h"
@@ -35,31 +32,30 @@ class RenderSVGContainer : public RenderSVGModelObject {
public:
virtual ~RenderSVGContainer();
- virtual void paint(PaintInfo&, const LayoutPoint&) override;
- virtual void setNeedsBoundariesUpdate() override final { m_needsBoundariesUpdate = true; }
- virtual bool needsBoundariesUpdate() override final { return m_needsBoundariesUpdate; }
+ void paint(PaintInfo&, const LayoutPoint&) override;
+ void setNeedsBoundariesUpdate() final { m_needsBoundariesUpdate = true; }
+ bool needsBoundariesUpdate() final { return m_needsBoundariesUpdate; }
virtual bool didTransformToRootUpdate() { return false; }
bool isObjectBoundingBoxValid() const { return m_objectBoundingBoxValid; }
protected:
- RenderSVGContainer(SVGElement&, PassRef<RenderStyle>);
+ RenderSVGContainer(SVGElement&, RenderStyle&&);
- virtual bool isSVGContainer() const override final { return true; }
- virtual const char* renderName() const override { return "RenderSVGContainer"; }
+ const char* renderName() const override { return "RenderSVGContainer"; }
- virtual bool canHaveChildren() const override final { return true; }
+ bool canHaveChildren() const final { return true; }
- virtual void layout() override;
+ void layout() override;
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) override final;
- virtual void removeChild(RenderObject&) override final;
- virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) override final;
+ void addChild(RenderObject* child, RenderObject* beforeChild = 0) final;
+ void removeChild(RenderObject&) final;
+ void addFocusRingRects(Vector<LayoutRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) final;
- virtual FloatRect objectBoundingBox() const override final { return m_objectBoundingBox; }
- virtual FloatRect strokeBoundingBox() const override final { return m_strokeBoundingBox; }
- virtual FloatRect repaintRectInLocalCoordinates() const override final { return m_repaintBoundingBox; }
+ FloatRect objectBoundingBox() const final { return m_objectBoundingBox; }
+ FloatRect strokeBoundingBox() const final { return m_strokeBoundingBox; }
+ FloatRect repaintRectInLocalCoordinates() const final { return m_repaintBoundingBox; }
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override;
+ bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override;
// Allow RenderSVGTransformableContainer to hook in at the right time in layout()
virtual bool calculateLocalTransform() { return false; }
@@ -75,6 +71,8 @@ protected:
void updateCachedBoundaries();
private:
+ bool isSVGContainer() const final { return true; }
+
FloatRect m_objectBoundingBox;
bool m_objectBoundingBoxValid;
FloatRect m_strokeBoundingBox;
@@ -82,9 +80,6 @@ private:
bool m_needsBoundariesUpdate : 1;
};
-RENDER_OBJECT_TYPE_CASTS(RenderSVGContainer, isSVGContainer())
-
} // namespace WebCore
-#endif // ENABLE(SVG)
-#endif // RenderSVGContainer_h
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGContainer, isSVGContainer())
diff --git a/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp b/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp
index dac2e84ff..4b6dd4585 100644
--- a/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp
@@ -25,18 +25,15 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGEllipse.h"
#include "SVGCircleElement.h"
#include "SVGEllipseElement.h"
-#include "SVGNames.h"
namespace WebCore {
-RenderSVGEllipse::RenderSVGEllipse(SVGGraphicsElement& element, PassRef<RenderStyle> style)
- : RenderSVGShape(element, std::move(style))
+RenderSVGEllipse::RenderSVGEllipse(SVGGraphicsElement& element, RenderStyle&& style)
+ : RenderSVGShape(element, WTFMove(style))
, m_usePathFallback(false)
{
}
@@ -54,20 +51,23 @@ void RenderSVGEllipse::updateShapeFromElement()
m_center = FloatPoint();
m_radii = FloatSize();
- // Fallback to RenderSVGShape if shape has a non-scaling stroke.
- if (hasNonScalingStroke()) {
- RenderSVGShape::updateShapeFromElement();
- m_usePathFallback = true;
- return;
- } else
- m_usePathFallback = false;
-
calculateRadiiAndCenter();
- // Spec: "A value of zero disables rendering of the element."
- if (m_radii.width() <= 0 || m_radii.height() <= 0)
+ // Element is invalid if either dimension is negative.
+ if (m_radii.width() < 0 || m_radii.height() < 0)
return;
+ // Spec: "A value of zero disables rendering of the element."
+ if (!m_radii.isEmpty()) {
+ if (hasNonScalingStroke()) {
+ // Fallback to RenderSVGShape if shape has a non-scaling stroke.
+ RenderSVGShape::updateShapeFromElement();
+ m_usePathFallback = true;
+ return;
+ }
+ m_usePathFallback = false;
+ }
+
m_fillBoundingBox = FloatRect(m_center.x() - m_radii.width(), m_center.y() - m_radii.height(), 2 * m_radii.width(), 2 * m_radii.height());
m_strokeBoundingBox = m_fillBoundingBox;
if (style().svgStyle().hasStroke())
@@ -76,41 +76,40 @@ void RenderSVGEllipse::updateShapeFromElement()
void RenderSVGEllipse::calculateRadiiAndCenter()
{
- if (isSVGCircleElement(graphicsElement())) {
- SVGCircleElement& circle = toSVGCircleElement(graphicsElement());
- SVGLengthContext lengthContext(&circle);
- float radius = circle.r().value(lengthContext);
+ SVGLengthContext lengthContext(&graphicsElement());
+ m_center = FloatPoint(
+ lengthContext.valueForLength(style().svgStyle().cx(), LengthModeWidth),
+ lengthContext.valueForLength(style().svgStyle().cy(), LengthModeHeight));
+ if (is<SVGCircleElement>(graphicsElement())) {
+ float radius = lengthContext.valueForLength(style().svgStyle().r());
m_radii = FloatSize(radius, radius);
- m_center = FloatPoint(circle.cx().value(lengthContext), circle.cy().value(lengthContext));
return;
}
- ASSERT(isSVGEllipseElement(graphicsElement()));
- SVGEllipseElement& ellipse = toSVGEllipseElement(graphicsElement());
-
- SVGLengthContext lengthContext(&ellipse);
- m_radii = FloatSize(ellipse.rx().value(lengthContext), ellipse.ry().value(lengthContext));
- m_center = FloatPoint(ellipse.cx().value(lengthContext), ellipse.cy().value(lengthContext));
+ ASSERT(is<SVGEllipseElement>(graphicsElement()));
+ m_radii = FloatSize(
+ lengthContext.valueForLength(style().svgStyle().rx(), LengthModeWidth),
+ lengthContext.valueForLength(style().svgStyle().ry(), LengthModeHeight));
}
-void RenderSVGEllipse::fillShape(GraphicsContext* context) const
+void RenderSVGEllipse::fillShape(GraphicsContext& context) const
{
if (m_usePathFallback) {
RenderSVGShape::fillShape(context);
return;
}
- context->fillEllipse(m_fillBoundingBox);
+ context.fillEllipse(m_fillBoundingBox);
}
-void RenderSVGEllipse::strokeShape(GraphicsContext* context) const
+void RenderSVGEllipse::strokeShape(GraphicsContext& context) const
{
- if (!style().svgStyle().hasVisibleStroke())
+ if (!style().hasVisibleStroke())
return;
if (m_usePathFallback) {
RenderSVGShape::strokeShape(context);
return;
}
- context->strokeEllipse(m_fillBoundingBox);
+ context.strokeEllipse(m_fillBoundingBox);
}
bool RenderSVGEllipse::shapeDependentStrokeContains(const FloatPoint& point)
@@ -152,6 +151,10 @@ bool RenderSVGEllipse::shapeDependentFillContains(const FloatPoint& point, const
return xrX * xrX + yrY * yrY <= 1.0;
}
+bool RenderSVGEllipse::isRenderingDisabled() const
+{
+ // A radius of zero disables rendering of the element, and results in an empty bounding box.
+ return m_fillBoundingBox.isEmpty();
}
-#endif // ENABLE(SVG)
+}
diff --git a/Source/WebCore/rendering/svg/RenderSVGEllipse.h b/Source/WebCore/rendering/svg/RenderSVGEllipse.h
index 4331c1841..a4deb99d8 100644
--- a/Source/WebCore/rendering/svg/RenderSVGEllipse.h
+++ b/Source/WebCore/rendering/svg/RenderSVGEllipse.h
@@ -24,28 +24,27 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef RenderSVGEllipse_h
-#define RenderSVGEllipse_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderSVGShape.h"
namespace WebCore {
class RenderSVGEllipse final : public RenderSVGShape {
public:
- RenderSVGEllipse(SVGGraphicsElement&, PassRef<RenderStyle>);
+ RenderSVGEllipse(SVGGraphicsElement&, RenderStyle&&);
virtual ~RenderSVGEllipse();
private:
- virtual const char* renderName() const { return "RenderSVGEllipse"; }
-
- virtual void updateShapeFromElement();
- virtual bool isEmpty() const { return m_usePathFallback ? RenderSVGShape::isEmpty() : m_fillBoundingBox.isEmpty(); };
- virtual void fillShape(GraphicsContext*) const;
- virtual void strokeShape(GraphicsContext*) const;
- virtual bool shapeDependentStrokeContains(const FloatPoint&);
- virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
+ const char* renderName() const override { return "RenderSVGEllipse"; }
+
+ void updateShapeFromElement() override;
+ bool isEmpty() const override { return m_usePathFallback ? RenderSVGShape::isEmpty() : m_fillBoundingBox.isEmpty(); }
+ bool isRenderingDisabled() const override;
+ void fillShape(GraphicsContext&) const override;
+ void strokeShape(GraphicsContext&) const override;
+ bool shapeDependentStrokeContains(const FloatPoint&) override;
+ bool shapeDependentFillContains(const FloatPoint&, const WindRule) const override;
void calculateRadiiAndCenter();
private:
@@ -54,7 +53,4 @@ private:
bool m_usePathFallback;
};
-}
-
-#endif // ENABLE(SVG)
-#endif
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
index 4ab82952b..b31f0211c 100644
--- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2009 Google, Inc.
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
*
@@ -20,8 +20,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGForeignObject.h"
#include "GraphicsContext.h"
@@ -33,14 +31,13 @@
#include "SVGForeignObjectElement.h"
#include "SVGRenderingContext.h"
#include "SVGResourcesCache.h"
-#include "SVGSVGElement.h"
#include "TransformState.h"
#include <wtf/StackStats.h>
namespace WebCore {
-RenderSVGForeignObject::RenderSVGForeignObject(SVGForeignObjectElement& element, PassRef<RenderStyle> style)
- : RenderSVGBlock(element, std::move(style))
+RenderSVGForeignObject::RenderSVGForeignObject(SVGForeignObjectElement& element, RenderStyle&& style)
+ : RenderSVGBlock(element, WTFMove(style))
, m_needsTransformUpdate(true)
{
}
@@ -51,47 +48,49 @@ RenderSVGForeignObject::~RenderSVGForeignObject()
SVGForeignObjectElement& RenderSVGForeignObject::foreignObjectElement() const
{
- return toSVGForeignObjectElement(RenderSVGBlock::graphicsElement());
+ return downcast<SVGForeignObjectElement>(RenderSVGBlock::graphicsElement());
}
void RenderSVGForeignObject::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
- if (paintInfo.context->paintingDisabled()
- || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
+ if (paintInfo.context().paintingDisabled())
+ return;
+
+ if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection)
return;
PaintInfo childPaintInfo(paintInfo);
- GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
+ GraphicsContextStateSaver stateSaver(childPaintInfo.context());
childPaintInfo.applyTransform(localTransform());
if (SVGRenderSupport::isOverflowHidden(*this))
- childPaintInfo.context->clip(m_viewport);
+ childPaintInfo.context().clip(m_viewport);
SVGRenderingContext renderingContext;
- bool continueRendering = true;
if (paintInfo.phase == PaintPhaseForeground) {
renderingContext.prepareToRenderSVGContent(*this, childPaintInfo);
- continueRendering = renderingContext.isRenderingPrepared();
+ if (!renderingContext.isRenderingPrepared())
+ return;
}
- if (continueRendering) {
- // Paint all phases of FO elements atomically, as though the FO element established its
- // own stacking context.
- bool preservePhase = paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip;
- LayoutPoint childPoint = IntPoint();
- childPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
- RenderBlock::paint(childPaintInfo, IntPoint());
- if (!preservePhase) {
- childPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
- RenderBlock::paint(childPaintInfo, childPoint);
- childPaintInfo.phase = PaintPhaseFloat;
- RenderBlock::paint(childPaintInfo, childPoint);
- childPaintInfo.phase = PaintPhaseForeground;
- RenderBlock::paint(childPaintInfo, childPoint);
- childPaintInfo.phase = PaintPhaseOutline;
- RenderBlock::paint(childPaintInfo, childPoint);
- }
+ LayoutPoint childPoint = IntPoint();
+ if (paintInfo.phase == PaintPhaseSelection) {
+ RenderBlock::paint(childPaintInfo, childPoint);
+ return;
}
+
+ // Paint all phases of FO elements atomically, as though the FO element established its
+ // own stacking context.
+ childPaintInfo.phase = PaintPhaseBlockBackground;
+ RenderBlock::paint(childPaintInfo, childPoint);
+ childPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
+ RenderBlock::paint(childPaintInfo, childPoint);
+ childPaintInfo.phase = PaintPhaseFloat;
+ RenderBlock::paint(childPaintInfo, childPoint);
+ childPaintInfo.phase = PaintPhaseForeground;
+ RenderBlock::paint(childPaintInfo, childPoint);
+ childPaintInfo.phase = PaintPhaseOutline;
+ RenderBlock::paint(childPaintInfo, childPoint);
}
LayoutRect RenderSVGForeignObject::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
@@ -99,9 +98,14 @@ LayoutRect RenderSVGForeignObject::clippedOverflowRectForRepaint(const RenderLay
return SVGRenderSupport::clippedOverflowRectForRepaint(*this, repaintContainer);
}
-void RenderSVGForeignObject::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+FloatRect RenderSVGForeignObject::computeFloatRectForRepaint(const FloatRect& repaintRect, const RenderLayerModelObject* repaintContainer, bool fixed) const
{
- SVGRenderSupport::computeFloatRectForRepaint(*this, repaintContainer, repaintRect, fixed);
+ return SVGRenderSupport::computeFloatRectForRepaint(*this, repaintRect, repaintContainer, fixed);
+}
+
+LayoutRect RenderSVGForeignObject::computeRectForRepaint(const LayoutRect& repaintRect, const RenderLayerModelObject* repaintContainer, RepaintContext context) const
+{
+ return enclosingLayoutRect(computeFloatRectForRepaint(repaintRect, repaintContainer, context.m_hasPositionFixedDescendant));
}
const AffineTransform& RenderSVGForeignObject::localToParentTransform() const
@@ -118,13 +122,12 @@ void RenderSVGForeignObject::updateLogicalWidth()
setWidth(static_cast<int>(roundf(m_viewport.width())));
}
-void RenderSVGForeignObject::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
+RenderBox::LogicalExtentComputedValues RenderSVGForeignObject::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop) const
{
// FIXME: Investigate in size rounding issues
// FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
// FIXME: Is this correct for vertical writing mode?
- computedValues.m_extent = static_cast<int>(roundf(m_viewport.height()));
- computedValues.m_position = logicalTop;
+ return { static_cast<int>(roundf(m_viewport.height())), logicalTop, ComputedMarginValues() };
}
void RenderSVGForeignObject::layout()
@@ -179,14 +182,14 @@ bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, Hit
if (hitTestAction != HitTestForeground)
return false;
- FloatPoint localPoint = localTransform().inverse().mapPoint(pointInParent);
+ FloatPoint localPoint = localTransform().inverse().value_or(AffineTransform()).mapPoint(pointInParent);
// Early exit if local point is not contained in clipped viewport area
if (SVGRenderSupport::isOverflowHidden(*this) && !m_viewport.contains(localPoint))
return false;
// FOs establish a stacking context, so we need to hit-test all layers.
- HitTestLocation hitTestLocation(roundedLayoutPoint(localPoint));
+ HitTestLocation hitTestLocation(localPoint);
return RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestForeground)
|| RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestFloat)
|| RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestChildBlockBackgrounds);
@@ -209,5 +212,3 @@ const RenderObject* RenderSVGForeignObject::pushMappingToContainer(const RenderL
}
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
index b75c373f9..1011353a5 100644
--- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
+++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2009 Google, Inc.
*
* This library is free software; you can redistribute it and/or
@@ -18,10 +18,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGForeignObject_h
-#define RenderSVGForeignObject_h
+#pragma once
-#if ENABLE(SVG)
#include "AffineTransform.h"
#include "FloatPoint.h"
#include "FloatRect.h"
@@ -33,40 +31,41 @@ class SVGForeignObjectElement;
class RenderSVGForeignObject final : public RenderSVGBlock {
public:
- RenderSVGForeignObject(SVGForeignObjectElement&, PassRef<RenderStyle>);
+ RenderSVGForeignObject(SVGForeignObjectElement&, RenderStyle&&);
virtual ~RenderSVGForeignObject();
SVGForeignObjectElement& foreignObjectElement() const;
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ void paint(PaintInfo&, const LayoutPoint&) override;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const override;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const override;
+ LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const override;
+ FloatRect computeFloatRectForRepaint(const FloatRect&, const RenderLayerModelObject* repaintContainer, bool fixed = false) const override;
+ LayoutRect computeRectForRepaint(const LayoutRect&, const RenderLayerModelObject* repaintContainer, RepaintContext = { }) const override;
- virtual bool requiresLayer() const { return false; }
- virtual void layout();
+ bool requiresLayer() const override { return false; }
+ void layout() override;
- virtual FloatRect objectBoundingBox() const { return FloatRect(FloatPoint(), m_viewport.size()); }
- virtual FloatRect strokeBoundingBox() const { return FloatRect(FloatPoint(), m_viewport.size()); }
- virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(FloatPoint(), m_viewport.size()); }
+ FloatRect objectBoundingBox() const override { return FloatRect(FloatPoint(), m_viewport.size()); }
+ FloatRect strokeBoundingBox() const override { return FloatRect(FloatPoint(), m_viewport.size()); }
+ FloatRect repaintRectInLocalCoordinates() const override { return FloatRect(FloatPoint(), m_viewport.size()); }
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
- virtual bool isSVGForeignObject() const { return true; }
+ bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override;
+ bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
- virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const override;
- virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const override;
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+ void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, bool* wasFixed) const override;
+ const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const override;
+ void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; }
private:
+ bool isSVGForeignObject() const override { return true; }
void graphicsElement() const = delete;
- virtual const char* renderName() const override { return "RenderSVGForeignObject"; }
+ const char* renderName() const override { return "RenderSVGForeignObject"; }
- virtual void updateLogicalWidth() override;
- virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const override;
+ void updateLogicalWidth() override;
+ LogicalExtentComputedValues computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop) const override;
- virtual const AffineTransform& localToParentTransform() const;
- virtual AffineTransform localTransform() const { return m_localTransform; }
+ const AffineTransform& localToParentTransform() const override;
+ AffineTransform localTransform() const override { return m_localTransform; }
bool m_needsTransformUpdate : 1;
FloatRect m_viewport;
@@ -74,7 +73,4 @@ private:
mutable AffineTransform m_localToParentTransform;
};
-}
-
-#endif
-#endif
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp b/Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp
index 6e90d6e01..41a159258 100644
--- a/Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp
@@ -18,8 +18,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGGradientStop.h"
#include "RenderSVGResourceContainer.h"
@@ -33,8 +31,8 @@ namespace WebCore {
using namespace SVGNames;
-RenderSVGGradientStop::RenderSVGGradientStop(SVGStopElement& element, PassRef<RenderStyle> style)
- : RenderElement(element, std::move(style), 0)
+RenderSVGGradientStop::RenderSVGGradientStop(SVGStopElement& element, RenderStyle&& style)
+ : RenderElement(element, WTFMove(style), 0)
{
}
@@ -50,17 +48,15 @@ void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderSty
// <stop> elements should only be allowed to make renderers under gradient elements
// but I can imagine a few cases we might not be catching, so let's not crash if our parent isn't a gradient.
- SVGGradientElement* gradient = gradientElement();
+ const auto* gradient = gradientElement();
if (!gradient)
return;
- RenderObject* renderer = gradient->renderer();
+ RenderElement* renderer = gradient->renderer();
if (!renderer)
return;
- ASSERT(renderer->isSVGResourceContainer());
- RenderSVGResourceContainer* container = renderer->toRenderSVGResourceContainer();
- container->removeAllClientsFromCache();
+ downcast<RenderSVGResourceContainer>(*renderer).removeAllClientsFromCache();
}
void RenderSVGGradientStop::layout()
@@ -69,14 +65,11 @@ void RenderSVGGradientStop::layout()
clearNeedsLayout();
}
-SVGGradientElement* RenderSVGGradientStop::gradientElement() const
+SVGGradientElement* RenderSVGGradientStop::gradientElement()
{
- ContainerNode* parentNode = element()->parentNode();
- if (parentNode->hasTagName(linearGradientTag) || parentNode->hasTagName(radialGradientTag))
- return toSVGGradientElement(parentNode);
- return 0;
+ if (is<SVGGradientElement>(element().parentElement()))
+ return downcast<SVGGradientElement>(element().parentElement());
+ return nullptr;
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGGradientStop.h b/Source/WebCore/rendering/svg/RenderSVGGradientStop.h
index 9428bb85a..46ba3d33d 100644
--- a/Source/WebCore/rendering/svg/RenderSVGGradientStop.h
+++ b/Source/WebCore/rendering/svg/RenderSVGGradientStop.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
* Copyright (C) 2009 Google, Inc.
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -18,50 +19,46 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGGradientStop_h
-#define RenderSVGGradientStop_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderElement.h"
+#include "SVGStopElement.h"
namespace WebCore {
class SVGGradientElement;
-class SVGStopElement;
// This class exists mostly so we can hear about gradient stop style changes
class RenderSVGGradientStop final : public RenderElement {
public:
- RenderSVGGradientStop(SVGStopElement&, PassRef<RenderStyle>);
+ RenderSVGGradientStop(SVGStopElement&, RenderStyle&&);
virtual ~RenderSVGGradientStop();
- virtual bool isSVGGradientStop() const { return true; }
- virtual const char* renderName() const { return "RenderSVGGradientStop"; }
+ SVGStopElement& element() const { return downcast<SVGStopElement>(RenderObject::nodeForNonAnonymous()); }
- virtual void layout();
+private:
+ void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
+
+ void layout() override;
- // This overrides are needed to prevent ASSERTs on <svg><stop /></svg>
+ // These overrides are needed to prevent ASSERTs on <svg><stop /></svg>
// RenderObject's default implementations ASSERT_NOT_REACHED()
// https://bugs.webkit.org/show_bug.cgi?id=20400
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject*) const override { return LayoutRect(); }
- virtual FloatRect objectBoundingBox() const { return FloatRect(); }
- virtual FloatRect strokeBoundingBox() const { return FloatRect(); }
- virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); }
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint&, HitTestAction) override { return false; }
+ LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject*) const override { return LayoutRect(); }
+ FloatRect objectBoundingBox() const override { return FloatRect(); }
+ FloatRect strokeBoundingBox() const override { return FloatRect(); }
+ FloatRect repaintRectInLocalCoordinates() const override { return FloatRect(); }
+ bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint&, HitTestAction) override { return false; }
-protected:
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ bool isSVGGradientStop() const override { return true; }
+ const char* renderName() const override { return "RenderSVGGradientStop"; }
-private:
- virtual bool canHaveChildren() const override { return false; }
- virtual void paint(PaintInfo&, const LayoutPoint&) override final { }
+ bool canHaveChildren() const override { return false; }
+ void paint(PaintInfo&, const LayoutPoint&) override { }
- SVGGradientElement* gradientElement() const;
+ SVGGradientElement* gradientElement();
};
-RENDER_OBJECT_TYPE_CASTS(RenderSVGGradientStop, isSVGGradientStop())
-
-}
+} // namespace WebCore
-#endif // ENABLE(SVG)
-#endif // RenderSVGGradientStop_h
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGGradientStop, isSVGGradientStop())
diff --git a/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp
index e874860ca..39487aad8 100644
--- a/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp
@@ -18,8 +18,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGHiddenContainer.h"
#include "RenderSVGPath.h"
@@ -27,8 +25,8 @@
namespace WebCore {
-RenderSVGHiddenContainer::RenderSVGHiddenContainer(SVGElement& element, PassRef<RenderStyle> style)
- : RenderSVGContainer(element, std::move(style))
+RenderSVGHiddenContainer::RenderSVGHiddenContainer(SVGElement& element, RenderStyle&& style)
+ : RenderSVGContainer(element, WTFMove(style))
{
}
@@ -56,5 +54,3 @@ bool RenderSVGHiddenContainer::nodeAtFloatPoint(const HitTestRequest&, HitTestRe
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.h b/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.h
index 44abca36d..236438d5c 100644
--- a/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.h
+++ b/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.h
@@ -17,10 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGHiddenContainer_h
-#define RenderSVGHiddenContainer_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderSVGContainer.h"
namespace WebCore {
@@ -31,23 +29,21 @@ class SVGElement;
// <defs>, <linearGradient>, <radialGradient> are all good examples
class RenderSVGHiddenContainer : public RenderSVGContainer {
public:
- RenderSVGHiddenContainer(SVGElement&, PassRef<RenderStyle>);
+ RenderSVGHiddenContainer(SVGElement&, RenderStyle&&);
protected:
- virtual void layout() override;
+ void layout() override;
private:
- virtual bool isSVGHiddenContainer() const override final { return true; }
- virtual const char* renderName() const override { return "RenderSVGHiddenContainer"; }
+ bool isSVGHiddenContainer() const final { return true; }
+ const char* renderName() const override { return "RenderSVGHiddenContainer"; }
- virtual void paint(PaintInfo&, const LayoutPoint&) override final;
+ void paint(PaintInfo&, const LayoutPoint&) final;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject*) const override final { return LayoutRect(); }
- virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override final;
+ LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject*) const final { return LayoutRect(); }
+ void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const final;
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override final;
+ bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) final;
};
-}
-#endif // ENABLE(SVG)
-#endif // RenderSVGHiddenContainer_h
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/RenderSVGImage.cpp b/Source/WebCore/rendering/svg/RenderSVGImage.cpp
index 58dc14597..cd2386d7a 100644
--- a/Source/WebCore/rendering/svg/RenderSVGImage.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGImage.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Alexander Kellett <lypanov@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) 2007, 2008, 2009 Rob Buis <buis@kde.org>
* Copyright (C) 2009 Google, Inc.
@@ -24,20 +24,17 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGImage.h"
-#include "Attr.h"
#include "FloatQuad.h"
#include "GraphicsContext.h"
#include "LayoutRepainter.h"
#include "PointerEventsHitRules.h"
#include "RenderImageResource.h"
#include "RenderLayer.h"
+#include "RenderSVGResource.h"
#include "RenderSVGResourceFilter.h"
#include "SVGImageElement.h"
-#include "SVGLength.h"
#include "SVGRenderingContext.h"
#include "SVGResources.h"
#include "SVGResourcesCache.h"
@@ -45,8 +42,8 @@
namespace WebCore {
-RenderSVGImage::RenderSVGImage(SVGImageElement& element, PassRef<RenderStyle> style)
- : RenderSVGModelObject(element, std::move(style))
+RenderSVGImage::RenderSVGImage(SVGImageElement& element, RenderStyle&& style)
+ : RenderSVGModelObject(element, WTFMove(style))
, m_needsBoundariesUpdate(true)
, m_needsTransformUpdate(true)
, m_imageResource(std::make_unique<RenderImageResource>())
@@ -56,27 +53,48 @@ RenderSVGImage::RenderSVGImage(SVGImageElement& element, PassRef<RenderStyle> st
RenderSVGImage::~RenderSVGImage()
{
+}
+
+void RenderSVGImage::willBeDestroyed()
+{
imageResource().shutdown();
+ RenderSVGModelObject::willBeDestroyed();
}
SVGImageElement& RenderSVGImage::imageElement() const
{
- return toSVGImageElement(RenderSVGModelObject::element());
+ return downcast<SVGImageElement>(RenderSVGModelObject::element());
}
bool RenderSVGImage::updateImageViewport()
{
FloatRect oldBoundaries = m_objectBoundingBox;
+ bool updatedViewport = false;
SVGLengthContext lengthContext(&imageElement());
m_objectBoundingBox = FloatRect(imageElement().x().value(lengthContext), imageElement().y().value(lengthContext), imageElement().width().value(lengthContext), imageElement().height().value(lengthContext));
- if (oldBoundaries == m_objectBoundingBox)
- return false;
+ // Images with preserveAspectRatio=none should force non-uniform scaling. This can be achieved
+ // by setting the image's container size to its intrinsic size.
+ // See: http://www.w3.org/TR/SVG/single-page.html, 7.8 The ‘preserveAspectRatio’ attribute.
+ if (imageElement().preserveAspectRatio().align() == SVGPreserveAspectRatioValue::SVG_PRESERVEASPECTRATIO_NONE) {
+ if (CachedImage* cachedImage = imageResource().cachedImage()) {
+ LayoutSize intrinsicSize = cachedImage->imageSizeForRenderer(0, style().effectiveZoom());
+ if (intrinsicSize != imageResource().imageSize(style().effectiveZoom())) {
+ imageResource().setContainerSizeForRenderer(roundedIntSize(intrinsicSize));
+ updatedViewport = true;
+ }
+ }
+ }
- imageResource().setContainerSizeForRenderer(enclosingIntRect(m_objectBoundingBox).size());
- m_needsBoundariesUpdate = true;
- return true;
+ if (oldBoundaries != m_objectBoundingBox) {
+ if (!updatedViewport)
+ imageResource().setContainerSizeForRenderer(enclosingIntRect(m_objectBoundingBox).size());
+ updatedViewport = true;
+ m_needsBoundariesUpdate = true;
+ }
+
+ return updatedViewport;
}
void RenderSVGImage::layout()
@@ -117,7 +135,8 @@ void RenderSVGImage::layout()
void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
- if (paintInfo.context->paintingDisabled() || style().visibility() == HIDDEN || !imageResource().hasImage())
+ if (paintInfo.context().paintingDisabled() || paintInfo.phase != PaintPhaseForeground
+ || style().visibility() == HIDDEN || !imageResource().hasImage())
return;
FloatRect boundingBox = repaintRectInLocalCoordinates();
@@ -125,36 +144,36 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&)
return;
PaintInfo childPaintInfo(paintInfo);
- bool drawsOutline = style().outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline);
- if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) {
- GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
- childPaintInfo.applyTransform(m_localTransform);
+ GraphicsContextStateSaver stateSaver(childPaintInfo.context());
+ childPaintInfo.applyTransform(m_localTransform);
- if (childPaintInfo.phase == PaintPhaseForeground) {
- SVGRenderingContext renderingContext(*this, childPaintInfo);
+ if (childPaintInfo.phase == PaintPhaseForeground) {
+ SVGRenderingContext renderingContext(*this, childPaintInfo);
- if (renderingContext.isRenderingPrepared()) {
- if (style().svgStyle().bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_bufferedForeground))
- return;
+ if (renderingContext.isRenderingPrepared()) {
+ if (style().svgStyle().bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_bufferedForeground))
+ return;
- paintForeground(childPaintInfo);
- }
+ paintForeground(childPaintInfo);
}
-
- if (drawsOutline)
- paintOutline(childPaintInfo, IntRect(boundingBox));
}
+
+ if (style().outlineWidth())
+ paintOutline(childPaintInfo, IntRect(boundingBox));
}
void RenderSVGImage::paintForeground(PaintInfo& paintInfo)
{
RefPtr<Image> image = imageResource().image();
+ if (!image)
+ return;
+
FloatRect destRect = m_objectBoundingBox;
FloatRect srcRect(0, 0, image->width(), image->height());
imageElement().preserveAspectRatio().transformRect(destRect, srcRect);
- paintInfo.context->drawImage(image.get(), ColorSpaceDeviceRGB, destRect, srcRect);
+ paintInfo.context().drawImage(*image, destRect, srcRect);
}
void RenderSVGImage::invalidateBufferedForeground()
@@ -171,14 +190,14 @@ bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& request, HitTestResu
PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING, request, style().pointerEvents());
bool isVisible = (style().visibility() == VISIBLE);
if (isVisible || !hitRules.requireVisible) {
- FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
+ FloatPoint localPoint = localToParentTransform().inverse().value_or(AffineTransform()).mapPoint(pointInParent);
if (!SVGRenderSupport::pointInClippingArea(*this, localPoint))
return false;
if (hitRules.canHitFill) {
if (m_objectBoundingBox.contains(localPoint)) {
- updateHitTestResult(result, roundedLayoutPoint(localPoint));
+ updateHitTestResult(result, LayoutPoint(localPoint));
return true;
}
}
@@ -191,7 +210,7 @@ void RenderSVGImage::imageChanged(WrappedImagePtr, const IntRect*)
{
// The image resource defaults to nullImage until the resource arrives.
// This empty image may be cached by SVG resources which must be invalidated.
- if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this))
+ if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this))
resources->removeClientFromCache(*this);
// Eventually notify parent resources, that we've changed.
@@ -207,14 +226,12 @@ void RenderSVGImage::imageChanged(WrappedImagePtr, const IntRect*)
repaint();
}
-void RenderSVGImage::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
+void RenderSVGImage::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
{
// this is called from paint() after the localTransform has already been applied
- IntRect contentRect = enclosingIntRect(repaintRectInLocalCoordinates());
+ LayoutRect contentRect = LayoutRect(repaintRectInLocalCoordinates());
if (!contentRect.isEmpty())
rects.append(contentRect);
}
} // namespace WebCore
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGImage.h b/Source/WebCore/rendering/svg/RenderSVGImage.h
index bb101cdaa..0b688f379 100644
--- a/Source/WebCore/rendering/svg/RenderSVGImage.h
+++ b/Source/WebCore/rendering/svg/RenderSVGImage.h
@@ -21,14 +21,11 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGImage_h
-#define RenderSVGImage_h
+#pragma once
-#if ENABLE(SVG)
#include "AffineTransform.h"
#include "FloatRect.h"
#include "RenderSVGModelObject.h"
-#include "SVGPreserveAspectRatio.h"
namespace WebCore {
@@ -37,15 +34,15 @@ class SVGImageElement;
class RenderSVGImage final : public RenderSVGModelObject {
public:
- RenderSVGImage(SVGImageElement&, PassRef<RenderStyle>);
+ RenderSVGImage(SVGImageElement&, RenderStyle&&);
virtual ~RenderSVGImage();
SVGImageElement& imageElement() const;
bool updateImageViewport();
- virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; }
- virtual bool needsBoundariesUpdate() override { return m_needsBoundariesUpdate; }
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+ void setNeedsBoundariesUpdate() override { m_needsBoundariesUpdate = true; }
+ bool needsBoundariesUpdate() override { return m_needsBoundariesUpdate; }
+ void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; }
RenderImageResource& imageResource() { return *m_imageResource; }
const RenderImageResource& imageResource() const { return *m_imageResource; }
@@ -54,31 +51,33 @@ public:
void paintForeground(PaintInfo&);
private:
+ void willBeDestroyed() override;
+
void element() const = delete;
- virtual const char* renderName() const { return "RenderSVGImage"; }
- virtual bool isSVGImage() const override { return true; }
- virtual bool canHaveChildren() const override { return false; }
+ const char* renderName() const override { return "RenderSVGImage"; }
+ bool isSVGImage() const override { return true; }
+ bool canHaveChildren() const override { return false; }
- virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
+ const AffineTransform& localToParentTransform() const override { return m_localTransform; }
- virtual FloatRect objectBoundingBox() const { return m_objectBoundingBox; }
- virtual FloatRect strokeBoundingBox() const { return m_objectBoundingBox; }
- virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; }
- virtual FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const override { return m_repaintBoundingBoxExcludingShadow; }
+ FloatRect objectBoundingBox() const override { return m_objectBoundingBox; }
+ FloatRect strokeBoundingBox() const override { return m_objectBoundingBox; }
+ FloatRect repaintRectInLocalCoordinates() const override { return m_repaintBoundingBox; }
+ FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const override { return m_repaintBoundingBoxExcludingShadow; }
- virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) override;
+ void addFocusRingRects(Vector<LayoutRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) override;
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+ void imageChanged(WrappedImagePtr, const IntRect* = nullptr) override;
- virtual void layout();
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ void layout() override;
+ void paint(PaintInfo&, const LayoutPoint&) override;
void invalidateBufferedForeground();
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
+ bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override;
- virtual AffineTransform localTransform() const { return m_localTransform; }
+ AffineTransform localTransform() const override { return m_localTransform; }
void calculateImageViewport();
bool m_needsBoundariesUpdate : 1;
@@ -91,9 +90,6 @@ private:
std::unique_ptr<ImageBuffer> m_bufferedForeground;
};
-RENDER_OBJECT_TYPE_CASTS(RenderSVGImage, isSVGImage())
-
} // namespace WebCore
-#endif // ENABLE(SVG)
-#endif // RenderSVGImage_h
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGImage, isSVGImage())
diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.cpp b/Source/WebCore/rendering/svg/RenderSVGInline.cpp
index f1f384e93..71489ad76 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInline.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGInline.cpp
@@ -20,8 +20,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGInline.h"
#include "RenderSVGInlineText.h"
@@ -32,8 +30,8 @@
namespace WebCore {
-RenderSVGInline::RenderSVGInline(SVGGraphicsElement& element, PassRef<RenderStyle> style)
- : RenderInline(element, std::move(style))
+RenderSVGInline::RenderSVGInline(SVGGraphicsElement& element, RenderStyle&& style)
+ : RenderInline(element, WTFMove(style))
{
setAlwaysCreateLineBoxes();
}
@@ -42,29 +40,29 @@ std::unique_ptr<InlineFlowBox> RenderSVGInline::createInlineFlowBox()
{
auto box = std::make_unique<SVGInlineFlowBox>(*this);
box->setHasVirtualLogicalHeight();
- return std::move(box);
+ return WTFMove(box);
}
FloatRect RenderSVGInline::objectBoundingBox() const
{
- if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this))
- return object->objectBoundingBox();
+ if (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this))
+ return textAncestor->objectBoundingBox();
return FloatRect();
}
FloatRect RenderSVGInline::strokeBoundingBox() const
{
- if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this))
- return object->strokeBoundingBox();
+ if (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this))
+ return textAncestor->strokeBoundingBox();
return FloatRect();
}
FloatRect RenderSVGInline::repaintRectInLocalCoordinates() const
{
- if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this))
- return object->repaintRectInLocalCoordinates();
+ if (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this))
+ return textAncestor->repaintRectInLocalCoordinates();
return FloatRect();
}
@@ -74,9 +72,9 @@ LayoutRect RenderSVGInline::clippedOverflowRectForRepaint(const RenderLayerModel
return SVGRenderSupport::clippedOverflowRectForRepaint(*this, repaintContainer);
}
-void RenderSVGInline::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+FloatRect RenderSVGInline::computeFloatRectForRepaint(const FloatRect& repaintRect, const RenderLayerModelObject* repaintContainer, bool fixed) const
{
- SVGRenderSupport::computeFloatRectForRepaint(*this, repaintContainer, repaintRect, fixed);
+ return SVGRenderSupport::computeFloatRectForRepaint(*this, repaintRect, repaintContainer, fixed);
}
void RenderSVGInline::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
@@ -91,13 +89,13 @@ const RenderObject* RenderSVGInline::pushMappingToContainer(const RenderLayerMod
void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
{
- const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this);
- if (!object)
+ auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this);
+ if (!textAncestor)
return;
- FloatRect textBoundingBox = object->strokeBoundingBox();
+ FloatRect textBoundingBox = textAncestor->strokeBoundingBox();
for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox())
- quads.append(localToAbsoluteQuad(FloatRect(textBoundingBox.x() + box->x(), textBoundingBox.y() + box->y(), box->logicalWidth(), box->logicalHeight()), false, wasFixed));
+ quads.append(localToAbsoluteQuad(FloatRect(textBoundingBox.x() + box->x(), textBoundingBox.y() + box->y(), box->logicalWidth(), box->logicalHeight()), UseTransforms, wasFixed));
}
void RenderSVGInline::willBeDestroyed()
@@ -114,30 +112,37 @@ void RenderSVGInline::styleDidChange(StyleDifference diff, const RenderStyle* ol
SVGResourcesCache::clientStyleChanged(*this, diff, style());
}
+void RenderSVGInline::updateFromStyle()
+{
+ RenderInline::updateFromStyle();
+
+ // SVG text layout code expects us to be an inline-level element.
+ setInline(true);
+}
+
void RenderSVGInline::addChild(RenderObject* child, RenderObject* beforeChild)
{
RenderInline::addChild(child, beforeChild);
SVGResourcesCache::clientWasAddedToTree(*child);
- if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
- textRenderer->subtreeChildWasAdded(child);
+ if (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this))
+ textAncestor->subtreeChildWasAdded(child);
}
void RenderSVGInline::removeChild(RenderObject& child)
{
SVGResourcesCache::clientWillBeRemovedFromTree(child);
- RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this);
- if (!textRenderer) {
+ auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this);
+ if (!textAncestor) {
RenderInline::removeChild(child);
return;
}
+
Vector<SVGTextLayoutAttributes*, 2> affectedAttributes;
- textRenderer->subtreeChildWillBeRemoved(&child, affectedAttributes);
+ textAncestor->subtreeChildWillBeRemoved(&child, affectedAttributes);
RenderInline::removeChild(child);
- textRenderer->subtreeChildWasRemoved(affectedAttributes);
+ textAncestor->subtreeChildWasRemoved(affectedAttributes);
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.h b/Source/WebCore/rendering/svg/RenderSVGInline.h
index f6dee80e9..07dd95043 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInline.h
+++ b/Source/WebCore/rendering/svg/RenderSVGInline.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
- * Copyright (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2006 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -18,10 +18,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGInline_h
-#define RenderSVGInline_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderInline.h"
#include "SVGGraphicsElement.h"
@@ -29,42 +27,43 @@ namespace WebCore {
class RenderSVGInline : public RenderInline {
public:
- RenderSVGInline(SVGGraphicsElement&, PassRef<RenderStyle>);
+ RenderSVGInline(SVGGraphicsElement&, RenderStyle&&);
- SVGGraphicsElement& graphicsElement() const { return toSVGGraphicsElement(nodeForNonAnonymous()); }
+ SVGGraphicsElement& graphicsElement() const { return downcast<SVGGraphicsElement>(nodeForNonAnonymous()); }
private:
void element() const = delete;
- virtual const char* renderName() const override { return "RenderSVGInline"; }
- virtual bool requiresLayer() const override final { return false; }
- virtual bool isSVGInline() const override final { return true; }
+ const char* renderName() const override { return "RenderSVGInline"; }
+ bool requiresLayer() const final { return false; }
+ bool isSVGInline() const final { return true; }
+
+ void updateFromStyle() final;
// Chapter 10.4 of the SVG Specification say that we should use the
// object bounding box of the parent text element.
// We search for the root text element and take its bounding box.
// It is also necessary to take the stroke and repaint rect of
// this element, since we need it for filters.
- virtual FloatRect objectBoundingBox() const override final;
- virtual FloatRect strokeBoundingBox() const override final;
- virtual FloatRect repaintRectInLocalCoordinates() const override final;
+ FloatRect objectBoundingBox() const final;
+ FloatRect strokeBoundingBox() const final;
+ FloatRect repaintRectInLocalCoordinates() const final;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const override final;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const override final;
- virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const override final;
- virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const override final;
- virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override final;
+ LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const final;
+ FloatRect computeFloatRectForRepaint(const FloatRect&, const RenderLayerModelObject* repaintContainer, bool fixed = false) const final;
+ void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, bool* wasFixed) const final;
+ const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const final;
+ void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const final;
- virtual std::unique_ptr<InlineFlowBox> createInlineFlowBox() override final;
+ std::unique_ptr<InlineFlowBox> createInlineFlowBox() final;
- virtual void willBeDestroyed() override final;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override final;
+ void willBeDestroyed() final;
+ void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final;
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) override final;
- virtual void removeChild(RenderObject&) override final;
+ void addChild(RenderObject* child, RenderObject* beforeChild = nullptr) final;
+ void removeChild(RenderObject&) final;
};
-}
+} // namespace WebCore
-#endif // ENABLE(SVG)
-#endif // !RenderSVGTSpan_H
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGInline, isSVGInline())
diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
index 0667e8479..5aebea8ab 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
- * Copyright (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) 2008 Rob Buis <buis@kde.org>
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
@@ -22,8 +22,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGInlineText.h"
#include "CSSFontSelector.h"
@@ -32,7 +30,6 @@
#include "RenderBlock.h"
#include "RenderSVGRoot.h"
#include "RenderSVGText.h"
-#include "Settings.h"
#include "SVGInlineTextBox.h"
#include "SVGRenderingContext.h"
#include "SVGRootInlineBox.h"
@@ -79,11 +76,11 @@ String RenderSVGInlineText::originalText() const
return textNode().data();
}
-void RenderSVGInlineText::setTextInternal(const String& text)
+void RenderSVGInlineText::setRenderedText(const String& text)
{
- RenderText::setTextInternal(text);
- if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
- textRenderer->subtreeTextDidChange(this);
+ RenderText::setRenderedText(text);
+ if (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this))
+ textAncestor->subtreeTextDidChange(this);
}
void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
@@ -107,35 +104,35 @@ void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle
return;
// The text metrics may be influenced by style changes.
- if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
- textRenderer->subtreeStyleDidChange(this);
+ if (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this))
+ textAncestor->subtreeStyleDidChange(this);
}
std::unique_ptr<InlineTextBox> RenderSVGInlineText::createTextBox()
{
auto box = std::make_unique<SVGInlineTextBox>(*this);
box->setHasVirtualLogicalHeight();
- return std::move(box);
+ return WTFMove(box);
}
-LayoutRect RenderSVGInlineText::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit*)
+LayoutRect RenderSVGInlineText::localCaretRect(InlineBox* box, unsigned caretOffset, LayoutUnit*)
{
- if (!box || !box->isInlineTextBox())
+ if (!is<InlineTextBox>(box))
return LayoutRect();
- InlineTextBox* textBox = toInlineTextBox(box);
- if (static_cast<unsigned>(caretOffset) < textBox->start() || static_cast<unsigned>(caretOffset) > textBox->start() + textBox->len())
+ auto& textBox = downcast<InlineTextBox>(*box);
+ if (caretOffset < textBox.start() || caretOffset > textBox.start() + textBox.len())
return LayoutRect();
// Use the edge of the selection rect to determine the caret rect.
- if (static_cast<unsigned>(caretOffset) < textBox->start() + textBox->len()) {
- LayoutRect rect = textBox->localSelectionRect(caretOffset, caretOffset + 1);
- LayoutUnit x = box->isLeftToRightDirection() ? rect.x() : rect.maxX();
+ if (caretOffset < textBox.start() + textBox.len()) {
+ LayoutRect rect = textBox.localSelectionRect(caretOffset, caretOffset + 1);
+ LayoutUnit x = textBox.isLeftToRightDirection() ? rect.x() : rect.maxX();
return LayoutRect(x, rect.y(), caretWidth, rect.height());
}
- LayoutRect rect = textBox->localSelectionRect(caretOffset - 1, caretOffset);
- LayoutUnit x = box->isLeftToRightDirection() ? rect.maxX() : rect.x();
+ LayoutRect rect = textBox.localSelectionRect(caretOffset - 1, caretOffset);
+ LayoutUnit x = textBox.isLeftToRightDirection() ? rect.maxX() : rect.x();
return LayoutRect(x, rect.y(), caretWidth, rect.height());
}
@@ -168,7 +165,7 @@ bool RenderSVGInlineText::characterStartsNewTextChunk(int position) const
return it->value.x != SVGTextLayoutAttributes::emptyValue() || it->value.y != SVGTextLayoutAttributes::emptyValue();
}
-VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point)
+VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point, const RenderRegion*)
{
if (!firstTextBox() || !textLength())
return createVisiblePosition(0, DOWNSTREAM);
@@ -184,16 +181,16 @@ VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point)
float closestDistance = std::numeric_limits<float>::max();
float closestDistancePosition = 0;
- const SVGTextFragment* closestDistanceFragment = 0;
- SVGInlineTextBox* closestDistanceBox = 0;
+ const SVGTextFragment* closestDistanceFragment = nullptr;
+ SVGInlineTextBox* closestDistanceBox = nullptr;
AffineTransform fragmentTransform;
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
- if (!box->isSVGInlineTextBox())
+ if (!is<SVGInlineTextBox>(*box))
continue;
- SVGInlineTextBox* textBox = toSVGInlineTextBox(box);
- Vector<SVGTextFragment>& fragments = textBox->textFragments();
+ auto& textBox = downcast<SVGInlineTextBox>(*box);
+ Vector<SVGTextFragment>& fragments = textBox.textFragments();
unsigned textFragmentsSize = fragments.size();
for (unsigned i = 0; i < textFragmentsSize; ++i) {
@@ -208,7 +205,7 @@ VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point)
if (distance < closestDistance) {
closestDistance = distance;
- closestDistanceBox = textBox;
+ closestDistanceBox = &textBox;
closestDistanceFragment = &fragment;
closestDistancePosition = fragmentRect.x();
}
@@ -224,31 +221,31 @@ VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point)
void RenderSVGInlineText::updateScaledFont()
{
- computeNewScaledFontForStyle(this, &style(), m_scalingFactor, m_scaledFont);
+ computeNewScaledFontForStyle(*this, style(), m_scalingFactor, m_scaledFont);
}
-void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, const RenderStyle* style, float& scalingFactor, Font& scaledFont)
+void RenderSVGInlineText::computeNewScaledFontForStyle(const RenderObject& renderer, const RenderStyle& style, float& scalingFactor, FontCascade& scaledFont)
{
- ASSERT(style);
- ASSERT(renderer);
-
// Alter font-size to the right on-screen value to avoid scaling the glyphs themselves, except when GeometricPrecision is specified
scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(renderer);
- if (scalingFactor == 1 || !scalingFactor || style->fontDescription().textRenderingMode() == GeometricPrecision) {
+ if (!scalingFactor || style.fontDescription().textRenderingMode() == GeometricPrecision) {
scalingFactor = 1;
- scaledFont = style->font();
+ scaledFont = style.fontCascade();
return;
}
- FontDescription fontDescription(style->fontDescription());
+ auto fontDescription = style.fontDescription();
// FIXME: We need to better handle the case when we compute very small fonts below (below 1pt).
- fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSizeForSVGInlineText(fontDescription.computedSize(), fontDescription.isAbsoluteSize(), scalingFactor, renderer->document()));
+ fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSizeForSVGInlineText(fontDescription.computedSize(), fontDescription.isAbsoluteSize(), scalingFactor, renderer.document()));
- scaledFont = Font(fontDescription, 0, 0);
- scaledFont.update(renderer->document().ensureStyleResolver().fontSelector());
-}
+ // SVG controls its own glyph orientation, so don't allow writing-mode
+ // to affect it.
+ if (fontDescription.orientation() != FontOrientation::Horizontal)
+ fontDescription.setOrientation(FontOrientation::Horizontal);
+ scaledFont = FontCascade(fontDescription, 0, 0);
+ scaledFont.update(&renderer.document().fontSelector());
}
-#endif // ENABLE(SVG)
+}
diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.h b/Source/WebCore/rendering/svg/RenderSVGInlineText.h
index c07228e21..1973d589e 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInlineText.h
+++ b/Source/WebCore/rendering/svg/RenderSVGInlineText.h
@@ -19,11 +19,9 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGInlineText_h
-#define RenderSVGInlineText_h
+#pragma once
-#if ENABLE(SVG)
-#include "Font.h"
+#include "FontCascade.h"
#include "RenderText.h"
#include "SVGTextLayoutAttributes.h"
#include "Text.h"
@@ -36,43 +34,40 @@ class RenderSVGInlineText final : public RenderText {
public:
RenderSVGInlineText(Text&, const String&);
- Text& textNode() const { return toText(nodeForNonAnonymous()); }
+ Text& textNode() const { return downcast<Text>(nodeForNonAnonymous()); }
bool characterStartsNewTextChunk(int position) const;
SVGTextLayoutAttributes* layoutAttributes() { return &m_layoutAttributes; }
float scalingFactor() const { return m_scalingFactor; }
- const Font& scaledFont() const { return m_scaledFont; }
+ const FontCascade& scaledFont() const { return m_scaledFont; }
void updateScaledFont();
- static void computeNewScaledFontForStyle(RenderObject*, const RenderStyle*, float& scalingFactor, Font& scaledFont);
+ static void computeNewScaledFontForStyle(const RenderObject&, const RenderStyle&, float& scalingFactor, FontCascade& scaledFont);
// Preserves floating point precision for the use in DRT. It knows how to round and does a better job than enclosingIntRect.
FloatRect floatLinesBoundingBox() const;
private:
- virtual const char* renderName() const override { return "RenderSVGInlineText"; }
+ const char* renderName() const override { return "RenderSVGInlineText"; }
- virtual String originalText() const override;
- virtual void setTextInternal(const String&) override;
- virtual void styleDidChange(StyleDifference, const RenderStyle*) override;
+ String originalText() const override;
+ void setRenderedText(const String&) override;
+ void styleDidChange(StyleDifference, const RenderStyle*) override;
- virtual FloatRect objectBoundingBox() const override { return floatLinesBoundingBox(); }
+ FloatRect objectBoundingBox() const override { return floatLinesBoundingBox(); }
- virtual bool isSVGInlineText() const override { return true; }
+ bool isSVGInlineText() const override { return true; }
- virtual VisiblePosition positionForPoint(const LayoutPoint&) override;
- virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0) override;
- virtual IntRect linesBoundingBox() const override;
- virtual std::unique_ptr<InlineTextBox> createTextBox() override;
+ VisiblePosition positionForPoint(const LayoutPoint&, const RenderRegion*) override;
+ LayoutRect localCaretRect(InlineBox*, unsigned caretOffset, LayoutUnit* extraWidthToEndOfLine = 0) override;
+ IntRect linesBoundingBox() const override;
+ std::unique_ptr<InlineTextBox> createTextBox() override;
float m_scalingFactor;
- Font m_scaledFont;
+ FontCascade m_scaledFont;
SVGTextLayoutAttributes m_layoutAttributes;
};
-RENDER_OBJECT_TYPE_CASTS(RenderSVGInlineText, isSVGInlineText())
+} // namespace WebCore
-}
-
-#endif // ENABLE(SVG)
-#endif // RenderSVGInlineText_h
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGInlineText, isSVGInlineText())
diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
index 78768eafe..e64cafa4d 100644
--- a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
@@ -29,8 +29,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGModelObject.h"
#include "RenderLayerModelObject.h"
@@ -41,8 +39,8 @@
namespace WebCore {
-RenderSVGModelObject::RenderSVGModelObject(SVGElement& element, PassRef<RenderStyle> style)
- : RenderElement(element, std::move(style), 0)
+RenderSVGModelObject::RenderSVGModelObject(SVGElement& element, RenderStyle&& style)
+ : RenderElement(element, WTFMove(style), 0)
, m_hasSVGShadow(false)
{
}
@@ -52,9 +50,9 @@ LayoutRect RenderSVGModelObject::clippedOverflowRectForRepaint(const RenderLayer
return SVGRenderSupport::clippedOverflowRectForRepaint(*this, repaintContainer);
}
-void RenderSVGModelObject::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+FloatRect RenderSVGModelObject::computeFloatRectForRepaint(const FloatRect& repaintRect, const RenderLayerModelObject* repaintContainer, bool fixed) const
{
- SVGRenderSupport::computeFloatRectForRepaint(*this, repaintContainer, repaintRect, fixed);
+ return SVGRenderSupport::computeFloatRectForRepaint(*this, repaintRect, repaintContainer, fixed);
}
void RenderSVGModelObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
@@ -76,7 +74,7 @@ LayoutRect RenderSVGModelObject::outlineBoundsForRepaint(const RenderLayerModelO
adjustRectForOutlineAndShadow(box);
FloatQuad containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
- return containerRelativeQuad.enclosingBoundingBox();
+ return LayoutRect(snapRectToDevicePixels(LayoutRect(containerRelativeQuad.boundingBox()), document().deviceScaleFactor()));
}
void RenderSVGModelObject::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
@@ -88,7 +86,7 @@ void RenderSVGModelObject::absoluteRects(Vector<IntRect>& rects, const LayoutPoi
void RenderSVGModelObject::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
{
- quads.append(localToAbsoluteQuad(strokeBoundingBox(), 0 /* mode */, wasFixed));
+ quads.append(localToAbsoluteQuad(strokeBoundingBox(), UseTransforms, wasFixed));
}
void RenderSVGModelObject::willBeDestroyed()
@@ -126,11 +124,11 @@ static void getElementCTM(SVGElement* element, AffineTransform& transform)
Node* current = element;
while (current && current->isSVGElement()) {
- SVGElement* currentElement = toSVGElement(current);
- localTransform = currentElement->renderer()->localToParentTransform();
+ SVGElement& currentElement = downcast<SVGElement>(*current);
+ localTransform = currentElement.renderer()->localToParentTransform();
transform = localTransform.multiply(transform);
// For getCTM() computation, stop at the nearest viewport element
- if (currentElement == stopAtElement)
+ if (&currentElement == stopAtElement)
break;
current = current->parentOrShadowHostNode();
@@ -173,7 +171,7 @@ bool RenderSVGModelObject::checkIntersection(RenderElement* renderer, const Floa
if (!isGraphicsElement(*renderer))
return false;
AffineTransform ctm;
- SVGElement* svgElement = toSVGElement(renderer->element());
+ SVGElement* svgElement = downcast<SVGElement>(renderer->element());
getElementCTM(svgElement, ctm);
ASSERT(svgElement->renderer());
return intersectsAllowingEmpty(rect, ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates()));
@@ -186,12 +184,10 @@ bool RenderSVGModelObject::checkEnclosure(RenderElement* renderer, const FloatRe
if (!isGraphicsElement(*renderer))
return false;
AffineTransform ctm;
- SVGElement* svgElement = toSVGElement(renderer->element());
+ SVGElement* svgElement = downcast<SVGElement>(renderer->element());
getElementCTM(svgElement, ctm);
ASSERT(svgElement->renderer());
return rect.contains(ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates()));
}
} // namespace WebCore
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.h b/Source/WebCore/rendering/svg/RenderSVGModelObject.h
index a7cd417aa..d396becff 100644
--- a/Source/WebCore/rendering/svg/RenderSVGModelObject.h
+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.h
@@ -28,10 +28,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef RenderSVGModelObject_h
-#define RenderSVGModelObject_h
-
-#if ENABLE(SVG)
+#pragma once
#include "RenderElement.h"
#include "SVGElement.h"
@@ -48,16 +45,16 @@ class SVGElement;
class RenderSVGModelObject : public RenderElement {
public:
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const override;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const override final;
- virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const override final;
+ LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const override;
+ FloatRect computeFloatRectForRepaint(const FloatRect&, const RenderLayerModelObject* repaintContainer, bool fixed = false) const final;
+ LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const final;
- virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const override final;
- virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override;
+ void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const final;
+ void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override;
- virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const override final;
- virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const override final;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
+ void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, bool* wasFixed) const final;
+ const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const final;
+ void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
static bool checkIntersection(RenderElement*, const FloatRect&);
static bool checkEnclosure(RenderElement*, const FloatRect&);
@@ -66,25 +63,22 @@ public:
bool hasSVGShadow() const { return m_hasSVGShadow; }
void setHasSVGShadow(bool hasShadow) { m_hasSVGShadow = hasShadow; }
- SVGElement& element() const { return toSVGElement(nodeForNonAnonymous()); }
+ SVGElement& element() const { return downcast<SVGElement>(nodeForNonAnonymous()); }
protected:
- RenderSVGModelObject(SVGElement&, PassRef<RenderStyle>);
+ RenderSVGModelObject(SVGElement&, RenderStyle&&);
- virtual void willBeDestroyed() override;
+ void willBeDestroyed() override;
private:
- virtual bool isRenderSVGModelObject() const override final { return true; }
+ bool isRenderSVGModelObject() const final { return true; }
// This method should never be called, SVG uses a different nodeAtPoint method
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
- virtual void absoluteFocusRingQuads(Vector<FloatQuad>&) override final;
+ bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
+ void absoluteFocusRingQuads(Vector<FloatQuad>&) final;
bool m_hasSVGShadow;
};
-RENDER_OBJECT_TYPE_CASTS(RenderSVGModelObject, isRenderSVGModelObject());
-
-}
+} // namespace WebCore
-#endif // ENABLE(SVG)
-#endif
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGModelObject, isRenderSVGModelObject())
diff --git a/Source/WebCore/rendering/svg/RenderSVGPath.cpp b/Source/WebCore/rendering/svg/RenderSVGPath.cpp
index 353dd238c..208f11f8c 100644
--- a/Source/WebCore/rendering/svg/RenderSVGPath.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGPath.cpp
@@ -26,8 +26,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGPath.h"
#include "SVGPathElement.h"
@@ -35,8 +33,8 @@
namespace WebCore {
-RenderSVGPath::RenderSVGPath(SVGGraphicsElement& element, PassRef<RenderStyle> style)
- : RenderSVGShape(element, std::move(style))
+RenderSVGPath::RenderSVGPath(SVGGraphicsElement& element, RenderStyle&& style)
+ : RenderSVGShape(element, WTFMove(style))
{
}
@@ -66,19 +64,19 @@ FloatRect RenderSVGPath::calculateUpdatedStrokeBoundingBox() const
return strokeBoundingBox;
}
-static void useStrokeStyleToFill(GraphicsContext* context)
+static void useStrokeStyleToFill(GraphicsContext& context)
{
- if (Gradient* gradient = context->strokeGradient())
- context->setFillGradient(gradient);
- else if (Pattern* pattern = context->strokePattern())
- context->setFillPattern(pattern);
+ if (Gradient* gradient = context.strokeGradient())
+ context.setFillGradient(*gradient);
+ else if (Pattern* pattern = context.strokePattern())
+ context.setFillPattern(*pattern);
else
- context->setFillColor(context->strokeColor(), context->strokeColorSpace());
+ context.setFillColor(context.strokeColor());
}
-void RenderSVGPath::strokeShape(GraphicsContext* context) const
+void RenderSVGPath::strokeShape(GraphicsContext& context) const
{
- if (!style().svgStyle().hasVisibleStroke())
+ if (!style().hasVisibleStroke())
return;
RenderSVGShape::strokeShape(context);
@@ -92,13 +90,13 @@ void RenderSVGPath::strokeShape(GraphicsContext* context) const
if (hasNonScalingStroke())
nonScalingTransform = nonScalingStrokeTransform();
- GraphicsContextStateSaver stateSaver(*context, true);
+ GraphicsContextStateSaver stateSaver(context, true);
useStrokeStyleToFill(context);
for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) {
usePath = zeroLengthLinecapPath(m_zeroLengthLinecapLocations[i]);
if (hasNonScalingStroke())
usePath = nonScalingStrokePath(usePath, nonScalingTransform);
- context->fillPath(*usePath);
+ context.fillPath(*usePath);
}
}
@@ -107,15 +105,14 @@ bool RenderSVGPath::shapeDependentStrokeContains(const FloatPoint& point)
if (RenderSVGShape::shapeDependentStrokeContains(point))
return true;
- const SVGRenderStyle& svgStyle = style().svgStyle();
for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) {
- ASSERT(svgStyle.hasStroke());
+ ASSERT(style().svgStyle().hasStroke());
float strokeWidth = this->strokeWidth();
- if (svgStyle.capStyle() == SquareCap) {
+ if (style().capStyle() == SquareCap) {
if (zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeWidth).contains(point))
return true;
} else {
- ASSERT(svgStyle.capStyle() == RoundCap);
+ ASSERT(style().capStyle() == RoundCap);
FloatPoint radiusVector(point.x() - m_zeroLengthLinecapLocations[i].x(), point.y() - m_zeroLengthLinecapLocations[i].y());
if (radiusVector.lengthSquared() < strokeWidth * strokeWidth * .25f)
return true;
@@ -128,20 +125,20 @@ bool RenderSVGPath::shouldStrokeZeroLengthSubpath() const
{
// Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-linecap" property has a value of butt
// but shall be stroked if the "stroke-linecap" property has a value of round or square
- return style().svgStyle().hasStroke() && style().svgStyle().capStyle() != ButtCap;
+ return style().svgStyle().hasStroke() && style().capStyle() != ButtCap;
}
Path* RenderSVGPath::zeroLengthLinecapPath(const FloatPoint& linecapPosition) const
{
- DEFINE_STATIC_LOCAL(Path, tempPath, ());
+ static NeverDestroyed<Path> tempPath;
- tempPath.clear();
- if (style().svgStyle().capStyle() == SquareCap)
- tempPath.addRect(zeroLengthSubpathRect(linecapPosition, this->strokeWidth()));
+ tempPath.get().clear();
+ if (style().capStyle() == SquareCap)
+ tempPath.get().addRect(zeroLengthSubpathRect(linecapPosition, this->strokeWidth()));
else
- tempPath.addEllipse(zeroLengthSubpathRect(linecapPosition, this->strokeWidth()));
+ tempPath.get().addEllipse(zeroLengthSubpathRect(linecapPosition, this->strokeWidth()));
- return &tempPath;
+ return &tempPath.get();
}
FloatRect RenderSVGPath::zeroLengthSubpathRect(const FloatPoint& linecapPosition, float strokeWidth) const
@@ -157,10 +154,17 @@ void RenderSVGPath::updateZeroLengthSubpaths()
return;
SVGSubpathData subpathData(m_zeroLengthLinecapLocations);
- path().apply(&subpathData, SVGSubpathData::updateFromPathElement);
+ path().apply([&subpathData](const PathElement& pathElement) {
+ SVGSubpathData::updateFromPathElement(subpathData, pathElement);
+ });
subpathData.pathIsDone();
}
+bool RenderSVGPath::isRenderingDisabled() const
+{
+ // For a polygon, polyline or path, rendering is disabled if there is no path data.
+ // No path data is possible in the case of a missing or empty 'd' or 'points' attribute.
+ return path().isEmpty();
}
-#endif // ENABLE(SVG)
+}
diff --git a/Source/WebCore/rendering/svg/RenderSVGPath.h b/Source/WebCore/rendering/svg/RenderSVGPath.h
index 5ffd494f4..6b69e23f9 100644
--- a/Source/WebCore/rendering/svg/RenderSVGPath.h
+++ b/Source/WebCore/rendering/svg/RenderSVGPath.h
@@ -2,7 +2,7 @@
* Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
- * Copyright (C) 2006 Apple Computer, Inc
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2009 Google, Inc.
* Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
* Copyright (C) 2011 University of Szeged
@@ -23,40 +23,37 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGPath_h
-#define RenderSVGPath_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderSVGShape.h"
namespace WebCore {
class RenderSVGPath final : public RenderSVGShape {
public:
- RenderSVGPath(SVGGraphicsElement&, PassRef<RenderStyle>);
+ RenderSVGPath(SVGGraphicsElement&, RenderStyle&&);
virtual ~RenderSVGPath();
private:
- virtual bool isSVGPath() const override { return true; }
- virtual const char* renderName() const { return "RenderSVGPath"; }
+ bool isSVGPath() const override { return true; }
+ const char* renderName() const override { return "RenderSVGPath"; }
- virtual void updateShapeFromElement() override;
+ void updateShapeFromElement() override;
FloatRect calculateUpdatedStrokeBoundingBox() const;
- virtual void strokeShape(GraphicsContext*) const override;
- virtual bool shapeDependentStrokeContains(const FloatPoint&) override;
+ void strokeShape(GraphicsContext&) const override;
+ bool shapeDependentStrokeContains(const FloatPoint&) override;
bool shouldStrokeZeroLengthSubpath() const;
Path* zeroLengthLinecapPath(const FloatPoint&) const;
FloatRect zeroLengthSubpathRect(const FloatPoint&, float) const;
void updateZeroLengthSubpaths();
+ bool isRenderingDisabled() const override;
+
Vector<FloatPoint> m_zeroLengthLinecapLocations;
};
-RENDER_OBJECT_TYPE_CASTS(RenderSVGPath, isSVGPath())
-
-}
+} // namespace WebCore
-#endif // ENABLE(SVG)
-#endif
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGPath, isSVGPath())
diff --git a/Source/WebCore/rendering/svg/RenderSVGRect.cpp b/Source/WebCore/rendering/svg/RenderSVGRect.cpp
index bfda62f5f..2ceba5d91 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRect.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGRect.cpp
@@ -26,16 +26,12 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGRect.h"
-#include "SVGNames.h"
-
namespace WebCore {
-RenderSVGRect::RenderSVGRect(SVGRectElement& element, PassRef<RenderStyle> style)
- : RenderSVGShape(element, std::move(style))
+RenderSVGRect::RenderSVGRect(SVGRectElement& element, RenderStyle&& style)
+ : RenderSVGShape(element, WTFMove(style))
, m_usePathFallback(false)
{
}
@@ -46,7 +42,7 @@ RenderSVGRect::~RenderSVGRect()
SVGRectElement& RenderSVGRect::rectElement() const
{
- return toSVGRectElement(RenderSVGShape::graphicsElement());
+ return downcast<SVGRectElement>(RenderSVGShape::graphicsElement());
}
void RenderSVGRect::updateShapeFromElement()
@@ -58,19 +54,26 @@ void RenderSVGRect::updateShapeFromElement()
m_outerStrokeRect = FloatRect();
SVGLengthContext lengthContext(&rectElement());
- // Fallback to RenderSVGShape if rect has rounded corners or a non-scaling stroke.
- if (rectElement().rx().value(lengthContext) > 0 || rectElement().ry().value(lengthContext) > 0 || hasNonScalingStroke()) {
- RenderSVGShape::updateShapeFromElement();
- m_usePathFallback = true;
- return;
- }
+ FloatSize boundingBoxSize(lengthContext.valueForLength(style().width(), LengthModeWidth), lengthContext.valueForLength(style().height(), LengthModeHeight));
- m_usePathFallback = false;
- FloatSize boundingBoxSize(rectElement().width().value(lengthContext), rectElement().height().value(lengthContext));
- if (boundingBoxSize.isEmpty())
+ // Element is invalid if either dimension is negative.
+ if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0)
return;
- m_fillBoundingBox = FloatRect(FloatPoint(rectElement().x().value(lengthContext), rectElement().y().value(lengthContext)), boundingBoxSize);
+ // Rendering enabled? Spec: "A value of zero disables rendering of the element."
+ if (!boundingBoxSize.isEmpty()) {
+ if (rectElement().rx().value(lengthContext) > 0 || rectElement().ry().value(lengthContext) > 0 || hasNonScalingStroke()) {
+ // Fall back to RenderSVGShape
+ RenderSVGShape::updateShapeFromElement();
+ m_usePathFallback = true;
+ return;
+ }
+ m_usePathFallback = false;
+ }
+
+ m_fillBoundingBox = FloatRect(FloatPoint(lengthContext.valueForLength(style().svgStyle().x(), LengthModeWidth),
+ lengthContext.valueForLength(style().svgStyle().y(), LengthModeHeight)),
+ boundingBoxSize);
// To decide if the stroke contains a point we create two rects which represent the inner and
// the outer stroke borders. A stroke contains the point, if the point is between them.
@@ -92,7 +95,7 @@ void RenderSVGRect::updateShapeFromElement()
#endif
}
-void RenderSVGRect::fillShape(GraphicsContext* context) const
+void RenderSVGRect::fillShape(GraphicsContext& context) const
{
if (m_usePathFallback) {
RenderSVGShape::fillShape(context);
@@ -104,20 +107,20 @@ void RenderSVGRect::fillShape(GraphicsContext* context) const
// shadow drawing method, which draws an extra shadow.
// This is a workaround for switching off the extra shadow.
// https://bugs.webkit.org/show_bug.cgi?id=68899
- if (context->hasShadow()) {
- GraphicsContextStateSaver stateSaver(*context);
- context->clearShadow();
- context->fillRect(m_fillBoundingBox);
+ if (context.hasShadow()) {
+ GraphicsContextStateSaver stateSaver(context);
+ context.clearShadow();
+ context.fillRect(m_fillBoundingBox);
return;
}
#endif
- context->fillRect(m_fillBoundingBox);
+ context.fillRect(m_fillBoundingBox);
}
-void RenderSVGRect::strokeShape(GraphicsContext* context) const
+void RenderSVGRect::strokeShape(GraphicsContext& context) const
{
- if (!style().svgStyle().hasVisibleStroke())
+ if (!style().hasVisibleStroke())
return;
if (m_usePathFallback) {
@@ -125,7 +128,7 @@ void RenderSVGRect::strokeShape(GraphicsContext* context) const
return;
}
- context->strokeRect(m_fillBoundingBox, strokeWidth());
+ context.strokeRect(m_fillBoundingBox, strokeWidth());
}
bool RenderSVGRect::shapeDependentStrokeContains(const FloatPoint& point)
@@ -148,6 +151,10 @@ bool RenderSVGRect::shapeDependentFillContains(const FloatPoint& point, const Wi
return m_fillBoundingBox.contains(point.x(), point.y());
}
+bool RenderSVGRect::isRenderingDisabled() const
+{
+ // A width or height of zero disables rendering for the element, and results in an empty bounding box.
+ return m_fillBoundingBox.isEmpty();
}
-#endif // ENABLE(SVG)
+}
diff --git a/Source/WebCore/rendering/svg/RenderSVGRect.h b/Source/WebCore/rendering/svg/RenderSVGRect.h
index c305726b8..98f7c5c91 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRect.h
+++ b/Source/WebCore/rendering/svg/RenderSVGRect.h
@@ -25,10 +25,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef RenderSVGRect_h
-#define RenderSVGRect_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderSVGPath.h"
#include "SVGRectElement.h"
@@ -36,7 +34,7 @@ namespace WebCore {
class RenderSVGRect final : public RenderSVGShape {
public:
- RenderSVGRect(SVGRectElement&, PassRef<RenderStyle>);
+ RenderSVGRect(SVGRectElement&, RenderStyle&&);
virtual ~RenderSVGRect();
SVGRectElement& rectElement() const;
@@ -44,14 +42,15 @@ public:
private:
void graphicsElement() const = delete;
- virtual const char* renderName() const { return "RenderSVGRect"; }
+ const char* renderName() const override { return "RenderSVGRect"; }
- virtual void updateShapeFromElement();
- virtual bool isEmpty() const { return m_usePathFallback ? RenderSVGShape::isEmpty() : m_fillBoundingBox.isEmpty(); };
- virtual void fillShape(GraphicsContext*) const;
- virtual void strokeShape(GraphicsContext*) const;
- virtual bool shapeDependentStrokeContains(const FloatPoint&);
- virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
+ void updateShapeFromElement() override;
+ bool isEmpty() const override { return m_usePathFallback ? RenderSVGShape::isEmpty() : m_fillBoundingBox.isEmpty(); }
+ bool isRenderingDisabled() const override;
+ void fillShape(GraphicsContext&) const override;
+ void strokeShape(GraphicsContext&) const override;
+ bool shapeDependentStrokeContains(const FloatPoint&) override;
+ bool shapeDependentFillContains(const FloatPoint&, const WindRule) const override;
private:
FloatRect m_innerStrokeRect;
@@ -59,7 +58,4 @@ private:
bool m_usePathFallback;
};
-}
-
-#endif // ENABLE(SVG)
-#endif
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/RenderSVGResource.cpp b/Source/WebCore/rendering/svg/RenderSVGResource.cpp
index d9e1d835e..e6c5c2401 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResource.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResource.cpp
@@ -21,8 +21,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGResource.h"
#include "Frame.h"
@@ -72,18 +70,16 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
}
bool applyToFill = mode == ApplyToFillMode;
- SVGPaint::SVGPaintType paintType = applyToFill ? svgStyle.fillPaintType() : svgStyle.strokePaintType();
- if (paintType == SVGPaint::SVG_PAINTTYPE_NONE)
+ SVGPaintType paintType = applyToFill ? svgStyle.fillPaintType() : svgStyle.strokePaintType();
+ if (paintType == SVG_PAINTTYPE_NONE)
return nullptr;
Color color;
switch (paintType) {
- case SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR:
- case SVGPaint::SVG_PAINTTYPE_RGBCOLOR:
- case SVGPaint::SVG_PAINTTYPE_RGBCOLOR_ICCCOLOR:
- case SVGPaint::SVG_PAINTTYPE_URI_CURRENTCOLOR:
- case SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR:
- case SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR_ICCCOLOR:
+ case SVG_PAINTTYPE_CURRENTCOLOR:
+ case SVG_PAINTTYPE_RGBCOLOR:
+ case SVG_PAINTTYPE_URI_CURRENTCOLOR:
+ case SVG_PAINTTYPE_URI_RGBCOLOR:
color = applyToFill ? svgStyle.fillPaintColor() : svgStyle.strokePaintColor();
break;
default:
@@ -92,19 +88,19 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
if (style.insideLink() == InsideVisitedLink) {
// FIXME: This code doesn't support the uri component of the visited link paint, https://bugs.webkit.org/show_bug.cgi?id=70006
- SVGPaint::SVGPaintType visitedPaintType = applyToFill ? svgStyle.visitedLinkFillPaintType() : svgStyle.visitedLinkStrokePaintType();
+ SVGPaintType visitedPaintType = applyToFill ? svgStyle.visitedLinkFillPaintType() : svgStyle.visitedLinkStrokePaintType();
// For SVG_PAINTTYPE_CURRENTCOLOR, 'color' already contains the 'visitedColor'.
- if (visitedPaintType < SVGPaint::SVG_PAINTTYPE_URI_NONE && visitedPaintType != SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) {
+ if (visitedPaintType < SVG_PAINTTYPE_URI_NONE && visitedPaintType != SVG_PAINTTYPE_CURRENTCOLOR) {
const Color& visitedColor = applyToFill ? svgStyle.visitedLinkFillPaintColor() : svgStyle.visitedLinkStrokePaintColor();
if (visitedColor.isValid())
- color = Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), color.alpha());
+ color = visitedColor.colorWithAlpha(color.alphaAsFloat());
}
}
// If the primary resource is just a color, return immediately.
RenderSVGResourceSolidColor* colorResource = RenderSVGResource::sharedSolidPaintingResource();
- if (paintType < SVGPaint::SVG_PAINTTYPE_URI_NONE) {
+ if (paintType < SVG_PAINTTYPE_URI_NONE) {
if (!inheritColorFromParentStyleIfNeeded(renderer, applyToFill, color))
return nullptr;
@@ -113,9 +109,9 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
}
// If no resources are associated with the given renderer, return the color resource.
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer);
if (!resources) {
- if (paintType == SVGPaint::SVG_PAINTTYPE_URI_NONE || !inheritColorFromParentStyleIfNeeded(renderer, applyToFill, color))
+ if (paintType == SVG_PAINTTYPE_URI_NONE || !inheritColorFromParentStyleIfNeeded(renderer, applyToFill, color))
return nullptr;
colorResource->setColor(color);
@@ -156,28 +152,38 @@ RenderSVGResourceSolidColor* RenderSVGResource::sharedSolidPaintingResource()
return s_sharedSolidPaintingResource;
}
-static inline void removeFromCacheAndInvalidateDependencies(RenderObject& object, bool needsLayout)
+static inline void removeFromCacheAndInvalidateDependencies(RenderElement& renderer, bool needsLayout)
{
- if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object)) {
-#if ENABLE(FILTERS)
+ if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) {
if (RenderSVGResourceFilter* filter = resources->filter())
- filter->removeClientFromCache(object);
-#endif
+ filter->removeClientFromCache(renderer);
+
if (RenderSVGResourceMasker* masker = resources->masker())
- masker->removeClientFromCache(object);
+ masker->removeClientFromCache(renderer);
if (RenderSVGResourceClipper* clipper = resources->clipper())
- clipper->removeClientFromCache(object);
+ clipper->removeClientFromCache(renderer);
}
- if (!object.node() || !object.node()->isSVGElement())
+ if (!renderer.element() || !renderer.element()->isSVGElement())
return;
- HashSet<SVGElement*>* dependencies = object.document().accessSVGExtensions()->setOfElementsReferencingTarget(toSVGElement(object.node()));
+ HashSet<SVGElement*>* dependencies = renderer.document().accessSVGExtensions().setOfElementsReferencingTarget(downcast<SVGElement>(renderer.element()));
if (!dependencies)
return;
- for (auto element : *dependencies) {
- if (auto renderer = element->renderer())
+
+ // We allow cycles in SVGDocumentExtensions reference sets in order to avoid expensive
+ // reference graph adjustments on changes, so we need to break possible cycles here.
+ static NeverDestroyed<HashSet<SVGElement*>> invalidatingDependencies;
+
+ for (auto* element : *dependencies) {
+ if (auto* renderer = element->renderer()) {
+ if (UNLIKELY(!invalidatingDependencies.get().add(element).isNewEntry)) {
+ // Reference cycle: we are in process of invalidating this dependant.
+ continue;
+ }
RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer, needsLayout);
+ invalidatingDependencies.get().remove(element);
+ }
}
}
@@ -185,19 +191,20 @@ void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject&
{
ASSERT(object.node());
- if (needsLayout && !object.documentBeingDestroyed())
+ if (needsLayout && !object.renderTreeBeingDestroyed())
object.setNeedsLayout();
- removeFromCacheAndInvalidateDependencies(object, needsLayout);
+ if (is<RenderElement>(object))
+ removeFromCacheAndInvalidateDependencies(downcast<RenderElement>(object), needsLayout);
// Invalidate resources in ancestor chain, if needed.
- RenderObject* current = object.parent();
+ auto current = object.parent();
while (current) {
removeFromCacheAndInvalidateDependencies(*current, needsLayout);
- if (current->isSVGResourceContainer()) {
+ if (is<RenderSVGResourceContainer>(*current)) {
// This will process the rest of the ancestors.
- current->toRenderSVGResourceContainer()->removeAllClientsFromCache();
+ downcast<RenderSVGResourceContainer>(*current).removeAllClientsFromCache();
break;
}
@@ -206,6 +213,3 @@ void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject&
}
}
-
-#endif
-
diff --git a/Source/WebCore/rendering/svg/RenderSVGResource.h b/Source/WebCore/rendering/svg/RenderSVGResource.h
index 2c66ffade..c06a30766 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResource.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResource.h
@@ -17,13 +17,12 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGResource_h
-#define RenderSVGResource_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderSVGShape.h"
#include "RenderStyleConstants.h"
#include "SVGDocumentExtensions.h"
+#include <wtf/TypeCasts.h>
namespace WebCore {
@@ -60,7 +59,7 @@ public:
virtual ~RenderSVGResource() { }
virtual void removeAllClientsFromCache(bool markForInvalidation = true) = 0;
- virtual void removeClientFromCache(RenderObject&, bool markForInvalidation = true) = 0;
+ virtual void removeClientFromCache(RenderElement&, bool markForInvalidation = true) = 0;
virtual bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) = 0;
virtual void postApplyResource(RenderElement&, GraphicsContext*&, unsigned short, const Path*, const RenderSVGShape*) { }
@@ -68,15 +67,6 @@ public:
virtual RenderSVGResourceType resourceType() const = 0;
- template<class Renderer>
- Renderer* cast()
- {
- if (Renderer::s_resourceType == resourceType())
- return static_cast<Renderer*>(this);
-
- return 0;
- }
-
// Helper utilities used in the render tree to access resources used for painting shapes/text (gradients & patterns & solid colors only)
static RenderSVGResource* fillPaintingResource(RenderElement&, const RenderStyle&, Color& fallbackColor);
static RenderSVGResource* strokePaintingResource(RenderElement&, const RenderStyle&, Color& fallbackColor);
@@ -85,7 +75,9 @@ public:
static void markForLayoutAndParentResourceInvalidation(RenderObject&, bool needsLayout = true);
};
-}
+} // namespace WebCore
-#endif
-#endif
+#define SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(ToValueTypeName, ResourceType) \
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
+ static bool isType(const WebCore::RenderSVGResource& resource) { return resource.resourceType() == WebCore::ResourceType; } \
+SPECIALIZE_TYPE_TRAITS_END()
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp
index 5a6af206d..5d835fe17 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp
@@ -21,8 +21,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGResourceClipper.h"
#include "ElementIterator.h"
@@ -42,10 +40,8 @@
namespace WebCore {
-RenderSVGResourceType RenderSVGResourceClipper::s_resourceType = ClipperResourceType;
-
-RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement& element, PassRef<RenderStyle> style)
- : RenderSVGResourceContainer(element, std::move(style))
+RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement& element, RenderStyle&& style)
+ : RenderSVGResourceContainer(element, WTFMove(style))
{
}
@@ -61,7 +57,7 @@ void RenderSVGResourceClipper::removeAllClientsFromCache(bool markForInvalidatio
markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation);
}
-void RenderSVGResourceClipper::removeClientFromCache(RenderObject& client, bool markForInvalidation)
+void RenderSVGResourceClipper::removeClientFromCache(RenderElement& client, bool markForInvalidation)
{
m_clipper.remove(&client);
@@ -73,10 +69,10 @@ bool RenderSVGResourceClipper::applyResource(RenderElement& renderer, const Rend
ASSERT(context);
ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
- return applyClippingToContext(renderer, renderer.objectBoundingBox(), renderer.repaintRectInLocalCoordinates(), context);
+ return applyClippingToContext(renderer, renderer.objectBoundingBox(), renderer.repaintRectInLocalCoordinates(), *context);
}
-bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const AffineTransform& animatedLocalTransform, const FloatRect& objectBoundingBox)
+bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext& context, const AffineTransform& animatedLocalTransform, const FloatRect& objectBoundingBox)
{
// If the current clip-path gets clipped itself, we have to fallback to masking.
if (!style().svgStyle().clipperResource().isEmpty())
@@ -96,9 +92,9 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const
// Only shapes or paths are supported for direct clipping. We need to fallback to masking for texts.
if (renderer->isSVGText())
return false;
- if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGGraphicsElement())
+ if (!childNode->isSVGElement() || !downcast<SVGElement>(*childNode).isSVGGraphicsElement())
continue;
- SVGGraphicsElement* styled = toSVGGraphicsElement(childNode);
+ SVGGraphicsElement& styled = downcast<SVGGraphicsElement>(*childNode);
const RenderStyle& style = renderer->style();
if (style.display() == NONE || style.visibility() != VISIBLE)
continue;
@@ -108,7 +104,7 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const
return false;
// Fallback to masking, if there is more than one clipping path.
if (clipPath.isEmpty()) {
- styled->toClipPath(clipPath);
+ styled.toClipPath(clipPath);
clipRule = svgStyle.clipRule();
} else
return false;
@@ -127,77 +123,68 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const
// The SVG specification wants us to clip everything, if clip-path doesn't have a child.
if (clipPath.isEmpty())
clipPath.addRect(FloatRect());
- context->clipPath(clipPath, clipRule);
+ context.clipPath(clipPath, clipRule);
return true;
}
-bool RenderSVGResourceClipper::applyClippingToContext(RenderElement& renderer, const FloatRect& objectBoundingBox,
- const FloatRect& repaintRect, GraphicsContext* context)
+bool RenderSVGResourceClipper::applyClippingToContext(RenderElement& renderer, const FloatRect& objectBoundingBox, const FloatRect& repaintRect, GraphicsContext& context)
{
- bool missingClipperData = !m_clipper.contains(&renderer);
- if (missingClipperData)
- m_clipper.set(&renderer, std::make_unique<ClipperData>());
+ ClipperMaskImage& clipperMaskImage = addRendererToClipper(renderer);
+ bool shouldCreateClipperMaskImage = !clipperMaskImage;
- bool shouldCreateClipData = false;
AffineTransform animatedLocalTransform = clipPathElement().animatedLocalTransform();
- ClipperData* clipperData = m_clipper.get(&renderer);
- if (!clipperData->clipMaskImage) {
- if (pathOnlyClipping(context, animatedLocalTransform, objectBoundingBox))
- return true;
- shouldCreateClipData = true;
- }
- AffineTransform absoluteTransform;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(&renderer, absoluteTransform);
+ if (shouldCreateClipperMaskImage && pathOnlyClipping(context, animatedLocalTransform, objectBoundingBox))
+ return true;
- if (shouldCreateClipData && !repaintRect.isEmpty()) {
- if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, clipperData->clipMaskImage, ColorSpaceDeviceRGB, Unaccelerated))
- return false;
+ AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
- GraphicsContext* maskContext = clipperData->clipMaskImage->context();
- ASSERT(maskContext);
+ if (shouldCreateClipperMaskImage && !repaintRect.isEmpty()) {
+ // FIXME (149469): This image buffer should not be unconditionally unaccelerated. Making it match the context breaks nested clipping, though.
+ clipperMaskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, ColorSpaceSRGB, Unaccelerated);
+ if (!clipperMaskImage)
+ return false;
- maskContext->concatCTM(animatedLocalTransform);
+ GraphicsContext& maskContext = clipperMaskImage->context();
+ maskContext.concatCTM(animatedLocalTransform);
// clipPath can also be clipped by another clipPath.
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this);
RenderSVGResourceClipper* clipper;
bool succeeded;
if (resources && (clipper = resources->clipper())) {
- GraphicsContextStateSaver stateSaver(*maskContext);
+ GraphicsContextStateSaver stateSaver(maskContext);
if (!clipper->applyClippingToContext(*this, objectBoundingBox, repaintRect, maskContext))
return false;
- succeeded = drawContentIntoMaskImage(clipperData, objectBoundingBox);
+ succeeded = drawContentIntoMaskImage(clipperMaskImage, objectBoundingBox);
// The context restore applies the clipping on non-CG platforms.
} else
- succeeded = drawContentIntoMaskImage(clipperData, objectBoundingBox);
+ succeeded = drawContentIntoMaskImage(clipperMaskImage, objectBoundingBox);
if (!succeeded)
- clipperData->clipMaskImage.reset();
+ clipperMaskImage.reset();
}
- if (!clipperData->clipMaskImage)
+ if (!clipperMaskImage)
return false;
- SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, clipperData->clipMaskImage, missingClipperData);
+ SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, clipperMaskImage, shouldCreateClipperMaskImage);
return true;
}
-bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData, const FloatRect& objectBoundingBox)
+bool RenderSVGResourceClipper::drawContentIntoMaskImage(const ClipperMaskImage& clipperMaskImage, const FloatRect& objectBoundingBox)
{
- ASSERT(clipperData);
- ASSERT(clipperData->clipMaskImage);
+ ASSERT(clipperMaskImage);
- GraphicsContext* maskContext = clipperData->clipMaskImage->context();
- ASSERT(maskContext);
+ GraphicsContext& maskContext = clipperMaskImage->context();
AffineTransform maskContentTransformation;
if (clipPathElement().clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
maskContentTransformation.translate(objectBoundingBox.x(), objectBoundingBox.y());
maskContentTransformation.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
- maskContext->concatCTM(maskContentTransformation);
+ maskContext.concatCTM(maskContentTransformation);
}
// Switch to a paint behavior where all children of this <clipPath> will be rendered using special constraints:
@@ -224,11 +211,11 @@ bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData
WindRule newClipRule = style.svgStyle().clipRule();
bool isUseElement = child.hasTagName(SVGNames::useTag);
if (isUseElement) {
- SVGUseElement& useElement = toSVGUseElement(child);
+ SVGUseElement& useElement = downcast<SVGUseElement>(child);
renderer = useElement.rendererClipChild();
if (!renderer)
continue;
- if (!useElement.hasAttribute(SVGNames::clip_ruleAttr))
+ if (!useElement.hasAttributeWithoutSynchronization(SVGNames::clip_ruleAttr))
newClipRule = renderer->style().svgStyle().clipRule();
}
@@ -236,12 +223,12 @@ bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData
if (!renderer->isSVGShape() && !renderer->isSVGText())
continue;
- maskContext->setFillRule(newClipRule);
+ maskContext.setFillRule(newClipRule);
// In the case of a <use> element, we obtained its renderere above, to retrieve its clipRule.
// We have to pass the <use> renderer itself to renderSubtreeToImageBuffer() to apply it's x/y/transform/etc. values when rendering.
// So if isUseElement is true, refetch the childNode->renderer(), as renderer got overriden above.
- SVGRenderingContext::renderSubtreeToImageBuffer(clipperData->clipMaskImage.get(), isUseElement ? *child.renderer() : *renderer, maskContentTransformation);
+ SVGRenderingContext::renderSubtreeToImageBuffer(clipperMaskImage.get(), isUseElement ? *child.renderer() : *renderer, maskContentTransformation);
}
view().frameView().setPaintBehavior(oldBehavior);
@@ -265,6 +252,11 @@ void RenderSVGResourceClipper::calculateClipContentRepaintRect()
m_clipBoundaries = clipPathElement().animatedLocalTransform().mapRect(m_clipBoundaries);
}
+ClipperMaskImage& RenderSVGResourceClipper::addRendererToClipper(const RenderObject& object)
+{
+ return m_clipper.add(&object, ClipperMaskImage()).iterator->value;
+}
+
bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundingBox, const FloatPoint& nodeAtPoint)
{
FloatPoint point = nodeAtPoint;
@@ -275,10 +267,10 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin
AffineTransform transform;
transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
- point = transform.inverse().mapPoint(point);
+ point = transform.inverse().value_or(AffineTransform()).mapPoint(point);
}
- point = clipPathElement().animatedLocalTransform().inverse().mapPoint(point);
+ point = clipPathElement().animatedLocalTransform().inverse().value_or(AffineTransform()).mapPoint(point);
for (Node* childNode = clipPathElement().firstChild(); childNode; childNode = childNode->nextSibling()) {
RenderObject* renderer = childNode->renderer();
@@ -288,7 +280,7 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin
continue;
IntPoint hitPoint;
HitTestResult result(hitPoint);
- if (renderer->nodeAtFloatPoint(HitTestRequest(HitTestRequest::SVGClipContent | HitTestRequest::DisallowShadowContent), result, point, HitTestForeground))
+ if (renderer->nodeAtFloatPoint(HitTestRequest(HitTestRequest::SVGClipContent | HitTestRequest::DisallowUserAgentShadowContent), result, point, HitTestForeground))
return true;
}
@@ -298,8 +290,10 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin
FloatRect RenderSVGResourceClipper::resourceBoundingBox(const RenderObject& object)
{
// Resource was not layouted yet. Give back the boundingBox of the object.
- if (selfNeedsLayout())
+ if (selfNeedsLayout()) {
+ addRendererToClipper(object);
return object.objectBoundingBox();
+ }
if (m_clipBoundaries.isEmpty())
calculateClipContentRepaintRect();
@@ -316,5 +310,3 @@ FloatRect RenderSVGResourceClipper::resourceBoundingBox(const RenderObject& obje
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.h b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.h
index 31c64b8b7..943e10312 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.h
@@ -17,13 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGResourceClipper_h
-#define RenderSVGResourceClipper_h
+#pragma once
-#if ENABLE(SVG)
-#include "GraphicsContext.h"
-#include "ImageBuffer.h"
-#include "IntSize.h"
#include "RenderSVGResourceContainer.h"
#include "SVGClipPathElement.h"
#include "SVGUnitTypes.h"
@@ -32,50 +27,55 @@
namespace WebCore {
-struct ClipperData {
- WTF_MAKE_FAST_ALLOCATED;
-public:
- std::unique_ptr<ImageBuffer> clipMaskImage;
-};
+class GraphicsContext;
+class ImageBuffer;
+
+typedef std::unique_ptr<ImageBuffer> ClipperMaskImage;
class RenderSVGResourceClipper final : public RenderSVGResourceContainer {
public:
- RenderSVGResourceClipper(SVGClipPathElement&, PassRef<RenderStyle>);
+ RenderSVGResourceClipper(SVGClipPathElement&, RenderStyle&&);
virtual ~RenderSVGResourceClipper();
- SVGClipPathElement& clipPathElement() const { return toSVGClipPathElement(nodeForNonAnonymous()); }
+ SVGClipPathElement& clipPathElement() const { return downcast<SVGClipPathElement>(nodeForNonAnonymous()); }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject&, bool markForInvalidation = true);
+ void removeAllClientsFromCache(bool markForInvalidation = true) override;
+ void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override;
- virtual bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) override;
+ bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) override;
// clipPath can be clipped too, but don't have a boundingBox or repaintRect. So we can't call
// applyResource directly and use the rects from the object, since they are empty for RenderSVGResources
// FIXME: We made applyClippingToContext public because we cannot call applyResource on HTML elements (it asserts on RenderObject::objectBoundingBox)
- bool applyClippingToContext(RenderElement&, const FloatRect&, const FloatRect&, GraphicsContext*);
- virtual FloatRect resourceBoundingBox(const RenderObject&) override;
+ bool applyClippingToContext(RenderElement&, const FloatRect&, const FloatRect&, GraphicsContext&);
+ FloatRect resourceBoundingBox(const RenderObject&) override;
- virtual RenderSVGResourceType resourceType() const { return ClipperResourceType; }
+ RenderSVGResourceType resourceType() const override { return ClipperResourceType; }
bool hitTestClipContent(const FloatRect&, const FloatPoint&);
SVGUnitTypes::SVGUnitType clipPathUnits() const { return clipPathElement().clipPathUnits(); }
- static RenderSVGResourceType s_resourceType;
+protected:
+ bool selfNeedsClientInvalidation() const override { return (everHadLayout() || m_clipper.size()) && selfNeedsLayout(); }
+
private:
void element() const = delete;
- virtual const char* renderName() const override { return "RenderSVGResourceClipper"; }
+ const char* renderName() const override { return "RenderSVGResourceClipper"; }
+ bool isSVGResourceClipper() const override { return true; }
- bool pathOnlyClipping(GraphicsContext*, const AffineTransform&, const FloatRect&);
- bool drawContentIntoMaskImage(ClipperData*, const FloatRect& objectBoundingBox);
+ bool pathOnlyClipping(GraphicsContext&, const AffineTransform&, const FloatRect&);
+ bool drawContentIntoMaskImage(const ClipperMaskImage&, const FloatRect& objectBoundingBox);
void calculateClipContentRepaintRect();
+ ClipperMaskImage& addRendererToClipper(const RenderObject&);
FloatRect m_clipBoundaries;
- HashMap<RenderObject*, std::unique_ptr<ClipperData>> m_clipper;
+ HashMap<const RenderObject*, ClipperMaskImage> m_clipper;
};
}
-#endif
-#endif
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::RenderSVGResourceClipper)
+static bool isType(const WebCore::RenderObject& renderer) { return renderer.isSVGResourceClipper(); }
+static bool isType(const WebCore::RenderSVGResource& resource) { return resource.resourceType() == WebCore::ClipperResourceType; }
+SPECIALIZE_TYPE_TRAITS_END()
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp
index 2d8a73138..3d44c6aaa 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp
@@ -18,8 +18,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGResourceContainer.h"
#include "RenderLayer.h"
@@ -33,12 +31,11 @@ namespace WebCore {
static inline SVGDocumentExtensions& svgExtensionsFromElement(SVGElement& element)
{
- // FIXME: accessSVGExtensions() should return a reference.
- return *element.document().accessSVGExtensions();
+ return element.document().accessSVGExtensions();
}
-RenderSVGResourceContainer::RenderSVGResourceContainer(SVGElement& element, PassRef<RenderStyle> style)
- : RenderSVGHiddenContainer(element, std::move(style))
+RenderSVGResourceContainer::RenderSVGResourceContainer(SVGElement& element, RenderStyle&& style)
+ : RenderSVGHiddenContainer(element, WTFMove(style))
, m_id(element.getIdAttribute())
, m_registered(false)
, m_isInvalidating(false)
@@ -47,15 +44,13 @@ RenderSVGResourceContainer::RenderSVGResourceContainer(SVGElement& element, Pass
RenderSVGResourceContainer::~RenderSVGResourceContainer()
{
- if (m_registered)
- svgExtensionsFromElement(element()).removeResource(m_id);
}
void RenderSVGResourceContainer::layout()
{
StackStats::LayoutCheckPoint layoutCheckPoint;
// Invalidate all resources if our layout changed.
- if (everHadLayout() && selfNeedsLayout())
+ if (selfNeedsClientInvalidation())
RenderSVGRoot::addResourceForClientInvalidation(this);
RenderSVGHiddenContainer::layout();
@@ -64,6 +59,12 @@ void RenderSVGResourceContainer::layout()
void RenderSVGResourceContainer::willBeDestroyed()
{
SVGResourcesCache::resourceDestroyed(*this);
+
+ if (m_registered) {
+ svgExtensionsFromElement(element()).removeResource(m_id);
+ m_registered = false;
+ }
+
RenderSVGHiddenContainer::willBeDestroyed();
}
@@ -97,10 +98,15 @@ void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode
m_isInvalidating = true;
bool needsLayout = mode == LayoutAndBoundariesInvalidation;
bool markForInvalidation = mode != ParentOnlyInvalidation;
+ auto* root = SVGRenderSupport::findTreeRootObject(*this);
- for (auto client : m_clients) {
- if (client->isSVGResourceContainer()) {
- client->toRenderSVGResourceContainer()->removeAllClientsFromCache(markForInvalidation);
+ for (auto* client : m_clients) {
+ // We should not mark any client outside the current root for invalidation
+ if (root != SVGRenderSupport::findTreeRootObject(*client))
+ continue;
+
+ if (is<RenderSVGResourceContainer>(*client)) {
+ downcast<RenderSVGResourceContainer>(*client).removeAllClientsFromCache(markForInvalidation);
continue;
}
@@ -117,10 +123,8 @@ void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode
void RenderSVGResourceContainer::markAllClientLayersForInvalidation()
{
-#if ENABLE(CSS_FILTERS)
- for (auto clientLayer : m_clientLayers)
+ for (auto* clientLayer : m_clientLayers)
clientLayer->filterNeedsRepaint();
-#endif
}
void RenderSVGResourceContainer::markClientForInvalidation(RenderObject& client, InvalidationMode mode)
@@ -133,7 +137,7 @@ void RenderSVGResourceContainer::markClientForInvalidation(RenderObject& client,
client.setNeedsBoundariesUpdate();
break;
case RepaintInvalidation:
- if (!client.documentBeingDestroyed())
+ if (!client.renderTreeBeingDestroyed())
client.repaint();
break;
case ParentOnlyInvalidation:
@@ -141,17 +145,15 @@ void RenderSVGResourceContainer::markClientForInvalidation(RenderObject& client,
}
}
-void RenderSVGResourceContainer::addClient(RenderObject* client)
+void RenderSVGResourceContainer::addClient(RenderElement& client)
{
- ASSERT(client);
- m_clients.add(client);
+ m_clients.add(&client);
}
-void RenderSVGResourceContainer::removeClient(RenderObject* client)
+void RenderSVGResourceContainer::removeClient(RenderElement& client)
{
- ASSERT(client);
- removeClientFromCache(*client, false);
- m_clients.remove(client);
+ removeClientFromCache(client, false);
+ m_clients.remove(&client);
}
void RenderSVGResourceContainer::addClientRenderLayer(RenderLayer* client)
@@ -180,11 +182,10 @@ void RenderSVGResourceContainer::registerResource()
extensions.addResource(m_id, this);
// Update cached resources of pending clients.
- auto end = clients->end();
- for (auto it = clients->begin(); it != end; ++it) {
- ASSERT((*it)->hasPendingResources());
- extensions.clearHasPendingResourcesIfPossible(*it);
- auto renderer = (*it)->renderer();
+ for (auto* client : *clients) {
+ ASSERT(client->hasPendingResources());
+ extensions.clearHasPendingResourcesIfPossible(client);
+ auto* renderer = client->renderer();
if (!renderer)
continue;
SVGResourcesCache::clientStyleChanged(*renderer, StyleDifferenceLayout, renderer->style());
@@ -192,20 +193,20 @@ void RenderSVGResourceContainer::registerResource()
}
}
-bool RenderSVGResourceContainer::shouldTransformOnTextPainting(RenderObject* object, AffineTransform& resourceTransform)
+bool RenderSVGResourceContainer::shouldTransformOnTextPainting(const RenderElement& renderer, AffineTransform& resourceTransform)
{
- ASSERT_UNUSED(object, object);
#if USE(CG)
+ UNUSED_PARAM(renderer);
UNUSED_PARAM(resourceTransform);
return false;
#else
// This method should only be called for RenderObjects that deal with text rendering. Cmp. RenderObject.h's is*() methods.
- ASSERT(object->isSVGText() || object->isSVGTextPath() || object->isSVGInline());
+ ASSERT(renderer.isSVGText() || renderer.isSVGTextPath() || renderer.isSVGInline());
// In text drawing, the scaling part of the graphics context CTM is removed, compare SVGInlineTextBox::paintTextWithShadows.
// So, we use that scaling factor here, too, and then push it down to pattern or gradient space
// in order to keep the pattern or gradient correctly scaled.
- float scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(object);
+ float scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(renderer);
if (scalingFactor == 1)
return false;
resourceTransform.scale(scalingFactor);
@@ -219,12 +220,10 @@ AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderOb
if (!object->isSVGShape())
return resourceTransform;
- SVGGraphicsElement* element = toSVGGraphicsElement(object->node());
+ SVGGraphicsElement* element = downcast<SVGGraphicsElement>(object->node());
AffineTransform transform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
transform *= resourceTransform;
return transform;
}
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h
index b4045cabe..0cd7f1655 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h
@@ -17,10 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGResourceContainer_h
-#define RenderSVGResourceContainer_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderSVGHiddenContainer.h"
#include "RenderSVGResource.h"
@@ -33,13 +31,12 @@ class RenderSVGResourceContainer : public RenderSVGHiddenContainer,
public:
virtual ~RenderSVGResourceContainer();
- virtual void layout() override;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override final;
+ void layout() override;
+ void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final;
- virtual bool isSVGResourceContainer() const override final { return true; }
- virtual RenderSVGResourceContainer* toRenderSVGResourceContainer() override final { return this; }
+ bool isSVGResourceContainer() const final { return true; }
- static bool shouldTransformOnTextPainting(RenderObject*, AffineTransform&);
+ static bool shouldTransformOnTextPainting(const RenderElement&, AffineTransform&);
static AffineTransform transformOnNonScalingStroke(RenderObject*, const AffineTransform& resourceTransform);
void idChanged();
@@ -47,7 +44,7 @@ public:
void removeClientRenderLayer(RenderLayer*);
protected:
- RenderSVGResourceContainer(SVGElement&, PassRef<RenderStyle>);
+ RenderSVGResourceContainer(SVGElement&, RenderStyle&&);
enum InvalidationMode {
LayoutAndBoundariesInvalidation,
@@ -57,47 +54,50 @@ protected:
};
// Used from the invalidateClient/invalidateClients methods from classes, inheriting from us.
+ virtual bool selfNeedsClientInvalidation() const { return everHadLayout() && selfNeedsLayout(); }
+
void markAllClientsForInvalidation(InvalidationMode);
void markAllClientLayersForInvalidation();
void markClientForInvalidation(RenderObject&, InvalidationMode);
private:
friend class SVGResourcesCache;
- void addClient(RenderObject*);
- void removeClient(RenderObject*);
+ void addClient(RenderElement&);
+ void removeClient(RenderElement&);
-private:
- virtual void willBeDestroyed() override final;
+ void willBeDestroyed() final;
void registerResource();
AtomicString m_id;
bool m_registered : 1;
bool m_isInvalidating : 1;
- HashSet<RenderObject*> m_clients;
+ HashSet<RenderElement*> m_clients;
HashSet<RenderLayer*> m_clientLayers;
};
inline RenderSVGResourceContainer* getRenderSVGResourceContainerById(Document& document, const AtomicString& id)
{
if (id.isEmpty())
- return 0;
+ return nullptr;
- if (RenderSVGResourceContainer* renderResource = document.accessSVGExtensions()->resourceById(id))
+ if (RenderSVGResourceContainer* renderResource = document.accessSVGExtensions().resourceById(id))
return renderResource;
- return 0;
+ return nullptr;
}
template<typename Renderer>
Renderer* getRenderSVGResourceById(Document& document, const AtomicString& id)
{
- if (RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id))
- return container->cast<Renderer>();
+ // Using the RenderSVGResource type here avoids ambiguous casts for types that
+ // descend from both RenderObject and RenderSVGResourceContainer.
+ RenderSVGResource* container = getRenderSVGResourceContainerById(document, id);
+ if (is<Renderer>(container))
+ return downcast<Renderer>(container);
- return 0;
+ return nullptr;
}
-}
+} // namespace WebCore
-#endif
-#endif
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGResourceContainer, isSVGResourceContainer())
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
index 9dd85d6d8..2394db6aa 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
@@ -22,8 +22,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG) && ENABLE(FILTERS)
#include "RenderSVGResourceFilter.h"
#include "ElementChildIterator.h"
@@ -34,22 +32,18 @@
#include "Image.h"
#include "ImageData.h"
#include "IntRect.h"
-#include "Page.h"
#include "RenderSVGResourceFilterPrimitive.h"
#include "RenderView.h"
#include "SVGFilterPrimitiveStandardAttributes.h"
#include "SVGNames.h"
#include "SVGRenderingContext.h"
#include "Settings.h"
-#include "SourceAlpha.h"
#include "SourceGraphic.h"
namespace WebCore {
-RenderSVGResourceType RenderSVGResourceFilter::s_resourceType = FilterResourceType;
-
-RenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement& element, PassRef<RenderStyle> style)
- : RenderSVGResourceContainer(element, std::move(style))
+RenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement& element, RenderStyle&& style)
+ : RenderSVGResourceContainer(element, WTFMove(style))
{
}
@@ -64,7 +58,7 @@ void RenderSVGResourceFilter::removeAllClientsFromCache(bool markForInvalidation
markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation);
}
-void RenderSVGResourceFilter::removeClientFromCache(RenderObject& client, bool markForInvalidation)
+void RenderSVGResourceFilter::removeClientFromCache(RenderElement& client, bool markForInvalidation)
{
if (FilterData* filterData = m_filter.get(&client)) {
if (filterData->savedContext)
@@ -76,46 +70,32 @@ void RenderSVGResourceFilter::removeClientFromCache(RenderObject& client, bool m
markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation);
}
-std::unique_ptr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* filter)
+std::unique_ptr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter& filter) const
{
static const unsigned maxCountChildNodes = 200;
- if (filterElement().childNodeCount() > maxCountChildNodes)
+ if (filterElement().countChildNodes() > maxCountChildNodes)
return nullptr;
- FloatRect targetBoundingBox = filter->targetBoundingBox();
+ FloatRect targetBoundingBox = filter.targetBoundingBox();
// Add effects to the builder
- auto builder = std::make_unique<SVGFilterBuilder>(SourceGraphic::create(filter), SourceAlpha::create(filter));
+ auto builder = std::make_unique<SVGFilterBuilder>(SourceGraphic::create(filter));
for (auto& element : childrenOfType<SVGFilterPrimitiveStandardAttributes>(filterElement())) {
RefPtr<FilterEffect> effect = element.build(builder.get(), filter);
if (!effect) {
builder->clearEffects();
return nullptr;
}
- builder->appendEffectToEffectReferences(effect, element.renderer());
+ builder->appendEffectToEffectReferences(effect.copyRef(), element.renderer());
element.setStandardAttributes(effect.get());
effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(&element, filterElement().primitiveUnits(), targetBoundingBox));
- effect->setOperatingColorSpace(element.renderer()->style().svgStyle().colorInterpolationFilters() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB);
- builder->add(element.result(), effect.release());
+ if (element.renderer())
+ effect->setOperatingColorSpace(element.renderer()->style().svgStyle().colorInterpolationFilters() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceSRGB);
+ builder->add(element.result(), WTFMove(effect));
}
return builder;
}
-bool RenderSVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size, FloatSize& scale)
-{
- bool matchesFilterSize = true;
- if (size.width() > kMaxFilterSize) {
- scale.setWidth(scale.width() * kMaxFilterSize / size.width());
- matchesFilterSize = false;
- }
- if (size.height() > kMaxFilterSize) {
- scale.setHeight(scale.height() * kMaxFilterSize / size.height());
- matchesFilterSize = false;
- }
-
- return matchesFilterSize;
-}
-
bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const RenderStyle&, GraphicsContext*& context, unsigned short resourceMode)
{
ASSERT(context);
@@ -136,8 +116,7 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende
return false;
// Determine absolute transformation matrix for filter.
- AffineTransform absoluteTransform;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(&renderer, absoluteTransform);
+ AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
if (!absoluteTransform.isInvertible())
return false;
@@ -155,7 +134,7 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende
filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, absoluteDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);
// Create all relevant filter primitives.
- filterData->builder = buildPrimitives(filterData->filter.get());
+ filterData->builder = buildPrimitives(*filterData->filter);
if (!filterData->builder)
return false;
@@ -172,8 +151,8 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende
// Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize.
FloatRect tempSourceRect = absoluteDrawingRegion;
+ ImageBuffer::sizeNeedsClamping(tempSourceRect.size(), scale);
tempSourceRect.scale(scale.width(), scale.height());
- fitsInMaximumImageSize(tempSourceRect.size(), scale);
// Set the scale level in SVGFilter.
filterData->filter->setFilterResolution(scale);
@@ -183,13 +162,13 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende
if (!lastEffect || lastEffect->totalNumberOfEffectInputs() > maxTotalOfEffectInputs)
return false;
- RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect);
+ RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(*lastEffect);
FloatRect subRegion = lastEffect->maxEffectRect();
// At least one FilterEffect has a too big image size,
// recalculate the effect sizes with new scale factors.
- if (!fitsInMaximumImageSize(subRegion.size(), scale)) {
+ if (ImageBuffer::sizeNeedsClamping(subRegion.size(), scale)) {
filterData->filter->setFilterResolution(scale);
- RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect);
+ RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(*lastEffect);
}
// If the drawingRegion is empty, we have something like <g filter=".."/>.
@@ -197,7 +176,7 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende
if (filterData->drawingRegion.isEmpty()) {
ASSERT(!m_filter.contains(&renderer));
filterData->savedContext = context;
- m_filter.set(&renderer, std::move(filterData));
+ m_filter.set(&renderer, WTFMove(filterData));
return false;
}
@@ -206,28 +185,27 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende
effectiveTransform.scale(scale.width(), scale.height());
effectiveTransform.multiply(filterData->shearFreeAbsoluteTransform);
- std::unique_ptr<ImageBuffer> sourceGraphic;
- RenderingMode renderingMode = renderer.frame().settings().acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
- if (!SVGRenderingContext::createImageBuffer(filterData->drawingRegion, effectiveTransform, sourceGraphic, ColorSpaceLinearRGB, renderingMode)) {
+ RenderingMode renderingMode = renderer.settings().acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
+ auto sourceGraphic = SVGRenderingContext::createImageBuffer(filterData->drawingRegion, effectiveTransform, ColorSpaceLinearRGB, renderingMode);
+ if (!sourceGraphic) {
ASSERT(!m_filter.contains(&renderer));
filterData->savedContext = context;
- m_filter.set(&renderer, std::move(filterData));
+ m_filter.set(&renderer, WTFMove(filterData));
return false;
}
// Set the rendering mode from the page's settings.
filterData->filter->setRenderingMode(renderingMode);
- GraphicsContext* sourceGraphicContext = sourceGraphic->context();
- ASSERT(sourceGraphicContext);
+ GraphicsContext& sourceGraphicContext = sourceGraphic->context();
- filterData->sourceGraphicBuffer = std::move(sourceGraphic);
+ filterData->sourceGraphicBuffer = WTFMove(sourceGraphic);
filterData->savedContext = context;
- context = sourceGraphicContext;
+ context = &sourceGraphicContext;
ASSERT(!m_filter.contains(&renderer));
- m_filter.set(&renderer, std::move(filterData));
+ m_filter.set(&renderer, WTFMove(filterData));
return true;
}
@@ -275,7 +253,7 @@ void RenderSVGResourceFilter::postApplyResource(RenderElement& renderer, Graphic
// initial filtering process. We just take the stored filter result on a
// second drawing.
if (filterData->state != FilterData::Built)
- filterData->filter->setSourceImage(std::move(filterData->sourceGraphicBuffer));
+ filterData->filter->setSourceImage(WTFMove(filterData->sourceGraphicBuffer));
// Always true if filterData is just built (filterData->state == FilterData::Built).
if (!lastEffect->hasResult()) {
@@ -288,10 +266,10 @@ void RenderSVGResourceFilter::postApplyResource(RenderElement& renderer, Graphic
ImageBuffer* resultImage = lastEffect->asImageBuffer();
if (resultImage) {
- context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse());
+ context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse().value_or(AffineTransform()));
context->scale(FloatSize(1 / filterData->filter->filterResolution().width(), 1 / filterData->filter->filterResolution().height()));
- context->drawImageBuffer(resultImage, renderer.style().colorSpace(), lastEffect->absolutePaintRect());
+ context->drawImageBuffer(*resultImage, lastEffect->absolutePaintRect());
context->scale(filterData->filter->filterResolution());
context->concatCTM(filterData->shearFreeAbsoluteTransform);
@@ -337,4 +315,3 @@ FloatRect RenderSVGResourceFilter::drawingRegion(RenderObject* object) const
}
}
-#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h
index 97e6fdbf9..2e7bbbee1 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h
@@ -21,17 +21,14 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGResourceFilter_h
-#define RenderSVGResourceFilter_h
+#pragma once
-#if ENABLE(SVG) && ENABLE(FILTERS)
#include "ImageBuffer.h"
#include "RenderSVGResourceContainer.h"
#include "SVGFilter.h"
#include "SVGFilterBuilder.h"
#include "SVGFilterElement.h"
#include "SVGUnitTypes.h"
-
#include <wtf/RefPtr.h>
namespace WebCore {
@@ -63,44 +60,41 @@ class GraphicsContext;
class RenderSVGResourceFilter final : public RenderSVGResourceContainer {
public:
- RenderSVGResourceFilter(SVGFilterElement&, PassRef<RenderStyle>);
+ RenderSVGResourceFilter(SVGFilterElement&, RenderStyle&&);
virtual ~RenderSVGResourceFilter();
- SVGFilterElement& filterElement() const { return toSVGFilterElement(RenderSVGResourceContainer::element()); }
+ SVGFilterElement& filterElement() const { return downcast<SVGFilterElement>(RenderSVGResourceContainer::element()); }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject&, bool markForInvalidation = true);
+ void removeAllClientsFromCache(bool markForInvalidation = true) override;
+ void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override;
- virtual bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) override;
- virtual void postApplyResource(RenderElement&, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) override;
+ bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) override;
+ void postApplyResource(RenderElement&, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) override;
- virtual FloatRect resourceBoundingBox(const RenderObject&) override;
+ FloatRect resourceBoundingBox(const RenderObject&) override;
- std::unique_ptr<SVGFilterBuilder> buildPrimitives(SVGFilter*);
+ std::unique_ptr<SVGFilterBuilder> buildPrimitives(SVGFilter&) const;
SVGUnitTypes::SVGUnitType filterUnits() const { return filterElement().filterUnits(); }
SVGUnitTypes::SVGUnitType primitiveUnits() const { return filterElement().primitiveUnits(); }
void primitiveAttributeChanged(RenderObject*, const QualifiedName&);
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
- static RenderSVGResourceType s_resourceType;
+ RenderSVGResourceType resourceType() const override { return FilterResourceType; }
FloatRect drawingRegion(RenderObject*) const;
private:
void element() const = delete;
- virtual const char* renderName() const override { return "RenderSVGResourceFilter"; }
- virtual bool isSVGResourceFilter() const override { return true; }
-
- bool fitsInMaximumImageSize(const FloatSize&, FloatSize&);
+ const char* renderName() const override { return "RenderSVGResourceFilter"; }
+ bool isSVGResourceFilter() const override { return true; }
HashMap<RenderObject*, std::unique_ptr<FilterData>> m_filter;
};
-RENDER_OBJECT_TYPE_CASTS(RenderSVGResourceFilter, isSVGResourceFilter())
-
-}
+} // namespace WebCore
-#endif
-#endif
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::RenderSVGResourceFilter)
+ static bool isType(const WebCore::RenderObject& renderer) { return renderer.isSVGResourceFilter(); }
+ static bool isType(const WebCore::RenderSVGResource& resource) { return resource.resourceType() == WebCore::FilterResourceType; }
+SPECIALIZE_TYPE_TRAITS_END()
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
index 24887b702..323643bf8 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
@@ -26,18 +26,19 @@
*/
#include "config.h"
-
-#if ENABLE(SVG) && ENABLE(FILTERS)
#include "RenderSVGResourceFilterPrimitive.h"
+#include "SVGFEDiffuseLightingElement.h"
+#include "SVGFEFloodElement.h"
#include "SVGFEImage.h"
+#include "SVGFESpecularLightingElement.h"
#include "SVGFilterPrimitiveStandardAttributes.h"
#include "SVGNames.h"
namespace WebCore {
-RenderSVGResourceFilterPrimitive::RenderSVGResourceFilterPrimitive(SVGFilterPrimitiveStandardAttributes& filterPrimitiveElement, PassRef<RenderStyle> style)
- : RenderSVGHiddenContainer(filterPrimitiveElement, std::move(style))
+RenderSVGResourceFilterPrimitive::RenderSVGResourceFilterPrimitive(SVGFilterPrimitiveStandardAttributes& filterPrimitiveElement, RenderStyle&& style)
+ : RenderSVGHiddenContainer(filterPrimitiveElement, WTFMove(style))
{
}
@@ -50,69 +51,65 @@ void RenderSVGResourceFilterPrimitive::styleDidChange(StyleDifference diff, cons
{
RenderSVGHiddenContainer::styleDidChange(diff, oldStyle);
- RenderObject* filter = parent();
+ auto* filter = parent();
if (!filter)
return;
- ASSERT(filter->isSVGResourceFilter());
if (diff == StyleDifferenceEqual || !oldStyle)
return;
const SVGRenderStyle& newStyle = style().svgStyle();
- if (filterPrimitiveElement().hasTagName(SVGNames::feFloodTag)) {
+ if (is<SVGFEFloodElement>(filterPrimitiveElement())) {
if (newStyle.floodColor() != oldStyle->svgStyle().floodColor())
- toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_colorAttr);
+ downcast<RenderSVGResourceFilter>(*filter).primitiveAttributeChanged(this, SVGNames::flood_colorAttr);
if (newStyle.floodOpacity() != oldStyle->svgStyle().floodOpacity())
- toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_opacityAttr);
- } else if (filterPrimitiveElement().hasTagName(SVGNames::feDiffuseLightingTag) || filterPrimitiveElement().hasTagName(SVGNames::feSpecularLightingTag)) {
+ downcast<RenderSVGResourceFilter>(*filter).primitiveAttributeChanged(this, SVGNames::flood_opacityAttr);
+ } else if (is<SVGFEDiffuseLightingElement>(filterPrimitiveElement()) || is<SVGFESpecularLightingElement>(filterPrimitiveElement())) {
if (newStyle.lightingColor() != oldStyle->svgStyle().lightingColor())
- toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::lighting_colorAttr);
+ downcast<RenderSVGResourceFilter>(*filter).primitiveAttributeChanged(this, SVGNames::lighting_colorAttr);
}
}
-FloatRect RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(FilterEffect* effect)
+FloatRect RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(FilterEffect& effect)
{
- SVGFilter* filter = toSVGFilter(effect->filter());
- ASSERT(filter);
+ auto& filter = downcast<SVGFilter>(effect.filter());
// FETile, FETurbulence, FEFlood don't have input effects, take the filter region as unite rect.
FloatRect subregion;
- if (unsigned numberOfInputEffects = effect->inputEffects().size()) {
- subregion = determineFilterPrimitiveSubregion(effect->inputEffect(0));
+ if (unsigned numberOfInputEffects = effect.inputEffects().size()) {
+ subregion = determineFilterPrimitiveSubregion(*effect.inputEffect(0));
for (unsigned i = 1; i < numberOfInputEffects; ++i)
- subregion.unite(determineFilterPrimitiveSubregion(effect->inputEffect(i)));
+ subregion.unite(determineFilterPrimitiveSubregion(*effect.inputEffect(i)));
} else
- subregion = filter->filterRegionInUserSpace();
+ subregion = filter.filterRegionInUserSpace();
// After calling determineFilterPrimitiveSubregion on the target effect, reset the subregion again for <feTile>.
- if (effect->filterEffectType() == FilterEffectTypeTile)
- subregion = filter->filterRegionInUserSpace();
+ if (effect.filterEffectType() == FilterEffectTypeTile)
+ subregion = filter.filterRegionInUserSpace();
- FloatRect effectBoundaries = effect->effectBoundaries();
- if (effect->hasX())
+ FloatRect effectBoundaries = effect.effectBoundaries();
+ if (effect.hasX())
subregion.setX(effectBoundaries.x());
- if (effect->hasY())
+ if (effect.hasY())
subregion.setY(effectBoundaries.y());
- if (effect->hasWidth())
+ if (effect.hasWidth())
subregion.setWidth(effectBoundaries.width());
- if (effect->hasHeight())
+ if (effect.hasHeight())
subregion.setHeight(effectBoundaries.height());
- effect->setFilterPrimitiveSubregion(subregion);
+ effect.setFilterPrimitiveSubregion(subregion);
- FloatRect absoluteSubregion = filter->absoluteTransform().mapRect(subregion);
- FloatSize filterResolution = filter->filterResolution();
+ FloatRect absoluteSubregion = filter.absoluteTransform().mapRect(subregion);
+ FloatSize filterResolution = filter.filterResolution();
absoluteSubregion.scale(filterResolution.width(), filterResolution.height());
// Clip every filter effect to the filter region.
- FloatRect absoluteScaledFilterRegion = filter->filterRegion();
+ FloatRect absoluteScaledFilterRegion = filter.filterRegion();
absoluteScaledFilterRegion.scale(filterResolution.width(), filterResolution.height());
absoluteSubregion.intersect(absoluteScaledFilterRegion);
- effect->setMaxEffectRect(absoluteSubregion);
+ effect.setMaxEffectRect(absoluteSubregion);
return subregion;
}
} // namespace WebCore
-
-#endif // ENABLE(SVG) && ENABLE(FILTERS)
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h
index f67d61a0f..7b546bf65 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h
@@ -24,10 +24,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef RenderSVGResourceFilterPrimitive_h
-#define RenderSVGResourceFilterPrimitive_h
-
-#if ENABLE(SVG) && ENABLE(FILTERS)
+#pragma once
#include "RenderSVGResourceFilter.h"
@@ -38,16 +35,15 @@ class SVGFilterPrimitiveStandardAttributes;
class RenderSVGResourceFilterPrimitive final : public RenderSVGHiddenContainer {
public:
- RenderSVGResourceFilterPrimitive(SVGFilterPrimitiveStandardAttributes&, PassRef<RenderStyle>);
+ RenderSVGResourceFilterPrimitive(SVGFilterPrimitiveStandardAttributes&, RenderStyle&&);
SVGFilterPrimitiveStandardAttributes& filterPrimitiveElement() const;
- virtual void styleDidChange(StyleDifference, const RenderStyle*);
+ void styleDidChange(StyleDifference, const RenderStyle*) override;
- virtual const char* renderName() const { return "RenderSVGResourceFilterPrimitive"; }
- virtual bool isSVGResourceFilterPrimitive() const { return true; }
+ const char* renderName() const override { return "RenderSVGResourceFilterPrimitive"; }
// They depend on the RenderObject argument of RenderSVGResourceFilter::applyResource.
- static FloatRect determineFilterPrimitiveSubregion(FilterEffect*);
+ static FloatRect determineFilterPrimitiveSubregion(FilterEffect&);
inline void primitiveAttributeChanged(const QualifiedName& attribute)
{
@@ -57,11 +53,8 @@ public:
static_cast<RenderSVGResourceFilter*>(filter)->primitiveAttributeChanged(this, attribute);
}
private:
+ bool isSVGResourceFilterPrimitive() const override { return true; }
void element() const = delete;
};
} // namespace WebCore
-
-#endif // ENABLE(SVG) && ENABLE(FILTERS)
-
-#endif // RenderSVGResourceFilterPrimitive_h
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
index 496a7be59..bc9d02a27 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
@@ -21,8 +21,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGResourceGradient.h"
#include "GradientAttributes.h"
@@ -32,8 +30,8 @@
namespace WebCore {
-RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement& node, PassRef<RenderStyle> style)
- : RenderSVGResourceContainer(node, std::move(style))
+RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement& node, RenderStyle&& style)
+ : RenderSVGResourceContainer(node, WTFMove(style))
, m_shouldCollectGradientAttributes(true)
#if USE(CG)
, m_savedContext(0)
@@ -48,7 +46,7 @@ void RenderSVGResourceGradient::removeAllClientsFromCache(bool markForInvalidati
markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
}
-void RenderSVGResourceGradient::removeClientFromCache(RenderObject& client, bool markForInvalidation)
+void RenderSVGResourceGradient::removeClientFromCache(RenderElement& client, bool markForInvalidation)
{
m_gradientMap.remove(&client);
markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
@@ -57,35 +55,33 @@ void RenderSVGResourceGradient::removeClientFromCache(RenderObject& client, bool
#if USE(CG)
static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& context, GraphicsContext*& savedContext, std::unique_ptr<ImageBuffer>& imageBuffer, RenderObject* object)
{
- RenderObject* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(object);
+ auto* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(*object);
ASSERT(textRootBlock);
- AffineTransform absoluteTransform;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(textRootBlock, absoluteTransform);
-
+ AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock);
FloatRect repaintRect = textRootBlock->repaintRectInLocalCoordinates();
- std::unique_ptr<ImageBuffer> maskImage;
- if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, maskImage, ColorSpaceDeviceRGB, Unaccelerated))
+
+ auto maskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, ColorSpaceSRGB, context->renderingMode());
+ if (!maskImage)
return false;
- GraphicsContext* maskImageContext = maskImage->context();
- ASSERT(maskImageContext);
+ GraphicsContext& maskImageContext = maskImage->context();
ASSERT(maskImage);
savedContext = context;
- context = maskImageContext;
- imageBuffer = std::move(maskImage);
+ context = &maskImageContext;
+ imageBuffer = WTFMove(maskImage);
return true;
}
-static inline AffineTransform clipToTextMask(GraphicsContext* context, std::unique_ptr<ImageBuffer>& imageBuffer, FloatRect& targetRect, RenderObject* object, bool boundingBoxMode, const AffineTransform& gradientTransform)
+static inline AffineTransform clipToTextMask(GraphicsContext& context, std::unique_ptr<ImageBuffer>& imageBuffer, FloatRect& targetRect, RenderObject* object, bool boundingBoxMode, const AffineTransform& gradientTransform)
{
- RenderObject* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(object);
+ auto* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(*object);
ASSERT(textRootBlock);
- AffineTransform absoluteTransform;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(textRootBlock, absoluteTransform);
+ AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock);
targetRect = textRootBlock->repaintRectInLocalCoordinates();
+
SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, targetRect, imageBuffer, false);
AffineTransform matrix;
@@ -122,9 +118,9 @@ bool RenderSVGResourceGradient::applyResource(RenderElement& renderer, const Ren
if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty())
return false;
- OwnPtr<GradientData>& gradientData = m_gradientMap.add(&renderer, nullptr).iterator->value;
+ auto& gradientData = m_gradientMap.add(&renderer, nullptr).iterator->value;
if (!gradientData)
- gradientData = adoptPtr(new GradientData);
+ gradientData = std::make_unique<GradientData>();
bool isPaintingText = resourceMode & ApplyToTextMode;
@@ -152,7 +148,7 @@ bool RenderSVGResourceGradient::applyResource(RenderElement& renderer, const Ren
// Depending on font scaling factor, we may need to rescale the gradient here since
// text painting removes the scale factor from the context.
AffineTransform additionalTextTransform;
- if (shouldTransformOnTextPainting(&renderer, additionalTextTransform))
+ if (shouldTransformOnTextPainting(renderer, additionalTextTransform))
gradientData->userspaceTransform *= additionalTextTransform;
}
gradientData->gradient->setGradientSpaceTransform(gradientData->userspaceTransform);
@@ -179,13 +175,13 @@ bool RenderSVGResourceGradient::applyResource(RenderElement& renderer, const Ren
if (resourceMode & ApplyToFillMode) {
context->setAlpha(svgStyle.fillOpacity());
- context->setFillGradient(gradientData->gradient);
+ context->setFillGradient(*gradientData->gradient);
context->setFillRule(svgStyle.fillRule());
} else if (resourceMode & ApplyToStrokeMode) {
if (svgStyle.vectorEffect() == VE_NON_SCALING_STROKE)
gradientData->gradient->setGradientSpaceTransform(transformOnNonScalingStroke(&renderer, gradientData->userspaceTransform));
context->setAlpha(svgStyle.strokeOpacity());
- context->setStrokeGradient(gradientData->gradient);
+ context->setStrokeGradient(*gradientData->gradient);
SVGRenderSupport::applyStrokeStyleToContext(context, style, renderer);
}
@@ -210,8 +206,8 @@ void RenderSVGResourceGradient::postApplyResource(RenderElement& renderer, Graph
calculateGradientTransform(gradientTransform);
FloatRect targetRect;
- gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, targetRect, &renderer, gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, gradientTransform));
- context->setFillGradient(gradientData->gradient);
+ gradientData->gradient->setGradientSpaceTransform(clipToTextMask(*context, m_imageBuffer, targetRect, &renderer, gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, gradientTransform));
+ context->setFillGradient(*gradientData->gradient);
context->fillRect(targetRect);
m_imageBuffer.reset();
@@ -224,13 +220,13 @@ void RenderSVGResourceGradient::postApplyResource(RenderElement& renderer, Graph
if (path)
context->fillPath(*path);
else if (shape)
- shape->fillShape(context);
+ shape->fillShape(*context);
}
if (resourceMode & ApplyToStrokeMode) {
if (path)
context->strokePath(*path);
else if (shape)
- shape->strokeShape(context);
+ shape->strokeShape(*context);
}
}
@@ -263,5 +259,3 @@ GradientSpreadMethod RenderSVGResourceGradient::platformSpreadMethodFromSVGType(
}
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h
index c37fc7a5c..e7918f594 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h
@@ -19,15 +19,13 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGResourceGradient_h
-#define RenderSVGResourceGradient_h
+#pragma once
-#if ENABLE(SVG)
#include "Gradient.h"
#include "ImageBuffer.h"
#include "RenderSVGResourceContainer.h"
#include "SVGGradientElement.h"
-
+#include <memory>
#include <wtf/HashMap.h>
namespace WebCore {
@@ -45,15 +43,15 @@ class RenderSVGResourceGradient : public RenderSVGResourceContainer {
public:
SVGGradientElement& gradientElement() const { return static_cast<SVGGradientElement&>(RenderSVGResourceContainer::element()); }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true) override final;
- virtual void removeClientFromCache(RenderObject&, bool markForInvalidation = true) override final;
+ void removeAllClientsFromCache(bool markForInvalidation = true) final;
+ void removeClientFromCache(RenderElement&, bool markForInvalidation = true) final;
- virtual bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) override final;
- virtual void postApplyResource(RenderElement&, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) override final;
- virtual FloatRect resourceBoundingBox(const RenderObject&) override final { return FloatRect(); }
+ bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) final;
+ void postApplyResource(RenderElement&, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) final;
+ FloatRect resourceBoundingBox(const RenderObject&) final { return FloatRect(); }
protected:
- RenderSVGResourceGradient(SVGGradientElement&, PassRef<RenderStyle>);
+ RenderSVGResourceGradient(SVGGradientElement&, RenderStyle&&);
void element() const = delete;
@@ -68,7 +66,7 @@ protected:
private:
bool m_shouldCollectGradientAttributes : 1;
- HashMap<RenderObject*, OwnPtr<GradientData>> m_gradientMap;
+ HashMap<RenderObject*, std::unique_ptr<GradientData>> m_gradientMap;
#if USE(CG)
GraphicsContext* m_savedContext;
@@ -76,7 +74,4 @@ private:
#endif
};
-}
-
-#endif
-#endif
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp
index c928e5b86..e51ff5fb3 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp
@@ -19,17 +19,13 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGResourceLinearGradient.h"
namespace WebCore {
-RenderSVGResourceType RenderSVGResourceLinearGradient::s_resourceType = LinearGradientResourceType;
-
-RenderSVGResourceLinearGradient::RenderSVGResourceLinearGradient(SVGLinearGradientElement& element, PassRef<RenderStyle> style)
- : RenderSVGResourceGradient(element, std::move(style))
+RenderSVGResourceLinearGradient::RenderSVGResourceLinearGradient(SVGLinearGradientElement& element, RenderStyle&& style)
+ : RenderSVGResourceGradient(element, WTFMove(style))
{
}
@@ -61,5 +57,3 @@ void RenderSVGResourceLinearGradient::buildGradient(GradientData* gradientData)
}
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h b/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h
index eaec65974..8a28d7557 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h
@@ -18,10 +18,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGResourceLinearGradient_h
-#define RenderSVGResourceLinearGradient_h
+#pragma once
-#if ENABLE(SVG)
#include "LinearGradientAttributes.h"
#include "RenderSVGResourceGradient.h"
#include "SVGLinearGradientElement.h"
@@ -30,18 +28,17 @@ namespace WebCore {
class RenderSVGResourceLinearGradient final : public RenderSVGResourceGradient {
public:
- RenderSVGResourceLinearGradient(SVGLinearGradientElement&, PassRef<RenderStyle>);
+ RenderSVGResourceLinearGradient(SVGLinearGradientElement&, RenderStyle&&);
virtual ~RenderSVGResourceLinearGradient();
- SVGLinearGradientElement& linearGradientElement() const { return toSVGLinearGradientElement(RenderSVGResourceGradient::gradientElement()); }
+ SVGLinearGradientElement& linearGradientElement() const { return downcast<SVGLinearGradientElement>(RenderSVGResourceGradient::gradientElement()); }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
- static RenderSVGResourceType s_resourceType;
+ RenderSVGResourceType resourceType() const override { return LinearGradientResourceType; }
- virtual SVGUnitTypes::SVGUnitType gradientUnits() const { return m_attributes.gradientUnits(); }
- virtual void calculateGradientTransform(AffineTransform& transform) { transform = m_attributes.gradientTransform(); }
- virtual bool collectGradientAttributes() override;
- virtual void buildGradient(GradientData*) const;
+ SVGUnitTypes::SVGUnitType gradientUnits() const override { return m_attributes.gradientUnits(); }
+ void calculateGradientTransform(AffineTransform& transform) override { transform = m_attributes.gradientTransform(); }
+ bool collectGradientAttributes() override;
+ void buildGradient(GradientData*) const override;
FloatPoint startPoint(const LinearGradientAttributes&) const;
FloatPoint endPoint(const LinearGradientAttributes&) const;
@@ -49,12 +46,11 @@ public:
private:
void gradientElement() const = delete;
- virtual const char* renderName() const override { return "RenderSVGResourceLinearGradient"; }
+ const char* renderName() const override { return "RenderSVGResourceLinearGradient"; }
LinearGradientAttributes m_attributes;
};
-}
+} // namespace WebCore
-#endif
-#endif
+SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourceLinearGradient, LinearGradientResourceType)
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp
index 3ea195056..75360ae6a 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp
@@ -20,8 +20,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGResourceMarker.h"
#include "GraphicsContext.h"
@@ -30,10 +28,8 @@
namespace WebCore {
-RenderSVGResourceType RenderSVGResourceMarker::s_resourceType = MarkerResourceType;
-
-RenderSVGResourceMarker::RenderSVGResourceMarker(SVGMarkerElement& element, PassRef<RenderStyle> style)
- : RenderSVGResourceContainer(element, std::move(style))
+RenderSVGResourceMarker::RenderSVGResourceMarker(SVGMarkerElement& element, RenderStyle&& style)
+ : RenderSVGResourceContainer(element, WTFMove(style))
{
}
@@ -59,7 +55,7 @@ void RenderSVGResourceMarker::removeAllClientsFromCache(bool markForInvalidation
markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation);
}
-void RenderSVGResourceMarker::removeClientFromCache(RenderObject& client, bool markForInvalidation)
+void RenderSVGResourceMarker::removeClientFromCache(RenderElement& client, bool markForInvalidation)
{
markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation);
}
@@ -67,7 +63,7 @@ void RenderSVGResourceMarker::removeClientFromCache(RenderObject& client, bool m
void RenderSVGResourceMarker::applyViewportClip(PaintInfo& paintInfo)
{
if (SVGRenderSupport::isOverflowHidden(*this))
- paintInfo.context->clip(m_viewport);
+ paintInfo.context().clip(m_viewport);
}
FloatRect RenderSVGResourceMarker::markerBoundaries(const AffineTransform& markerTransformation) const
@@ -122,7 +118,7 @@ void RenderSVGResourceMarker::draw(PaintInfo& paintInfo, const AffineTransform&
return;
PaintInfo info(paintInfo);
- GraphicsContextStateSaver stateSaver(*info.context);
+ GraphicsContextStateSaver stateSaver(info.context());
info.applyTransform(transform);
RenderSVGContainer::paint(info, IntPoint());
}
@@ -157,5 +153,3 @@ void RenderSVGResourceMarker::calcViewport()
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h
index 442cc60d7..63c8bf785 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h
@@ -17,13 +17,10 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGResourceMarker_h
-#define RenderSVGResourceMarker_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderSVGResourceContainer.h"
#include "SVGMarkerElement.h"
-
#include <wtf/HashSet.h>
namespace WebCore {
@@ -33,40 +30,39 @@ class RenderObject;
class RenderSVGResourceMarker final : public RenderSVGResourceContainer {
public:
- RenderSVGResourceMarker(SVGMarkerElement&, PassRef<RenderStyle>);
+ RenderSVGResourceMarker(SVGMarkerElement&, RenderStyle&&);
virtual ~RenderSVGResourceMarker();
- SVGMarkerElement& markerElement() const { return toSVGMarkerElement(RenderSVGResourceContainer::element()); }
+ SVGMarkerElement& markerElement() const { return downcast<SVGMarkerElement>(RenderSVGResourceContainer::element()); }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject&, bool markForInvalidation = true);
+ void removeAllClientsFromCache(bool markForInvalidation = true) override;
+ void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override;
void draw(PaintInfo&, const AffineTransform&);
// Calculates marker boundaries, mapped to the target element's coordinate space
FloatRect markerBoundaries(const AffineTransform& markerTransformation) const;
- virtual void applyViewportClip(PaintInfo&);
- virtual void layout();
- virtual void calcViewport();
+ void applyViewportClip(PaintInfo&) override;
+ void layout() override;
+ void calcViewport() override;
- virtual const AffineTransform& localToParentTransform() const;
+ const AffineTransform& localToParentTransform() const override;
AffineTransform markerTransformation(const FloatPoint& origin, float angle, float strokeWidth) const;
- virtual bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short) override { return false; }
- virtual FloatRect resourceBoundingBox(const RenderObject&) override { return FloatRect(); }
+ bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short) override { return false; }
+ FloatRect resourceBoundingBox(const RenderObject&) override { return FloatRect(); }
FloatPoint referencePoint() const;
float angle() const;
SVGMarkerUnitsType markerUnits() const { return markerElement().markerUnits(); }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
- static RenderSVGResourceType s_resourceType;
+ RenderSVGResourceType resourceType() const override { return MarkerResourceType; }
private:
void element() const = delete;
- virtual const char* renderName() const override { return "RenderSVGResourceMarker"; }
+ const char* renderName() const override { return "RenderSVGResourceMarker"; }
// Generates a transformation matrix usable to render marker content. Handles scaling the marker content
// acording to SVGs markerUnits="strokeWidth" concept, when a strokeWidth value != -1 is passed in.
@@ -78,7 +74,6 @@ private:
FloatRect m_viewport;
};
-}
-#endif
+} // namespace WebCore
-#endif
+SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourceMarker, MarkerResourceType)
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp
index e02fab47b..f0d6744c0 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp
@@ -18,8 +18,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGResourceMasker.h"
#include "Element.h"
@@ -31,10 +29,8 @@
namespace WebCore {
-RenderSVGResourceType RenderSVGResourceMasker::s_resourceType = MaskerResourceType;
-
-RenderSVGResourceMasker::RenderSVGResourceMasker(SVGMaskElement& element, PassRef<RenderStyle> style)
- : RenderSVGResourceContainer(element, std::move(style))
+RenderSVGResourceMasker::RenderSVGResourceMasker(SVGMaskElement& element, RenderStyle&& style)
+ : RenderSVGResourceContainer(element, WTFMove(style))
{
}
@@ -50,7 +46,7 @@ void RenderSVGResourceMasker::removeAllClientsFromCache(bool markForInvalidation
markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation);
}
-void RenderSVGResourceMasker::removeClientFromCache(RenderObject& client, bool markForInvalidation)
+void RenderSVGResourceMasker::removeClientFromCache(RenderElement& client, bool markForInvalidation)
{
m_masker.remove(&client);
@@ -67,34 +63,31 @@ bool RenderSVGResourceMasker::applyResource(RenderElement& renderer, const Rende
m_masker.set(&renderer, std::make_unique<MaskerData>());
MaskerData* maskerData = m_masker.get(&renderer);
-
- AffineTransform absoluteTransform;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(&renderer, absoluteTransform);
-
+ AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
FloatRect repaintRect = renderer.repaintRectInLocalCoordinates();
if (!maskerData->maskImage && !repaintRect.isEmpty()) {
const SVGRenderStyle& svgStyle = style().svgStyle();
- ColorSpace colorSpace = svgStyle.colorInterpolation() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB;
- if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, maskerData->maskImage, colorSpace, Unaccelerated))
+ ColorSpace colorSpace = svgStyle.colorInterpolation() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceSRGB;
+ // FIXME (149470): This image buffer should not be unconditionally unaccelerated. Making it match the context breaks alpha masking, though.
+ maskerData->maskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, colorSpace, Unaccelerated);
+ if (!maskerData->maskImage)
return false;
- if (!drawContentIntoMaskImage(maskerData, colorSpace, &renderer)) {
+ if (!drawContentIntoMaskImage(maskerData, colorSpace, &renderer))
maskerData->maskImage.reset();
- }
}
if (!maskerData->maskImage)
return false;
- SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, maskerData->maskImage, missingMaskerData);
+ SVGRenderingContext::clipToImageBuffer(*context, absoluteTransform, repaintRect, maskerData->maskImage, missingMaskerData);
return true;
}
bool RenderSVGResourceMasker::drawContentIntoMaskImage(MaskerData* maskerData, ColorSpace colorSpace, RenderObject* object)
{
- GraphicsContext* maskImageContext = maskerData->maskImage->context();
- ASSERT(maskImageContext);
+ GraphicsContext& maskImageContext = maskerData->maskImage->context();
// Eventually adjust the mask image context according to the target objectBoundingBox.
AffineTransform maskContentTransformation;
@@ -102,7 +95,7 @@ bool RenderSVGResourceMasker::drawContentIntoMaskImage(MaskerData* maskerData, C
FloatRect objectBoundingBox = object->objectBoundingBox();
maskContentTransformation.translate(objectBoundingBox.x(), objectBoundingBox.y());
maskContentTransformation.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
- maskImageContext->concatCTM(maskContentTransformation);
+ maskImageContext.concatCTM(maskContentTransformation);
}
// Draw the content into the ImageBuffer.
@@ -169,5 +162,3 @@ FloatRect RenderSVGResourceMasker::resourceBoundingBox(const RenderObject& objec
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.h b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.h
index ecae4332e..5b93ac9e6 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.h
@@ -17,11 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGResourceMasker_h
-#define RenderSVGResourceMasker_h
+#pragma once
-#if ENABLE(SVG)
-#include "GraphicsContext.h"
#include "ImageBuffer.h"
#include "IntSize.h"
#include "RenderSVGResourceContainer.h"
@@ -32,32 +29,33 @@
namespace WebCore {
+class GraphicsContext;
+
struct MaskerData {
std::unique_ptr<ImageBuffer> maskImage;
};
class RenderSVGResourceMasker final : public RenderSVGResourceContainer {
public:
- RenderSVGResourceMasker(SVGMaskElement&, PassRef<RenderStyle>);
+ RenderSVGResourceMasker(SVGMaskElement&, RenderStyle&&);
virtual ~RenderSVGResourceMasker();
- SVGMaskElement& maskElement() const { return toSVGMaskElement(RenderSVGResourceContainer::element()); }
+ SVGMaskElement& maskElement() const { return downcast<SVGMaskElement>(RenderSVGResourceContainer::element()); }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject&, bool markForInvalidation = true);
- virtual bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) override;
- virtual FloatRect resourceBoundingBox(const RenderObject&) override;
+ void removeAllClientsFromCache(bool markForInvalidation = true) override;
+ void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override;
+ bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) override;
+ FloatRect resourceBoundingBox(const RenderObject&) override;
SVGUnitTypes::SVGUnitType maskUnits() const { return maskElement().maskUnits(); }
SVGUnitTypes::SVGUnitType maskContentUnits() const { return maskElement().maskContentUnits(); }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
- static RenderSVGResourceType s_resourceType;
+ RenderSVGResourceType resourceType() const override { return MaskerResourceType; }
private:
void element() const = delete;
- virtual const char* renderName() const override { return "RenderSVGResourceMasker"; }
+ const char* renderName() const override { return "RenderSVGResourceMasker"; }
bool drawContentIntoMaskImage(MaskerData*, ColorSpace, RenderObject*);
void calculateMaskContentRepaintRect();
@@ -68,5 +66,4 @@ private:
}
-#endif
-#endif
+SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourceMasker, MaskerResourceType)
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp
index 4ed8e6a98..ea936a4dc 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp
@@ -19,8 +19,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGResourcePattern.h"
#include "ElementIterator.h"
@@ -29,20 +27,20 @@
#include "RenderSVGRoot.h"
#include "SVGFitToViewBox.h"
#include "SVGRenderingContext.h"
+#include "SVGResources.h"
+#include "SVGResourcesCache.h"
namespace WebCore {
-RenderSVGResourceType RenderSVGResourcePattern::s_resourceType = PatternResourceType;
-
-RenderSVGResourcePattern::RenderSVGResourcePattern(SVGPatternElement& element, PassRef<RenderStyle> style)
- : RenderSVGResourceContainer(element, std::move(style))
+RenderSVGResourcePattern::RenderSVGResourcePattern(SVGPatternElement& element, RenderStyle&& style)
+ : RenderSVGResourceContainer(element, WTFMove(style))
, m_shouldCollectPatternAttributes(true)
{
}
SVGPatternElement& RenderSVGResourcePattern::patternElement() const
{
- return toSVGPatternElement(RenderSVGResourceContainer::element());
+ return downcast<SVGPatternElement>(RenderSVGResourceContainer::element());
}
void RenderSVGResourcePattern::removeAllClientsFromCache(bool markForInvalidation)
@@ -52,42 +50,48 @@ void RenderSVGResourcePattern::removeAllClientsFromCache(bool markForInvalidatio
markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
}
-void RenderSVGResourcePattern::removeClientFromCache(RenderObject& client, bool markForInvalidation)
+void RenderSVGResourcePattern::removeClientFromCache(RenderElement& client, bool markForInvalidation)
{
m_patternMap.remove(&client);
markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
}
-PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsigned short resourceMode)
+void RenderSVGResourcePattern::collectPatternAttributes(PatternAttributes& attributes) const
{
- PatternData* currentData = m_patternMap.get(object);
- if (currentData && currentData->pattern)
- return currentData;
+ const RenderSVGResourcePattern* current = this;
- if (m_shouldCollectPatternAttributes) {
- patternElement().synchronizeAnimatedSVGAttribute(anyQName());
+ while (current) {
+ const SVGPatternElement& pattern = current->patternElement();
+ pattern.collectPatternAttributes(attributes);
- m_attributes = PatternAttributes();
- patternElement().collectPatternAttributes(m_attributes);
- m_shouldCollectPatternAttributes = false;
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*current);
+ current = resources ? downcast<RenderSVGResourcePattern>(resources->linkedResource()) : nullptr;
}
+}
+
+PatternData* RenderSVGResourcePattern::buildPattern(RenderElement& renderer, unsigned short resourceMode, GraphicsContext& context)
+{
+ ASSERT(!m_shouldCollectPatternAttributes);
+
+ PatternData* currentData = m_patternMap.get(&renderer);
+ if (currentData && currentData->pattern)
+ return currentData;
// If we couldn't determine the pattern content element root, stop here.
if (!m_attributes.patternContentElement())
- return 0;
+ return nullptr;
// An empty viewBox disables rendering.
if (m_attributes.hasViewBox() && m_attributes.viewBox().isEmpty())
- return 0;
+ return nullptr;
// Compute all necessary transformations to build the tile image & the pattern.
FloatRect tileBoundaries;
AffineTransform tileImageTransform;
- if (!buildTileImageTransform(object, m_attributes, patternElement(), tileBoundaries, tileImageTransform))
- return 0;
+ if (!buildTileImageTransform(renderer, m_attributes, patternElement(), tileBoundaries, tileImageTransform))
+ return nullptr;
- AffineTransform absoluteTransformIgnoringRotation;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransformIgnoringRotation);
+ AffineTransform absoluteTransformIgnoringRotation = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
// Ignore 2D rotation, as it doesn't affect the size of the tile.
SVGRenderingContext::clear2DRotation(absoluteTransformIgnoringRotation);
@@ -99,20 +103,22 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign
static_cast<float>(m_attributes.patternTransform().yScale()));
// Build tile image.
- std::unique_ptr<ImageBuffer> tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries);
+ auto tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries, context.renderingMode());
if (!tileImage)
- return 0;
+ return nullptr;
- RefPtr<Image> copiedImage = tileImage->copyImage(CopyBackingStore);
+ const IntSize tileImageSize = tileImage->logicalSize();
+
+ RefPtr<Image> copiedImage = ImageBuffer::sinkIntoImage(WTFMove(tileImage));
if (!copiedImage)
- return 0;
+ return nullptr;
// Build pattern.
- OwnPtr<PatternData> patternData = adoptPtr(new PatternData);
+ auto patternData = std::make_unique<PatternData>();
patternData->pattern = Pattern::create(copiedImage, true, true);
// Compute pattern space transformation.
- const IntSize tileImageSize = tileImage->logicalSize();
+
patternData->transform.translate(tileBoundaries.x(), tileBoundaries.y());
patternData->transform.scale(tileBoundaries.width() / tileImageSize.width(), tileBoundaries.height() / tileImageSize.height());
@@ -123,7 +129,7 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign
// Account for text drawing resetting the context to non-scaled, see SVGInlineTextBox::paintTextWithShadows.
if (resourceMode & ApplyToTextMode) {
AffineTransform additionalTextTransformation;
- if (shouldTransformOnTextPainting(object, additionalTextTransformation))
+ if (shouldTransformOnTextPainting(renderer, additionalTextTransformation))
patternData->transform *= additionalTextTransformation;
}
patternData->pattern->setPatternSpaceTransform(patternData->transform);
@@ -131,7 +137,7 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign
// Various calls above may trigger invalidations in some fringe cases (ImageBuffer allocation
// failures in the SVG image cache for example). To avoid having our PatternData deleted by
// removeAllClientsFromCache(), we only make it visible in the cache at the very end.
- return m_patternMap.set(object, patternData.release()).iterator->value.get();
+ return m_patternMap.set(&renderer, WTFMove(patternData)).iterator->value.get();
}
bool RenderSVGResourcePattern::applyResource(RenderElement& renderer, const RenderStyle& style, GraphicsContext*& context, unsigned short resourceMode)
@@ -139,13 +145,21 @@ bool RenderSVGResourcePattern::applyResource(RenderElement& renderer, const Rend
ASSERT(context);
ASSERT(resourceMode != ApplyToDefaultMode);
+ if (m_shouldCollectPatternAttributes) {
+ patternElement().synchronizeAnimatedSVGAttribute(anyQName());
+
+ m_attributes = PatternAttributes();
+ collectPatternAttributes(m_attributes);
+ m_shouldCollectPatternAttributes = false;
+ }
+
// Spec: When the geometry of the applicable element has no width or height and objectBoundingBox is specified,
// then the given effect (e.g. a gradient or a filter) will be ignored.
FloatRect objectBoundingBox = renderer.objectBoundingBox();
if (m_attributes.patternUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty())
return false;
- PatternData* patternData = buildPattern(&renderer, resourceMode);
+ PatternData* patternData = buildPattern(renderer, resourceMode, *context);
if (!patternData)
return false;
@@ -156,13 +170,13 @@ bool RenderSVGResourcePattern::applyResource(RenderElement& renderer, const Rend
if (resourceMode & ApplyToFillMode) {
context->setAlpha(svgStyle.fillOpacity());
- context->setFillPattern(patternData->pattern);
+ context->setFillPattern(*patternData->pattern);
context->setFillRule(svgStyle.fillRule());
} else if (resourceMode & ApplyToStrokeMode) {
if (svgStyle.vectorEffect() == VE_NON_SCALING_STROKE)
patternData->pattern->setPatternSpaceTransform(transformOnNonScalingStroke(&renderer, patternData->transform));
context->setAlpha(svgStyle.strokeOpacity());
- context->setStrokePattern(patternData->pattern);
+ context->setStrokePattern(*patternData->pattern);
SVGRenderSupport::applyStrokeStyleToContext(context, style, renderer);
}
@@ -194,13 +208,13 @@ void RenderSVGResourcePattern::postApplyResource(RenderElement&, GraphicsContext
if (path)
context->fillPath(*path);
else if (shape)
- shape->fillShape(context);
+ shape->fillShape(*context);
}
if (resourceMode & ApplyToStrokeMode) {
if (path)
context->strokePath(*path);
else if (shape)
- shape->strokeShape(context);
+ shape->strokeShape(*context);
}
context->restore();
@@ -213,15 +227,13 @@ static inline FloatRect calculatePatternBoundaries(const PatternAttributes& attr
return SVGLengthContext::resolveRectangle(&patternElement, attributes.patternUnits(), objectBoundingBox, attributes.x(), attributes.y(), attributes.width(), attributes.height());
}
-bool RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer,
+bool RenderSVGResourcePattern::buildTileImageTransform(RenderElement& renderer,
const PatternAttributes& attributes,
const SVGPatternElement& patternElement,
FloatRect& patternBoundaries,
AffineTransform& tileImageTransform) const
{
- ASSERT(renderer);
-
- FloatRect objectBoundingBox = renderer->objectBoundingBox();
+ FloatRect objectBoundingBox = renderer.objectBoundingBox();
patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement);
if (patternBoundaries.width() <= 0 || patternBoundaries.height() <= 0)
return false;
@@ -237,25 +249,22 @@ bool RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer,
return true;
}
-std::unique_ptr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes, const FloatRect& tileBoundaries, const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform, FloatRect& clampedAbsoluteTileBoundaries) const
+std::unique_ptr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes, const FloatRect& tileBoundaries, const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform, FloatRect& clampedAbsoluteTileBoundaries, RenderingMode renderingMode) const
{
- clampedAbsoluteTileBoundaries = SVGRenderingContext::clampedAbsoluteTargetRect(absoluteTileBoundaries);
-
- std::unique_ptr<ImageBuffer> tileImage;
-
- if (!SVGRenderingContext::createImageBufferForPattern(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, tileImage, ColorSpaceDeviceRGB, Unaccelerated))
+ clampedAbsoluteTileBoundaries = ImageBuffer::clampedRect(absoluteTileBoundaries);
+ auto tileImage = SVGRenderingContext::createImageBuffer(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, ColorSpaceSRGB, renderingMode);
+ if (!tileImage)
return nullptr;
- GraphicsContext* tileImageContext = tileImage->context();
- ASSERT(tileImageContext);
+ GraphicsContext& tileImageContext = tileImage->context();
// The image buffer represents the final rendered size, so the content has to be scaled (to avoid pixelation).
- tileImageContext->scale(FloatSize(clampedAbsoluteTileBoundaries.width() / tileBoundaries.width(),
+ tileImageContext.scale(FloatSize(clampedAbsoluteTileBoundaries.width() / tileBoundaries.width(),
clampedAbsoluteTileBoundaries.height() / tileBoundaries.height()));
// Apply tile image transformations.
if (!tileImageTransform.isIdentity())
- tileImageContext->concatCTM(tileImageTransform);
+ tileImageContext.concatCTM(tileImageTransform);
AffineTransform contentTransformation;
if (attributes.patternContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
@@ -274,5 +283,3 @@ std::unique_ptr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const Pat
}
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h
index 9eebeefa4..5f5b560df 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h
@@ -18,17 +18,15 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGResourcePattern_h
-#define RenderSVGResourcePattern_h
+#pragma once
-#if ENABLE(SVG)
#include "ImageBuffer.h"
#include "Pattern.h"
#include "PatternAttributes.h"
#include "RenderSVGResourceContainer.h"
#include "SVGPatternElement.h"
#include "SVGUnitTypes.h"
-
+#include <memory>
#include <wtf/HashMap.h>
namespace WebCore {
@@ -42,35 +40,35 @@ public:
class RenderSVGResourcePattern final : public RenderSVGResourceContainer {
public:
- RenderSVGResourcePattern(SVGPatternElement&, PassRef<RenderStyle>);
+ RenderSVGResourcePattern(SVGPatternElement&, RenderStyle&&);
SVGPatternElement& patternElement() const;
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject&, bool markForInvalidation = true);
+ void removeAllClientsFromCache(bool markForInvalidation = true) override;
+ void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override;
+
+ bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) override;
+ void postApplyResource(RenderElement&, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) override;
+ FloatRect resourceBoundingBox(const RenderObject&) override { return FloatRect(); }
- virtual bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) override;
- virtual void postApplyResource(RenderElement&, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) override;
- virtual FloatRect resourceBoundingBox(const RenderObject&) override { return FloatRect(); }
+ RenderSVGResourceType resourceType() const override { return PatternResourceType; }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
- static RenderSVGResourceType s_resourceType;
+ void collectPatternAttributes(PatternAttributes&) const;
private:
void element() const = delete;
- virtual const char* renderName() const override { return "RenderSVGResourcePattern"; }
+ const char* renderName() const override { return "RenderSVGResourcePattern"; }
- bool buildTileImageTransform(RenderObject*, const PatternAttributes&, const SVGPatternElement&, FloatRect& patternBoundaries, AffineTransform& tileImageTransform) const;
+ bool buildTileImageTransform(RenderElement&, const PatternAttributes&, const SVGPatternElement&, FloatRect& patternBoundaries, AffineTransform& tileImageTransform) const;
- std::unique_ptr<ImageBuffer> createTileImage(const PatternAttributes&, const FloatRect& tileBoundaries, const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform, FloatRect& clampedAbsoluteTileBoundaries) const;
+ std::unique_ptr<ImageBuffer> createTileImage(const PatternAttributes&, const FloatRect& tileBoundaries, const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform, FloatRect& clampedAbsoluteTileBoundaries, RenderingMode) const;
- PatternData* buildPattern(RenderObject*, unsigned short resourceMode);
+ PatternData* buildPattern(RenderElement&, unsigned short resourceMode, GraphicsContext&);
bool m_shouldCollectPatternAttributes : 1;
PatternAttributes m_attributes;
- HashMap<RenderObject*, OwnPtr<PatternData>> m_patternMap;
+ HashMap<RenderElement*, std::unique_ptr<PatternData>> m_patternMap;
};
-}
+} // namespace WebCore
-#endif
-#endif
+SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourcePattern, PatternResourceType)
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp
index 1f5b8d163..ecbc39b89 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp
@@ -20,17 +20,12 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGResourceRadialGradient.h"
-
namespace WebCore {
-RenderSVGResourceType RenderSVGResourceRadialGradient::s_resourceType = RadialGradientResourceType;
-
-RenderSVGResourceRadialGradient::RenderSVGResourceRadialGradient(SVGRadialGradientElement& element, PassRef<RenderStyle> style)
- : RenderSVGResourceGradient(element, std::move(style))
+RenderSVGResourceRadialGradient::RenderSVGResourceRadialGradient(SVGRadialGradientElement& element, RenderStyle&& style)
+ : RenderSVGResourceGradient(element, WTFMove(style))
{
}
@@ -77,5 +72,3 @@ void RenderSVGResourceRadialGradient::buildGradient(GradientData* gradientData)
}
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h b/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h
index f1e61a4ee..0b8ae3efd 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h
@@ -18,10 +18,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGResourceRadialGradient_h
-#define RenderSVGResourceRadialGradient_h
+#pragma once
-#if ENABLE(SVG)
#include "RadialGradientAttributes.h"
#include "RenderSVGResourceGradient.h"
#include "SVGRadialGradientElement.h"
@@ -32,17 +30,16 @@ class SVGRadialGradientElement;
class RenderSVGResourceRadialGradient final : public RenderSVGResourceGradient {
public:
- RenderSVGResourceRadialGradient(SVGRadialGradientElement&, PassRef<RenderStyle>);
+ RenderSVGResourceRadialGradient(SVGRadialGradientElement&, RenderStyle&&);
virtual ~RenderSVGResourceRadialGradient();
- SVGRadialGradientElement& radialGradientElement() const { return toSVGRadialGradientElement(RenderSVGResourceGradient::gradientElement()); }
+ SVGRadialGradientElement& radialGradientElement() const { return downcast<SVGRadialGradientElement>(RenderSVGResourceGradient::gradientElement()); }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
- static RenderSVGResourceType s_resourceType;
+ RenderSVGResourceType resourceType() const override { return RadialGradientResourceType; }
- virtual SVGUnitTypes::SVGUnitType gradientUnits() const { return m_attributes.gradientUnits(); }
- virtual void calculateGradientTransform(AffineTransform& transform) { transform = m_attributes.gradientTransform(); }
- virtual void buildGradient(GradientData*) const;
+ SVGUnitTypes::SVGUnitType gradientUnits() const override { return m_attributes.gradientUnits(); }
+ void calculateGradientTransform(AffineTransform& transform) override { transform = m_attributes.gradientTransform(); }
+ void buildGradient(GradientData*) const override;
FloatPoint centerPoint(const RadialGradientAttributes&) const;
FloatPoint focalPoint(const RadialGradientAttributes&) const;
@@ -52,13 +49,12 @@ public:
private:
void gradientElement() const = delete;
- virtual const char* renderName() const override { return "RenderSVGResourceRadialGradient"; }
- virtual bool collectGradientAttributes() override;
+ const char* renderName() const override { return "RenderSVGResourceRadialGradient"; }
+ bool collectGradientAttributes() override;
RadialGradientAttributes m_attributes;
};
-}
+} // namespace WebCore
-#endif
-#endif
+SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourceRadialGradient, RadialGradientResourceType)
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp
index 1d9ada519..4b20da58f 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp
@@ -18,8 +18,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGResourceSolidColor.h"
#include "Frame.h"
@@ -30,8 +28,6 @@
namespace WebCore {
-RenderSVGResourceType RenderSVGResourceSolidColor::s_resourceType = SolidColorResourceType;
-
RenderSVGResourceSolidColor::RenderSVGResourceSolidColor()
{
}
@@ -46,7 +42,6 @@ bool RenderSVGResourceSolidColor::applyResource(RenderElement& renderer, const R
ASSERT(resourceMode != ApplyToDefaultMode);
const SVGRenderStyle& svgStyle = style.svgStyle();
- ColorSpace colorSpace = style.colorSpace();
bool isRenderingMask = renderer.view().frameView().paintBehavior() & PaintBehaviorRenderingSVGMask;
@@ -55,7 +50,7 @@ bool RenderSVGResourceSolidColor::applyResource(RenderElement& renderer, const R
context->setAlpha(svgStyle.fillOpacity());
else
context->setAlpha(1);
- context->setFillColor(m_color, colorSpace);
+ context->setFillColor(m_color);
if (!isRenderingMask)
context->setFillRule(svgStyle.fillRule());
@@ -65,7 +60,7 @@ bool RenderSVGResourceSolidColor::applyResource(RenderElement& renderer, const R
// When rendering the mask for a RenderSVGResourceClipper, the stroke code path is never hit.
ASSERT(!isRenderingMask);
context->setAlpha(svgStyle.strokeOpacity());
- context->setStrokeColor(m_color, colorSpace);
+ context->setStrokeColor(m_color);
SVGRenderSupport::applyStrokeStyleToContext(context, style, renderer);
@@ -85,16 +80,14 @@ void RenderSVGResourceSolidColor::postApplyResource(RenderElement&, GraphicsCont
if (path)
context->fillPath(*path);
else if (shape)
- shape->fillShape(context);
+ shape->fillShape(*context);
}
if (resourceMode & ApplyToStrokeMode) {
if (path)
context->strokePath(*path);
else if (shape)
- shape->strokeShape(context);
+ shape->strokeShape(*context);
}
}
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h b/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h
index 80eb45df6..79301bcab 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h
@@ -17,29 +17,27 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGResourceSolidColor_h
-#define RenderSVGResourceSolidColor_h
+#pragma once
-#if ENABLE(SVG)
#include "Color.h"
#include "RenderSVGResource.h"
namespace WebCore {
-class RenderSVGResourceSolidColor : public RenderSVGResource {
+class RenderSVGResourceSolidColor final : public RenderSVGResource {
+ WTF_MAKE_FAST_ALLOCATED;
public:
RenderSVGResourceSolidColor();
virtual ~RenderSVGResourceSolidColor();
- virtual void removeAllClientsFromCache(bool = true) { }
- virtual void removeClientFromCache(RenderObject&, bool = true) { }
+ void removeAllClientsFromCache(bool = true) override { }
+ void removeClientFromCache(RenderElement&, bool = true) override { }
- virtual bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) override;
- virtual void postApplyResource(RenderElement&, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) override;
- virtual FloatRect resourceBoundingBox(const RenderObject&) override { return FloatRect(); }
+ bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) override;
+ void postApplyResource(RenderElement&, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) override;
+ FloatRect resourceBoundingBox(const RenderObject&) override { return FloatRect(); }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
- static RenderSVGResourceType s_resourceType;
+ RenderSVGResourceType resourceType() const override { return SolidColorResourceType; }
const Color& color() const { return m_color; }
void setColor(const Color& color) { m_color = color; }
@@ -48,7 +46,6 @@ private:
Color m_color;
};
-}
+} // namespace WebCore
-#endif
-#endif
+SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourceSolidColor, SolidColorResourceType)
diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
index 6de3aa3c6..0ddbbbcac 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
@@ -22,21 +22,21 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGRoot.h"
-#include "Chrome.h"
-#include "ChromeClient.h"
#include "Frame.h"
#include "GraphicsContext.h"
#include "HitTestResult.h"
#include "LayoutRepainter.h"
#include "Page.h"
#include "RenderIterator.h"
+#include "RenderLayer.h"
+#include "RenderNamedFlowFragment.h"
+#include "RenderSVGResource.h"
+#include "RenderSVGResourceContainer.h"
+#include "RenderSVGResourceFilter.h"
#include "RenderView.h"
#include "SVGImage.h"
-#include "SVGLength.h"
#include "SVGRenderingContext.h"
#include "SVGResources.h"
#include "SVGResourcesCache.h"
@@ -45,18 +45,15 @@
#include "TransformState.h"
#include <wtf/StackStats.h>
-#if ENABLE(FILTERS)
-#include "RenderSVGResourceFilter.h"
-#endif
-
namespace WebCore {
-RenderSVGRoot::RenderSVGRoot(SVGSVGElement& element, PassRef<RenderStyle> style)
- : RenderReplaced(element, std::move(style))
+RenderSVGRoot::RenderSVGRoot(SVGSVGElement& element, RenderStyle&& style)
+ : RenderReplaced(element, WTFMove(style))
, m_objectBoundingBoxValid(false)
, m_isLayoutSizeChanged(false)
, m_needsBoundariesOrTransformUpdate(true)
, m_hasSVGShadow(false)
+ , m_hasBoxDecorations(false)
{
}
@@ -66,20 +63,13 @@ RenderSVGRoot::~RenderSVGRoot()
SVGSVGElement& RenderSVGRoot::svgSVGElement() const
{
- return toSVGSVGElement(nodeForNonAnonymous());
+ return downcast<SVGSVGElement>(nodeForNonAnonymous());
}
-void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const
{
// Spec: http://www.w3.org/TR/SVG/coords.html#IntrinsicSizing
// SVG needs to specify how to calculate some intrinsic sizing properties to enable inclusion within other languages.
- // The intrinsic width and height of the viewport of SVG content must be determined from the ‘width’ and ‘height’ attributes.
- // If either of these are not specified, a value of '100%' must be assumed. Note: the ‘width’ and ‘height’ attributes are not
- // the same as the CSS width and height properties. Specifically, percentage values do not provide an intrinsic width or height,
- // and do not indicate a percentage of the containing block. Rather, once the viewport is established, they indicate the portion
- // of the viewport that is actually covered by image data.
- Length intrinsicWidthAttribute = svgSVGElement().intrinsicWidth(SVGSVGElement::IgnoreCSSProperties);
- Length intrinsicHeightAttribute = svgSVGElement().intrinsicHeight(SVGSVGElement::IgnoreCSSProperties);
// The intrinsic aspect ratio of the viewport of SVG content is necessary for example, when including SVG from an ‘object’
// element in HTML styled with CSS. It is possible (indeed, common) for an SVG graphic to have an intrinsic aspect ratio but
@@ -88,33 +78,22 @@ void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, d
// - If the ‘width’ and ‘height’ of the rootmost ‘svg’ element are both specified with unit identifiers (in, mm, cm, pt, pc,
// px, em, ex) or in user units, then the aspect ratio is calculated from the ‘width’ and ‘height’ attributes after
// resolving both values to user units.
- if (intrinsicWidthAttribute.isFixed() || intrinsicHeightAttribute.isFixed()) {
- if (intrinsicWidthAttribute.isFixed())
- intrinsicSize.setWidth(floatValueForLength(intrinsicWidthAttribute, 0));
- if (intrinsicHeightAttribute.isFixed())
- intrinsicSize.setHeight(floatValueForLength(intrinsicHeightAttribute, 0));
- if (!intrinsicSize.isEmpty())
- intrinsicRatio = intrinsicSize.width() / static_cast<double>(intrinsicSize.height());
- return;
- }
+ intrinsicSize.setWidth(floatValueForLength(svgSVGElement().intrinsicWidth(), 0));
+ intrinsicSize.setHeight(floatValueForLength(svgSVGElement().intrinsicHeight(), 0));
- // - If either/both of the ‘width’ and ‘height’ of the rootmost ‘svg’ element are in percentage units (or omitted), the
- // aspect ratio is calculated from the width and height values of the ‘viewBox’ specified for the current SVG document
- // fragment. If the ‘viewBox’ is not correctly specified, or set to 'none', the intrinsic aspect ratio cannot be
- // calculated and is considered unspecified.
- intrinsicSize = svgSVGElement().viewBox().size();
- if (!intrinsicSize.isEmpty()) {
- // The viewBox can only yield an intrinsic ratio, not an intrinsic size.
- intrinsicRatio = intrinsicSize.width() / static_cast<double>(intrinsicSize.height());
- intrinsicSize = FloatSize();
- return;
- }
- // If our intrinsic size is in percentage units, return those to the caller through the intrinsicSize. Notify the caller
- // about the special situation, by setting isPercentageIntrinsicSize=true, so it knows how to interpret the return values.
- if (intrinsicWidthAttribute.isPercent() && intrinsicHeightAttribute.isPercent()) {
- isPercentageIntrinsicSize = true;
- intrinsicSize = FloatSize(intrinsicWidthAttribute.percent(), intrinsicHeightAttribute.percent());
+ if (!intrinsicSize.isEmpty())
+ intrinsicRatio = intrinsicSize.width() / static_cast<double>(intrinsicSize.height());
+ else {
+ // - If either/both of the ‘width’ and ‘height’ of the rootmost ‘svg’ element are in percentage units (or omitted), the
+ // aspect ratio is calculated from the width and height values of the ‘viewBox’ specified for the current SVG document
+ // fragment. If the ‘viewBox’ is not correctly specified, or set to 'none', the intrinsic aspect ratio cannot be
+ // calculated and is considered unspecified.
+ FloatSize viewBoxSize = svgSVGElement().viewBox().size();
+ if (!viewBoxSize.isEmpty()) {
+ // The viewBox can only yield an intrinsic ratio, not an intrinsic size.
+ intrinsicRatio = viewBoxSize.width() / static_cast<double>(viewBoxSize.height());
+ }
}
}
@@ -132,9 +111,9 @@ bool RenderSVGRoot::isEmbeddedThroughFrameContainingSVGDocument() const
return frame().document()->isSVGDocument();
}
-static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize, RenderView* renderView)
+static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize)
{
- return static_cast<LayoutUnit>(valueForLength(length, maxSize, renderView) * (length.isFixed() ? scale : 1));
+ return valueForLength(length, maxSize) * (length.isFixed() ? scale : 1);
}
LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const
@@ -143,50 +122,24 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(ShouldComputePreferred sho
if (!m_containerSize.isEmpty())
return m_containerSize.width();
- if (style().logicalWidth().isSpecified() || style().logicalMaxWidth().isSpecified())
- return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred);
-
- if (svgSVGElement().widthAttributeEstablishesViewport())
- return resolveLengthAttributeForSVG(svgSVGElement().intrinsicWidth(SVGSVGElement::IgnoreCSSProperties), style().effectiveZoom(), containingBlock()->availableLogicalWidth(), &view());
-
- // SVG embedded through object/embed/iframe.
if (isEmbeddedThroughFrameContainingSVGDocument())
- return frame().ownerRenderer()->availableLogicalWidth();
+ return containingBlock()->availableLogicalWidth();
// SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG.
return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred);
}
-LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const
+LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight(std::optional<LayoutUnit> estimatedUsedWidth) const
{
// When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size.
if (!m_containerSize.isEmpty())
return m_containerSize.height();
- if (style().logicalHeight().isSpecified() || style().logicalMaxHeight().isSpecified())
- return RenderReplaced::computeReplacedLogicalHeight();
-
- if (svgSVGElement().heightAttributeEstablishesViewport()) {
- Length height = svgSVGElement().intrinsicHeight(SVGSVGElement::IgnoreCSSProperties);
- if (height.isPercent()) {
- RenderBlock* cb = containingBlock();
- ASSERT(cb);
- while (cb->isAnonymous() && !cb->isRenderView()) {
- cb = cb->containingBlock();
- cb->addPercentHeightDescendant(const_cast<RenderSVGRoot&>(*this));
- }
- } else
- RenderBlock::removePercentHeightDescendant(const_cast<RenderSVGRoot&>(*this));
-
- return resolveLengthAttributeForSVG(height, style().effectiveZoom(), containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding), &view());
- }
-
- // SVG embedded through object/embed/iframe.
if (isEmbeddedThroughFrameContainingSVGDocument())
- return frame().ownerRenderer()->availableLogicalHeight(IncludeMarginBorderPadding);
+ return containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding);
// SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG.
- return RenderReplaced::computeReplacedLogicalHeight();
+ return RenderReplaced::computeReplacedLogicalHeight(estimatedUsedWidth);
}
void RenderSVGRoot::layout()
@@ -197,7 +150,7 @@ void RenderSVGRoot::layout()
m_resourcesNeedingToInvalidateClients.clear();
// Arbitrary affine transforms are incompatible with LayoutState.
- LayoutStateDisabler layoutStateDisabler(&view());
+ LayoutStateDisabler layoutStateDisabler(view());
bool needsLayout = selfNeedsLayout();
LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && needsLayout);
@@ -212,9 +165,10 @@ void RenderSVGRoot::layout()
if (!m_resourcesNeedingToInvalidateClients.isEmpty()) {
// Invalidate resource clients, which may mark some nodes for layout.
- HashSet<RenderSVGResourceContainer*>::iterator end = m_resourcesNeedingToInvalidateClients.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = m_resourcesNeedingToInvalidateClients.begin(); it != end; ++it)
- (*it)->removeAllClientsFromCache();
+ for (auto& resource : m_resourcesNeedingToInvalidateClients) {
+ resource->removeAllClientsFromCache();
+ SVGResourcesCache::clientStyleChanged(*resource, StyleDifferenceLayout, resource->style());
+ }
m_isLayoutSizeChanged = false;
SVGRenderSupport::layoutChildren(*this, false);
@@ -227,21 +181,45 @@ void RenderSVGRoot::layout()
m_needsBoundariesOrTransformUpdate = false;
}
+ clearOverflow();
+ if (!shouldApplyViewportClip()) {
+ FloatRect contentRepaintRect = repaintRectInLocalCoordinates();
+ contentRepaintRect = m_localToBorderBoxTransform.mapRect(contentRepaintRect);
+ addVisualOverflow(enclosingLayoutRect(contentRepaintRect));
+ }
+
updateLayerTransform();
+ m_hasBoxDecorations = isDocumentElementRenderer() ? hasVisibleBoxDecorationStyle() : hasVisibleBoxDecorations();
+ invalidateBackgroundObscurationStatus();
repainter.repaintAfterLayout();
clearNeedsLayout();
}
+bool RenderSVGRoot::shouldApplyViewportClip() const
+{
+ // the outermost svg is clipped if auto, and svg document roots are always clipped
+ // When the svg is stand-alone (isDocumentElement() == true) the viewport clipping should always
+ // be applied, noting that the window scrollbars should be hidden if overflow=hidden.
+ return style().overflowX() == OHIDDEN
+ || style().overflowX() == OAUTO
+ || style().overflowX() == OSCROLL
+ || this->isDocumentElementRenderer();
+}
+
void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
// An empty viewport disables rendering.
- if (pixelSnappedBorderBoxRect().isEmpty())
+ if (borderBoxRect().isEmpty())
return;
// Don't paint, if the context explicitly disabled it.
- if (paintInfo.context->paintingDisabled())
+ if (paintInfo.context().paintingDisabled())
+ return;
+
+ // SVG outlines are painted during PaintPhaseForeground.
+ if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline)
return;
// An empty viewBox also disables rendering.
@@ -249,34 +227,33 @@ void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paint
if (svgSVGElement().hasEmptyViewBox())
return;
- Page* page = frame().page();
-
// Don't paint if we don't have kids, except if we have filters we should paint those.
if (!firstChild()) {
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this);
if (!resources || !resources->filter()) {
- if (page && paintInfo.phase == PaintPhaseForeground)
- page->addRelevantUnpaintedObject(this, visualOverflowRect());
+ if (paintInfo.phase == PaintPhaseForeground)
+ page().addRelevantUnpaintedObject(this, visualOverflowRect());
return;
}
}
- if (page && paintInfo.phase == PaintPhaseForeground)
- page->addRelevantRepaintedObject(this, visualOverflowRect());
+ if (paintInfo.phase == PaintPhaseForeground)
+ page().addRelevantRepaintedObject(this, visualOverflowRect());
// Make a copy of the PaintInfo because applyTransform will modify the damage rect.
PaintInfo childPaintInfo(paintInfo);
- childPaintInfo.context->save();
+ childPaintInfo.context().save();
- // Apply initial viewport clip - not affected by overflow handling
- childPaintInfo.context->clip(pixelSnappedIntRect(overflowClipRect(paintOffset, paintInfo.renderRegion)));
+ // Apply initial viewport clip
+ if (shouldApplyViewportClip())
+ childPaintInfo.context().clip(snappedIntRect(overflowClipRect(paintOffset, currentRenderNamedFlowFragment())));
// Convert from container offsets (html renderers) to a relative transform (svg renderers).
// Transform from our paint container's coordinate system to our local coords.
IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset);
childPaintInfo.applyTransform(AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y()) * localToBorderBoxTransform());
- // SVGRenderingContext must be destroyed before we restore the childPaintInfo.context, because a filter may have
+ // SVGRenderingContext must be destroyed before we restore the childPaintInfo.context(), because a filter may have
// changed the context and it is only reverted when the SVGRenderingContext destructor finishes applying the filter.
{
SVGRenderingContext renderingContext;
@@ -293,7 +270,7 @@ void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paint
}
}
- childPaintInfo.context->restore();
+ childPaintInfo.context().restore();
}
void RenderSVGRoot::willBeDestroyed()
@@ -304,10 +281,27 @@ void RenderSVGRoot::willBeDestroyed()
RenderReplaced::willBeDestroyed();
}
+void RenderSVGRoot::insertedIntoTree()
+{
+ RenderReplaced::insertedIntoTree();
+ SVGResourcesCache::clientWasAddedToTree(*this);
+}
+
+void RenderSVGRoot::willBeRemovedFromTree()
+{
+ SVGResourcesCache::clientWillBeRemovedFromTree(*this);
+ RenderReplaced::willBeRemovedFromTree();
+}
+
void RenderSVGRoot::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
if (diff == StyleDifferenceLayout)
setNeedsBoundariesUpdate();
+
+ // Box decorations may have appeared/disappeared - recompute status.
+ if (diff == StyleDifferenceRepaint)
+ m_hasBoxDecorations = hasVisibleBoxDecorationStyle();
+
RenderReplaced::styleDidChange(diff, oldStyle);
SVGResourcesCache::clientStyleChanged(*this, diff, style());
}
@@ -329,10 +323,10 @@ void RenderSVGRoot::removeChild(RenderObject& child)
void RenderSVGRoot::buildLocalToBorderBoxTransform()
{
float scale = style().effectiveZoom();
- SVGPoint translate = svgSVGElement().currentTranslate();
+ FloatPoint translate = svgSVGElement().currentTranslateValue();
LayoutSize borderAndPadding(borderLeft() + paddingLeft(), borderTop() + paddingTop());
m_localToBorderBoxTransform = svgSVGElement().viewBoxToViewTransform(contentWidth() / scale, contentHeight() / scale);
- if (borderAndPadding.isEmpty() && scale == 1 && translate == SVGPoint::zero())
+ if (borderAndPadding.isZero() && scale == 1 && translate == FloatPoint::zero())
return;
m_localToBorderBoxTransform = AffineTransform(scale, 0, 0, scale, borderAndPadding.width() + translate.x(), borderAndPadding.height() + translate.y()) * m_localToBorderBoxTransform;
}
@@ -350,25 +344,40 @@ const AffineTransform& RenderSVGRoot::localToParentTransform() const
LayoutRect RenderSVGRoot::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
{
- return SVGRenderSupport::clippedOverflowRectForRepaint(*this, repaintContainer);
+ if (style().visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
+ return LayoutRect();
+
+ FloatRect contentRepaintRect = m_localToBorderBoxTransform.mapRect(repaintRectInLocalCoordinates());
+ contentRepaintRect.intersect(snappedIntRect(borderBoxRect()));
+
+ LayoutRect repaintRect = enclosingLayoutRect(contentRepaintRect);
+ if (m_hasBoxDecorations || hasRenderOverflow())
+ repaintRect.unite(unionRect(localSelectionRect(false), visualOverflowRect()));
+
+ return RenderReplaced::computeRectForRepaint(enclosingIntRect(repaintRect), repaintContainer);
}
-void RenderSVGRoot::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+FloatRect RenderSVGRoot::computeFloatRectForRepaint(const FloatRect& repaintRect, const RenderLayerModelObject* repaintContainer, bool fixed) const
{
// Apply our local transforms (except for x/y translation), then our shadow,
// and then call RenderBox's method to handle all the normal CSS Box model bits
- repaintRect = m_localToBorderBoxTransform.mapRect(repaintRect);
+ FloatRect adjustedRect = m_localToBorderBoxTransform.mapRect(repaintRect);
const SVGRenderStyle& svgStyle = style().svgStyle();
if (const ShadowData* shadow = svgStyle.shadow())
- shadow->adjustRectForShadow(repaintRect);
+ shadow->adjustRectForShadow(adjustedRect);
- // Apply initial viewport clip - not affected by overflow settings
- repaintRect.intersect(pixelSnappedBorderBoxRect());
+ // Apply initial viewport clip
+ if (shouldApplyViewportClip())
+ adjustedRect.intersect(snappedIntRect(borderBoxRect()));
- LayoutRect rect = enclosingIntRect(repaintRect);
- RenderReplaced::computeRectForRepaint(repaintContainer, rect, fixed);
- repaintRect = rect;
+ if (m_hasBoxDecorations || hasRenderOverflow()) {
+ // The selectionRect can project outside of the overflowRect, so take their union
+ // for repainting to avoid selection painting glitches.
+ LayoutRect decoratedRepaintRect = unionRect(localSelectionRect(false), visualOverflowRect());
+ adjustedRect.unite(decoratedRepaintRect);
+ }
+ return RenderReplaced::computeRectForRepaint(enclosingIntRect(adjustedRect), repaintContainer, {fixed, false});
}
// This method expects local CSS box coordinates.
@@ -391,7 +400,7 @@ void RenderSVGRoot::updateCachedBoundaries()
{
SVGRenderSupport::computeContainerBoundingBoxes(*this, m_objectBoundingBox, m_objectBoundingBoxValid, m_strokeBoundingBox, m_repaintBoundingBoxExcludingShadow);
SVGRenderSupport::intersectRepaintRectWithResources(*this, m_repaintBoundingBoxExcludingShadow);
- m_repaintBoundingBoxExcludingShadow.inflate(borderAndPaddingWidth());
+ m_repaintBoundingBoxExcludingShadow.inflate(horizontalBorderAndPaddingExtent());
m_repaintBoundingBox = m_repaintBoundingBoxExcludingShadow;
SVGRenderSupport::intersectRepaintRectWithShadows(*this, m_repaintBoundingBox);
@@ -405,7 +414,7 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
// Only test SVG content if the point is in our content box.
// FIXME: This should be an intersection when rect-based hit tests are supported by nodeAtFloatPoint.
if (contentBoxRect().contains(pointInBorderBox)) {
- FloatPoint localPoint = localToParentTransform().inverse().mapPoint(FloatPoint(pointInParent));
+ FloatPoint localPoint = localToParentTransform().inverse().value_or(AffineTransform()).mapPoint(FloatPoint(pointInParent));
for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
// FIXME: nodeAtFloatPoint() doesn't handle rect-based hit tests yet.
@@ -418,7 +427,7 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
}
// If we didn't early exit above, we've just hit the container <svg> element. Unlike SVG 1.1, 2nd Edition allows container elements to be hit.
- if (hitTestAction == HitTestBlockBackground && visibleToHitTesting()) {
+ if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && visibleToHitTesting()) {
// Only return true here, if the last hit testing phase 'BlockBackground' is executed. If we'd return true in the 'Foreground' phase,
// hit testing would stop immediately. For SVG only trees this doesn't matter. Though when we have a <foreignObject> subtree we need
// to be able to detect hits on the background of a <div> element. If we'd return true here in the 'Foreground' phase, we are not able
@@ -436,29 +445,15 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
bool RenderSVGRoot::hasRelativeDimensions() const
{
- return svgSVGElement().intrinsicHeight(SVGSVGElement::IgnoreCSSProperties).isPercent() || svgSVGElement().intrinsicWidth(SVGSVGElement::IgnoreCSSProperties).isPercent();
-}
-
-bool RenderSVGRoot::hasRelativeIntrinsicLogicalWidth() const
-{
- return svgSVGElement().intrinsicWidth(SVGSVGElement::IgnoreCSSProperties).isPercent();
-}
-
-bool RenderSVGRoot::hasRelativeLogicalHeight() const
-{
- return svgSVGElement().intrinsicHeight(SVGSVGElement::IgnoreCSSProperties).isPercent();
+ return svgSVGElement().intrinsicHeight().isPercentOrCalculated() || svgSVGElement().intrinsicWidth().isPercentOrCalculated();
}
void RenderSVGRoot::addResourceForClientInvalidation(RenderSVGResourceContainer* resource)
{
- RenderObject* svgRoot = resource->parent();
- while (svgRoot && !svgRoot->isSVGRoot())
- svgRoot = svgRoot->parent();
+ RenderSVGRoot* svgRoot = SVGRenderSupport::findTreeRootObject(*resource);
if (!svgRoot)
return;
- toRenderSVGRoot(svgRoot)->m_resourcesNeedingToInvalidateClients.add(resource);
+ svgRoot->m_resourcesNeedingToInvalidateClients.add(resource);
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.h b/Source/WebCore/rendering/svg/RenderSVGRoot.h
index edebf1cf8..ecff184fa 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRoot.h
+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.h
@@ -20,23 +20,21 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGRoot_h
-#define RenderSVGRoot_h
+#pragma once
-#if ENABLE(SVG)
#include "FloatRect.h"
#include "RenderReplaced.h"
-
#include "SVGRenderSupport.h"
namespace WebCore {
class AffineTransform;
+class RenderSVGResourceContainer;
class SVGSVGElement;
class RenderSVGRoot final : public RenderReplaced {
public:
- RenderSVGRoot(SVGSVGElement&, PassRef<RenderStyle>);
+ RenderSVGRoot(SVGSVGElement&, RenderStyle&&);
virtual ~RenderSVGRoot();
SVGSVGElement& svgSVGElement() const;
@@ -44,19 +42,17 @@ public:
bool isEmbeddedThroughSVGImage() const;
bool isEmbeddedThroughFrameContainingSVGDocument() const;
- virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const override;
+ void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const override;
bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; }
- virtual void setNeedsBoundariesUpdate() override { m_needsBoundariesOrTransformUpdate = true; }
- virtual bool needsBoundariesUpdate() override { return m_needsBoundariesOrTransformUpdate; }
- virtual void setNeedsTransformUpdate() override { m_needsBoundariesOrTransformUpdate = true; }
+ void setNeedsBoundariesUpdate() override { m_needsBoundariesOrTransformUpdate = true; }
+ bool needsBoundariesUpdate() override { return m_needsBoundariesOrTransformUpdate; }
+ void setNeedsTransformUpdate() override { m_needsBoundariesOrTransformUpdate = true; }
IntSize containerSize() const { return m_containerSize; }
void setContainerSize(const IntSize& containerSize) { m_containerSize = containerSize; }
- virtual bool hasRelativeDimensions() const override;
- virtual bool hasRelativeIntrinsicLogicalWidth() const override;
- virtual bool hasRelativeLogicalHeight() const override;
+ bool hasRelativeDimensions() const override;
// localToBorderBoxTransform maps local SVG viewport coordinates to local CSS box coordinates.
const AffineTransform& localToBorderBoxTransform() const { return m_localToBorderBoxTransform; }
@@ -71,40 +67,45 @@ public:
private:
void element() const = delete;
- virtual bool isSVGRoot() const override { return true; }
- virtual const char* renderName() const override { return "RenderSVGRoot"; }
+ bool isSVGRoot() const override { return true; }
+ const char* renderName() const override { return "RenderSVGRoot"; }
+
+ LayoutUnit computeReplacedLogicalWidth(ShouldComputePreferred = ComputeActual) const override;
+ LayoutUnit computeReplacedLogicalHeight(std::optional<LayoutUnit> estimatedUsedWidth = std::nullopt) const override;
+ void layout() override;
+ void paintReplaced(PaintInfo&, const LayoutPoint&) override;
- virtual LayoutUnit computeReplacedLogicalWidth(ShouldComputePreferred = ComputeActual) const override;
- virtual LayoutUnit computeReplacedLogicalHeight() const override;
- virtual void layout() override;
- virtual void paintReplaced(PaintInfo&, const LayoutPoint&) override;
+ void willBeDestroyed() override;
- virtual void willBeDestroyed() override;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) override;
- virtual void removeChild(RenderObject&) override;
+ void insertedIntoTree() override;
+ void willBeRemovedFromTree() override;
- virtual const AffineTransform& localToParentTransform() const override;
+ void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
+ void addChild(RenderObject* child, RenderObject* beforeChild = 0) override;
+ void removeChild(RenderObject&) override;
+
+ const AffineTransform& localToParentTransform() const override;
bool fillContains(const FloatPoint&) const;
bool strokeContains(const FloatPoint&) const;
- virtual FloatRect objectBoundingBox() const override { return m_objectBoundingBox; }
- virtual FloatRect strokeBoundingBox() const override { return m_strokeBoundingBox; }
- virtual FloatRect repaintRectInLocalCoordinates() const override { return m_repaintBoundingBox; }
- virtual FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const { return m_repaintBoundingBoxExcludingShadow; }
+ FloatRect objectBoundingBox() const override { return m_objectBoundingBox; }
+ FloatRect strokeBoundingBox() const override { return m_strokeBoundingBox; }
+ FloatRect repaintRectInLocalCoordinates() const override { return m_repaintBoundingBox; }
+ FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const { return m_repaintBoundingBoxExcludingShadow; }
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
+ bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const override;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const override;
+ LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const override;
+ FloatRect computeFloatRectForRepaint(const FloatRect&, const RenderLayerModelObject* repaintContainer, bool fixed) const override;
- virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const override;
- virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const override;
+ void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, bool* wasFixed) const override;
+ const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const override;
- virtual bool canBeSelectionLeaf() const override { return false; }
- virtual bool canHaveChildren() const override { return true; }
+ bool canBeSelectionLeaf() const override { return false; }
+ bool canHaveChildren() const override { return true; }
+ bool shouldApplyViewportClip() const;
void updateCachedBoundaries();
void buildLocalToBorderBoxTransform();
@@ -120,12 +121,9 @@ private:
bool m_isLayoutSizeChanged : 1;
bool m_needsBoundariesOrTransformUpdate : 1;
bool m_hasSVGShadow : 1;
+ bool m_hasBoxDecorations : 1;
};
-template<> inline bool isRendererOfType<const RenderSVGRoot>(const RenderObject& renderer) { return renderer.isSVGRoot(); }
-RENDER_OBJECT_TYPE_CASTS(RenderSVGRoot, isSVGRoot())
-
} // namespace WebCore
-#endif // ENABLE(SVG)
-#endif // RenderSVGRoot_h
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGRoot, isSVGRoot())
diff --git a/Source/WebCore/rendering/svg/RenderSVGShape.cpp b/Source/WebCore/rendering/svg/RenderSVGShape.cpp
index b93a028b5..d46734084 100644
--- a/Source/WebCore/rendering/svg/RenderSVGShape.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGShape.cpp
@@ -26,8 +26,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGShape.h"
#include "FloatPoint.h"
@@ -42,7 +40,6 @@
#include "SVGRenderingContext.h"
#include "SVGResources.h"
#include "SVGResourcesCache.h"
-#include "SVGTransformList.h"
#include "SVGURIReference.h"
#include "StrokeStyleApplier.h"
#include <wtf/StackStats.h>
@@ -56,7 +53,7 @@ public:
{
}
- virtual void strokeStyle(GraphicsContext* context) override
+ void strokeStyle(GraphicsContext* context) override
{
SVGRenderSupport::applyStrokeStyleToContext(context, m_renderer.style(), m_renderer);
}
@@ -65,8 +62,8 @@ private:
const RenderSVGShape& m_renderer;
};
-RenderSVGShape::RenderSVGShape(SVGGraphicsElement& element, PassRef<RenderStyle> style)
- : RenderSVGModelObject(element, std::move(style))
+RenderSVGShape::RenderSVGShape(SVGGraphicsElement& element, RenderStyle&& style)
+ : RenderSVGModelObject(element, WTFMove(style))
, m_needsBoundariesUpdate(false) // Default is false, the cached rects are empty from the beginning.
, m_needsShapeUpdate(true) // Default is true, so we grab a Path object once from SVGGraphicsElement.
, m_needsTransformUpdate(true) // Default is true, so we grab a AffineTransform object once from SVGGraphicsElement.
@@ -79,8 +76,7 @@ RenderSVGShape::~RenderSVGShape()
void RenderSVGShape::updateShapeFromElement()
{
- m_path.clear();
- m_path = adoptPtr(new Path);
+ m_path = std::make_unique<Path>();
ASSERT(RenderSVGShape::isEmpty());
updatePathFromGraphicsElement(&graphicsElement(), path());
@@ -92,15 +88,19 @@ void RenderSVGShape::updateShapeFromElement()
bool RenderSVGShape::isEmpty() const
{
- return path().isEmpty();
+ // 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
+void RenderSVGShape::fillShape(GraphicsContext& context) const
{
- context->fillPath(path());
+ context.fillPath(path());
}
-void RenderSVGShape::strokeShape(GraphicsContext* context) const
+void RenderSVGShape::strokeShape(GraphicsContext& context) const
{
ASSERT(m_path);
Path* usePath = m_path.get();
@@ -108,7 +108,7 @@ void RenderSVGShape::strokeShape(GraphicsContext* context) const
if (hasNonScalingStroke())
usePath = nonScalingStrokePath(usePath, nonScalingStrokeTransform());
- context->strokePath(*usePath);
+ context.strokePath(*usePath);
}
bool RenderSVGShape::shapeDependentStrokeContains(const FloatPoint& point)
@@ -190,21 +190,22 @@ void RenderSVGShape::layout()
Path* RenderSVGShape::nonScalingStrokePath(const Path* path, const AffineTransform& strokeTransform) const
{
- DEFINE_STATIC_LOCAL(Path, tempPath, ());
+ static NeverDestroyed<Path> tempPath;
- tempPath = *path;
- tempPath.transform(strokeTransform);
+ tempPath.get() = *path;
+ tempPath.get().transform(strokeTransform);
- return &tempPath;
+ return &tempPath.get();
}
bool RenderSVGShape::setupNonScalingStrokeContext(AffineTransform& strokeTransform, GraphicsContextStateSaver& stateSaver)
{
- if (!strokeTransform.isInvertible())
+ std::optional<AffineTransform> inverse = strokeTransform.inverse();
+ if (!inverse)
return false;
stateSaver.save();
- stateSaver.context()->concatCTM(strokeTransform.inverse());
+ stateSaver.context()->concatCTM(inverse.value());
return true;
}
@@ -221,15 +222,16 @@ bool RenderSVGShape::shouldGenerateMarkerPositions() const
if (!graphicsElement().supportsMarkers())
return false;
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this);
if (!resources)
return false;
return resources->markerStart() || resources->markerMid() || resources->markerEnd();
}
-void RenderSVGShape::fillShape(const RenderStyle& style, GraphicsContext* context)
+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, ApplyToFillMode))
@@ -243,8 +245,9 @@ void RenderSVGShape::fillShape(const RenderStyle& style, GraphicsContext* contex
}
}
-void RenderSVGShape::strokeShape(const RenderStyle& style, GraphicsContext* context)
+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, ApplyToStrokeMode))
@@ -258,62 +261,73 @@ void RenderSVGShape::strokeShape(const RenderStyle& style, GraphicsContext* cont
}
}
-void RenderSVGShape::fillAndStrokeShape(GraphicsContext* context)
+void RenderSVGShape::strokeShape(GraphicsContext& context)
{
- fillShape(style(), context);
-
- if (!style().svgStyle().hasVisibleStroke())
+ if (!style().hasVisibleStroke())
return;
- GraphicsContextStateSaver stateSaver(*context, false);
-
+ GraphicsContextStateSaver stateSaver(context, false);
if (hasNonScalingStroke()) {
AffineTransform nonScalingTransform = nonScalingStrokeTransform();
if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
return;
}
-
strokeShape(style(), context);
}
+void RenderSVGShape::fillStrokeMarkers(PaintInfo& childPaintInfo)
+{
+ auto paintOrder = style().paintTypesForPaintOrder();
+ for (unsigned i = 0; i < paintOrder.size(); ++i) {
+ switch (paintOrder.at(i)) {
+ case PaintTypeFill:
+ fillShape(style(), childPaintInfo.context());
+ break;
+ case PaintTypeStroke:
+ strokeShape(childPaintInfo.context());
+ break;
+ case PaintTypeMarkers:
+ if (!m_markerPositions.isEmpty())
+ drawMarkers(childPaintInfo);
+ break;
+ }
+ }
+}
+
void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
- if (paintInfo.context->paintingDisabled() || style().visibility() == HIDDEN || isEmpty())
+ if (paintInfo.context().paintingDisabled() || paintInfo.phase != PaintPhaseForeground
+ || style().visibility() == HIDDEN || isEmpty())
return;
FloatRect boundingBox = repaintRectInLocalCoordinates();
if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo))
return;
PaintInfo childPaintInfo(paintInfo);
- bool drawsOutline = style().outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline);
- if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) {
- GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
- childPaintInfo.applyTransform(m_localTransform);
-
- if (childPaintInfo.phase == PaintPhaseForeground) {
- SVGRenderingContext renderingContext(*this, childPaintInfo);
-
- if (renderingContext.isRenderingPrepared()) {
- const SVGRenderStyle& svgStyle = style().svgStyle();
- if (svgStyle.shapeRendering() == SR_CRISPEDGES)
- childPaintInfo.context->setShouldAntialias(false);
-
- fillAndStrokeShape(childPaintInfo.context);
- if (!m_markerPositions.isEmpty())
- drawMarkers(childPaintInfo);
- }
- }
+ GraphicsContextStateSaver stateSaver(childPaintInfo.context());
+ childPaintInfo.applyTransform(m_localTransform);
+
+ if (childPaintInfo.phase == PaintPhaseForeground) {
+ SVGRenderingContext renderingContext(*this, childPaintInfo);
- if (drawsOutline)
- paintOutline(childPaintInfo, IntRect(boundingBox));
+ if (renderingContext.isRenderingPrepared()) {
+ const SVGRenderStyle& svgStyle = style().svgStyle();
+ if (svgStyle.shapeRendering() == SR_CRISPEDGES)
+ childPaintInfo.context().setShouldAntialias(false);
+
+ fillStrokeMarkers(childPaintInfo);
+ }
}
+
+ if (style().outlineWidth())
+ paintOutline(childPaintInfo, IntRect(boundingBox));
}
// This method is called from inside paintOutline() since we call paintOutline()
// while transformed to our coord system, return local coords
-void RenderSVGShape::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
+void RenderSVGShape::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
{
- IntRect rect = enclosingIntRect(repaintRectInLocalCoordinates());
+ LayoutRect rect = LayoutRect(repaintRectInLocalCoordinates());
if (!rect.isEmpty())
rects.append(rect);
}
@@ -324,7 +338,7 @@ bool RenderSVGShape::nodeAtFloatPoint(const HitTestRequest& request, HitTestResu
if (hitTestAction != HitTestForeground)
return false;
- FloatPoint localPoint = m_localTransform.inverse().mapPoint(pointInParent);
+ FloatPoint localPoint = m_localTransform.inverse().value_or(AffineTransform()).mapPoint(pointInParent);
if (!SVGRenderSupport::pointInClippingArea(*this, localPoint))
return false;
@@ -338,7 +352,7 @@ bool RenderSVGShape::nodeAtFloatPoint(const HitTestRequest& request, HitTestResu
fillRule = svgStyle.clipRule();
if ((hitRules.canHitStroke && (svgStyle.hasStroke() || !hitRules.requireStroke) && strokeContains(localPoint, hitRules.requireStroke))
|| (hitRules.canHitFill && (svgStyle.hasFill() || !hitRules.requireFill) && fillContains(localPoint, hitRules.requireFill, fillRule))) {
- updateHitTestResult(result, roundedLayoutPoint(localPoint));
+ updateHitTestResult(result, LayoutPoint(localPoint));
return true;
}
}
@@ -364,7 +378,7 @@ FloatRect RenderSVGShape::markerRect(float strokeWidth) const
{
ASSERT(!m_markerPositions.isEmpty());
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this);
ASSERT(resources);
RenderSVGResourceMarker* markerStart = resources->markerStart();
@@ -396,10 +410,10 @@ FloatRect RenderSVGShape::calculateStrokeBoundingBox() const
BoundingRectStrokeStyleApplier strokeStyle(*this);
if (hasNonScalingStroke()) {
AffineTransform nonScalingTransform = nonScalingStrokeTransform();
- if (nonScalingTransform.isInvertible()) {
+ if (std::optional<AffineTransform> inverse = nonScalingTransform.inverse()) {
Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform);
FloatRect strokeBoundingRect = usePath->strokeBoundingRect(&strokeStyle);
- strokeBoundingRect = nonScalingTransform.inverse().mapRect(strokeBoundingRect);
+ strokeBoundingRect = inverse.value().mapRect(strokeBoundingRect);
strokeBoundingBox.unite(strokeBoundingRect);
}
} else
@@ -424,7 +438,7 @@ void RenderSVGShape::updateRepaintBoundingBox()
float RenderSVGShape::strokeWidth() const
{
SVGLengthContext lengthContext(&graphicsElement());
- return style().svgStyle().strokeWidth().value(lengthContext);
+ return lengthContext.valueForLength(style().strokeWidth());
}
bool RenderSVGShape::hasSmoothStroke() const
@@ -432,15 +446,15 @@ bool RenderSVGShape::hasSmoothStroke() const
const SVGRenderStyle& svgStyle = style().svgStyle();
return svgStyle.strokeDashArray().isEmpty()
&& svgStyle.strokeMiterLimit() == svgStyle.initialStrokeMiterLimit()
- && svgStyle.joinStyle() == svgStyle.initialJoinStyle()
- && svgStyle.capStyle() == svgStyle.initialCapStyle();
+ && style().joinStyle() == style().initialJoinStyle()
+ && style().capStyle() == style().initialCapStyle();
}
void RenderSVGShape::drawMarkers(PaintInfo& paintInfo)
{
ASSERT(!m_markerPositions.isEmpty());
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this);
if (!resources)
return;
@@ -467,11 +481,11 @@ void RenderSVGShape::processMarkerPositions()
ASSERT(m_path);
- SVGMarkerData markerData(m_markerPositions);
- m_path->apply(&markerData, SVGMarkerData::updateFromPathElement);
+ SVGMarkerData markerData(m_markerPositions, SVGResourcesCache::cachedResourcesForRenderer(*this)->markerReverseStart());
+ m_path->apply([&markerData](const PathElement& pathElement) {
+ SVGMarkerData::updateFromPathElement(markerData, pathElement);
+ });
markerData.pathIsDone();
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGShape.h b/Source/WebCore/rendering/svg/RenderSVGShape.h
index e27b4b42f..f1db416e4 100644
--- a/Source/WebCore/rendering/svg/RenderSVGShape.h
+++ b/Source/WebCore/rendering/svg/RenderSVGShape.h
@@ -2,7 +2,7 @@
* Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
- * Copyright (C) 2006 Apple Computer, Inc
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2009 Google, Inc.
* Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
* Copyright (C) 2011 University of Szeged
@@ -23,16 +23,14 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGShape_h
-#define RenderSVGShape_h
+#pragma once
-#if ENABLE(SVG)
#include "AffineTransform.h"
#include "FloatRect.h"
#include "RenderSVGModelObject.h"
#include "SVGGraphicsElement.h"
#include "SVGMarkerData.h"
-#include <wtf/OwnPtr.h>
+#include <memory>
#include <wtf/Vector.h>
namespace WebCore {
@@ -46,18 +44,18 @@ class SVGGraphicsElement;
class RenderSVGShape : public RenderSVGModelObject {
public:
- RenderSVGShape(SVGGraphicsElement&, PassRef<RenderStyle>);
- RenderSVGShape(SVGGraphicsElement&, PassRef<RenderStyle>, Path*, bool);
+ RenderSVGShape(SVGGraphicsElement&, RenderStyle&&);
virtual ~RenderSVGShape();
- SVGGraphicsElement& graphicsElement() const { return toSVGGraphicsElement(RenderSVGModelObject::element()); }
+ SVGGraphicsElement& graphicsElement() const { return downcast<SVGGraphicsElement>(RenderSVGModelObject::element()); }
void setNeedsShapeUpdate() { m_needsShapeUpdate = true; }
- virtual void setNeedsBoundariesUpdate() override final { m_needsBoundariesUpdate = true; }
- virtual bool needsBoundariesUpdate() override final { return m_needsBoundariesUpdate; }
- virtual void setNeedsTransformUpdate() override final { m_needsTransformUpdate = true; }
- virtual void fillShape(GraphicsContext*) const;
- virtual void strokeShape(GraphicsContext*) const;
+ void setNeedsBoundariesUpdate() final { m_needsBoundariesUpdate = true; }
+ bool needsBoundariesUpdate() final { return m_needsBoundariesUpdate; }
+ void setNeedsTransformUpdate() final { m_needsTransformUpdate = true; }
+ virtual void fillShape(GraphicsContext&) const;
+ virtual void strokeShape(GraphicsContext&) const;
+ virtual bool isRenderingDisabled() const = 0;
bool hasPath() const { return m_path.get(); }
Path& path() const
@@ -70,7 +68,7 @@ protected:
void element() const = delete;
virtual void updateShapeFromElement();
- virtual bool isEmpty() const override;
+ virtual bool isEmpty() const;
virtual bool shapeDependentStrokeContains(const FloatPoint&);
virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
float strokeWidth() const;
@@ -88,23 +86,23 @@ private:
bool fillContains(const FloatPoint&, bool requiresFill = true, const WindRule fillRule = RULE_NONZERO);
bool strokeContains(const FloatPoint&, bool requiresStroke = true);
- virtual FloatRect repaintRectInLocalCoordinates() const override final { return m_repaintBoundingBox; }
- virtual FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const override final { return m_repaintBoundingBoxExcludingShadow; }
- virtual const AffineTransform& localToParentTransform() const override final { return m_localTransform; }
- virtual AffineTransform localTransform() const override final { return m_localTransform; }
+ FloatRect repaintRectInLocalCoordinates() const final { return m_repaintBoundingBox; }
+ FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const final { return m_repaintBoundingBoxExcludingShadow; }
+ const AffineTransform& localToParentTransform() const final { return m_localTransform; }
+ AffineTransform localTransform() const final { return m_localTransform; }
- virtual bool isSVGShape() const override final { return true; }
- virtual bool canHaveChildren() const override final { return false; }
- virtual const char* renderName() const override { return "RenderSVGShape"; }
+ bool isSVGShape() const final { return true; }
+ bool canHaveChildren() const final { return false; }
+ const char* renderName() const override { return "RenderSVGShape"; }
- virtual void layout() override final;
- virtual void paint(PaintInfo&, const LayoutPoint&) override final;
- virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) override final;
+ void layout() final;
+ void paint(PaintInfo&, const LayoutPoint&) final;
+ void addFocusRingRects(Vector<LayoutRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) final;
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override final;
+ bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) final;
- virtual FloatRect objectBoundingBox() const override final { return m_fillBoundingBox; }
- virtual FloatRect strokeBoundingBox() const override final { return m_strokeBoundingBox; }
+ FloatRect objectBoundingBox() const final { return m_fillBoundingBox; }
+ FloatRect strokeBoundingBox() const final { return m_strokeBoundingBox; }
FloatRect calculateObjectBoundingBox() const;
FloatRect calculateStrokeBoundingBox() const;
void updateRepaintBoundingBox();
@@ -115,16 +113,17 @@ private:
FloatRect markerRect(float strokeWidth) const;
void processMarkerPositions();
- void fillShape(const RenderStyle&, GraphicsContext*);
- void strokeShape(const RenderStyle&, GraphicsContext*);
- void fillAndStrokeShape(GraphicsContext*);
+ void fillShape(const RenderStyle&, GraphicsContext&);
+ void strokeShape(const RenderStyle&, GraphicsContext&);
+ void strokeShape(GraphicsContext&);
+ void fillStrokeMarkers(PaintInfo&);
void drawMarkers(PaintInfo&);
private:
FloatRect m_repaintBoundingBox;
FloatRect m_repaintBoundingBoxExcludingShadow;
AffineTransform m_localTransform;
- OwnPtr<Path> m_path;
+ std::unique_ptr<Path> m_path;
Vector<MarkerPosition> m_markerPositions;
bool m_needsBoundariesUpdate : 1;
@@ -132,9 +131,6 @@ private:
bool m_needsTransformUpdate : 1;
};
-RENDER_OBJECT_TYPE_CASTS(RenderSVGShape, isSVGShape())
+} // namespace WebCore
-}
-
-#endif // ENABLE(SVG)
-#endif
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGShape, isSVGShape())
diff --git a/Source/WebCore/rendering/svg/RenderSVGTSpan.h b/Source/WebCore/rendering/svg/RenderSVGTSpan.h
index bdd33bbb0..fd75d1525 100644
--- a/Source/WebCore/rendering/svg/RenderSVGTSpan.h
+++ b/Source/WebCore/rendering/svg/RenderSVGTSpan.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
- * Copyright (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2009 Google Inc.
*
* This library is free software; you can redistribute it and/or
@@ -19,18 +19,17 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGTSpan_h
-#define RenderSVGTSpan_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderSVGInline.h"
#include "SVGTextPositioningElement.h"
namespace WebCore {
+
class RenderSVGTSpan final : public RenderSVGInline {
public:
- explicit RenderSVGTSpan(SVGTextPositioningElement& element, PassRef<RenderStyle> style)
- : RenderSVGInline(element, std::move(style))
+ explicit RenderSVGTSpan(SVGTextPositioningElement& element, RenderStyle&& style)
+ : RenderSVGInline(element, WTFMove(style))
{
}
@@ -38,9 +37,10 @@ public:
private:
void graphicsElement() const = delete;
- virtual const char* renderName() const { return "RenderSVGTSpan"; }
+ const char* renderName() const override { return "RenderSVGTSpan"; }
+ bool isSVGTSpan() const override { return true; }
};
-}
-#endif // ENABLE(SVG)
-#endif // !RenderSVGTSpan_h
+} // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGTSpan, isSVGTSpan())
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.cpp b/Source/WebCore/rendering/svg/RenderSVGText.cpp
index 22c1cdaab..8f3b60f0d 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGText.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2006 Alexander Kellett <lypanov@kde.org>
* Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
* Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
@@ -25,17 +25,17 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGText.h"
#include "FloatQuad.h"
-#include "FontCache.h"
+#include "Font.h"
#include "GraphicsContext.h"
#include "HitTestRequest.h"
#include "HitTestResult.h"
#include "LayoutRepainter.h"
#include "PointerEventsHitRules.h"
+#include "RenderIterator.h"
+#include "RenderSVGInline.h"
#include "RenderSVGInlineText.h"
#include "RenderSVGResource.h"
#include "RenderSVGRoot.h"
@@ -43,18 +43,15 @@
#include "SVGResourcesCache.h"
#include "SVGRootInlineBox.h"
#include "SVGTextElement.h"
-#include "SVGTextRunRenderingContext.h"
-#include "SVGTransformList.h"
#include "SVGURIReference.h"
-#include "SimpleFontData.h"
#include "TransformState.h"
#include "VisiblePosition.h"
#include <wtf/StackStats.h>
namespace WebCore {
-RenderSVGText::RenderSVGText(SVGTextElement& element, PassRef<RenderStyle> style)
- : RenderSVGBlock(element, std::move(style))
+RenderSVGText::RenderSVGText(SVGTextElement& element, RenderStyle&& style)
+ : RenderSVGBlock(element, WTFMove(style))
, m_needsReordering(false)
, m_needsPositioningValuesUpdate(false)
, m_needsTransformUpdate(true)
@@ -69,7 +66,7 @@ RenderSVGText::~RenderSVGText()
SVGTextElement& RenderSVGText::textElement() const
{
- return toSVGTextElement(RenderSVGBlock::graphicsElement());
+ return downcast<SVGTextElement>(RenderSVGBlock::graphicsElement());
}
bool RenderSVGText::isChildAllowed(const RenderObject& child, const RenderStyle&) const
@@ -77,24 +74,14 @@ bool RenderSVGText::isChildAllowed(const RenderObject& child, const RenderStyle&
return child.isInline();
}
-RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(RenderObject* start)
+RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(RenderObject& start)
{
- ASSERT(start);
- while (start && !start->isSVGText())
- start = start->parent();
- if (!start || !start->isSVGText())
- return 0;
- return toRenderSVGText(start);
+ return lineageOfType<RenderSVGText>(start).first();
}
-const RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(const RenderObject* start)
+const RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(const RenderObject& start)
{
- ASSERT(start);
- while (start && !start->isSVGText())
- start = start->parent();
- if (!start || !start->isSVGText())
- return 0;
- return toRenderSVGText(start);
+ return lineageOfType<RenderSVGText>(start).first();
}
LayoutRect RenderSVGText::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
@@ -102,16 +89,14 @@ LayoutRect RenderSVGText::clippedOverflowRectForRepaint(const RenderLayerModelOb
return SVGRenderSupport::clippedOverflowRectForRepaint(*this, repaintContainer);
}
-void RenderSVGText::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+LayoutRect RenderSVGText::computeRectForRepaint(const LayoutRect& rect, const RenderLayerModelObject* repaintContainer, RepaintContext context) const
{
- FloatRect repaintRect = rect;
- computeFloatRectForRepaint(repaintContainer, repaintRect, fixed);
- rect = enclosingLayoutRect(repaintRect);
+ return enclosingLayoutRect(computeFloatRectForRepaint(rect, repaintContainer, context.m_hasPositionFixedDescendant));
}
-void RenderSVGText::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+FloatRect RenderSVGText::computeFloatRectForRepaint(const FloatRect& repaintRect, const RenderLayerModelObject* repaintContainer, bool fixed) const
{
- SVGRenderSupport::computeFloatRectForRepaint(*this, repaintContainer, repaintRect, fixed);
+ return SVGRenderSupport::computeFloatRectForRepaint(*this, repaintRect, repaintContainer, fixed);
}
void RenderSVGText::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
@@ -127,26 +112,25 @@ const RenderObject* RenderSVGText::pushMappingToContainer(const RenderLayerModel
static inline void collectLayoutAttributes(RenderObject* text, Vector<SVGTextLayoutAttributes*>& attributes)
{
for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
- if (descendant->isSVGInlineText())
- attributes.append(toRenderSVGInlineText(descendant)->layoutAttributes());
+ if (is<RenderSVGInlineText>(*descendant))
+ attributes.append(downcast<RenderSVGInlineText>(*descendant).layoutAttributes());
}
}
-static inline bool findPreviousAndNextAttributes(RenderElement* start, RenderSVGInlineText* locateElement, bool& stopAfterNext, SVGTextLayoutAttributes*& previous, SVGTextLayoutAttributes*& next)
+static inline bool findPreviousAndNextAttributes(RenderElement& start, RenderSVGInlineText* locateElement, bool& stopAfterNext, SVGTextLayoutAttributes*& previous, SVGTextLayoutAttributes*& next)
{
- ASSERT(start);
ASSERT(locateElement);
// FIXME: Make this iterative.
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
- if (child->isSVGInlineText()) {
- RenderSVGInlineText* text = toRenderSVGInlineText(child);
- if (locateElement != text) {
+ for (auto& child : childrenOfType<RenderObject>(start)) {
+ if (is<RenderSVGInlineText>(child)) {
+ auto& text = downcast<RenderSVGInlineText>(child);
+ if (locateElement != &text) {
if (stopAfterNext) {
- next = text->layoutAttributes();
+ next = text.layoutAttributes();
return true;
}
- previous = text->layoutAttributes();
+ previous = text.layoutAttributes();
continue;
}
@@ -154,10 +138,10 @@ static inline bool findPreviousAndNextAttributes(RenderElement* start, RenderSVG
continue;
}
- if (!child->isSVGInline())
+ if (!is<RenderSVGInline>(child))
continue;
- if (findPreviousAndNextAttributes(toRenderElement(child), locateElement, stopAfterNext, previous, next))
+ if (findPreviousAndNextAttributes(downcast<RenderElement>(child), locateElement, stopAfterNext, previous, next))
return true;
}
@@ -177,12 +161,9 @@ inline bool RenderSVGText::shouldHandleSubtreeMutations() const
void RenderSVGText::subtreeChildWasAdded(RenderObject* child)
{
ASSERT(child);
- if (!shouldHandleSubtreeMutations() || documentBeingDestroyed())
+ if (!shouldHandleSubtreeMutations() || renderTreeBeingDestroyed())
return;
- // Always protect the cache before clearing text positioning elements when the cache will subsequently be rebuilt.
- FontCachePurgePreventer fontCachePurgePreventer;
-
// The positioning elements cache doesn't include the new 'child' yet. Clear the
// cache, as the next buildLayoutAttributesForTextRenderer() call rebuilds it.
m_layoutAttributesBuilder.clearTextPositioningElements();
@@ -209,7 +190,7 @@ void RenderSVGText::subtreeChildWasAdded(RenderObject* child)
SVGTextLayoutAttributes* previous = 0;
SVGTextLayoutAttributes* next = 0;
ASSERT_UNUSED(child, &attributes->context() == child);
- findPreviousAndNextAttributes(this, &attributes->context(), stopAfterNext, previous, next);
+ findPreviousAndNextAttributes(*this, &attributes->context(), stopAfterNext, previous, next);
if (previous)
m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(previous->context());
@@ -264,26 +245,25 @@ void RenderSVGText::subtreeChildWillBeRemoved(RenderObject* child, Vector<SVGTex
return;
// This logic requires that the 'text' child is still inserted in the tree.
- RenderSVGInlineText* text = toRenderSVGInlineText(child);
+ auto& text = downcast<RenderSVGInlineText>(*child);
bool stopAfterNext = false;
- SVGTextLayoutAttributes* previous = 0;
- SVGTextLayoutAttributes* next = 0;
- if (!documentBeingDestroyed())
- findPreviousAndNextAttributes(this, text, stopAfterNext, previous, next);
+ SVGTextLayoutAttributes* previous = nullptr;
+ SVGTextLayoutAttributes* next = nullptr;
+ if (!renderTreeBeingDestroyed())
+ findPreviousAndNextAttributes(*this, &text, stopAfterNext, previous, next);
if (previous)
affectedAttributes.append(previous);
if (next)
affectedAttributes.append(next);
- size_t position = m_layoutAttributes.find(text->layoutAttributes());
- ASSERT(position != notFound);
- m_layoutAttributes.remove(position);
+ bool removed = m_layoutAttributes.removeFirst(text.layoutAttributes());
+ ASSERT_UNUSED(removed, removed);
}
void RenderSVGText::subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes)
{
- if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) {
+ if (!shouldHandleSubtreeMutations() || renderTreeBeingDestroyed()) {
ASSERT(affectedAttributes.isEmpty());
return;
}
@@ -298,17 +278,16 @@ void RenderSVGText::subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*
void RenderSVGText::subtreeStyleDidChange(RenderSVGInlineText* text)
{
ASSERT(text);
- if (!shouldHandleSubtreeMutations() || documentBeingDestroyed())
+ if (!shouldHandleSubtreeMutations() || renderTreeBeingDestroyed())
return;
checkLayoutAttributesConsistency(this, m_layoutAttributes);
// Only update the metrics cache, but not the text positioning element cache
// nor the layout attributes cached in the leaf #text renderers.
- FontCachePurgePreventer fontCachePurgePreventer;
for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
- if (descendant->isSVGInlineText())
- m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(toRenderSVGInlineText(descendant));
+ if (is<RenderSVGInlineText>(*descendant))
+ m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(downcast<RenderSVGInlineText>(*descendant));
}
}
@@ -327,29 +306,26 @@ void RenderSVGText::subtreeTextDidChange(RenderSVGInlineText* text)
return;
}
- // Always protect the cache before clearing text positioning elements when the cache will subsequently be rebuilt.
- FontCachePurgePreventer fontCachePurgePreventer;
-
// The positioning elements cache depends on the size of each text renderer in the
// subtree. If this changes, clear the cache. It's going to be rebuilt below.
m_layoutAttributesBuilder.clearTextPositioningElements();
checkLayoutAttributesConsistency(this, m_layoutAttributes);
for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
- if (descendant->isSVGInlineText())
- m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(toRenderSVGInlineText(*descendant));
+ if (is<RenderSVGInlineText>(*descendant))
+ m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(downcast<RenderSVGInlineText>(*descendant));
}
}
-static inline void updateFontInAllDescendants(RenderObject* start, SVGTextLayoutAttributesBuilder* builder = 0)
+static inline void updateFontInAllDescendants(RenderObject* start, SVGTextLayoutAttributesBuilder* builder = nullptr)
{
for (RenderObject* descendant = start; descendant; descendant = descendant->nextInPreOrder(start)) {
- if (!descendant->isSVGInlineText())
+ if (!is<RenderSVGInlineText>(*descendant))
continue;
- RenderSVGInlineText& text = toRenderSVGInlineText(*descendant);
+ auto& text = downcast<RenderSVGInlineText>(*descendant);
text.updateScaledFont();
if (builder)
- builder->rebuildMetricsForTextRenderer(&text);
+ builder->rebuildMetricsForTextRenderer(text);
}
}
@@ -372,7 +348,7 @@ void RenderSVGText::layout()
ASSERT(m_layoutAttributes.isEmpty());
collectLayoutAttributes(this, m_layoutAttributes);
updateFontInAllDescendants(this);
- m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(this);
+ m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(*this);
m_needsReordering = true;
m_needsTextMetricsUpdate = false;
@@ -386,11 +362,11 @@ void RenderSVGText::layout()
m_needsTextMetricsUpdate = false;
}
- m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(this);
+ m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(*this);
m_needsReordering = true;
m_needsPositioningValuesUpdate = false;
updateCachedBoundariesInParents = true;
- } else if (m_needsTextMetricsUpdate || SVGRenderSupport::findTreeRootObject(*this).isLayoutSizeChanged()) {
+ } else if (m_needsTextMetricsUpdate || SVGRenderSupport::findTreeRootObject(*this)->isLayoutSizeChanged()) {
// If the root layout size changed (eg. window size changes) or the transform to the root
// context has changed then recompute the on-screen font size.
updateFontInAllDescendants(this, &m_layoutAttributesBuilder);
@@ -409,7 +385,7 @@ void RenderSVGText::layout()
ASSERT(!simplifiedLayout());
ASSERT(!scrollsOverflow());
ASSERT(!hasControlClip());
- ASSERT(!hasColumns());
+ ASSERT(!multiColumnFlowThread());
ASSERT(!positionedObjects());
ASSERT(!m_overflow);
ASSERT(!isAnonymousBlock());
@@ -422,7 +398,7 @@ void RenderSVGText::layout()
ASSERT(childrenInline());
LayoutUnit repaintLogicalTop = 0;
LayoutUnit repaintLogicalBottom = 0;
- clearFloats();
+ rebuildFloatingObjectSetFromIntrudingFloats();
layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom);
if (m_needsReordering)
@@ -447,7 +423,7 @@ std::unique_ptr<RootInlineBox> RenderSVGText::createRootInlineBox()
{
auto box = std::make_unique<SVGRootInlineBox>(*this);
box->setHasVirtualLogicalHeight();
- return std::move(box);
+ return WTFMove(box);
}
bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
@@ -457,7 +433,7 @@ bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResul
if (isVisible || !hitRules.requireVisible) {
if ((hitRules.canHitStroke && (style().svgStyle().hasStroke() || !hitRules.requireStroke))
|| (hitRules.canHitFill && (style().svgStyle().hasFill() || !hitRules.requireFill))) {
- FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
+ FloatPoint localPoint = localToParentTransform().inverse().value_or(AffineTransform()).mapPoint(pointInParent);
if (!SVGRenderSupport::pointInClippingArea(*this, localPoint))
return false;
@@ -476,42 +452,46 @@ bool RenderSVGText::nodeAtPoint(const HitTestRequest&, HitTestResult&, const Hit
return false;
}
-VisiblePosition RenderSVGText::positionForPoint(const LayoutPoint& pointInContents)
+VisiblePosition RenderSVGText::positionForPoint(const LayoutPoint& pointInContents, const RenderRegion* region)
{
RootInlineBox* rootBox = firstRootBox();
if (!rootBox)
return createVisiblePosition(0, DOWNSTREAM);
- ASSERT_WITH_SECURITY_IMPLICATION(rootBox->isSVGRootInlineBox());
ASSERT(!rootBox->nextRootBox());
ASSERT(childrenInline());
- InlineBox* closestBox = toSVGRootInlineBox(rootBox)->closestLeafChildForPosition(pointInContents);
+ InlineBox* closestBox = downcast<SVGRootInlineBox>(*rootBox).closestLeafChildForPosition(pointInContents);
if (!closestBox)
return createVisiblePosition(0, DOWNSTREAM);
- return closestBox->renderer().positionForPoint(LayoutPoint(pointInContents.x(), closestBox->y()));
+ return closestBox->renderer().positionForPoint(LayoutPoint(pointInContents.x(), closestBox->y()), region);
}
void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
{
- quads.append(localToAbsoluteQuad(strokeBoundingBox(), 0 /* mode */, wasFixed));
+ quads.append(localToAbsoluteQuad(strokeBoundingBox(), UseTransforms, wasFixed));
}
void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
- if (paintInfo.context->paintingDisabled())
+ if (paintInfo.context().paintingDisabled())
return;
if (paintInfo.phase != PaintPhaseForeground
- && paintInfo.phase != PaintPhaseSelfOutline
&& paintInfo.phase != PaintPhaseSelection)
return;
PaintInfo blockInfo(paintInfo);
- GraphicsContextStateSaver stateSaver(*blockInfo.context);
+ GraphicsContextStateSaver stateSaver(blockInfo.context());
blockInfo.applyTransform(localToParentTransform());
RenderBlock::paint(blockInfo, LayoutPoint());
+
+ // Paint the outlines, if any
+ if (paintInfo.phase == PaintPhaseForeground) {
+ blockInfo.phase = PaintPhaseSelfOutline;
+ RenderBlock::paint(blockInfo, LayoutPoint());
+ }
}
FloatRect RenderSVGText::strokeBoundingBox() const
@@ -522,7 +502,7 @@ FloatRect RenderSVGText::strokeBoundingBox() const
return strokeBoundaries;
SVGLengthContext lengthContext(&textElement());
- strokeBoundaries.inflate(svgStyle.strokeWidth().value(lengthContext));
+ strokeBoundaries.inflate(lengthContext.valueForLength(style().strokeWidth()));
return strokeBoundaries;
}
@@ -550,7 +530,6 @@ void RenderSVGText::removeChild(RenderObject& child)
SVGResourcesCache::clientWillBeRemovedFromTree(child);
Vector<SVGTextLayoutAttributes*, 2> affectedAttributes;
- FontCachePurgePreventer fontCachePurgePreventer;
subtreeChildWillBeRemoved(&child, affectedAttributes);
RenderSVGBlock::removeChild(child);
subtreeChildWasRemoved(affectedAttributes);
@@ -565,10 +544,8 @@ RenderBlock* RenderSVGText::firstLineBlock() const
// Fix for <rdar://problem/8048875>. We should not render :first-letter CSS Style
// in a SVG text element context.
-void RenderSVGText::updateFirstLetter()
+void RenderSVGText::updateFirstLetter(RenderTreeMutationIsAllowed)
{
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.h b/Source/WebCore/rendering/svg/RenderSVGText.h
index 93ac44246..6ef1bd3a9 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.h
+++ b/Source/WebCore/rendering/svg/RenderSVGText.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) Research In Motion Limited 2010-2012. All rights reserved.
*
@@ -19,10 +19,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGText_h
-#define RenderSVGText_h
+#pragma once
-#if ENABLE(SVG)
#include "AffineTransform.h"
#include "RenderSVGBlock.h"
#include "SVGTextLayoutAttributesBuilder.h"
@@ -35,20 +33,20 @@ class RenderSVGInlineText;
class RenderSVGText final : public RenderSVGBlock {
public:
- RenderSVGText(SVGTextElement&, PassRef<RenderStyle>);
+ RenderSVGText(SVGTextElement&, RenderStyle&&);
virtual ~RenderSVGText();
SVGTextElement& textElement() const;
- virtual bool isChildAllowed(const RenderObject&, const RenderStyle&) const;
+ bool isChildAllowed(const RenderObject&, const RenderStyle&) const override;
void setNeedsPositioningValuesUpdate() { m_needsPositioningValuesUpdate = true; }
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+ void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; }
void setNeedsTextMetricsUpdate() { m_needsTextMetricsUpdate = true; }
- virtual FloatRect repaintRectInLocalCoordinates() const;
+ FloatRect repaintRectInLocalCoordinates() const override;
- static RenderSVGText* locateRenderSVGTextAncestor(RenderObject*);
- static const RenderSVGText* locateRenderSVGTextAncestor(const RenderObject*);
+ static RenderSVGText* locateRenderSVGTextAncestor(RenderObject&);
+ static const RenderSVGText* locateRenderSVGTextAncestor(const RenderObject&);
bool needsReordering() const { return m_needsReordering; }
Vector<SVGTextLayoutAttributes*>& layoutAttributes() { return m_layoutAttributes; }
@@ -59,41 +57,41 @@ public:
void subtreeStyleDidChange(RenderSVGInlineText*);
void subtreeTextDidChange(RenderSVGInlineText*);
+ FloatRect objectBoundingBox() const override { return frameRect(); }
+ FloatRect strokeBoundingBox() const override;
+
private:
void graphicsElement() const = delete;
- virtual const char* renderName() const { return "RenderSVGText"; }
- virtual bool isSVGText() const { return true; }
-
- virtual void paint(PaintInfo&, const LayoutPoint&);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
- virtual VisiblePosition positionForPoint(const LayoutPoint&);
+ const char* renderName() const override { return "RenderSVGText"; }
+ bool isSVGText() const override { return true; }
- virtual bool requiresLayer() const { return false; }
- virtual void layout();
+ void paint(PaintInfo&, const LayoutPoint&) override;
+ bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
+ bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override;
+ VisiblePosition positionForPoint(const LayoutPoint&, const RenderRegion*) override;
- virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+ bool requiresLayer() const override { return false; }
+ void layout() override;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const override;
- virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const override;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const override;
+ void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override;
- virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const override;
- virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const override;
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
- virtual void removeChild(RenderObject&) override;
- virtual void willBeDestroyed() override;
+ LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const override;
+ LayoutRect computeRectForRepaint(const LayoutRect&, const RenderLayerModelObject* repaintContainer, RepaintContext = { }) const override;
+ FloatRect computeFloatRectForRepaint(const FloatRect&, const RenderLayerModelObject* repaintContainer, bool fixed = false) const override;
- virtual FloatRect objectBoundingBox() const { return frameRect(); }
- virtual FloatRect strokeBoundingBox() const;
+ void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, bool* wasFixed) const override;
+ const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const override;
+ void addChild(RenderObject* child, RenderObject* beforeChild = nullptr) override;
+ void removeChild(RenderObject&) override;
+ void willBeDestroyed() override;
- virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
- virtual AffineTransform localTransform() const { return m_localTransform; }
- virtual std::unique_ptr<RootInlineBox> createRootInlineBox() override;
+ const AffineTransform& localToParentTransform() const override { return m_localTransform; }
+ AffineTransform localTransform() const override { return m_localTransform; }
+ std::unique_ptr<RootInlineBox> createRootInlineBox() override;
- virtual RenderBlock* firstLineBlock() const;
- virtual void updateFirstLetter();
+ RenderBlock* firstLineBlock() const override;
+ void updateFirstLetter(RenderTreeMutationIsAllowed = RenderTreeMutationIsAllowed::Yes) override;
bool shouldHandleSubtreeMutations() const;
@@ -106,9 +104,6 @@ private:
Vector<SVGTextLayoutAttributes*> m_layoutAttributes;
};
-RENDER_OBJECT_TYPE_CASTS(RenderSVGText, isSVGText())
-
-}
+} // namespace WebCore
-#endif // ENABLE(SVG)
-#endif
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGText, isSVGText())
diff --git a/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp b/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp
index 12cb6d361..3d5f36528 100644
--- a/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp
@@ -18,8 +18,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGTextPath.h"
#include "FloatQuad.h"
@@ -30,18 +28,17 @@
#include "SVGPathElement.h"
#include "SVGRootInlineBox.h"
#include "SVGTextPathElement.h"
-#include "SVGTransformList.h"
namespace WebCore {
-RenderSVGTextPath::RenderSVGTextPath(SVGTextPathElement& element, PassRef<RenderStyle> style)
- : RenderSVGInline(element, std::move(style))
+RenderSVGTextPath::RenderSVGTextPath(SVGTextPathElement& element, RenderStyle&& style)
+ : RenderSVGInline(element, WTFMove(style))
{
}
SVGTextPathElement& RenderSVGTextPath::textPathElement() const
{
- return toSVGTextPathElement(RenderSVGInline::graphicsElement());
+ return downcast<SVGTextPathElement>(RenderSVGInline::graphicsElement());
}
Path RenderSVGTextPath::layoutPath() const
@@ -50,17 +47,17 @@ Path RenderSVGTextPath::layoutPath() const
if (!targetElement || !targetElement->hasTagName(SVGNames::pathTag))
return Path();
- SVGPathElement* pathElement = toSVGPathElement(targetElement);
+ SVGPathElement& pathElement = downcast<SVGPathElement>(*targetElement);
Path pathData;
- updatePathFromGraphicsElement(pathElement, pathData);
+ updatePathFromGraphicsElement(&pathElement, pathData);
// Spec: The transform attribute on the referenced 'path' element represents a
// supplemental transformation relative to the current user coordinate system for
// the current 'text' element, including any adjustments to the current user coordinate
// system due to a possible transform attribute on the current 'text' element.
// http://www.w3.org/TR/SVG/text.html#TextPathElement
- pathData.transform(pathElement->animatedLocalTransform());
+ pathData.transform(pathElement.animatedLocalTransform());
return pathData;
}
@@ -80,5 +77,3 @@ bool RenderSVGTextPath::stretchMethod() const
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGTextPath.h b/Source/WebCore/rendering/svg/RenderSVGTextPath.h
index e7e11ad98..95a379274 100644
--- a/Source/WebCore/rendering/svg/RenderSVGTextPath.h
+++ b/Source/WebCore/rendering/svg/RenderSVGTextPath.h
@@ -18,17 +18,15 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGTextPath_h
-#define RenderSVGTextPath_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderSVGInline.h"
namespace WebCore {
class RenderSVGTextPath final : public RenderSVGInline {
public:
- RenderSVGTextPath(SVGTextPathElement&, PassRef<RenderStyle>);
+ RenderSVGTextPath(SVGTextPathElement&, RenderStyle&&);
SVGTextPathElement& textPathElement() const;
@@ -40,15 +38,12 @@ public:
private:
void graphicsElement() const = delete;
- virtual bool isSVGTextPath() const override { return true; }
- virtual const char* renderName() const override { return "RenderSVGTextPath"; }
+ bool isSVGTextPath() const override { return true; }
+ const char* renderName() const override { return "RenderSVGTextPath"; }
Path m_layoutPath;
};
-RENDER_OBJECT_TYPE_CASTS(RenderSVGTextPath, isSVGTextPath())
+} // namespace WebCore
-}
-
-#endif // ENABLE(SVG)
-#endif // RenderSVGTextPath_h
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGTextPath, isSVGTextPath())
diff --git a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp
index 3268b676a..0b08a17b8 100644
--- a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp
@@ -20,17 +20,15 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGTransformableContainer.h"
-#include "SVGNames.h"
+#include "SVGGElement.h"
#include "SVGUseElement.h"
namespace WebCore {
-RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGGraphicsElement& element, PassRef<RenderStyle> style)
- : RenderSVGContainer(element, std::move(style))
+RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGGraphicsElement& element, RenderStyle&& style)
+ : RenderSVGContainer(element, WTFMove(style))
, m_needsTransformUpdate(true)
, m_didTransformToRootUpdate(false)
{
@@ -43,13 +41,13 @@ bool RenderSVGTransformableContainer::calculateLocalTransform()
// If we're either the renderer for a <use> element, or for any <g> element inside the shadow
// tree, that was created during the use/symbol/svg expansion in SVGUseElement. These containers
// need to respect the translations induced by their corresponding use elements x/y attributes.
- SVGUseElement* useElement = 0;
- if (isSVGUseElement(element))
- useElement = &toSVGUseElement(element);
- else if (element.isInShadowTree() && isSVGGElement(element)) {
+ SVGUseElement* useElement = nullptr;
+ if (is<SVGUseElement>(element))
+ useElement = &downcast<SVGUseElement>(element);
+ else if (element.isInShadowTree() && is<SVGGElement>(element)) {
SVGElement* correspondingElement = element.correspondingElement();
- if (correspondingElement && isSVGUseElement(correspondingElement))
- useElement = toSVGUseElement(correspondingElement);
+ if (is<SVGUseElement>(correspondingElement))
+ useElement = downcast<SVGUseElement>(correspondingElement);
}
if (useElement) {
@@ -71,5 +69,3 @@ bool RenderSVGTransformableContainer::calculateLocalTransform()
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h
index d97eafda0..f21199004 100644
--- a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h
+++ b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h
@@ -18,10 +18,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGTransformableContainer_h
-#define RenderSVGTransformableContainer_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderSVGContainer.h"
#include "SVGGraphicsElement.h"
@@ -30,18 +28,18 @@ namespace WebCore {
class SVGGraphicsElement;
class RenderSVGTransformableContainer final : public RenderSVGContainer {
public:
- RenderSVGTransformableContainer(SVGGraphicsElement&, PassRef<RenderStyle>);
- SVGGraphicsElement& graphicsElement() { return toSVGGraphicsElement(RenderSVGContainer::element()); }
+ RenderSVGTransformableContainer(SVGGraphicsElement&, RenderStyle&&);
+ SVGGraphicsElement& graphicsElement() { return downcast<SVGGraphicsElement>(RenderSVGContainer::element()); }
- virtual bool isSVGTransformableContainer() const { return true; }
- virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
- virtual bool didTransformToRootUpdate() { return m_didTransformToRootUpdate; }
+ bool isSVGTransformableContainer() const override { return true; }
+ const AffineTransform& localToParentTransform() const override { return m_localTransform; }
+ void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; }
+ bool didTransformToRootUpdate() override { return m_didTransformToRootUpdate; }
private:
void element() const = delete;
- virtual bool calculateLocalTransform();
- virtual AffineTransform localTransform() const { return m_localTransform; }
+ bool calculateLocalTransform() override;
+ AffineTransform localTransform() const override { return m_localTransform; }
bool m_needsTransformUpdate : 1;
bool m_didTransformToRootUpdate : 1;
@@ -49,7 +47,6 @@ private:
FloatSize m_lastTranslation;
};
-}
+} // namespace WebCore
-#endif // ENABLE(SVG)
-#endif // RenderSVGTransformableContainer_h
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGTransformableContainer, isSVGTransformableContainer())
diff --git a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp
index f03467c62..932fb8517 100644
--- a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp
@@ -21,21 +21,16 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "RenderSVGViewportContainer.h"
#include "GraphicsContext.h"
#include "RenderView.h"
-#include "SVGElementInstance.h"
-#include "SVGNames.h"
#include "SVGSVGElement.h"
-#include "SVGUseElement.h"
namespace WebCore {
-RenderSVGViewportContainer::RenderSVGViewportContainer(SVGSVGElement& element, PassRef<RenderStyle> style)
- : RenderSVGContainer(element, std::move(style))
+RenderSVGViewportContainer::RenderSVGViewportContainer(SVGSVGElement& element, RenderStyle&& style)
+ : RenderSVGContainer(element, WTFMove(style))
, m_didTransformToRootUpdate(false)
, m_isLayoutSizeChanged(false)
, m_needsTransformUpdate(true)
@@ -44,7 +39,7 @@ RenderSVGViewportContainer::RenderSVGViewportContainer(SVGSVGElement& element, P
SVGSVGElement& RenderSVGViewportContainer::svgSVGElement() const
{
- return toSVGSVGElement(RenderSVGContainer::element());
+ return downcast<SVGSVGElement>(RenderSVGContainer::element());
}
void RenderSVGViewportContainer::determineIfLayoutSizeChanged()
@@ -55,67 +50,22 @@ void RenderSVGViewportContainer::determineIfLayoutSizeChanged()
void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo)
{
if (SVGRenderSupport::isOverflowHidden(*this))
- paintInfo.context->clip(m_viewport);
+ paintInfo.context().clip(m_viewport);
}
void RenderSVGViewportContainer::calcViewport()
{
- SVGSVGElement& svg = svgSVGElement();
- FloatRect oldViewport = m_viewport;
-
- SVGLengthContext lengthContext(&svg);
- m_viewport = FloatRect(svg.x().value(lengthContext), svg.y().value(lengthContext), svg.width().value(lengthContext), svg.height().value(lengthContext));
-
- SVGElement* correspondingElement = svg.correspondingElement();
- if (correspondingElement && svg.isInShadowTree()) {
- const HashSet<SVGElementInstance*>& instances = correspondingElement->instancesForElement();
- ASSERT(!instances.isEmpty());
-
- SVGUseElement* useElement = 0;
- const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
- for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
- const SVGElementInstance* instance = (*it);
- ASSERT(instance->correspondingElement()->hasTagName(SVGNames::svgTag) || instance->correspondingElement()->hasTagName(SVGNames::symbolTag));
- if (instance->shadowTreeElement() == &svg) {
- ASSERT(correspondingElement == instance->correspondingElement());
- useElement = instance->directUseElement();
- if (!useElement)
- useElement = instance->correspondingUseElement();
- break;
- }
- }
-
- ASSERT(useElement);
- bool isSymbolElement = correspondingElement->hasTagName(SVGNames::symbolTag);
-
- // Spec (<use> on <symbol>): This generated 'svg' will always have explicit values for attributes width and height.
- // If attributes width and/or height are provided on the 'use' element, then these attributes
- // will be transferred to the generated 'svg'. If attributes width and/or height are not specified,
- // the generated 'svg' element will use values of 100% for these attributes.
-
- // Spec (<use> on <svg>): If attributes width and/or height are provided on the 'use' element, then these
- // values will override the corresponding attributes on the 'svg' in the generated tree.
-
- SVGLengthContext lengthContext(&svg);
- if (useElement->hasAttribute(SVGNames::widthAttr))
- m_viewport.setWidth(useElement->width().value(lengthContext));
- else if (isSymbolElement && svg.hasAttribute(SVGNames::widthAttr)) {
- SVGLength containerWidth(LengthModeWidth, "100%");
- m_viewport.setWidth(containerWidth.value(lengthContext));
- }
-
- if (useElement->hasAttribute(SVGNames::heightAttr))
- m_viewport.setHeight(useElement->height().value(lengthContext));
- else if (isSymbolElement && svg.hasAttribute(SVGNames::heightAttr)) {
- SVGLength containerHeight(LengthModeHeight, "100%");
- m_viewport.setHeight(containerHeight.value(lengthContext));
- }
- }
-
- if (oldViewport != m_viewport) {
- setNeedsBoundariesUpdate();
- setNeedsTransformUpdate();
- }
+ SVGSVGElement& element = svgSVGElement();
+ SVGLengthContext lengthContext(&element);
+ FloatRect newViewport(element.x().value(lengthContext), element.y().value(lengthContext), element.width().value(lengthContext), element.height().value(lengthContext));
+
+ if (m_viewport == newViewport)
+ return;
+
+ m_viewport = newViewport;
+
+ setNeedsBoundariesUpdate();
+ setNeedsTransformUpdate();
}
bool RenderSVGViewportContainer::calculateLocalTransform()
@@ -153,5 +103,3 @@ void RenderSVGViewportContainer::paint(PaintInfo& paintInfo, const LayoutPoint&
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h
index 182431eb5..56ac6fc1b 100644
--- a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h
+++ b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h
@@ -20,10 +20,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef RenderSVGViewportContainer_h
-#define RenderSVGViewportContainer_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderSVGContainer.h"
namespace WebCore {
@@ -32,34 +30,34 @@ namespace WebCore {
// thus we inherit from RenderSVGContainer instead of RenderSVGTransformableContainer
class RenderSVGViewportContainer final : public RenderSVGContainer {
public:
- RenderSVGViewportContainer(SVGSVGElement&, PassRef<RenderStyle>);
+ RenderSVGViewportContainer(SVGSVGElement&, RenderStyle&&);
SVGSVGElement& svgSVGElement() const;
FloatRect viewport() const { return m_viewport; }
bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; }
- virtual bool didTransformToRootUpdate() { return m_didTransformToRootUpdate; }
+ bool didTransformToRootUpdate() override { return m_didTransformToRootUpdate; }
- virtual void determineIfLayoutSizeChanged();
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+ void determineIfLayoutSizeChanged() override;
+ void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; }
- virtual void paint(PaintInfo&, const LayoutPoint&) override;
+ void paint(PaintInfo&, const LayoutPoint&) override;
private:
void element() const = delete;
- virtual bool isSVGViewportContainer() const { return true; }
- virtual const char* renderName() const { return "RenderSVGViewportContainer"; }
+ bool isSVGViewportContainer() const override { return true; }
+ const char* renderName() const override { return "RenderSVGViewportContainer"; }
AffineTransform viewportTransform() const;
- virtual const AffineTransform& localToParentTransform() const { return m_localToParentTransform; }
+ const AffineTransform& localToParentTransform() const override { return m_localToParentTransform; }
- virtual void calcViewport();
- virtual bool calculateLocalTransform();
+ void calcViewport() override;
+ bool calculateLocalTransform() override;
- virtual void applyViewportClip(PaintInfo&);
- virtual bool pointIsInsideViewportClip(const FloatPoint& pointInParent);
+ void applyViewportClip(PaintInfo&) override;
+ bool pointIsInsideViewportClip(const FloatPoint& pointInParent) override;
FloatRect m_viewport;
mutable AffineTransform m_localToParentTransform;
@@ -68,9 +66,6 @@ private:
bool m_needsTransformUpdate : 1;
};
-RENDER_OBJECT_TYPE_CASTS(RenderSVGViewportContainer, isSVGViewportContainer())
-
} // namespace WebCore
-#endif // ENABLE(SVG)
-#endif // RenderSVGViewportContainer_h
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGViewportContainer, isSVGViewportContainer())
diff --git a/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp b/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp
index db017adba..2d5079e32 100644
--- a/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp
+++ b/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
- * Copyright (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
*
@@ -23,10 +23,7 @@
#include "config.h"
#include "SVGInlineFlowBox.h"
-#if ENABLE(SVG)
-#include "DocumentMarkerController.h"
#include "GraphicsContext.h"
-#include "RenderedDocumentMarker.h"
#include "SVGInlineTextBox.h"
#include "SVGRenderingContext.h"
@@ -35,30 +32,26 @@ namespace WebCore {
void SVGInlineFlowBox::paintSelectionBackground(PaintInfo& paintInfo)
{
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
- ASSERT(!paintInfo.context->paintingDisabled());
+ ASSERT(!paintInfo.context().paintingDisabled());
PaintInfo childPaintInfo(paintInfo);
for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
- if (child->isSVGInlineTextBox())
- toSVGInlineTextBox(child)->paintSelectionBackground(childPaintInfo);
- else if (child->isSVGInlineFlowBox())
- toSVGInlineFlowBox(child)->paintSelectionBackground(childPaintInfo);
+ if (is<SVGInlineTextBox>(*child))
+ downcast<SVGInlineTextBox>(*child).paintSelectionBackground(childPaintInfo);
+ else if (is<SVGInlineFlowBox>(*child))
+ downcast<SVGInlineFlowBox>(*child).paintSelectionBackground(childPaintInfo);
}
}
-void SVGInlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit)
+void SVGInlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
{
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
- ASSERT(!paintInfo.context->paintingDisabled());
+ ASSERT(!paintInfo.context().paintingDisabled());
SVGRenderingContext renderingContext(renderer(), paintInfo, SVGRenderingContext::SaveGraphicsContext);
if (renderingContext.isRenderingPrepared()) {
- for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
- if (child->isSVGInlineTextBox())
- computeTextMatchMarkerRectForRenderer(&(toSVGInlineTextBox(child)->renderer()));
-
- child->paint(paintInfo, LayoutPoint(), 0, 0);
- }
+ for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+ child->paint(paintInfo, paintOffset, 0, 0);
}
}
@@ -73,66 +66,4 @@ FloatRect SVGInlineFlowBox::calculateBoundaries() const
return childRect;
}
-void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText* textRenderer)
-{
- ASSERT(textRenderer);
-
- Text& textNode = textRenderer->textNode();
- if (!textNode.inDocument())
- return;
-
- RenderStyle& style = textRenderer->style();
-
- AffineTransform fragmentTransform;
- Vector<DocumentMarker*> markers = textRenderer->document().markers().markersFor(&textNode);
-
- Vector<DocumentMarker*>::iterator markerEnd = markers.end();
- for (Vector<DocumentMarker*>::iterator markerIt = markers.begin(); markerIt != markerEnd; ++markerIt) {
- DocumentMarker* marker = *markerIt;
-
- // SVG is only interessted in the TextMatch marker, for now.
- if (marker->type() != DocumentMarker::TextMatch)
- continue;
-
- FloatRect markerRect;
- for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
- if (!box->isSVGInlineTextBox())
- continue;
-
- SVGInlineTextBox* textBox = toSVGInlineTextBox(box);
-
- int markerStartPosition = std::max<int>(marker->startOffset() - textBox->start(), 0);
- int markerEndPosition = std::min<int>(marker->endOffset() - textBox->start(), textBox->len());
-
- if (markerStartPosition >= markerEndPosition)
- continue;
-
- int fragmentStartPosition = 0;
- int fragmentEndPosition = 0;
-
- const Vector<SVGTextFragment>& fragments = textBox->textFragments();
- unsigned textFragmentsSize = fragments.size();
- for (unsigned i = 0; i < textFragmentsSize; ++i) {
- const SVGTextFragment& fragment = fragments.at(i);
-
- fragmentStartPosition = markerStartPosition;
- fragmentEndPosition = markerEndPosition;
- if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
- continue;
-
- FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, &style);
- fragment.buildFragmentTransform(fragmentTransform);
- if (!fragmentTransform.isIdentity())
- fragmentRect = fragmentTransform.mapRect(fragmentRect);
-
- markerRect.unite(fragmentRect);
- }
- }
-
- toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer->localToAbsoluteQuad(markerRect).enclosingBoundingBox());
- }
-}
-
} // namespace WebCore
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGInlineFlowBox.h b/Source/WebCore/rendering/svg/SVGInlineFlowBox.h
index 88165dfda..58cc1fcaa 100644
--- a/Source/WebCore/rendering/svg/SVGInlineFlowBox.h
+++ b/Source/WebCore/rendering/svg/SVGInlineFlowBox.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
- * Copyright (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2006 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -18,10 +18,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGInlineFlowBox_h
-#define SVGInlineFlowBox_h
+#pragma once
-#if ENABLE(SVG)
#include "InlineFlowBox.h"
#include "RenderSVGInline.h"
@@ -39,24 +37,19 @@ public:
RenderSVGInline& renderer() { return static_cast<RenderSVGInline&>(InlineFlowBox::renderer()); }
- virtual FloatRect calculateBoundaries() const override;
+ FloatRect calculateBoundaries() const override;
void setLogicalHeight(float h) { m_logicalHeight = h; }
void paintSelectionBackground(PaintInfo&);
- static void computeTextMatchMarkerRectForRenderer(RenderSVGInlineText*);
private:
- virtual bool isSVGInlineFlowBox() const override { return true; }
- virtual float virtualLogicalHeight() const override { return m_logicalHeight; }
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override;
+ bool isSVGInlineFlowBox() const override { return true; }
+ float virtualLogicalHeight() const override { return m_logicalHeight; }
+ void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override;
float m_logicalHeight;
};
-INLINE_BOX_OBJECT_TYPE_CASTS(SVGInlineFlowBox, isSVGInlineFlowBox())
-
} // namespace WebCore
-#endif // ENABLE(SVG)
-
-#endif // SVGInlineFlowBox_h
+SPECIALIZE_TYPE_TRAITS_INLINE_BOX(SVGInlineFlowBox, isSVGInlineFlowBox())
diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
index f55976e95..e70f0903a 100644
--- a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
+++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
@@ -22,8 +22,6 @@
#include "config.h"
#include "SVGInlineTextBox.h"
-#if ENABLE(SVG)
-#include "FontCache.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
@@ -31,12 +29,13 @@
#include "InlineFlowBox.h"
#include "PointerEventsHitRules.h"
#include "RenderBlock.h"
+#include "RenderInline.h"
#include "RenderSVGResourceSolidColor.h"
#include "RenderView.h"
#include "SVGRenderingContext.h"
#include "SVGResourcesCache.h"
#include "SVGRootInlineBox.h"
-#include "SVGTextRunRenderingContext.h"
+#include "TextPainter.h"
namespace WebCore {
@@ -54,7 +53,7 @@ SVGInlineTextBox::SVGInlineTextBox(RenderSVGInlineText& renderer)
, m_logicalHeight(0)
, m_paintingResourceMode(ApplyToDefaultMode)
, m_startsNewTextChunk(false)
- , m_paintingResource(0)
+ , m_paintingResource(nullptr)
{
}
@@ -89,7 +88,7 @@ int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragmen
float scalingFactor = renderer().scalingFactor();
ASSERT(scalingFactor);
- TextRun textRun = constructTextRun(&renderer().style(), fragment);
+ TextRun textRun = constructTextRun(renderer().style(), fragment);
// Eventually handle lengthAdjust="spacingAndGlyphs".
// FIXME: Handle vertical text.
@@ -101,53 +100,52 @@ int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragmen
return fragment.characterOffset - start() + renderer().scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
}
-float SVGInlineTextBox::positionForOffset(int) const
+float SVGInlineTextBox::positionForOffset(unsigned) const
{
// SVG doesn't use the offset <-> position selection system.
ASSERT_NOT_REACHED();
return 0;
}
-FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment& fragment, int startPosition, int endPosition, RenderStyle* style) const
+FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment& fragment, unsigned startPosition, unsigned endPosition, const RenderStyle& style) const
{
ASSERT_WITH_SECURITY_IMPLICATION(startPosition < endPosition);
- ASSERT(style);
-
- FontCachePurgePreventer fontCachePurgePreventer;
float scalingFactor = renderer().scalingFactor();
ASSERT(scalingFactor);
- const Font& scaledFont = renderer().scaledFont();
+ const FontCascade& scaledFont = renderer().scaledFont();
const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
FloatPoint textOrigin(fragment.x, fragment.y);
if (scalingFactor != 1)
- textOrigin.scale(scalingFactor, scalingFactor);
+ textOrigin.scale(scalingFactor);
textOrigin.move(0, -scaledFontMetrics.floatAscent());
- FloatRect selectionRect = scaledFont.selectionRectForText(constructTextRun(style, fragment), textOrigin, fragment.height * scalingFactor, startPosition, endPosition);
+ LayoutRect selectionRect = LayoutRect(textOrigin, LayoutSize(0, fragment.height * scalingFactor));
+ TextRun run = constructTextRun(style, fragment);
+ scaledFont.adjustSelectionRectForText(run, selectionRect, startPosition, endPosition);
+ FloatRect snappedSelectionRect = snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), run.ltr());
if (scalingFactor == 1)
- return selectionRect;
+ return snappedSelectionRect;
- selectionRect.scale(1 / scalingFactor);
- return selectionRect;
+ snappedSelectionRect.scale(1 / scalingFactor);
+ return snappedSelectionRect;
}
-LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPosition) const
+LayoutRect SVGInlineTextBox::localSelectionRect(unsigned startPosition, unsigned endPosition) const
{
- int boxStart = start();
- startPosition = std::max(startPosition - boxStart, 0);
- endPosition = std::min(endPosition - boxStart, static_cast<int>(len()));
+ startPosition = clampedOffset(startPosition);
+ endPosition = clampedOffset(endPosition);
if (startPosition >= endPosition)
return LayoutRect();
- RenderStyle& style = renderer().style();
+ auto& style = renderer().style();
AffineTransform fragmentTransform;
FloatRect selectionRect;
- int fragmentStartPosition = 0;
- int fragmentEndPosition = 0;
+ unsigned fragmentStartPosition = 0;
+ unsigned fragmentEndPosition = 0;
unsigned textFragmentsSize = m_textFragments.size();
for (unsigned i = 0; i < textFragmentsSize; ++i) {
@@ -158,7 +156,7 @@ LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi
if (!mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
continue;
- FloatRect fragmentRect = selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, &style);
+ FloatRect fragmentRect = selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
fragment.buildFragmentTransform(fragmentTransform);
if (!fragmentTransform.isIdentity())
fragmentRect = fragmentTransform.mapRect(fragmentRect);
@@ -171,7 +169,7 @@ LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi
static inline bool textShouldBePainted(const RenderSVGInlineText& textRenderer)
{
- // Font::pixelSize(), returns FontDescription::computedPixelSize(), which returns "int(x + 0.5)".
+ // FontCascade::pixelSize(), returns FontDescription::computedPixelSize(), which returns "int(x + 0.5)".
// If the absolute font size on screen is below x=0.5, don't render anything.
return textRenderer.scaledFont().pixelSize();
}
@@ -185,7 +183,7 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
if (renderer().style().visibility() != VISIBLE)
return;
- RenderObject& parentRenderer = parent()->renderer();
+ auto& parentRenderer = parent()->renderer();
ASSERT(!parentRenderer.document().printing());
// Determine whether or not we're selected.
@@ -195,26 +193,20 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
return;
Color backgroundColor = renderer().selectionBackgroundColor();
- if (!backgroundColor.isValid() || !backgroundColor.alpha())
+ if (!backgroundColor.isVisible())
return;
if (!textShouldBePainted(renderer()))
return;
- RenderStyle& style = parentRenderer.style();
+ auto& style = parentRenderer.style();
- RenderStyle* selectionStyle = &style;
- if (hasSelection) {
- selectionStyle = parentRenderer.getCachedPseudoStyle(SELECTION);
- if (!selectionStyle)
- selectionStyle = &style;
- }
-
- int startPosition, endPosition;
- selectionStartEnd(startPosition, endPosition);
+ unsigned startPosition;
+ unsigned endPosition;
+ std::tie(startPosition, endPosition) = selectionStartEnd();
- int fragmentStartPosition = 0;
- int fragmentEndPosition = 0;
+ unsigned fragmentStartPosition = 0;
+ unsigned fragmentEndPosition = 0;
AffineTransform fragmentTransform;
unsigned textFragmentsSize = m_textFragments.size();
for (unsigned i = 0; i < textFragmentsSize; ++i) {
@@ -226,13 +218,13 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
if (!mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
continue;
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
+ GraphicsContextStateSaver stateSaver(paintInfo.context());
fragment.buildFragmentTransform(fragmentTransform);
if (!fragmentTransform.isIdentity())
- paintInfo.context->concatCTM(fragmentTransform);
+ paintInfo.context().concatCTM(fragmentTransform);
- paintInfo.context->setFillColor(backgroundColor, style.colorSpace());
- paintInfo.context->fillRect(selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, &style), backgroundColor, style.colorSpace());
+ paintInfo.context().setFillColor(backgroundColor);
+ paintInfo.context().fillRect(selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style), backgroundColor);
m_paintingResourceMode = ApplyToDefaultMode;
}
@@ -240,7 +232,7 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
ASSERT(!m_paintingResource);
}
-void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit)
+void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
{
ASSERT(paintInfo.shouldPaintWithinRoot(renderer()));
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
@@ -252,9 +244,10 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
// Note: We're explicitely not supporting composition & custom underlines and custom highlighters - unlike InlineTextBox.
// If we ever need that for SVG, it's very easy to refactor and reuse the code.
- RenderObject& parentRenderer = parent()->renderer();
+ auto& parentRenderer = parent()->renderer();
bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection;
+ bool shouldPaintSelectionHighlight = !(paintInfo.paintBehavior & PaintBehaviorSkipSelectionHighlight);
bool hasSelection = !parentRenderer.document().printing() && selectionState() != RenderObject::SelectionNone;
if (!hasSelection && paintSelectedTextOnly)
return;
@@ -262,15 +255,15 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
if (!textShouldBePainted(renderer()))
return;
- RenderStyle& style = parentRenderer.style();
+ auto& style = parentRenderer.style();
const SVGRenderStyle& svgStyle = style.svgStyle();
bool hasFill = svgStyle.hasFill();
- bool hasVisibleStroke = svgStyle.hasVisibleStroke();
+ bool hasVisibleStroke = style.hasVisibleStroke();
- RenderStyle* selectionStyle = &style;
- if (hasSelection) {
+ const RenderStyle* selectionStyle = &style;
+ if (hasSelection && shouldPaintSelectionHighlight) {
selectionStyle = parentRenderer.getCachedPseudoStyle(SELECTION);
if (selectionStyle) {
const SVGRenderStyle& svgSelectionStyle = selectionStyle->svgStyle();
@@ -278,7 +271,7 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
if (!hasFill)
hasFill = svgSelectionStyle.hasFill();
if (!hasVisibleStroke)
- hasVisibleStroke = svgSelectionStyle.hasVisibleStroke();
+ hasVisibleStroke = selectionStyle->hasVisibleStroke();
} else
selectionStyle = &style;
}
@@ -294,51 +287,64 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
SVGTextFragment& fragment = m_textFragments.at(i);
ASSERT(!m_paintingResource);
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
+ GraphicsContextStateSaver stateSaver(paintInfo.context());
fragment.buildFragmentTransform(fragmentTransform);
if (!fragmentTransform.isIdentity())
- paintInfo.context->concatCTM(fragmentTransform);
+ paintInfo.context().concatCTM(fragmentTransform);
// Spec: All text decorations except line-through should be drawn before the text is filled and stroked; thus, the text is rendered on top of these decorations.
int decorations = style.textDecorationsInEffect();
if (decorations & TextDecorationUnderline)
- paintDecoration(paintInfo.context, TextDecorationUnderline, fragment);
+ paintDecoration(paintInfo.context(), TextDecorationUnderline, fragment);
if (decorations & TextDecorationOverline)
- paintDecoration(paintInfo.context, TextDecorationOverline, fragment);
-
- // Fill text
- if (hasFill) {
- m_paintingResourceMode = ApplyToFillMode | ApplyToTextMode;
- paintText(paintInfo.context, &style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
- }
-
- // Stroke text
- if (hasVisibleStroke) {
- m_paintingResourceMode = ApplyToStrokeMode | ApplyToTextMode;
- paintText(paintInfo.context, &style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
+ paintDecoration(paintInfo.context(), TextDecorationOverline, fragment);
+
+ auto paintOrder = style.paintTypesForPaintOrder();
+ for (unsigned i = 0; i < paintOrder.size(); ++i) {
+ switch (paintOrder.at(i)) {
+ case PaintTypeFill:
+ if (!hasFill)
+ continue;
+ m_paintingResourceMode = ApplyToFillMode | ApplyToTextMode;
+ ASSERT(selectionStyle);
+ paintText(paintInfo.context(), style, *selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
+ break;
+ case PaintTypeStroke:
+ if (!hasVisibleStroke)
+ continue;
+ m_paintingResourceMode = ApplyToStrokeMode | ApplyToTextMode;
+ ASSERT(selectionStyle);
+ paintText(paintInfo.context(), style, *selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
+ break;
+ case PaintTypeMarkers:
+ continue;
+ }
}
// Spec: Line-through should be drawn after the text is filled and stroked; thus, the line-through is rendered on top of the text.
if (decorations & TextDecorationLineThrough)
- paintDecoration(paintInfo.context, TextDecorationLineThrough, fragment);
+ paintDecoration(paintInfo.context(), TextDecorationLineThrough, fragment);
m_paintingResourceMode = ApplyToDefaultMode;
}
+ // Finally, paint the outline if any.
+ if (renderer().style().hasOutline() && is<RenderInline>(parentRenderer))
+ downcast<RenderInline>(parentRenderer).paintOutline(paintInfo, paintOffset);
+
ASSERT(!m_paintingResource);
}
-bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, float scalingFactor, RenderBoxModelObject& renderer, RenderStyle* style)
+bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, float scalingFactor, RenderBoxModelObject& renderer, const RenderStyle& style)
{
ASSERT(scalingFactor);
- ASSERT(style);
ASSERT(m_paintingResourceMode != ApplyToDefaultMode);
Color fallbackColor;
if (m_paintingResourceMode & ApplyToFillMode)
- m_paintingResource = RenderSVGResource::fillPaintingResource(renderer, *style, fallbackColor);
+ m_paintingResource = RenderSVGResource::fillPaintingResource(renderer, style, fallbackColor);
else if (m_paintingResourceMode & ApplyToStrokeMode)
- m_paintingResource = RenderSVGResource::strokePaintingResource(renderer, *style, fallbackColor);
+ m_paintingResource = RenderSVGResource::strokePaintingResource(renderer, style, fallbackColor);
else {
// We're either called for stroking or filling.
ASSERT_NOT_REACHED();
@@ -347,13 +353,13 @@ bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, float
if (!m_paintingResource)
return false;
- if (!m_paintingResource->applyResource(renderer, *style, context, m_paintingResourceMode)) {
+ if (!m_paintingResource->applyResource(renderer, style, context, m_paintingResourceMode)) {
if (fallbackColor.isValid()) {
RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
fallbackResource->setColor(fallbackColor);
m_paintingResource = fallbackResource;
- m_paintingResource->applyResource(renderer, *style, context, m_paintingResourceMode);
+ m_paintingResource->applyResource(renderer, style, context, m_paintingResourceMode);
}
}
@@ -367,55 +373,28 @@ void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const
{
ASSERT(m_paintingResource);
- m_paintingResource->postApplyResource(parent()->renderer(), context, m_paintingResourceMode, path, /*RenderSVGShape*/ 0);
+ m_paintingResource->postApplyResource(parent()->renderer(), context, m_paintingResourceMode, path, /*RenderSVGShape*/ nullptr);
m_paintingResource = nullptr;
}
-bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& context, float scalingFactor, TextRun& textRun, RenderStyle* style)
+bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& context, float scalingFactor, const RenderStyle& style)
{
- bool acquiredResource = acquirePaintingResource(context, scalingFactor, parent()->renderer(), style);
- if (!acquiredResource)
- return false;
-
-#if ENABLE(SVG_FONTS)
- // SVG Fonts need access to the painting resource used to draw the current text chunk.
- TextRun::RenderingContext* renderingContext = textRun.renderingContext();
- if (renderingContext)
- static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePaintingResource(m_paintingResource);
-#endif
-
- return true;
+ return acquirePaintingResource(context, scalingFactor, parent()->renderer(), style);
}
-void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*& context, TextRun& textRun)
+void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*& context)
{
- releasePaintingResource(context, /* path */0);
-
-#if ENABLE(SVG_FONTS)
- TextRun::RenderingContext* renderingContext = textRun.renderingContext();
- if (renderingContext)
- static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePaintingResource(0);
-#else
- UNUSED_PARAM(textRun);
-#endif
+ releasePaintingResource(context, /* path */nullptr);
}
-TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFragment& fragment) const
+TextRun SVGInlineTextBox::constructTextRun(const RenderStyle& style, const SVGTextFragment& fragment) const
{
- ASSERT(style);
-
- TextRun run(renderer().deprecatedCharacters() + fragment.characterOffset
- , fragment.length
+ TextRun run(StringView(renderer().text()).substring(fragment.characterOffset, fragment.length)
, 0 /* xPos, only relevant with allowTabs=true */
, 0 /* padding, only relevant for justified text, not relevant for SVG */
- , TextRun::AllowTrailingExpansion
+ , AllowTrailingExpansion
, direction()
- , dirOverride() || style->rtlOrdering() == VisualOrder /* directionalOverride */);
-
- if (style->font().isSVGFont())
- run.setRenderingContext(SVGTextRunRenderingContext::create(renderer()));
-
- run.disableRoundingHacks();
+ , dirOverride() || style.rtlOrdering() == VisualOrder /* directionalOverride */);
// We handle letter & word spacing ourselves.
run.disableSpacing();
@@ -426,21 +405,24 @@ TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFrag
return run;
}
-bool SVGInlineTextBox::mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment& fragment, int& startPosition, int& endPosition) const
+bool SVGInlineTextBox::mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment& fragment, unsigned& startPosition, unsigned& endPosition) const
{
if (startPosition >= endPosition)
return false;
- int offset = static_cast<int>(fragment.characterOffset) - start();
- int length = static_cast<int>(fragment.length);
+ ASSERT(fragment.characterOffset >= start());
+ unsigned offset = fragment.characterOffset - start();
+ unsigned length = fragment.length;
if (startPosition >= offset + length || endPosition <= offset)
return false;
if (startPosition < offset)
startPosition = 0;
- else
+ else {
+ ASSERT(startPosition >= offset);
startPosition -= offset;
+ }
if (endPosition > offset + length)
endPosition = length;
@@ -468,7 +450,7 @@ static inline float positionOffsetForDecoration(TextDecoration decoration, const
return 0.0f;
}
-static inline float thicknessForDecoration(TextDecoration, const Font& font)
+static inline float thicknessForDecoration(TextDecoration, const FontCascade& font)
{
// FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified.
// Compatible with Batik/Opera
@@ -492,7 +474,7 @@ static inline RenderBoxModelObject& findRendererDefininingTextDecoration(InlineF
return *renderer;
}
-void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration decoration, const SVGTextFragment& fragment)
+void SVGInlineTextBox::paintDecoration(GraphicsContext& context, TextDecoration decoration, const SVGTextFragment& fragment)
{
if (renderer().style().textDecorationsInEffect() == TextDecorationNone)
return;
@@ -507,7 +489,7 @@ void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration
const SVGRenderStyle& svgDecorationStyle = decorationStyle.svgStyle();
bool hasDecorationFill = svgDecorationStyle.hasFill();
- bool hasVisibleDecorationStroke = svgDecorationStyle.hasVisibleStroke();
+ bool hasVisibleDecorationStroke = decorationStyle.hasVisibleStroke();
if (hasDecorationFill) {
m_paintingResourceMode = ApplyToFillMode;
@@ -520,16 +502,16 @@ void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration
}
}
-void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDecoration decoration, const SVGTextFragment& fragment, RenderBoxModelObject& decorationRenderer)
+void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext& context, TextDecoration decoration, const SVGTextFragment& fragment, RenderBoxModelObject& decorationRenderer)
{
ASSERT(!m_paintingResource);
ASSERT(m_paintingResourceMode != ApplyToDefaultMode);
- RenderStyle& decorationStyle = decorationRenderer.style();
+ auto& decorationStyle = decorationRenderer.style();
float scalingFactor = 1;
- Font scaledFont;
- RenderSVGInlineText::computeNewScaledFontForStyle(&decorationRenderer, &decorationStyle, scalingFactor, scaledFont);
+ FontCascade scaledFont;
+ RenderSVGInlineText::computeNewScaledFontForStyle(decorationRenderer, decorationStyle, scalingFactor, scaledFont);
ASSERT(scalingFactor);
// The initial y value refers to overline position.
@@ -542,11 +524,11 @@ void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDe
float width = fragment.width;
const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
- GraphicsContextStateSaver stateSaver(*context);
+ GraphicsContextStateSaver stateSaver(context);
if (scalingFactor != 1) {
width *= scalingFactor;
- decorationOrigin.scale(scalingFactor, scalingFactor);
- context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor));
+ decorationOrigin.scale(scalingFactor);
+ context.scale(1 / scalingFactor);
}
decorationOrigin.move(0, -scaledFontMetrics.floatAscent() + positionOffsetForDecoration(decoration, scaledFontMetrics, thickness));
@@ -554,66 +536,62 @@ void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDe
Path path;
path.addRect(FloatRect(decorationOrigin, FloatSize(width, thickness)));
- if (acquirePaintingResource(context, scalingFactor, decorationRenderer, &decorationStyle))
- releasePaintingResource(context, &path);
+ GraphicsContext* contextPtr = &context;
+ if (acquirePaintingResource(contextPtr, scalingFactor, decorationRenderer, decorationStyle))
+ releasePaintingResource(contextPtr, &path);
}
-void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyle* style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition)
+void SVGInlineTextBox::paintTextWithShadows(GraphicsContext& context, const RenderStyle& style, TextRun& textRun, const SVGTextFragment& fragment, unsigned startPosition, unsigned endPosition)
{
float scalingFactor = renderer().scalingFactor();
ASSERT(scalingFactor);
- const Font& scaledFont = renderer().scaledFont();
- const ShadowData* shadow = style->textShadow();
+ const FontCascade& scaledFont = renderer().scaledFont();
+ const ShadowData* shadow = style.textShadow();
FloatPoint textOrigin(fragment.x, fragment.y);
FloatSize textSize(fragment.width, fragment.height);
if (scalingFactor != 1) {
- textOrigin.scale(scalingFactor, scalingFactor);
+ textOrigin.scale(scalingFactor);
textSize.scale(scalingFactor);
}
FloatRect shadowRect(FloatPoint(textOrigin.x(), textOrigin.y() - scaledFont.fontMetrics().floatAscent()), textSize);
+ GraphicsContext* usedContext = &context;
do {
- if (!prepareGraphicsContextForTextPainting(context, scalingFactor, textRun, style))
+ if (!prepareGraphicsContextForTextPainting(usedContext, scalingFactor, style))
break;
- FloatSize extraOffset;
- if (shadow)
- extraOffset = applyShadowToGraphicsContext(context, shadow, shadowRect, false /* stroked */, true /* opaque */, true /* horizontal */);
+ {
+ ShadowApplier shadowApplier(*usedContext, shadow, shadowRect);
- context->save();
- context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor));
+ if (!shadowApplier.didSaveContext())
+ usedContext->save();
+ usedContext->scale(1 / scalingFactor);
- scaledFont.drawText(context, textRun, textOrigin + extraOffset, startPosition, endPosition);
+ scaledFont.drawText(*usedContext, textRun, textOrigin + shadowApplier.extraOffset(), startPosition, endPosition);
- context->restore();
+ if (!shadowApplier.didSaveContext())
+ usedContext->restore();
+ }
- restoreGraphicsContextAfterTextPainting(context, textRun);
+ restoreGraphicsContextAfterTextPainting(usedContext);
if (!shadow)
break;
- if (shadow->next())
- context->restore();
- else
- context->clearShadow();
-
shadow = shadow->next();
} while (shadow);
}
-void SVGInlineTextBox::paintText(GraphicsContext* context, RenderStyle* style, RenderStyle* selectionStyle, const SVGTextFragment& fragment, bool hasSelection, bool paintSelectedTextOnly)
+void SVGInlineTextBox::paintText(GraphicsContext& context, const RenderStyle& style, const RenderStyle& selectionStyle, const SVGTextFragment& fragment, bool hasSelection, bool paintSelectedTextOnly)
{
- ASSERT(style);
- ASSERT(selectionStyle);
-
- int startPosition = 0;
- int endPosition = 0;
+ unsigned startPosition = 0;
+ unsigned endPosition = 0;
if (hasSelection) {
- selectionStartEnd(startPosition, endPosition);
+ std::tie(startPosition, endPosition) = selectionStartEnd();
hasSelection = mapStartEndPositionsIntoFragmentCoordinates(fragment, startPosition, endPosition);
}
@@ -630,16 +608,15 @@ void SVGInlineTextBox::paintText(GraphicsContext* context, RenderStyle* style, R
// Draw text using selection style from the start to the end position of the selection
if (style != selectionStyle)
- SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, *selectionStyle);
+ SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, selectionStyle);
- TextRun selectionTextRun = constructTextRun(selectionStyle, fragment);
paintTextWithShadows(context, selectionStyle, textRun, fragment, startPosition, endPosition);
if (style != selectionStyle)
- SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, *style);
+ SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, style);
// Eventually draw text using regular style from the end position of the selection to the end of the current chunk part
- if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnly)
+ if (endPosition < fragment.length && !paintSelectedTextOnly)
paintTextWithShadows(context, style, textRun, fragment, endPosition, fragment.length);
}
@@ -667,7 +644,7 @@ FloatRect SVGInlineTextBox::calculateBoundaries() const
return textRect;
}
-bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit, LayoutUnit)
+bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit, LayoutUnit, HitTestAction)
{
// FIXME: integrate with InlineTextBox::nodeAtPoint better.
ASSERT(!isLineBreak());
@@ -681,9 +658,25 @@ bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult&
boxOrigin.moveBy(accumulatedOffset);
FloatRect rect(boxOrigin, size());
if (locationInContainer.intersects(rect)) {
- renderer().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
- if (!result.addNodeToRectBasedTestResult(&renderer().textNode(), request, locationInContainer, rect))
- return true;
+
+ float scalingFactor = renderer().scalingFactor();
+ ASSERT(scalingFactor);
+
+ float baseline = renderer().scaledFont().fontMetrics().floatAscent() / scalingFactor;
+
+ AffineTransform fragmentTransform;
+ for (auto& fragment : m_textFragments) {
+ FloatQuad fragmentQuad(FloatRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height));
+ fragment.buildFragmentTransform(fragmentTransform);
+ if (!fragmentTransform.isIdentity())
+ fragmentQuad = fragmentTransform.mapQuad(fragmentQuad);
+
+ if (fragmentQuad.containsPoint(locationInContainer.point())) {
+ renderer().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
+ if (!result.addNodeToRectBasedTestResult(&renderer().textNode(), request, locationInContainer, rect))
+ return true;
+ }
+ }
}
}
}
@@ -691,5 +684,3 @@ bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult&
}
} // namespace WebCore
-
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.h b/Source/WebCore/rendering/svg/SVGInlineTextBox.h
index 97df4d698..217bac12e 100644
--- a/Source/WebCore/rendering/svg/SVGInlineTextBox.h
+++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.h
@@ -19,10 +19,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGInlineTextBox_h
-#define SVGInlineTextBox_h
+#pragma once
-#if ENABLE(SVG)
#include "InlineTextBox.h"
#include "SVGTextLayoutEngine.h"
#include "RenderSVGInlineText.h"
@@ -36,54 +34,54 @@ class SVGInlineTextBox final : public InlineTextBox {
public:
explicit SVGInlineTextBox(RenderSVGInlineText&);
- RenderSVGInlineText& renderer() const { return toRenderSVGInlineText(InlineTextBox::renderer()); }
+ RenderSVGInlineText& renderer() const { return downcast<RenderSVGInlineText>(InlineTextBox::renderer()); }
- virtual float virtualLogicalHeight() const { return m_logicalHeight; }
+ float virtualLogicalHeight() const override { return m_logicalHeight; }
void setLogicalHeight(float height) { m_logicalHeight = height; }
- virtual int selectionTop() { return top(); }
- virtual int selectionHeight() { return static_cast<int>(ceilf(m_logicalHeight)); }
- virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const;
- virtual float positionForOffset(int offset) const;
+ int selectionTop() { return top(); }
+ int selectionHeight() { return static_cast<int>(ceilf(m_logicalHeight)); }
+ int offsetForPosition(float x, bool includePartialGlyphs = true) const override;
+ float positionForOffset(unsigned offset) const override;
void paintSelectionBackground(PaintInfo&);
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
- virtual LayoutRect localSelectionRect(int startPosition, int endPosition) const override;
+ void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override;
+ LayoutRect localSelectionRect(unsigned startPosition, unsigned endPosition) const override;
- bool mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment&, int& startPosition, int& endPosition) const;
+ bool mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment&, unsigned& startPosition, unsigned& endPosition) const;
- virtual FloatRect calculateBoundaries() const;
+ FloatRect calculateBoundaries() const override;
void clearTextFragments() { m_textFragments.clear(); }
Vector<SVGTextFragment>& textFragments() { return m_textFragments; }
const Vector<SVGTextFragment>& textFragments() const { return m_textFragments; }
- virtual void dirtyOwnLineBoxes() override final;
- virtual void dirtyLineBoxes() override final;
+ void dirtyOwnLineBoxes() override;
+ void dirtyLineBoxes() override;
bool startsNewTextChunk() const { return m_startsNewTextChunk; }
void setStartsNewTextChunk(bool newTextChunk) { m_startsNewTextChunk = newTextChunk; }
int offsetForPositionInFragment(const SVGTextFragment&, float position, bool includePartialGlyphs) const;
- FloatRect selectionRectForTextFragment(const SVGTextFragment&, int fragmentStartPosition, int fragmentEndPosition, RenderStyle*) const;
+ FloatRect selectionRectForTextFragment(const SVGTextFragment&, unsigned fragmentStartPosition, unsigned fragmentEndPosition, const RenderStyle&) const;
private:
- virtual bool isSVGInlineTextBox() const override { return true; }
+ bool isSVGInlineTextBox() const override { return true; }
- TextRun constructTextRun(RenderStyle*, const SVGTextFragment&) const;
+ TextRun constructTextRun(const RenderStyle&, const SVGTextFragment&) const;
- bool acquirePaintingResource(GraphicsContext*&, float scalingFactor, RenderBoxModelObject&, RenderStyle*);
+ bool acquirePaintingResource(GraphicsContext*&, float scalingFactor, RenderBoxModelObject&, const RenderStyle&);
void releasePaintingResource(GraphicsContext*&, const Path*);
- bool prepareGraphicsContextForTextPainting(GraphicsContext*&, float scalingFactor, TextRun&, RenderStyle*);
- void restoreGraphicsContextAfterTextPainting(GraphicsContext*&, TextRun&);
+ bool prepareGraphicsContextForTextPainting(GraphicsContext*&, float scalingFactor, const RenderStyle&);
+ void restoreGraphicsContextAfterTextPainting(GraphicsContext*&);
- void paintDecoration(GraphicsContext*, TextDecoration, const SVGTextFragment&);
- void paintDecorationWithStyle(GraphicsContext*, TextDecoration, const SVGTextFragment&, RenderBoxModelObject& decorationRenderer);
- void paintTextWithShadows(GraphicsContext*, RenderStyle*, TextRun&, const SVGTextFragment&, int startPosition, int endPosition);
- void paintText(GraphicsContext*, RenderStyle*, RenderStyle* selectionStyle, const SVGTextFragment&, bool hasSelection, bool paintSelectedTextOnly);
+ void paintDecoration(GraphicsContext&, TextDecoration, const SVGTextFragment&);
+ void paintDecorationWithStyle(GraphicsContext&, TextDecoration, const SVGTextFragment&, RenderBoxModelObject& decorationRenderer);
+ void paintTextWithShadows(GraphicsContext&, const RenderStyle&, TextRun&, const SVGTextFragment&, unsigned startPosition, unsigned endPosition);
+ void paintText(GraphicsContext&, const RenderStyle&, const RenderStyle& selectionStyle, const SVGTextFragment&, bool hasSelection, bool paintSelectedTextOnly);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) override;
+ bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom, HitTestAction) override;
private:
float m_logicalHeight;
@@ -93,9 +91,6 @@ private:
Vector<SVGTextFragment> m_textFragments;
};
-INLINE_BOX_OBJECT_TYPE_CASTS(SVGInlineTextBox, isSVGInlineTextBox())
-
} // namespace WebCore
-#endif
-#endif // SVGInlineTextBox_h
+SPECIALIZE_TYPE_TRAITS_INLINE_BOX(SVGInlineTextBox, isSVGInlineTextBox())
diff --git a/Source/WebCore/rendering/svg/SVGMarkerData.h b/Source/WebCore/rendering/svg/SVGMarkerData.h
index 5d5a86d98..53da371f7 100644
--- a/Source/WebCore/rendering/svg/SVGMarkerData.h
+++ b/Source/WebCore/rendering/svg/SVGMarkerData.h
@@ -17,13 +17,10 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGMarkerData_h
-#define SVGMarkerData_h
+#pragma once
-#if ENABLE(SVG)
#include "FloatConversion.h"
#include "Path.h"
-#include <wtf/MathExtras.h>
namespace WebCore {
@@ -50,28 +47,27 @@ struct MarkerPosition {
class SVGMarkerData {
public:
- SVGMarkerData(Vector<MarkerPosition>& positions)
+ SVGMarkerData(Vector<MarkerPosition>& positions, bool reverseStart)
: m_positions(positions)
, m_elementIndex(0)
+ , m_reverseStart(reverseStart)
{
}
- static void updateFromPathElement(void* info, const PathElement* element)
+ static void updateFromPathElement(SVGMarkerData& markerData, const PathElement& element)
{
- SVGMarkerData* markerData = static_cast<SVGMarkerData*>(info);
-
// First update the outslope for the previous element.
- markerData->updateOutslope(element->points[0]);
+ markerData.updateOutslope(element.points[0]);
// Record the marker for the previous element.
- if (markerData->m_elementIndex > 0) {
- SVGMarkerType markerType = markerData->m_elementIndex == 1 ? StartMarker : MidMarker;
- markerData->m_positions.append(MarkerPosition(markerType, markerData->m_origin, markerData->currentAngle(markerType)));
+ if (markerData.m_elementIndex > 0) {
+ SVGMarkerType markerType = markerData.m_elementIndex == 1 ? StartMarker : MidMarker;
+ markerData.m_positions.append(MarkerPosition(markerType, markerData.m_origin, markerData.currentAngle(markerType)));
}
// Update our marker data for this element.
- markerData->updateMarkerDataForPathElement(element);
- ++markerData->m_elementIndex;
+ markerData.updateMarkerDataForPathElement(element);
+ ++markerData.m_elementIndex;
}
void pathIsDone()
@@ -91,6 +87,8 @@ private:
switch (type) {
case StartMarker:
+ if (m_reverseStart)
+ return narrowPrecisionToFloat(outAngle - 180);
return narrowPrecisionToFloat(outAngle);
case MidMarker:
// WK193015: Prevent bugs due to angles being non-continuous.
@@ -111,11 +109,11 @@ private:
m_outslopePoints[1] = point;
}
- void updateMarkerDataForPathElement(const PathElement* element)
+ void updateMarkerDataForPathElement(const PathElement& element)
{
- FloatPoint* points = element->points;
+ FloatPoint* points = element.points;
- switch (element->type) {
+ switch (element.type) {
case PathElementAddQuadCurveToPoint:
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=33115 (PathElementAddQuadCurveToPoint not handled for <marker>)
m_origin = points[1];
@@ -151,9 +149,7 @@ private:
FloatPoint m_subpathStart;
FloatPoint m_inslopePoints[2];
FloatPoint m_outslopePoints[2];
+ bool m_reverseStart;
};
-}
-
-#endif // ENABLE(SVG)
-#endif // SVGMarkerData_h
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/SVGPathData.cpp b/Source/WebCore/rendering/svg/SVGPathData.cpp
index 01ef871f7..6eeb5476c 100644
--- a/Source/WebCore/rendering/svg/SVGPathData.cpp
+++ b/Source/WebCore/rendering/svg/SVGPathData.cpp
@@ -20,14 +20,18 @@
#include "config.h"
#include "SVGPathData.h"
-#if ENABLE(SVG)
#include "Path.h"
+#include "RenderElement.h"
+#include "RenderStyle.h"
#include "SVGCircleElement.h"
#include "SVGEllipseElement.h"
+#include "SVGLengthContext.h"
#include "SVGLineElement.h"
#include "SVGNames.h"
#include "SVGPathElement.h"
#include "SVGPathUtilities.h"
+#include "SVGPoint.h"
+#include "SVGPointList.h"
#include "SVGPolygonElement.h"
#include "SVGPolylineElement.h"
#include "SVGRectElement.h"
@@ -37,32 +41,42 @@ namespace WebCore {
static void updatePathFromCircleElement(SVGElement* element, Path& path)
{
- ASSERT(isSVGCircleElement(element));
- SVGCircleElement* circle = toSVGCircleElement(element);
+ ASSERT(is<SVGCircleElement>(element));
SVGLengthContext lengthContext(element);
- float r = circle->r().value(lengthContext);
- if (r > 0)
- path.addEllipse(FloatRect(circle->cx().value(lengthContext) - r, circle->cy().value(lengthContext) - r, r * 2, r * 2));
+ RenderElement* renderer = element->renderer();
+ if (!renderer)
+ return;
+ auto& style = renderer->style();
+ float r = lengthContext.valueForLength(style.svgStyle().r());
+ if (r > 0) {
+ float cx = lengthContext.valueForLength(style.svgStyle().cx(), LengthModeWidth);
+ float cy = lengthContext.valueForLength(style.svgStyle().cy(), LengthModeHeight);
+ path.addEllipse(FloatRect(cx - r, cy - r, r * 2, r * 2));
+ }
}
static void updatePathFromEllipseElement(SVGElement* element, Path& path)
{
- SVGEllipseElement* ellipse = toSVGEllipseElement(element);
-
+ RenderElement* renderer = element->renderer();
+ if (!renderer)
+ return;
+ auto& style = renderer->style();
SVGLengthContext lengthContext(element);
- float rx = ellipse->rx().value(lengthContext);
+ float rx = lengthContext.valueForLength(style.svgStyle().rx(), LengthModeWidth);
if (rx <= 0)
return;
- float ry = ellipse->ry().value(lengthContext);
+ float ry = lengthContext.valueForLength(style.svgStyle().ry(), LengthModeHeight);
if (ry <= 0)
return;
- path.addEllipse(FloatRect(ellipse->cx().value(lengthContext) - rx, ellipse->cy().value(lengthContext) - ry, rx * 2, ry * 2));
+ float cx = lengthContext.valueForLength(style.svgStyle().cx(), LengthModeWidth);
+ float cy = lengthContext.valueForLength(style.svgStyle().cy(), LengthModeHeight);
+ path.addEllipse(FloatRect(cx - rx, cy - ry, rx * 2, ry * 2));
}
static void updatePathFromLineElement(SVGElement* element, Path& path)
{
- SVGLineElement* line = toSVGLineElement(element);
+ SVGLineElement* line = downcast<SVGLineElement>(element);
SVGLengthContext lengthContext(element);
path.moveTo(FloatPoint(line->x1().value(lengthContext), line->y1().value(lengthContext)));
@@ -71,12 +85,12 @@ static void updatePathFromLineElement(SVGElement* element, Path& path)
static void updatePathFromPathElement(SVGElement* element, Path& path)
{
- buildPathFromByteStream(toSVGPathElement(element)->pathByteStream(), path);
+ buildPathFromByteStream(downcast<SVGPathElement>(element)->pathByteStream(), path);
}
static void updatePathFromPolygonElement(SVGElement* element, Path& path)
{
- SVGPointList& points = toSVGPolygonElement(element)->animatedPoints()->values();
+ auto& points = downcast<SVGPolygonElement>(element)->animatedPoints()->values();
if (points.isEmpty())
return;
@@ -91,7 +105,7 @@ static void updatePathFromPolygonElement(SVGElement* element, Path& path)
static void updatePathFromPolylineElement(SVGElement* element, Path& path)
{
- SVGPointList& points = toSVGPolylineElement(element)->animatedPoints()->values();
+ auto& points = downcast<SVGPolylineElement>(element)->animatedPoints()->values();
if (points.isEmpty())
return;
@@ -104,19 +118,22 @@ static void updatePathFromPolylineElement(SVGElement* element, Path& path)
static void updatePathFromRectElement(SVGElement* element, Path& path)
{
- SVGRectElement* rect = toSVGRectElement(element);
+ RenderElement* renderer = element->renderer();
+ if (!renderer)
+ return;
+ auto& style = renderer->style();
SVGLengthContext lengthContext(element);
- float width = rect->width().value(lengthContext);
+ float width = lengthContext.valueForLength(style.width(), LengthModeWidth);
if (width <= 0)
return;
- float height = rect->height().value(lengthContext);
+ float height = lengthContext.valueForLength(style.height(), LengthModeHeight);
if (height <= 0)
return;
- float x = rect->x().value(lengthContext);
- float y = rect->y().value(lengthContext);
- float rx = rect->rx().value(lengthContext);
- float ry = rect->ry().value(lengthContext);
+ float x = lengthContext.valueForLength(style.svgStyle().x(), LengthModeWidth);
+ float y = lengthContext.valueForLength(style.svgStyle().y(), LengthModeHeight);
+ float rx = lengthContext.valueForLength(style.svgStyle().rx(), LengthModeWidth);
+ float ry = lengthContext.valueForLength(style.svgStyle().ry(), LengthModeHeight);
bool hasRx = rx > 0;
bool hasRy = ry > 0;
if (hasRx || hasRy) {
@@ -143,13 +160,13 @@ void updatePathFromGraphicsElement(SVGElement* element, Path& path)
static HashMap<AtomicStringImpl*, PathUpdateFunction>* map = 0;
if (!map) {
map = new HashMap<AtomicStringImpl*, PathUpdateFunction>;
- map->set(SVGNames::circleTag.localName().impl(), &updatePathFromCircleElement);
- map->set(SVGNames::ellipseTag.localName().impl(), &updatePathFromEllipseElement);
- map->set(SVGNames::lineTag.localName().impl(), &updatePathFromLineElement);
- map->set(SVGNames::pathTag.localName().impl(), &updatePathFromPathElement);
- map->set(SVGNames::polygonTag.localName().impl(), &updatePathFromPolygonElement);
- map->set(SVGNames::polylineTag.localName().impl(), &updatePathFromPolylineElement);
- map->set(SVGNames::rectTag.localName().impl(), &updatePathFromRectElement);
+ map->set(SVGNames::circleTag.localName().impl(), updatePathFromCircleElement);
+ map->set(SVGNames::ellipseTag.localName().impl(), updatePathFromEllipseElement);
+ map->set(SVGNames::lineTag.localName().impl(), updatePathFromLineElement);
+ map->set(SVGNames::pathTag.localName().impl(), updatePathFromPathElement);
+ map->set(SVGNames::polygonTag.localName().impl(), updatePathFromPolygonElement);
+ map->set(SVGNames::polylineTag.localName().impl(), updatePathFromPolylineElement);
+ map->set(SVGNames::rectTag.localName().impl(), updatePathFromRectElement);
}
if (PathUpdateFunction pathUpdateFunction = map->get(element->localName().impl()))
@@ -157,5 +174,3 @@ void updatePathFromGraphicsElement(SVGElement* element, Path& path)
}
} // namespace WebCore
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGPathData.h b/Source/WebCore/rendering/svg/SVGPathData.h
index 1a4b7ba89..9da6bad30 100644
--- a/Source/WebCore/rendering/svg/SVGPathData.h
+++ b/Source/WebCore/rendering/svg/SVGPathData.h
@@ -17,10 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGPathData_h
-#define SVGPathData_h
+#pragma once
-#if ENABLE(SVG)
namespace WebCore {
class SVGElement;
@@ -28,7 +26,4 @@ class Path;
void updatePathFromGraphicsElement(SVGElement*, Path&);
-};
-
-#endif // ENABLE(SVG)
-#endif // SVGPathData_h
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
index 9602927f2..0113c7015 100644
--- a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
+++ b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
@@ -23,21 +23,22 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGRenderSupport.h"
#include "NodeRenderStyle.h"
+#include "RenderChildIterator.h"
#include "RenderElement.h"
#include "RenderGeometryMap.h"
#include "RenderIterator.h"
#include "RenderLayer.h"
+#include "RenderSVGImage.h"
#include "RenderSVGResourceClipper.h"
#include "RenderSVGResourceFilter.h"
#include "RenderSVGResourceMarker.h"
#include "RenderSVGResourceMasker.h"
#include "RenderSVGRoot.h"
#include "RenderSVGText.h"
+#include "RenderSVGTransformableContainer.h"
#include "RenderSVGViewportContainer.h"
#include "SVGResources.h"
#include "SVGResourcesCache.h"
@@ -49,8 +50,8 @@ FloatRect SVGRenderSupport::repaintRectForRendererInLocalCoordinatesExcludingSVG
{
// FIXME: Add support for RenderSVGBlock.
- if (renderer.isSVGShape() || renderer.isSVGImage() || renderer.isSVGContainer())
- return toRenderSVGModelObject(renderer).repaintRectInLocalCoordinatesExcludingSVGShadow();
+ if (is<RenderSVGModelObject>(renderer))
+ return downcast<RenderSVGModelObject>(renderer).repaintRectInLocalCoordinatesExcludingSVGShadow();
return renderer.repaintRectInLocalCoordinates();
}
@@ -67,34 +68,43 @@ LayoutRect SVGRenderSupport::clippedOverflowRectForRepaint(const RenderElement&
const SVGRenderStyle& svgStyle = renderer.style().svgStyle();
if (const ShadowData* shadow = svgStyle.shadow())
shadow->adjustRectForShadow(repaintRect);
- renderer.computeFloatRectForRepaint(repaintContainer, repaintRect);
- return enclosingLayoutRect(repaintRect);
+ return enclosingLayoutRect(renderer.computeFloatRectForRepaint(repaintRect, repaintContainer));
}
-void SVGRenderSupport::computeFloatRectForRepaint(const RenderElement& renderer, const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed)
+FloatRect SVGRenderSupport::computeFloatRectForRepaint(const RenderElement& renderer, const FloatRect& repaintRect, const RenderLayerModelObject* repaintContainer, bool fixed)
{
+ FloatRect adjustedRect = repaintRect;
const SVGRenderStyle& svgStyle = renderer.style().svgStyle();
if (const ShadowData* shadow = svgStyle.shadow())
- shadow->adjustRectForShadow(repaintRect);
- repaintRect.inflate(renderer.style().outlineWidth());
+ shadow->adjustRectForShadow(adjustedRect);
+ adjustedRect.inflate(renderer.style().outlineWidth());
// Translate to coords in our parent renderer, and then call computeFloatRectForRepaint() on our parent.
- repaintRect = renderer.localToParentTransform().mapRect(repaintRect);
- renderer.parent()->computeFloatRectForRepaint(repaintContainer, repaintRect, fixed);
+ adjustedRect = renderer.localToParentTransform().mapRect(adjustedRect);
+ return renderer.parent()->computeFloatRectForRepaint(adjustedRect, repaintContainer, fixed);
}
-void SVGRenderSupport::mapLocalToContainer(const RenderElement& renderer, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool* wasFixed)
+const RenderElement& SVGRenderSupport::localToParentTransform(const RenderElement& renderer, AffineTransform &transform)
{
- transformState.applyTransform(renderer.localToParentTransform());
-
ASSERT(renderer.parent());
auto& parent = *renderer.parent();
-
- // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform
+
+ // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform
// to map an element from SVG viewport coordinates to CSS box coordinates.
- // RenderSVGRoot's mapLocalToContainer method expects CSS box coordinates.
- if (parent.isSVGRoot())
- transformState.applyTransform(toRenderSVGRoot(parent).localToBorderBoxTransform());
+ if (is<RenderSVGRoot>(parent))
+ transform = downcast<RenderSVGRoot>(parent).localToBorderBoxTransform() * renderer.localToParentTransform();
+ else
+ transform = renderer.localToParentTransform();
+
+ return parent;
+}
+
+void SVGRenderSupport::mapLocalToContainer(const RenderElement& renderer, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool* wasFixed)
+{
+ AffineTransform transform;
+ auto& parent = localToParentTransform(renderer, transform);
+
+ transformState.applyTransform(transform);
MapCoordinatesFlags mode = UseTransforms;
parent.mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
@@ -104,19 +114,10 @@ const RenderElement* SVGRenderSupport::pushMappingToContainer(const RenderElemen
{
ASSERT_UNUSED(ancestorToStopAt, ancestorToStopAt != &renderer);
- ASSERT(renderer.parent());
- auto& parent = *renderer.parent();
-
- // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform
- // to map an element from SVG viewport coordinates to CSS box coordinates.
- // RenderSVGRoot's mapLocalToContainer method expects CSS box coordinates.
- if (parent.isSVGRoot()) {
- TransformationMatrix matrix(renderer.localToParentTransform());
- matrix.multiply(toRenderSVGRoot(parent).localToBorderBoxTransform());
- geometryMap.push(&renderer, matrix);
- } else
- geometryMap.push(&renderer, renderer.localToParentTransform());
+ AffineTransform transform;
+ auto& parent = localToParentTransform(renderer, transform);
+ geometryMap.push(&renderer, transform);
return &parent;
}
@@ -127,13 +128,13 @@ bool SVGRenderSupport::checkForSVGRepaintDuringLayout(const RenderElement& rende
// When a parent container is transformed in SVG, all children will be painted automatically
// so we are able to skip redundant repaint checks.
auto parent = renderer.parent();
- return !(parent && parent->isSVGContainer() && toRenderSVGContainer(parent)->didTransformToRootUpdate());
+ return !(is<RenderSVGContainer>(parent) && downcast<RenderSVGContainer>(*parent).didTransformToRootUpdate());
}
// Update a bounding box taking into account the validity of the other bounding box.
-static inline void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox)
+static inline void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, const RenderObject* other, FloatRect otherBoundingBox)
{
- bool otherValid = other->isSVGContainer() ? toRenderSVGContainer(other)->isObjectBoundingBoxValid() : true;
+ bool otherValid = is<RenderSVGContainer>(*other) ? downcast<RenderSVGContainer>(*other).isObjectBoundingBoxValid() : true;
if (!otherValid)
return;
@@ -155,17 +156,21 @@ void SVGRenderSupport::computeContainerBoundingBoxes(const RenderElement& contai
// When computing the strokeBoundingBox, we use the repaintRects of the container's children so that the container's stroke includes
// the resources applied to the children (such as clips and filters). This allows filters applied to containers to correctly bound
// the children, and also improves inlining of SVG content, as the stroke bound is used in that situation also.
- for (RenderObject* current = container.firstChild(); current; current = current->nextSibling()) {
- if (current->isSVGHiddenContainer())
+ for (auto& current : childrenOfType<RenderObject>(container)) {
+ if (current.isSVGHiddenContainer())
+ continue;
+
+ // Don't include elements in the union that do not render.
+ if (is<RenderSVGShape>(current) && downcast<RenderSVGShape>(current).isRenderingDisabled())
continue;
- const AffineTransform& transform = current->localToParentTransform();
+ const AffineTransform& transform = current.localToParentTransform();
if (transform.isIdentity()) {
- updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, current->objectBoundingBox());
- strokeBoundingBox.unite(current->repaintRectInLocalCoordinates());
+ updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, &current, current.objectBoundingBox());
+ strokeBoundingBox.unite(current.repaintRectInLocalCoordinates());
} else {
- updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, transform.mapRect(current->objectBoundingBox()));
- strokeBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoordinates()));
+ updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, &current, transform.mapRect(current.objectBoundingBox()));
+ strokeBoundingBox.unite(transform.mapRect(current.repaintRectInLocalCoordinates()));
}
}
@@ -180,141 +185,149 @@ bool SVGRenderSupport::paintInfoIntersectsRepaintRect(const FloatRect& localRepa
return localTransform.mapRect(localRepaintRect).intersects(paintInfo.rect);
}
-const RenderSVGRoot& SVGRenderSupport::findTreeRootObject(const RenderElement& start)
+RenderSVGRoot* SVGRenderSupport::findTreeRootObject(RenderElement& start)
{
- return *lineageOfType<RenderSVGRoot>(start).first();
+ return lineageOfType<RenderSVGRoot>(start).first();
}
-static inline void invalidateResourcesOfChildren(RenderObject& start)
+const RenderSVGRoot* SVGRenderSupport::findTreeRootObject(const RenderElement& start)
{
- ASSERT(!start.needsLayout());
- if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(start))
- resources->removeClientFromCache(start, false);
+ return lineageOfType<RenderSVGRoot>(start).first();
+}
+
+static inline void invalidateResourcesOfChildren(RenderElement& renderer)
+{
+ ASSERT(!renderer.needsLayout());
+ if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer))
+ resources->removeClientFromCache(renderer, false);
- for (RenderObject* child = start.firstChildSlow(); child; child = child->nextSibling())
- invalidateResourcesOfChildren(*child);
+ for (auto& child : childrenOfType<RenderElement>(renderer))
+ invalidateResourcesOfChildren(child);
}
static inline bool layoutSizeOfNearestViewportChanged(const RenderElement& renderer)
{
const RenderElement* start = &renderer;
- while (start && !start->isSVGRoot() && !start->isSVGViewportContainer())
+ while (start && !is<RenderSVGRoot>(*start) && !is<RenderSVGViewportContainer>(*start))
start = start->parent();
ASSERT(start);
- ASSERT(start->isSVGRoot() || start->isSVGViewportContainer());
- if (start->isSVGViewportContainer())
- return toRenderSVGViewportContainer(start)->isLayoutSizeChanged();
+ if (is<RenderSVGViewportContainer>(*start))
+ return downcast<RenderSVGViewportContainer>(*start).isLayoutSizeChanged();
- return toRenderSVGRoot(start)->isLayoutSizeChanged();
+ return downcast<RenderSVGRoot>(*start).isLayoutSizeChanged();
}
bool SVGRenderSupport::transformToRootChanged(RenderElement* ancestor)
{
- while (ancestor && !ancestor->isSVGRoot()) {
- if (ancestor->isSVGTransformableContainer())
- return toRenderSVGContainer(ancestor)->didTransformToRootUpdate();
- if (ancestor->isSVGViewportContainer())
- return toRenderSVGViewportContainer(ancestor)->didTransformToRootUpdate();
+ while (ancestor && !is<RenderSVGRoot>(*ancestor)) {
+ if (is<RenderSVGTransformableContainer>(*ancestor))
+ return downcast<RenderSVGTransformableContainer>(*ancestor).didTransformToRootUpdate();
+ if (is<RenderSVGViewportContainer>(*ancestor))
+ return downcast<RenderSVGViewportContainer>(*ancestor).didTransformToRootUpdate();
ancestor = ancestor->parent();
}
return false;
}
+void SVGRenderSupport::layoutDifferentRootIfNeeded(const RenderElement& renderer)
+{
+ if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) {
+ auto* svgRoot = SVGRenderSupport::findTreeRootObject(renderer);
+ ASSERT(svgRoot);
+ resources->layoutDifferentRootIfNeeded(svgRoot);
+ }
+}
+
void SVGRenderSupport::layoutChildren(RenderElement& start, bool selfNeedsLayout)
{
bool layoutSizeChanged = layoutSizeOfNearestViewportChanged(start);
bool transformChanged = transformToRootChanged(&start);
bool hasSVGShadow = rendererHasSVGShadow(start);
bool needsBoundariesUpdate = start.needsBoundariesUpdate();
- HashSet<RenderObject*> notlayoutedObjects;
+ HashSet<RenderElement*> elementsThatDidNotReceiveLayout;
- for (RenderObject* child = start.firstChild(); child; child = child->nextSibling()) {
+ for (auto& child : childrenOfType<RenderObject>(start)) {
bool needsLayout = selfNeedsLayout;
- bool childEverHadLayout = child->everHadLayout();
+ bool childEverHadLayout = child.everHadLayout();
if (needsBoundariesUpdate && hasSVGShadow) {
// If we have a shadow, our shadow is baked into our children's cached boundaries,
// so they need to update.
- child->setNeedsBoundariesUpdate();
+ child.setNeedsBoundariesUpdate();
needsLayout = true;
}
if (transformChanged) {
// If the transform changed we need to update the text metrics (note: this also happens for layoutSizeChanged=true).
- if (child->isSVGText())
- toRenderSVGText(child)->setNeedsTextMetricsUpdate();
+ if (is<RenderSVGText>(child))
+ downcast<RenderSVGText>(child).setNeedsTextMetricsUpdate();
needsLayout = true;
}
- if (layoutSizeChanged) {
+ if (layoutSizeChanged && is<SVGElement>(*child.node())) {
// When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths
- if (SVGElement* element = child->node()->isSVGElement() ? toSVGElement(child->node()) : 0) {
- if (element->hasRelativeLengths()) {
- // When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object
- if (child->isSVGShape())
- toRenderSVGShape(child)->setNeedsShapeUpdate();
- else if (child->isSVGText()) {
- toRenderSVGText(child)->setNeedsTextMetricsUpdate();
- toRenderSVGText(child)->setNeedsPositioningValuesUpdate();
- }
-
- needsLayout = true;
+ auto& element = downcast<SVGElement>(*child.node());
+ if (element.hasRelativeLengths()) {
+ // When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object
+ if (is<RenderSVGShape>(child))
+ downcast<RenderSVGShape>(child).setNeedsShapeUpdate();
+ else if (is<RenderSVGText>(child)) {
+ auto& svgText = downcast<RenderSVGText>(child);
+ svgText.setNeedsTextMetricsUpdate();
+ svgText.setNeedsPositioningValuesUpdate();
}
+
+ needsLayout = true;
}
}
if (needsLayout)
- child->setNeedsLayout(MarkOnlyThis);
+ child.setNeedsLayout(MarkOnlyThis);
- if (child->needsLayout()) {
- toRenderElement(child)->layout();
+ if (child.needsLayout()) {
+ layoutDifferentRootIfNeeded(downcast<RenderElement>(child));
+ downcast<RenderElement>(child).layout();
// Renderers are responsible for repainting themselves when changing, except
// for the initial paint to avoid potential double-painting caused by non-sensical "old" bounds.
// We could handle this in the individual objects, but for now it's easier to have
// parent containers call repaint(). (RenderBlock::layout* has similar logic.)
if (!childEverHadLayout)
- child->repaint();
- } else if (layoutSizeChanged)
- notlayoutedObjects.add(child);
+ child.repaint();
+ } else if (layoutSizeChanged && is<RenderElement>(child))
+ elementsThatDidNotReceiveLayout.add(&downcast<RenderElement>(child));
- ASSERT(!child->needsLayout());
+ ASSERT(!child.needsLayout());
}
if (!layoutSizeChanged) {
- ASSERT(notlayoutedObjects.isEmpty());
+ ASSERT(elementsThatDidNotReceiveLayout.isEmpty());
return;
}
// If the layout size changed, invalidate all resources of all children that didn't go through the layout() code path.
- for (auto child : notlayoutedObjects)
- invalidateResourcesOfChildren(*child);
+ for (auto* element : elementsThatDidNotReceiveLayout)
+ invalidateResourcesOfChildren(*element);
}
bool SVGRenderSupport::isOverflowHidden(const RenderElement& renderer)
{
- // SVG doesn't support independent x/y overflow
- ASSERT(renderer.style().overflowX() == renderer.style().overflowY());
-
- // OSCROLL is never set for SVG - see StyleResolver::adjustRenderStyle
- ASSERT(renderer.style().overflowX() != OSCROLL);
-
// RenderSVGRoot should never query for overflow state - it should always clip itself to the initial viewport size.
- ASSERT(!renderer.isRoot());
+ ASSERT(!renderer.isDocumentElementRenderer());
- return renderer.style().overflowX() == OHIDDEN;
+ return renderer.style().overflowX() == OHIDDEN || renderer.style().overflowX() == OSCROLL;
}
bool SVGRenderSupport::rendererHasSVGShadow(const RenderObject& renderer)
{
// FIXME: Add support for RenderSVGBlock.
- if (renderer.isSVGShape() || renderer.isSVGImage() || renderer.isSVGContainer())
- return toRenderSVGModelObject(renderer).hasSVGShadow();
+ if (is<RenderSVGModelObject>(renderer))
+ return downcast<RenderSVGModelObject>(renderer).hasSVGShadow();
- if (renderer.isSVGRoot())
- return toRenderSVGRoot(renderer).hasSVGShadow();
+ if (is<RenderSVGRoot>(renderer))
+ return downcast<RenderSVGRoot>(renderer).hasSVGShadow();
return false;
}
@@ -323,13 +336,13 @@ void SVGRenderSupport::setRendererHasSVGShadow(RenderObject& renderer, bool hasS
{
// FIXME: Add support for RenderSVGBlock.
- if (renderer.isSVGShape() || renderer.isSVGImage() || renderer.isSVGContainer()) {
- toRenderSVGModelObject(renderer).setHasSVGShadow(hasShadow);
+ if (is<RenderSVGModelObject>(renderer)) {
+ downcast<RenderSVGModelObject>(renderer).setHasSVGShadow(hasShadow);
return;
}
- if (renderer.isSVGRoot())
- toRenderSVGRoot(renderer).setHasSVGShadow(hasShadow);
+ if (is<RenderSVGRoot>(renderer))
+ downcast<RenderSVGRoot>(renderer).setHasSVGShadow(hasShadow);
}
void SVGRenderSupport::intersectRepaintRectWithShadows(const RenderElement& renderer, FloatRect& repaintRect)
@@ -357,20 +370,18 @@ void SVGRenderSupport::intersectRepaintRectWithShadows(const RenderElement& rend
if (localToRootTransform.isIdentity())
return;
- AffineTransform rootToLocalTransform = localToRootTransform.inverse();
+ AffineTransform rootToLocalTransform = localToRootTransform.inverse().value_or(AffineTransform());
repaintRect = rootToLocalTransform.mapRect(repaintRect);
}
void SVGRenderSupport::intersectRepaintRectWithResources(const RenderElement& renderer, FloatRect& repaintRect)
{
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer);
if (!resources)
return;
-#if ENABLE(FILTERS)
if (RenderSVGResourceFilter* filter = resources->filter())
repaintRect = filter->resourceBoundingBox(renderer);
-#endif
if (RenderSVGResourceClipper* clipper = resources->clipper())
repaintRect.intersect(clipper->resourceBoundingBox(renderer));
@@ -386,7 +397,7 @@ bool SVGRenderSupport::filtersForceContainerLayout(const RenderElement& renderer
if (!renderer.normalChildNeedsLayout())
return false;
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer);
if (!resources || !resources->filter())
return false;
@@ -397,7 +408,7 @@ bool SVGRenderSupport::pointInClippingArea(const RenderElement& renderer, const
{
// We just take clippers into account to determine if a point is on the node. The Specification may
// change later and we also need to check maskers.
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer);
if (!resources)
return true;
@@ -415,23 +426,31 @@ void SVGRenderSupport::applyStrokeStyleToContext(GraphicsContext* context, const
const SVGRenderStyle& svgStyle = style.svgStyle();
- SVGLengthContext lengthContext(toSVGElement(renderer.element()));
- context->setStrokeThickness(svgStyle.strokeWidth().value(lengthContext));
- context->setLineCap(svgStyle.capStyle());
- context->setLineJoin(svgStyle.joinStyle());
- if (svgStyle.joinStyle() == MiterJoin)
+ SVGLengthContext lengthContext(downcast<SVGElement>(renderer.element()));
+ context->setStrokeThickness(lengthContext.valueForLength(style.strokeWidth()));
+ context->setLineCap(style.capStyle());
+ context->setLineJoin(style.joinStyle());
+ if (style.joinStyle() == MiterJoin)
context->setMiterLimit(svgStyle.strokeMiterLimit());
- const Vector<SVGLength>& dashes = svgStyle.strokeDashArray();
+ const Vector<SVGLengthValue>& dashes = svgStyle.strokeDashArray();
if (dashes.isEmpty())
context->setStrokeStyle(SolidStroke);
else {
DashArray dashArray;
dashArray.reserveInitialCapacity(dashes.size());
- for (unsigned i = 0, size = dashes.size(); i < size; ++i)
- dashArray.uncheckedAppend(dashes[i].value(lengthContext));
+ bool canSetLineDash = false;
- context->setLineDash(dashArray, svgStyle.strokeDashOffset().value(lengthContext));
+ for (auto& dash : dashes) {
+ dashArray.uncheckedAppend(dash.value(lengthContext));
+ if (dashArray.last() > 0)
+ canSetLineDash = true;
+ }
+
+ if (canSetLineDash)
+ context->setLineDash(dashArray, lengthContext.valueForLength(svgStyle.strokeDashOffset()));
+ else
+ context->setStrokeStyle(SolidStroke);
}
}
@@ -440,12 +459,40 @@ void SVGRenderSupport::childAdded(RenderElement& parent, RenderObject& child)
SVGRenderSupport::setRendererHasSVGShadow(child, SVGRenderSupport::rendererHasSVGShadow(parent) || SVGRenderSupport::rendererHasSVGShadow(child));
}
-void SVGRenderSupport::styleChanged(RenderElement& renderer)
+void SVGRenderSupport::styleChanged(RenderElement& renderer, const RenderStyle* oldStyle)
{
auto parent = renderer.parent();
SVGRenderSupport::setRendererHasSVGShadow(renderer, (parent && SVGRenderSupport::rendererHasSVGShadow(*parent)) || renderer.style().svgStyle().shadow());
+
+#if ENABLE(CSS_COMPOSITING)
+ if (renderer.element() && renderer.element()->isSVGElement() && (!oldStyle || renderer.style().hasBlendMode() != oldStyle->hasBlendMode()))
+ SVGRenderSupport::updateMaskedAncestorShouldIsolateBlending(renderer);
+#else
+ UNUSED_PARAM(oldStyle);
+#endif
}
+#if ENABLE(CSS_COMPOSITING)
+bool SVGRenderSupport::isolatesBlending(const RenderStyle& style)
+{
+ return style.svgStyle().isolatesBlending() || style.hasFilter() || style.hasBlendMode() || style.opacity() < 1.0f;
}
+void SVGRenderSupport::updateMaskedAncestorShouldIsolateBlending(const RenderElement& renderer)
+{
+ ASSERT(renderer.element());
+ ASSERT(renderer.element()->isSVGElement());
+
+ bool maskedAncestorShouldIsolateBlending = renderer.style().hasBlendMode();
+ for (auto* ancestor = renderer.element()->parentElement(); ancestor && ancestor->isSVGElement(); ancestor = ancestor->parentElement()) {
+ if (!downcast<SVGElement>(*ancestor).isSVGGraphicsElement() || !isolatesBlending(*ancestor->computedStyle()))
+ continue;
+
+ if (ancestor->computedStyle()->svgStyle().hasMasker())
+ downcast<SVGGraphicsElement>(*ancestor).setShouldIsolateBlending(maskedAncestorShouldIsolateBlending);
+
+ return;
+ }
+}
#endif
+}
diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.h b/Source/WebCore/rendering/svg/SVGRenderSupport.h
index 026c14e7a..d6ff72d7c 100644
--- a/Source/WebCore/rendering/svg/SVGRenderSupport.h
+++ b/Source/WebCore/rendering/svg/SVGRenderSupport.h
@@ -21,10 +21,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGRenderSupport_h
-#define SVGRenderSupport_h
+#pragma once
-#if ENABLE(SVG)
#include "PaintInfo.h"
namespace WebCore {
@@ -45,6 +43,8 @@ class TransformState;
// SVGRendererSupport is a helper class sharing code between all SVG renderers.
class SVGRenderSupport {
public:
+ static void layoutDifferentRootIfNeeded(const RenderElement&);
+
// Shares child layouting code between RenderSVGRoot/RenderSVG(Hidden)Container
static void layoutChildren(RenderElement&, bool selfNeedsLayout);
@@ -68,8 +68,9 @@ public:
// Important functions used by nearly all SVG renderers centralizing coordinate transformations / repaint rect calculations
static FloatRect repaintRectForRendererInLocalCoordinatesExcludingSVGShadow(const RenderElement&);
static LayoutRect clippedOverflowRectForRepaint(const RenderElement&, const RenderLayerModelObject* repaintContainer);
- static void computeFloatRectForRepaint(const RenderElement&, const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed);
- static void mapLocalToContainer(const RenderElement&, const RenderLayerModelObject* repaintContainer, TransformState&, bool* wasFixed = 0);
+ static FloatRect computeFloatRectForRepaint(const RenderElement&, const FloatRect&, const RenderLayerModelObject* repaintContainer, bool fixed);
+ static const RenderElement& localToParentTransform(const RenderElement&, AffineTransform &);
+ static void mapLocalToContainer(const RenderElement&, const RenderLayerModelObject* repaintContainer, TransformState&, bool* wasFixed);
static const RenderElement* pushMappingToContainer(const RenderElement&, const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&);
static bool checkForSVGRepaintDuringLayout(const RenderElement&);
@@ -84,10 +85,15 @@ public:
static void setRendererHasSVGShadow(RenderObject&, bool hasShadow);
static void childAdded(RenderElement& parent, RenderObject& child);
- static void styleChanged(RenderElement&);
+ static void styleChanged(RenderElement&, const RenderStyle*);
+
+#if ENABLE(CSS_COMPOSITING)
+ static bool isolatesBlending(const RenderStyle&);
+ static void updateMaskedAncestorShouldIsolateBlending(const RenderElement&);
+#endif
- // FIXME: These methods do not belong here.
- static const RenderSVGRoot& findTreeRootObject(const RenderElement&);
+ static RenderSVGRoot* findTreeRootObject(RenderElement&);
+ static const RenderSVGRoot* findTreeRootObject(const RenderElement&);
private:
// This class is not constructable.
@@ -96,6 +102,3 @@ private:
};
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif // SVGRenderSupport_h
diff --git a/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp b/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp
index aa6040968..8823bc668 100644
--- a/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp
+++ b/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp
@@ -13,10 +13,10 @@
* 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 COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. 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
@@ -27,14 +27,12 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGRenderTreeAsText.h"
#include "GraphicsTypes.h"
-#include "HTMLNames.h"
#include "NodeRenderStyle.h"
#include "RenderImage.h"
+#include "RenderIterator.h"
#include "RenderSVGGradientStop.h"
#include "RenderSVGImage.h"
#include "RenderSVGPath.h"
@@ -48,15 +46,12 @@
#include "RenderSVGResourceSolidColor.h"
#include "RenderSVGRoot.h"
#include "RenderSVGText.h"
-#include "RenderTreeAsText.h"
#include "SVGCircleElement.h"
#include "SVGEllipseElement.h"
#include "SVGInlineTextBox.h"
#include "SVGLineElement.h"
-#include "SVGNames.h"
#include "SVGPathElement.h"
#include "SVGPathUtilities.h"
-#include "SVGPointList.h"
#include "SVGPolyElement.h"
#include "SVGRectElement.h"
#include "SVGRootInlineBox.h"
@@ -119,45 +114,6 @@ static void writeIfNotDefault(TextStream& ts, const char* name, ValueType value,
writeNameValuePair(ts, name, value);
}
-TextStream& operator<<(TextStream& ts, const FloatRect& r)
-{
- ts << "at (" << TextStream::FormatNumberRespectingIntegers(r.x());
- ts << "," << TextStream::FormatNumberRespectingIntegers(r.y());
- ts << ") size " << TextStream::FormatNumberRespectingIntegers(r.width());
- ts << "x" << TextStream::FormatNumberRespectingIntegers(r.height());
- return ts;
-}
-
-TextStream& operator<<(TextStream& ts, const AffineTransform& transform)
-{
- if (transform.isIdentity())
- ts << "identity";
- else
- ts << "{m=(("
- << transform.a() << "," << transform.b()
- << ")("
- << transform.c() << "," << transform.d()
- << ")) t=("
- << transform.e() << "," << transform.f()
- << ")}";
-
- return ts;
-}
-
-static TextStream& operator<<(TextStream& ts, const WindRule rule)
-{
- switch (rule) {
- case RULE_NONZERO:
- ts << "NON-ZERO";
- break;
- case RULE_EVENODD:
- ts << "EVEN-ODD";
- break;
- }
-
- return ts;
-}
-
static TextStream& operator<<(TextStream& ts, const SVGUnitTypes::SVGUnitType& unitType)
{
ts << SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::toString(unitType);
@@ -170,11 +126,6 @@ static TextStream& operator<<(TextStream& ts, const SVGMarkerUnitsType& markerUn
return ts;
}
-TextStream& operator<<(TextStream& ts, const Color& c)
-{
- return ts << c.nameForRenderTreeAsText();
-}
-
// FIXME: Maybe this should be in KCanvasRenderingStyle.cpp
static TextStream& operator<<(TextStream& ts, const DashArray& a)
{
@@ -189,43 +140,9 @@ static TextStream& operator<<(TextStream& ts, const DashArray& a)
return ts;
}
-// FIXME: Maybe this should be in GraphicsTypes.cpp
-static TextStream& operator<<(TextStream& ts, LineCap style)
-{
- switch (style) {
- case ButtCap:
- ts << "BUTT";
- break;
- case RoundCap:
- ts << "ROUND";
- break;
- case SquareCap:
- ts << "SQUARE";
- break;
- }
- return ts;
-}
-
-// FIXME: Maybe this should be in GraphicsTypes.cpp
-static TextStream& operator<<(TextStream& ts, LineJoin style)
-{
- switch (style) {
- case MiterJoin:
- ts << "MITER";
- break;
- case RoundJoin:
- ts << "ROUND";
- break;
- case BevelJoin:
- ts << "BEVEL";
- break;
- }
- return ts;
-}
-
static TextStream& operator<<(TextStream& ts, const SVGSpreadMethodType& type)
{
- ts << SVGPropertyTraits<SVGSpreadMethodType>::toString(type).upper();
+ ts << SVGPropertyTraits<SVGSpreadMethodType>::toString(type).convertToASCIIUppercase();
return ts;
}
@@ -250,17 +167,17 @@ static void writeSVGPaintingResource(TextStream& ts, RenderSVGResource* resource
ts << " [id=\"" << element.getIdAttribute() << "\"]";
}
-static void writeStyle(TextStream& ts, const RenderObject& object)
+static void writeStyle(TextStream& ts, const RenderElement& renderer)
{
- const RenderStyle& style = object.style();
+ const RenderStyle& style = renderer.style();
const SVGRenderStyle& svgStyle = style.svgStyle();
- if (!object.localTransform().isIdentity())
- writeNameValuePair(ts, "transform", object.localTransform());
+ if (!renderer.localTransform().isIdentity())
+ writeNameValuePair(ts, "transform", renderer.localTransform());
writeIfNotDefault(ts, "image rendering", style.imageRendering(), RenderStyle::initialImageRendering());
writeIfNotDefault(ts, "opacity", style.opacity(), RenderStyle::initialOpacity());
- if (object.isSVGShape()) {
- const RenderSVGShape& shape = static_cast<const RenderSVGShape&>(object);
+ if (is<RenderSVGShape>(renderer)) {
+ const auto& shape = downcast<RenderSVGShape>(renderer);
Color fallbackColor;
if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<RenderSVGShape&>(shape), shape.style(), fallbackColor)) {
@@ -269,20 +186,19 @@ static void writeStyle(TextStream& ts, const RenderObject& object)
writeSVGPaintingResource(ts, strokePaintingResource);
SVGLengthContext lengthContext(&shape.graphicsElement());
- double dashOffset = svgStyle.strokeDashOffset().value(lengthContext);
- double strokeWidth = svgStyle.strokeWidth().value(lengthContext);
- const Vector<SVGLength>& dashes = svgStyle.strokeDashArray();
+ double dashOffset = lengthContext.valueForLength(svgStyle.strokeDashOffset());
+ double strokeWidth = lengthContext.valueForLength(style.strokeWidth());
+ const auto& dashes = svgStyle.strokeDashArray();
DashArray dashArray;
- const Vector<SVGLength>::const_iterator end = dashes.end();
- for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it)
- dashArray.append((*it).value(lengthContext));
+ 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", svgStyle.strokeMiterLimit(), 4.0f);
- writeIfNotDefault(ts, "line cap", svgStyle.capStyle(), ButtCap);
- writeIfNotDefault(ts, "line join", svgStyle.joinStyle(), MiterJoin);
+ writeIfNotDefault(ts, "line cap", style.capStyle(), ButtCap);
+ writeIfNotDefault(ts, "line join", style.joinStyle(), MiterJoin);
writeIfNotDefault(ts, "dash offset", dashOffset, 0.0);
if (!dashArray.isEmpty())
writeNameValuePair(ts, "dash array", dashArray);
@@ -307,10 +223,20 @@ static void writeStyle(TextStream& ts, const RenderObject& object)
writeIfNotEmpty(ts, "end marker", svgStyle.markerEndResource());
}
-static TextStream& writePositionAndStyle(TextStream& ts, const RenderObject& object)
+static TextStream& writePositionAndStyle(TextStream& ts, const RenderElement& renderer, RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal)
{
- ts << " " << enclosingIntRect(const_cast<RenderObject&>(object).absoluteClippedOverflowRect());
- writeStyle(ts, object);
+ if (behavior & RenderAsTextShowSVGGeometry) {
+ if (is<RenderBox>(renderer)) {
+ LayoutRect r = downcast<RenderBox>(renderer).frameRect();
+ ts << " " << enclosingIntRect(r);
+ }
+
+ ts << " clipped";
+ }
+
+ ts << " " << enclosingIntRect(renderer.absoluteClippedOverflowRect());
+
+ writeStyle(ts, renderer);
return ts;
}
@@ -321,34 +247,34 @@ static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape)
SVGGraphicsElement& svgElement = shape.graphicsElement();
SVGLengthContext lengthContext(&svgElement);
- if (isSVGRectElement(svgElement)) {
- const SVGRectElement& element = toSVGRectElement(svgElement);
+ if (is<SVGRectElement>(svgElement)) {
+ const SVGRectElement& element = downcast<SVGRectElement>(svgElement);
writeNameValuePair(ts, "x", element.x().value(lengthContext));
writeNameValuePair(ts, "y", element.y().value(lengthContext));
writeNameValuePair(ts, "width", element.width().value(lengthContext));
writeNameValuePair(ts, "height", element.height().value(lengthContext));
- } else if (isSVGLineElement(svgElement)) {
- const SVGLineElement& element = toSVGLineElement(svgElement);
+ } else if (is<SVGLineElement>(svgElement)) {
+ const SVGLineElement& element = downcast<SVGLineElement>(svgElement);
writeNameValuePair(ts, "x1", element.x1().value(lengthContext));
writeNameValuePair(ts, "y1", element.y1().value(lengthContext));
writeNameValuePair(ts, "x2", element.x2().value(lengthContext));
writeNameValuePair(ts, "y2", element.y2().value(lengthContext));
- } else if (isSVGEllipseElement(svgElement)) {
- const SVGEllipseElement& element = toSVGEllipseElement(svgElement);
+ } else if (is<SVGEllipseElement>(svgElement)) {
+ const SVGEllipseElement& element = downcast<SVGEllipseElement>(svgElement);
writeNameValuePair(ts, "cx", element.cx().value(lengthContext));
writeNameValuePair(ts, "cy", element.cy().value(lengthContext));
writeNameValuePair(ts, "rx", element.rx().value(lengthContext));
writeNameValuePair(ts, "ry", element.ry().value(lengthContext));
- } else if (isSVGCircleElement(svgElement)) {
- const SVGCircleElement& element = toSVGCircleElement(svgElement);
+ } else if (is<SVGCircleElement>(svgElement)) {
+ const SVGCircleElement& element = downcast<SVGCircleElement>(svgElement);
writeNameValuePair(ts, "cx", element.cx().value(lengthContext));
writeNameValuePair(ts, "cy", element.cy().value(lengthContext));
writeNameValuePair(ts, "r", element.r().value(lengthContext));
- } else if (svgElement.hasTagName(SVGNames::polygonTag) || svgElement.hasTagName(SVGNames::polylineTag)) {
- const SVGPolyElement& element = toSVGPolyElement(svgElement);
+ } else if (is<SVGPolyElement>(svgElement)) {
+ const SVGPolyElement& element = downcast<SVGPolyElement>(svgElement);
writeNameAndQuotedValue(ts, "points", element.pointList().valueAsString());
- } else if (isSVGPathElement(svgElement)) {
- const SVGPathElement& element = toSVGPathElement(svgElement);
+ } else if (is<SVGPathElement>(svgElement)) {
+ const SVGPathElement& element = downcast<SVGPathElement>(svgElement);
String pathString;
// FIXME: We should switch to UnalteredParsing here - this will affect the path dumping output of dozens of tests.
buildStringFromByteStream(element.pathByteStream(), pathString, NormalizedParsing);
@@ -358,14 +284,9 @@ static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape)
return ts;
}
-static TextStream& operator<<(TextStream& ts, const RenderSVGRoot& root)
-{
- return writePositionAndStyle(ts, root);
-}
-
static void writeRenderSVGTextBox(TextStream& ts, const RenderSVGText& text)
{
- SVGRootInlineBox* box = toSVGRootInlineBox(text.firstRootBox());
+ auto* box = downcast<SVGRootInlineBox>(text.firstRootBox());
if (!box)
return;
@@ -398,7 +319,7 @@ static inline void writeSVGInlineTextBox(TextStream& ts, SVGInlineTextBox* textB
// FIXME: Remove this hack, once the new text layout engine is completly landed. We want to preserve the old layout test results for now.
ts << "chunk 1 ";
ETextAnchor anchor = svgStyle.textAnchor();
- bool isVerticalText = svgStyle.isVerticalWritingMode();
+ bool isVerticalText = textBox->renderer().style().isVerticalWritingMode();
if (anchor == TA_MIDDLE) {
ts << "(middle anchor";
if (isVerticalText)
@@ -435,26 +356,31 @@ static inline void writeSVGInlineTextBox(TextStream& ts, SVGInlineTextBox* textB
static inline void writeSVGInlineTextBoxes(TextStream& ts, const RenderText& text, int indent)
{
for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox()) {
- if (!box->isSVGInlineTextBox())
+ if (!is<SVGInlineTextBox>(*box))
continue;
- writeSVGInlineTextBox(ts, toSVGInlineTextBox(box), indent);
+ writeSVGInlineTextBox(ts, downcast<SVGInlineTextBox>(box), indent);
}
}
-static void writeStandardPrefix(TextStream& ts, const RenderObject& object, int indent)
+static void writeStandardPrefix(TextStream& ts, const RenderObject& object, int indent, RenderAsTextBehavior behavior)
{
writeIndent(ts, indent);
ts << object.renderName();
+ if (behavior & RenderAsTextShowAddresses)
+ ts << " " << static_cast<const void*>(&object);
+
if (object.node())
ts << " {" << object.node()->nodeName() << "}";
+
+ writeDebugInfo(ts, object, behavior);
}
-static void writeChildren(TextStream& ts, const RenderObject& object, int indent)
+static void writeChildren(TextStream& ts, const RenderElement& parent, int indent, RenderAsTextBehavior behavior)
{
- for (RenderObject* child = object.firstChildSlow(); child; child = child->nextSibling())
- write(ts, *child, indent + 1);
+ for (const auto& child : childrenOfType<RenderObject>(parent))
+ write(ts, child, indent + 1, behavior);
}
static inline void writeCommonGradientProperties(TextStream& ts, SVGSpreadMethodType spreadMethod, const AffineTransform& gradientTransform, SVGUnitTypes::SVGUnitType gradientUnits)
@@ -468,56 +394,50 @@ static inline void writeCommonGradientProperties(TextStream& ts, SVGSpreadMethod
ts << " [gradientTransform=" << gradientTransform << "]";
}
-void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int indent)
+void writeSVGResourceContainer(TextStream& ts, const RenderSVGResourceContainer& resource, int indent, RenderAsTextBehavior behavior)
{
- writeStandardPrefix(ts, object, indent);
+ writeStandardPrefix(ts, resource, indent, behavior);
- Element* element = toElement(object.node());
- const AtomicString& id = element->getIdAttribute();
+ const AtomicString& id = resource.element().getIdAttribute();
writeNameAndQuotedValue(ts, "id", id);
- RenderSVGResourceContainer* resource = const_cast<RenderObject&>(object).toRenderSVGResourceContainer();
- ASSERT(resource);
-
- if (resource->resourceType() == MaskerResourceType) {
- RenderSVGResourceMasker* masker = static_cast<RenderSVGResourceMasker*>(resource);
- writeNameValuePair(ts, "maskUnits", masker->maskUnits());
- writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits());
+ if (resource.resourceType() == MaskerResourceType) {
+ const auto& masker = static_cast<const RenderSVGResourceMasker&>(resource);
+ writeNameValuePair(ts, "maskUnits", masker.maskUnits());
+ writeNameValuePair(ts, "maskContentUnits", masker.maskContentUnits());
ts << "\n";
-#if ENABLE(FILTERS)
- } else if (resource->resourceType() == FilterResourceType) {
- RenderSVGResourceFilter* filter = static_cast<RenderSVGResourceFilter*>(resource);
- writeNameValuePair(ts, "filterUnits", filter->filterUnits());
- writeNameValuePair(ts, "primitiveUnits", filter->primitiveUnits());
+ } else if (resource.resourceType() == FilterResourceType) {
+ const auto& filter = static_cast<const RenderSVGResourceFilter&>(resource);
+ writeNameValuePair(ts, "filterUnits", filter.filterUnits());
+ writeNameValuePair(ts, "primitiveUnits", filter.primitiveUnits());
ts << "\n";
// Creating a placeholder filter which is passed to the builder.
FloatRect dummyRect;
RefPtr<SVGFilter> dummyFilter = SVGFilter::create(AffineTransform(), dummyRect, dummyRect, dummyRect, true);
- if (auto builder = filter->buildPrimitives(dummyFilter.get())) {
+ if (auto builder = filter.buildPrimitives(*dummyFilter)) {
if (FilterEffect* lastEffect = builder->lastEffect())
lastEffect->externalRepresentation(ts, indent + 1);
}
-#endif
- } else if (resource->resourceType() == ClipperResourceType) {
- RenderSVGResourceClipper* clipper = static_cast<RenderSVGResourceClipper*>(resource);
- writeNameValuePair(ts, "clipPathUnits", clipper->clipPathUnits());
+ } else if (resource.resourceType() == ClipperResourceType) {
+ const auto& clipper = static_cast<const RenderSVGResourceClipper&>(resource);
+ writeNameValuePair(ts, "clipPathUnits", clipper.clipPathUnits());
ts << "\n";
- } else if (resource->resourceType() == MarkerResourceType) {
- RenderSVGResourceMarker* marker = static_cast<RenderSVGResourceMarker*>(resource);
- writeNameValuePair(ts, "markerUnits", marker->markerUnits());
- ts << " [ref at " << marker->referencePoint() << "]";
+ } else if (resource.resourceType() == MarkerResourceType) {
+ const auto& marker = static_cast<const RenderSVGResourceMarker&>(resource);
+ writeNameValuePair(ts, "markerUnits", marker.markerUnits());
+ ts << " [ref at " << marker.referencePoint() << "]";
ts << " [angle=";
- if (marker->angle() == -1)
+ if (marker.angle() == -1)
ts << "auto" << "]\n";
else
- ts << marker->angle() << "]\n";
- } else if (resource->resourceType() == PatternResourceType) {
- RenderSVGResourcePattern* pattern = static_cast<RenderSVGResourcePattern*>(resource);
+ ts << marker.angle() << "]\n";
+ } else if (resource.resourceType() == PatternResourceType) {
+ const auto& pattern = static_cast<const RenderSVGResourcePattern&>(resource);
// Dump final results that are used for rendering. No use in asking SVGPatternElement for its patternUnits(), as it may
// link to other patterns using xlink:href, we need to build the full inheritance chain, aka. collectPatternProperties()
PatternAttributes attributes;
- pattern->patternElement().collectPatternAttributes(attributes);
+ pattern.collectPatternAttributes(attributes);
writeNameValuePair(ts, "patternUnits", attributes.patternUnits());
writeNameValuePair(ts, "patternContentUnits", attributes.patternContentUnits());
@@ -526,139 +446,140 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i
if (!transform.isIdentity())
ts << " [patternTransform=" << transform << "]";
ts << "\n";
- } else if (resource->resourceType() == LinearGradientResourceType) {
- RenderSVGResourceLinearGradient* gradient = static_cast<RenderSVGResourceLinearGradient*>(resource);
+ } else if (resource.resourceType() == LinearGradientResourceType) {
+ const auto& gradient = static_cast<const RenderSVGResourceLinearGradient&>(resource);
// Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may
// link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties()
LinearGradientAttributes attributes;
- gradient->linearGradientElement().collectGradientAttributes(attributes);
+ gradient.linearGradientElement().collectGradientAttributes(attributes);
writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits());
- ts << " [start=" << gradient->startPoint(attributes) << "] [end=" << gradient->endPoint(attributes) << "]\n";
- } else if (resource->resourceType() == RadialGradientResourceType) {
- RenderSVGResourceRadialGradient* gradient = static_cast<RenderSVGResourceRadialGradient*>(resource);
+ ts << " [start=" << gradient.startPoint(attributes) << "] [end=" << gradient.endPoint(attributes) << "]\n";
+ } else if (resource.resourceType() == RadialGradientResourceType) {
+ const auto& gradient = static_cast<const RenderSVGResourceRadialGradient&>(resource);
// Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may
// link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties()
RadialGradientAttributes attributes;
- gradient->radialGradientElement().collectGradientAttributes(attributes);
+ gradient.radialGradientElement().collectGradientAttributes(attributes);
writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits());
- FloatPoint focalPoint = gradient->focalPoint(attributes);
- FloatPoint centerPoint = gradient->centerPoint(attributes);
- float radius = gradient->radius(attributes);
- float focalRadius = gradient->focalRadius(attributes);
+ FloatPoint focalPoint = gradient.focalPoint(attributes);
+ FloatPoint centerPoint = gradient.centerPoint(attributes);
+ float radius = gradient.radius(attributes);
+ float focalRadius = gradient.focalRadius(attributes);
ts << " [center=" << centerPoint << "] [focal=" << focalPoint << "] [radius=" << radius << "] [focalRadius=" << focalRadius << "]\n";
} else
ts << "\n";
- writeChildren(ts, object, indent);
+ writeChildren(ts, resource, indent, behavior);
}
-void writeSVGContainer(TextStream& ts, const RenderObject& container, int indent)
+void writeSVGContainer(TextStream& ts, const RenderSVGContainer& container, int indent, RenderAsTextBehavior behavior)
{
// Currently RenderSVGResourceFilterPrimitive has no meaningful output.
if (container.isSVGResourceFilterPrimitive())
return;
- writeStandardPrefix(ts, container, indent);
- writePositionAndStyle(ts, container);
+ writeStandardPrefix(ts, container, indent, behavior);
+ writePositionAndStyle(ts, container, behavior);
ts << "\n";
- writeResources(ts, container, indent);
- writeChildren(ts, container, indent);
+ writeResources(ts, container, indent, behavior);
+ writeChildren(ts, container, indent, behavior);
}
-void write(TextStream& ts, const RenderSVGRoot& root, int indent)
+void write(TextStream& ts, const RenderSVGRoot& root, int indent, RenderAsTextBehavior behavior)
{
- writeStandardPrefix(ts, root, indent);
- ts << root << "\n";
- writeChildren(ts, root, indent);
+ writeStandardPrefix(ts, root, indent, behavior);
+ writePositionAndStyle(ts, root, behavior);
+ ts << "\n";
+ writeChildren(ts, root, indent, behavior);
}
-void writeSVGText(TextStream& ts, const RenderSVGText& text, int indent)
+void writeSVGText(TextStream& ts, const RenderSVGText& text, int indent, RenderAsTextBehavior behavior)
{
- writeStandardPrefix(ts, text, indent);
+ writeStandardPrefix(ts, text, indent, behavior);
writeRenderSVGTextBox(ts, text);
ts << "\n";
- writeResources(ts, text, indent);
- writeChildren(ts, text, indent);
+ writeResources(ts, text, indent, behavior);
+ writeChildren(ts, text, indent, behavior);
}
-void writeSVGInlineText(TextStream& ts, const RenderSVGInlineText& text, int indent)
+void writeSVGInlineText(TextStream& ts, const RenderSVGInlineText& text, int indent, RenderAsTextBehavior behavior)
{
- writeStandardPrefix(ts, text, indent);
- ts << " " << enclosingIntRect(FloatRect(text.firstRunOrigin(), text.floatLinesBoundingBox().size())) << "\n";
- writeResources(ts, text, indent);
+ writeStandardPrefix(ts, text, indent, behavior);
+ ts << " " << enclosingIntRect(FloatRect(text.firstRunLocation(), text.floatLinesBoundingBox().size())) << "\n";
+ writeResources(ts, text, indent, behavior);
writeSVGInlineTextBoxes(ts, text, indent);
}
-void writeSVGImage(TextStream& ts, const RenderSVGImage& image, int indent)
+void writeSVGImage(TextStream& ts, const RenderSVGImage& image, int indent, RenderAsTextBehavior behavior)
{
- writeStandardPrefix(ts, image, indent);
- writePositionAndStyle(ts, image);
+ writeStandardPrefix(ts, image, indent, behavior);
+ writePositionAndStyle(ts, image, behavior);
ts << "\n";
- writeResources(ts, image, indent);
+ writeResources(ts, image, indent, behavior);
}
-void write(TextStream& ts, const RenderSVGShape& shape, int indent)
+void write(TextStream& ts, const RenderSVGShape& shape, int indent, RenderAsTextBehavior behavior)
{
- writeStandardPrefix(ts, shape, indent);
+ writeStandardPrefix(ts, shape, indent, behavior);
ts << shape << "\n";
- writeResources(ts, shape, indent);
+ writeResources(ts, shape, indent, behavior);
}
-void writeSVGGradientStop(TextStream& ts, const RenderSVGGradientStop& stop, int indent)
+void writeSVGGradientStop(TextStream& ts, const RenderSVGGradientStop& stop, int indent, RenderAsTextBehavior behavior)
{
- writeStandardPrefix(ts, stop, indent);
+ writeStandardPrefix(ts, stop, indent, behavior);
- SVGStopElement* stopElement = toSVGStopElement(toSVGElement(stop.element()));
- ASSERT(stopElement);
-
- ts << " [offset=" << stopElement->offset() << "] [color=" << stopElement->stopColorIncludingOpacity() << "]\n";
+ ts << " [offset=" << stop.element().offset() << "] [color=" << stop.element().stopColorIncludingOpacity() << "]\n";
}
-void writeResources(TextStream& ts, const RenderObject& object, int indent)
+void writeResources(TextStream& ts, const RenderObject& renderer, int indent, RenderAsTextBehavior behavior)
{
- const RenderStyle& style = object.style();
+ const RenderStyle& style = renderer.style();
const SVGRenderStyle& svgStyle = style.svgStyle();
// FIXME: We want to use SVGResourcesCache to determine which resources are present, instead of quering the resource <-> id cache.
// For now leave the DRT output as is, but later on we should change this so cycles are properly ignored in the DRT output.
- RenderObject& renderer = const_cast<RenderObject&>(object);
if (!svgStyle.maskerResource().isEmpty()) {
- if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object.document(), svgStyle.maskerResource())) {
+ if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(renderer.document(), svgStyle.maskerResource())) {
writeIndent(ts, indent);
ts << " ";
writeNameAndQuotedValue(ts, "masker", svgStyle.maskerResource());
ts << " ";
- writeStandardPrefix(ts, *masker, 0);
+ writeStandardPrefix(ts, *masker, 0, behavior);
ts << " " << masker->resourceBoundingBox(renderer) << "\n";
}
}
if (!svgStyle.clipperResource().isEmpty()) {
- if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(object.document(), svgStyle.clipperResource())) {
+ if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(renderer.document(), svgStyle.clipperResource())) {
writeIndent(ts, indent);
ts << " ";
writeNameAndQuotedValue(ts, "clipPath", svgStyle.clipperResource());
ts << " ";
- writeStandardPrefix(ts, *clipper, 0);
+ writeStandardPrefix(ts, *clipper, 0, behavior);
ts << " " << clipper->resourceBoundingBox(renderer) << "\n";
}
}
-#if ENABLE(FILTERS)
- if (!svgStyle.filterResource().isEmpty()) {
- if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(object.document(), svgStyle.filterResource())) {
- writeIndent(ts, indent);
- ts << " ";
- writeNameAndQuotedValue(ts, "filter", svgStyle.filterResource());
- ts << " ";
- writeStandardPrefix(ts, *filter, 0);
- ts << " " << filter->resourceBoundingBox(renderer) << "\n";
+ if (style.hasFilter()) {
+ const FilterOperations& filterOperations = style.filter();
+ if (filterOperations.size() == 1) {
+ const FilterOperation& filterOperation = *filterOperations.at(0);
+ if (filterOperation.type() == FilterOperation::REFERENCE) {
+ const auto& referenceFilterOperation = downcast<ReferenceFilterOperation>(filterOperation);
+ AtomicString id = SVGURIReference::fragmentIdentifierFromIRIString(referenceFilterOperation.url(), renderer.document());
+ if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(renderer.document(), id)) {
+ writeIndent(ts, indent);
+ ts << " ";
+ writeNameAndQuotedValue(ts, "filter", id);
+ ts << " ";
+ writeStandardPrefix(ts, *filter, 0, behavior);
+ ts << " " << filter->resourceBoundingBox(renderer) << "\n";
+ }
+ }
}
}
-#endif
}
} // namespace WebCore
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGRenderTreeAsText.h b/Source/WebCore/rendering/svg/SVGRenderTreeAsText.h
index 5458c0dd2..7cce1c6a9 100644
--- a/Source/WebCore/rendering/svg/SVGRenderTreeAsText.h
+++ b/Source/WebCore/rendering/svg/SVGRenderTreeAsText.h
@@ -10,10 +10,10 @@
* 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 COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. 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
@@ -23,11 +23,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SVGRenderTreeAsText_h
-#define SVGRenderTreeAsText_h
-
-#if ENABLE(SVG)
+#pragma once
+#include "RenderTreeAsText.h"
#include "TextStream.h"
namespace WebCore {
@@ -38,9 +36,11 @@ class FloatSize;
class Node;
class RenderImage;
class RenderObject;
+class RenderSVGContainer;
class RenderSVGGradientStop;
class RenderSVGImage;
class RenderSVGInlineText;
+class RenderSVGResourceContainer;
class RenderSVGShape;
class RenderSVGRoot;
class RenderSVGText;
@@ -48,20 +48,15 @@ class AffineTransform;
class SVGUnitTypes;
// functions used by the main RenderTreeAsText code
-void write(TextStream&, const RenderSVGShape&, int indent);
-void write(TextStream&, const RenderSVGRoot&, int indent);
-void writeSVGGradientStop(TextStream&, const RenderSVGGradientStop&, int indent);
-void writeSVGResourceContainer(TextStream&, const RenderObject&, int indent);
-void writeSVGContainer(TextStream&, const RenderObject&, int indent);
-void writeSVGImage(TextStream&, const RenderSVGImage&, int indent);
-void writeSVGInlineText(TextStream&, const RenderSVGInlineText&, int indent);
-void writeSVGText(TextStream&, const RenderSVGText&, int indent);
-void writeResources(TextStream&, const RenderObject&, int indent);
-
-// helper operators defined used in various classes to dump the render tree.
-TextStream& operator<<(TextStream&, const AffineTransform&);
-TextStream& operator<<(TextStream&, const Color&);
-TextStream& operator<<(TextStream&, const FloatRect&);
+void write(TextStream&, const RenderSVGShape&, int indent, RenderAsTextBehavior);
+void write(TextStream&, const RenderSVGRoot&, int indent, RenderAsTextBehavior);
+void writeSVGGradientStop(TextStream&, const RenderSVGGradientStop&, int indent, RenderAsTextBehavior);
+void writeSVGResourceContainer(TextStream&, const RenderSVGResourceContainer&, int indent, RenderAsTextBehavior);
+void writeSVGContainer(TextStream&, const RenderSVGContainer&, int indent, RenderAsTextBehavior);
+void writeSVGImage(TextStream&, const RenderSVGImage&, int indent, RenderAsTextBehavior);
+void writeSVGInlineText(TextStream&, const RenderSVGInlineText&, int indent, RenderAsTextBehavior);
+void writeSVGText(TextStream&, const RenderSVGText&, int indent, RenderAsTextBehavior);
+void writeResources(TextStream&, const RenderObject&, int indent, RenderAsTextBehavior);
// helper operators specific to dumping the render tree. these are used in various classes to dump the render tree
// these could be defined in separate namespace to avoid matching these generic signatures unintentionally.
@@ -89,7 +84,3 @@ TextStream& operator<<(TextStream& ts, Pointer* t)
}
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-
-#endif // SVGRenderTreeAsText_h
diff --git a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp
index a0ad33016..67c55967b 100644
--- a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp
+++ b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp
@@ -23,25 +23,21 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGRenderingContext.h"
#include "BasicShapes.h"
#include "Frame.h"
#include "FrameView.h"
-#include "Page.h"
#include "RenderLayer.h"
#include "RenderSVGImage.h"
#include "RenderSVGResourceClipper.h"
#include "RenderSVGResourceFilter.h"
#include "RenderSVGResourceMasker.h"
#include "RenderView.h"
+#include "SVGLengthContext.h"
#include "SVGResources.h"
#include "SVGResourcesCache.h"
-static int kMaxImageBufferSize = 4096;
-
namespace WebCore {
static inline bool isRenderingMaskImage(const RenderObject& object)
@@ -57,23 +53,22 @@ SVGRenderingContext::~SVGRenderingContext()
ASSERT(m_renderer && m_paintInfo);
-#if ENABLE(FILTERS)
if (m_renderingFlags & EndFilterLayer) {
ASSERT(m_filter);
- m_filter->postApplyResource(*m_renderer, m_paintInfo->context, ApplyToDefaultMode, 0, 0);
- m_paintInfo->context = m_savedContext;
+ GraphicsContext* contextPtr = &m_paintInfo->context();
+ m_filter->postApplyResource(*m_renderer, contextPtr, ApplyToDefaultMode, 0, 0);
+ m_paintInfo->setContext(*m_savedContext);
m_paintInfo->rect = m_savedPaintRect;
}
-#endif
if (m_renderingFlags & EndOpacityLayer)
- m_paintInfo->context->endTransparencyLayer();
+ m_paintInfo->context().endTransparencyLayer();
if (m_renderingFlags & EndShadowLayer)
- m_paintInfo->context->endTransparencyLayer();
+ m_paintInfo->context().endTransparencyLayer();
if (m_renderingFlags & RestoreGraphicsContext)
- m_paintInfo->context->restore();
+ m_paintInfo->context().restore();
}
void SVGRenderingContext::prepareToRenderSVGContent(RenderElement& renderer, PaintInfo& paintInfo, NeedsGraphicsContextSave needsGraphicsContextSave)
@@ -86,80 +81,115 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderElement& renderer, Pai
m_renderer = &renderer;
m_paintInfo = &paintInfo;
-#if ENABLE(FILTERS)
m_filter = 0;
-#endif
// We need to save / restore the context even if the initialization failed.
if (needsGraphicsContextSave == SaveGraphicsContext) {
- m_paintInfo->context->save();
+ m_paintInfo->context().save();
m_renderingFlags |= RestoreGraphicsContext;
}
- RenderStyle& style = m_renderer->style();
+ auto& style = m_renderer->style();
const SVGRenderStyle& svgStyle = style.svgStyle();
// Setup transparency layers before setting up SVG resources!
bool isRenderingMask = isRenderingMaskImage(*m_renderer);
- float opacity = isRenderingMask ? 1 : style.opacity();
+ // RenderLayer takes care of root opacity.
+ float opacity = (renderer.isSVGRoot() || isRenderingMask) ? 1 : style.opacity();
const ShadowData* shadow = svgStyle.shadow();
- if (opacity < 1 || shadow) {
+ bool hasBlendMode = style.hasBlendMode();
+ bool hasIsolation = style.hasIsolation();
+ bool isolateMaskForBlending = false;
+
+#if ENABLE(CSS_COMPOSITING)
+ if (svgStyle.hasMasker() && is<SVGGraphicsElement>(downcast<SVGElement>(*renderer.element()))) {
+ SVGGraphicsElement& graphicsElement = downcast<SVGGraphicsElement>(*renderer.element());
+ isolateMaskForBlending = graphicsElement.shouldIsolateBlending();
+ }
+#endif
+
+ if (opacity < 1 || shadow || hasBlendMode || isolateMaskForBlending || hasIsolation) {
FloatRect repaintRect = m_renderer->repaintRectInLocalCoordinates();
+ m_paintInfo->context().clip(repaintRect);
+
+ if (opacity < 1 || hasBlendMode || isolateMaskForBlending || hasIsolation) {
+
+ if (hasBlendMode)
+ m_paintInfo->context().setCompositeOperation(m_paintInfo->context().compositeOperation(), style.blendMode());
+
+ m_paintInfo->context().beginTransparencyLayer(opacity);
+
+ if (hasBlendMode)
+ m_paintInfo->context().setCompositeOperation(m_paintInfo->context().compositeOperation(), BlendModeNormal);
- if (opacity < 1) {
- m_paintInfo->context->clip(repaintRect);
- m_paintInfo->context->beginTransparencyLayer(opacity);
m_renderingFlags |= EndOpacityLayer;
}
if (shadow) {
- m_paintInfo->context->clip(repaintRect);
- m_paintInfo->context->setShadow(IntSize(roundToInt(shadow->x()), roundToInt(shadow->y())), shadow->radius(), shadow->color(), style.colorSpace());
- m_paintInfo->context->beginTransparencyLayer(1);
+ m_paintInfo->context().setShadow(IntSize(roundToInt(shadow->x()), roundToInt(shadow->y())), shadow->radius(), shadow->color());
+ m_paintInfo->context().beginTransparencyLayer(1);
m_renderingFlags |= EndShadowLayer;
}
}
ClipPathOperation* clipPathOperation = style.clipPath();
- if (clipPathOperation && clipPathOperation->type() == ClipPathOperation::Shape) {
- ShapeClipPathOperation* clipPath = static_cast<ShapeClipPathOperation*>(clipPathOperation);
- m_paintInfo->context->clipPath(clipPath->pathForReferenceRect(renderer.objectBoundingBox()), clipPath->windRule());
+ if (is<ShapeClipPathOperation>(clipPathOperation)) {
+ auto& clipPath = downcast<ShapeClipPathOperation>(*clipPathOperation);
+ FloatRect referenceBox;
+ if (clipPath.referenceBox() == Stroke)
+ // FIXME: strokeBoundingBox() takes dasharray into account but shouldn't.
+ referenceBox = renderer.strokeBoundingBox();
+ else if (clipPath.referenceBox() == ViewBox && renderer.element()) {
+ FloatSize viewportSize;
+ SVGLengthContext(downcast<SVGElement>(renderer.element())).determineViewport(viewportSize);
+ referenceBox.setWidth(viewportSize.width());
+ referenceBox.setHeight(viewportSize.height());
+ } else
+ referenceBox = renderer.objectBoundingBox();
+ m_paintInfo->context().clipPath(clipPath.pathForReferenceRect(referenceBox), clipPath.windRule());
}
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*m_renderer);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*m_renderer);
if (!resources) {
-#if ENABLE(FILTERS)
- if (svgStyle.hasFilter())
+ if (style.hasReferenceFilterOnly())
return;
-#endif
+
m_renderingFlags |= RenderingPrepared;
return;
}
if (!isRenderingMask) {
if (RenderSVGResourceMasker* masker = resources->masker()) {
- if (!masker->applyResource(*m_renderer, style, m_paintInfo->context, ApplyToDefaultMode))
+ GraphicsContext* contextPtr = &m_paintInfo->context();
+ bool result = masker->applyResource(*m_renderer, style, contextPtr, ApplyToDefaultMode);
+ m_paintInfo->setContext(*contextPtr);
+ if (!result)
return;
}
}
RenderSVGResourceClipper* clipper = resources->clipper();
if (!clipPathOperation && clipper) {
- if (!clipper->applyResource(*m_renderer, style, m_paintInfo->context, ApplyToDefaultMode))
+ GraphicsContext* contextPtr = &m_paintInfo->context();
+ bool result = clipper->applyResource(*m_renderer, style, contextPtr, ApplyToDefaultMode);
+ m_paintInfo->setContext(*contextPtr);
+ if (!result)
return;
}
-#if ENABLE(FILTERS)
if (!isRenderingMask) {
m_filter = resources->filter();
if (m_filter) {
- m_savedContext = m_paintInfo->context;
+ m_savedContext = &m_paintInfo->context();
m_savedPaintRect = m_paintInfo->rect;
// Return with false here may mean that we don't need to draw the content
// (because it was either drawn before or empty) but we still need to apply the filter.
m_renderingFlags |= EndFilterLayer;
- if (!m_filter->applyResource(*m_renderer, style, m_paintInfo->context, ApplyToDefaultMode))
+ GraphicsContext* contextPtr = &m_paintInfo->context();
+ bool result = m_filter->applyResource(*m_renderer, style, contextPtr, ApplyToDefaultMode);
+ m_paintInfo->setContext(*contextPtr);
+ if (!result)
return;
// Since we're caching the resulting bitmap and do not invalidate it on repaint rect
@@ -169,45 +199,38 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderElement& renderer, Pai
m_paintInfo->rect = IntRect(m_filter->drawingRegion(m_renderer));
}
}
-#endif
m_renderingFlags |= RenderingPrepared;
}
static AffineTransform& currentContentTransformation()
{
- DEFINE_STATIC_LOCAL(AffineTransform, s_currentContentTransformation, ());
+ static NeverDestroyed<AffineTransform> s_currentContentTransformation;
return s_currentContentTransformation;
}
-float SVGRenderingContext::calculateScreenFontSizeScalingFactor(const RenderObject* renderer)
+float SVGRenderingContext::calculateScreenFontSizeScalingFactor(const RenderObject& renderer)
{
- ASSERT(renderer);
-
- AffineTransform ctm;
- calculateTransformationToOutermostCoordinateSystem(renderer, ctm);
+ AffineTransform ctm = calculateTransformationToOutermostCoordinateSystem(renderer);
return narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2));
}
-void SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject* renderer, AffineTransform& absoluteTransform)
+AffineTransform SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject& renderer)
{
- ASSERT(renderer);
- absoluteTransform = currentContentTransformation();
-
- float deviceScaleFactor = 1;
- if (Page* page = renderer->document().page())
- deviceScaleFactor = page->deviceScaleFactor();
+ AffineTransform absoluteTransform = currentContentTransformation();
+ float deviceScaleFactor = renderer.document().deviceScaleFactor();
// Walk up the render tree, accumulating SVG transforms.
- while (renderer) {
- absoluteTransform = renderer->localToParentTransform() * absoluteTransform;
- if (renderer->isSVGRoot())
+ const RenderObject* ancestor = &renderer;
+ while (ancestor) {
+ absoluteTransform = ancestor->localToParentTransform() * absoluteTransform;
+ if (ancestor->isSVGRoot())
break;
- renderer = renderer->parent();
+ ancestor = ancestor->parent();
}
// Continue walking up the layer tree, accumulating CSS transforms.
- RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0;
+ RenderLayer* layer = ancestor ? ancestor->enclosingLayer() : nullptr;
while (layer) {
if (TransformationMatrix* layerTransform = layer->transform())
absoluteTransform = layerTransform->toAffineTransform() * absoluteTransform;
@@ -220,61 +243,60 @@ void SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(con
}
absoluteTransform.scale(deviceScaleFactor);
+ return absoluteTransform;
}
-bool SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, std::unique_ptr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode)
+std::unique_ptr<ImageBuffer> SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, ColorSpace colorSpace, RenderingMode renderingMode)
{
IntRect paintRect = calculateImageBufferRect(targetRect, absoluteTransform);
// Don't create empty ImageBuffers.
if (paintRect.isEmpty())
- return false;
+ return nullptr;
- IntSize clampedSize = clampedAbsoluteSize(paintRect.size());
- std::unique_ptr<ImageBuffer> image = ImageBuffer::create(clampedSize, 1, colorSpace, renderingMode);
- if (!image)
- return false;
+ FloatSize scale;
+ FloatSize clampedSize = ImageBuffer::clampedSize(paintRect.size(), scale);
- GraphicsContext* imageContext = image->context();
- ASSERT(imageContext);
+ auto imageBuffer = ImageBuffer::create(clampedSize, renderingMode, 1, colorSpace);
+ if (!imageBuffer)
+ return nullptr;
- imageContext->scale(FloatSize(static_cast<float>(clampedSize.width()) / paintRect.width(),
- static_cast<float>(clampedSize.height()) / paintRect.height()));
- imageContext->translate(-paintRect.x(), -paintRect.y());
- imageContext->concatCTM(absoluteTransform);
+ AffineTransform transform;
+ transform.scale(scale).translate(-paintRect.location()).multiply(absoluteTransform);
- imageBuffer = std::move(image);
- return true;
+ GraphicsContext& imageContext = imageBuffer->context();
+ imageContext.concatCTM(transform);
+
+ return imageBuffer;
}
-bool SVGRenderingContext::createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, std::unique_ptr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode)
+std::unique_ptr<ImageBuffer> SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const FloatRect& clampedRect, ColorSpace colorSpace, RenderingMode renderingMode)
{
- IntSize imageSize(roundedIntSize(clampedAbsoluteTargetRect.size()));
- IntSize unclampedImageSize(roundedIntSize(absoluteTargetRect.size()));
+ IntSize clampedSize = roundedIntSize(clampedRect.size());
+ IntSize unclampedSize = roundedIntSize(targetRect.size());
// Don't create empty ImageBuffers.
- if (imageSize.isEmpty())
- return false;
+ if (clampedSize.isEmpty())
+ return nullptr;
- std::unique_ptr<ImageBuffer> image = ImageBuffer::create(imageSize, 1, colorSpace, renderingMode);
- if (!image)
- return false;
+ auto imageBuffer = ImageBuffer::create(clampedSize, renderingMode, 1, colorSpace);
+ if (!imageBuffer)
+ return nullptr;
- GraphicsContext* imageContext = image->context();
- ASSERT(imageContext);
+ GraphicsContext& imageContext = imageBuffer->context();
// Compensate rounding effects, as the absolute target rect is using floating-point numbers and the image buffer size is integer.
- imageContext->scale(FloatSize(unclampedImageSize.width() / absoluteTargetRect.width(), unclampedImageSize.height() / absoluteTargetRect.height()));
+ imageContext.scale(FloatSize(unclampedSize.width() / targetRect.width(), unclampedSize.height() / targetRect.height()));
- imageBuffer = std::move(image);
- return true;
+ return imageBuffer;
}
void SVGRenderingContext::renderSubtreeToImageBuffer(ImageBuffer* image, RenderElement& item, const AffineTransform& subtreeContentTransformation)
{
ASSERT(image);
- ASSERT(image->context());
- PaintInfo info(image->context(), IntRect::infiniteRect(), PaintPhaseForeground, PaintBehaviorNormal);
+ // Rendering into a buffer implies we're being used for masking, clipping, patterns or filters. In each of these
+ // cases we don't want to paint the selection.
+ PaintInfo info(image->context(), LayoutRect::infiniteRect(), PaintPhaseForeground, PaintBehaviorSkipSelectionHighlight);
AffineTransform& contentTransformation = currentContentTransformation();
AffineTransform savedContentTransformation = contentTransformation;
@@ -286,18 +308,18 @@ void SVGRenderingContext::renderSubtreeToImageBuffer(ImageBuffer* image, RenderE
contentTransformation = savedContentTransformation;
}
-void SVGRenderingContext::clipToImageBuffer(GraphicsContext* context, const AffineTransform& absoluteTransform, const FloatRect& targetRect, std::unique_ptr<ImageBuffer>& imageBuffer, bool safeToClear)
+void SVGRenderingContext::clipToImageBuffer(GraphicsContext& context, const AffineTransform& absoluteTransform, const FloatRect& targetRect, std::unique_ptr<ImageBuffer>& imageBuffer, bool safeToClear)
{
- ASSERT(context);
- ASSERT(imageBuffer);
+ if (!imageBuffer)
+ return;
FloatRect absoluteTargetRect = calculateImageBufferRect(targetRect, absoluteTransform);
// The mask image has been created in the absolute coordinate space, as the image should not be scaled.
// So the actual masking process has to be done in the absolute coordinate space as well.
- context->concatCTM(absoluteTransform.inverse());
- context->clipToImageBuffer(imageBuffer.get(), absoluteTargetRect);
- context->concatCTM(absoluteTransform);
+ context.concatCTM(absoluteTransform.inverse().value_or(AffineTransform()));
+ context.clipToImageBuffer(*imageBuffer, absoluteTargetRect);
+ context.concatCTM(absoluteTransform);
// When nesting resources, with objectBoundingBox as content unit types, there's no use in caching the
// resulting image buffer as the parent resource already caches the result.
@@ -305,18 +327,6 @@ void SVGRenderingContext::clipToImageBuffer(GraphicsContext* context, const Affi
imageBuffer.reset();
}
-FloatRect SVGRenderingContext::clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect)
-{
- const FloatSize maxImageBufferSize(kMaxImageBufferSize, kMaxImageBufferSize);
- return FloatRect(absoluteTargetRect.location(), absoluteTargetRect.size().shrunkTo(maxImageBufferSize));
-}
-
-IntSize SVGRenderingContext::clampedAbsoluteSize(const IntSize& absoluteSize)
-{
- const IntSize maxImageBufferSize(kMaxImageBufferSize, kMaxImageBufferSize);
- return absoluteSize.shrunkTo(maxImageBufferSize);
-}
-
void SVGRenderingContext::clear2DRotation(AffineTransform& transform)
{
AffineTransform::DecomposedType decomposition;
@@ -328,12 +338,12 @@ void SVGRenderingContext::clear2DRotation(AffineTransform& transform)
bool SVGRenderingContext::bufferForeground(std::unique_ptr<ImageBuffer>& imageBuffer)
{
ASSERT(m_paintInfo);
- ASSERT(m_renderer->isSVGImage());
+ ASSERT(is<RenderSVGImage>(*m_renderer));
FloatRect boundingBox = m_renderer->objectBoundingBox();
// Invalidate an existing buffer if the scale is not correct.
if (imageBuffer) {
- AffineTransform transform = m_paintInfo->context->getCTM(GraphicsContext::DefinitelyIncludeDeviceScale);
+ AffineTransform transform = m_paintInfo->context().getCTM(GraphicsContext::DefinitelyIncludeDeviceScale);
IntSize expandedBoundingBox = expandedIntSize(boundingBox.size());
IntSize bufferSize(static_cast<int>(ceil(expandedBoundingBox.width() * transform.xScale())), static_cast<int>(ceil(expandedBoundingBox.height() * transform.yScale())));
if (bufferSize != imageBuffer->internalSize())
@@ -342,20 +352,18 @@ bool SVGRenderingContext::bufferForeground(std::unique_ptr<ImageBuffer>& imageBu
// Create a new buffer and paint the foreground into it.
if (!imageBuffer) {
- if ((imageBuffer = m_paintInfo->context->createCompatibleBuffer(expandedIntSize(boundingBox.size()), true))) {
- GraphicsContext* bufferedRenderingContext = imageBuffer->context();
- bufferedRenderingContext->translate(-boundingBox.x(), -boundingBox.y());
+ if ((imageBuffer = ImageBuffer::createCompatibleBuffer(expandedIntSize(boundingBox.size()), ColorSpaceSRGB, m_paintInfo->context()))) {
+ GraphicsContext& bufferedRenderingContext = imageBuffer->context();
+ bufferedRenderingContext.translate(-boundingBox.x(), -boundingBox.y());
PaintInfo bufferedInfo(*m_paintInfo);
- bufferedInfo.context = bufferedRenderingContext;
- toRenderSVGImage(m_renderer)->paintForeground(bufferedInfo);
+ bufferedInfo.setContext(bufferedRenderingContext);
+ downcast<RenderSVGImage>(*m_renderer).paintForeground(bufferedInfo);
} else
return false;
}
- m_paintInfo->context->drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, boundingBox);
+ m_paintInfo->context().drawImageBuffer(*imageBuffer, boundingBox);
return true;
}
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGRenderingContext.h b/Source/WebCore/rendering/svg/SVGRenderingContext.h
index 3bf604cc2..fb6c29c97 100644
--- a/Source/WebCore/rendering/svg/SVGRenderingContext.h
+++ b/Source/WebCore/rendering/svg/SVGRenderingContext.h
@@ -22,19 +22,17 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGRenderingContext_h
-#define SVGRenderingContext_h
+#pragma once
-#if ENABLE(SVG)
#include "ImageBuffer.h"
#include "PaintInfo.h"
namespace WebCore {
class AffineTransform;
+class FloatRect;
class RenderElement;
class RenderObject;
-class FloatRect;
class RenderSVGResourceFilter;
// SVGRenderingContext
@@ -51,9 +49,7 @@ public:
, m_renderer(nullptr)
, m_paintInfo(nullptr)
, m_savedContext(nullptr)
-#if ENABLE(FILTERS)
, m_filter(nullptr)
-#endif
{
}
@@ -62,9 +58,7 @@ public:
, m_renderer(nullptr)
, m_paintInfo(nullptr)
, m_savedContext(nullptr)
-#if ENABLE(FILTERS)
, m_filter(nullptr)
-#endif
{
prepareToRenderSVGContent(object, paintinfo, needsGraphicsContextSave);
}
@@ -76,17 +70,14 @@ public:
void prepareToRenderSVGContent(RenderElement&, PaintInfo&, NeedsGraphicsContextSave = DontSaveGraphicsContext);
bool isRenderingPrepared() const { return m_renderingFlags & RenderingPrepared; }
- static bool createImageBuffer(const FloatRect& paintRect, const AffineTransform& absoluteTransform, std::unique_ptr<ImageBuffer>&, ColorSpace, RenderingMode);
- // Patterns need a different float-to-integer coordinate mapping.
- static bool createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, std::unique_ptr<ImageBuffer>&, ColorSpace, RenderingMode);
+ static std::unique_ptr<ImageBuffer> createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, ColorSpace, RenderingMode);
+ static std::unique_ptr<ImageBuffer> createImageBuffer(const FloatRect& targetRect, const FloatRect& clampedRect, ColorSpace, RenderingMode);
static void renderSubtreeToImageBuffer(ImageBuffer*, RenderElement&, const AffineTransform&);
- static void clipToImageBuffer(GraphicsContext*, const AffineTransform& absoluteTransform, const FloatRect& targetRect, std::unique_ptr<ImageBuffer>&, bool safeToClear);
+ static void clipToImageBuffer(GraphicsContext&, const AffineTransform& absoluteTransform, const FloatRect& targetRect, std::unique_ptr<ImageBuffer>&, bool safeToClear);
- static float calculateScreenFontSizeScalingFactor(const RenderObject*);
- static void calculateTransformationToOutermostCoordinateSystem(const RenderObject*, AffineTransform& absoluteTransform);
- static IntSize clampedAbsoluteSize(const IntSize&);
- static FloatRect clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect);
+ static float calculateScreenFontSizeScalingFactor(const RenderObject&);
+ static AffineTransform calculateTransformationToOutermostCoordinateSystem(const RenderObject&);
static void clear2DRotation(AffineTransform&);
static IntRect calculateImageBufferRect(const FloatRect& targetRect, const AffineTransform& absoluteTransform)
@@ -116,12 +107,7 @@ private:
PaintInfo* m_paintInfo;
GraphicsContext* m_savedContext;
LayoutRect m_savedPaintRect;
-#if ENABLE(FILTERS)
RenderSVGResourceFilter* m_filter;
-#endif
};
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif // SVGRenderingContext_h
diff --git a/Source/WebCore/rendering/svg/SVGResources.cpp b/Source/WebCore/rendering/svg/SVGResources.cpp
index bdb586b89..ea9b45211 100644
--- a/Source/WebCore/rendering/svg/SVGResources.cpp
+++ b/Source/WebCore/rendering/svg/SVGResources.cpp
@@ -20,19 +20,19 @@
#include "config.h"
#include "SVGResources.h"
-#if ENABLE(SVG)
+#include "FilterOperation.h"
#include "RenderSVGResourceClipper.h"
#include "RenderSVGResourceFilter.h"
#include "RenderSVGResourceMarker.h"
#include "RenderSVGResourceMasker.h"
+#include "RenderSVGRoot.h"
#include "SVGGradientElement.h"
#include "SVGNames.h"
-#include "SVGPaint.h"
#include "SVGPatternElement.h"
#include "SVGRenderStyle.h"
#include "SVGURIReference.h"
-#ifndef NDEBUG
+#if ENABLE(TREE_DEBUGGING)
#include <stdio.h>
#endif
@@ -45,44 +45,44 @@ SVGResources::SVGResources()
static HashSet<AtomicString>& clipperFilterMaskerTags()
{
- DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
- if (s_tagList.isEmpty()) {
+ static NeverDestroyed<HashSet<AtomicString>> s_tagList;
+ if (s_tagList.get().isEmpty()) {
// "container elements": http://www.w3.org/TR/SVG11/intro.html#TermContainerElement
// "graphics elements" : http://www.w3.org/TR/SVG11/intro.html#TermGraphicsElement
- s_tagList.add(SVGNames::aTag.localName());
- s_tagList.add(SVGNames::circleTag.localName());
- s_tagList.add(SVGNames::ellipseTag.localName());
- s_tagList.add(SVGNames::glyphTag.localName());
- s_tagList.add(SVGNames::gTag.localName());
- s_tagList.add(SVGNames::imageTag.localName());
- s_tagList.add(SVGNames::lineTag.localName());
- s_tagList.add(SVGNames::markerTag.localName());
- s_tagList.add(SVGNames::maskTag.localName());
- s_tagList.add(SVGNames::missing_glyphTag.localName());
- s_tagList.add(SVGNames::pathTag.localName());
- s_tagList.add(SVGNames::polygonTag.localName());
- s_tagList.add(SVGNames::polylineTag.localName());
- s_tagList.add(SVGNames::rectTag.localName());
- s_tagList.add(SVGNames::svgTag.localName());
- s_tagList.add(SVGNames::textTag.localName());
- s_tagList.add(SVGNames::useTag.localName());
+ s_tagList.get().add(SVGNames::aTag.localName());
+ s_tagList.get().add(SVGNames::circleTag.localName());
+ s_tagList.get().add(SVGNames::ellipseTag.localName());
+ s_tagList.get().add(SVGNames::glyphTag.localName());
+ s_tagList.get().add(SVGNames::gTag.localName());
+ s_tagList.get().add(SVGNames::imageTag.localName());
+ s_tagList.get().add(SVGNames::lineTag.localName());
+ s_tagList.get().add(SVGNames::markerTag.localName());
+ s_tagList.get().add(SVGNames::maskTag.localName());
+ s_tagList.get().add(SVGNames::missing_glyphTag.localName());
+ s_tagList.get().add(SVGNames::pathTag.localName());
+ s_tagList.get().add(SVGNames::polygonTag.localName());
+ s_tagList.get().add(SVGNames::polylineTag.localName());
+ s_tagList.get().add(SVGNames::rectTag.localName());
+ s_tagList.get().add(SVGNames::svgTag.localName());
+ s_tagList.get().add(SVGNames::textTag.localName());
+ s_tagList.get().add(SVGNames::useTag.localName());
// Not listed in the definitions is the clipPath element, the SVG spec says though:
// The "clipPath" element or any of its children can specify property "clip-path".
// So we have to add clipPathTag here, otherwhise clip-path on clipPath will fail.
// (Already mailed SVG WG, waiting for a solution)
- s_tagList.add(SVGNames::clipPathTag.localName());
+ s_tagList.get().add(SVGNames::clipPathTag.localName());
// Not listed in the definitions are the text content elements, though filter/clipper/masker on tspan/text/.. is allowed.
// (Already mailed SVG WG, waiting for a solution)
- s_tagList.add(SVGNames::altGlyphTag.localName());
- s_tagList.add(SVGNames::textPathTag.localName());
- s_tagList.add(SVGNames::trefTag.localName());
- s_tagList.add(SVGNames::tspanTag.localName());
+ s_tagList.get().add(SVGNames::altGlyphTag.localName());
+ s_tagList.get().add(SVGNames::textPathTag.localName());
+ s_tagList.get().add(SVGNames::trefTag.localName());
+ s_tagList.get().add(SVGNames::tspanTag.localName());
// Not listed in the definitions is the foreignObject element, but clip-path
// is a supported attribute.
- s_tagList.add(SVGNames::foreignObjectTag.localName());
+ s_tagList.get().add(SVGNames::foreignObjectTag.localName());
// Elements that we ignore, as it doesn't make any sense.
// defs, pattern, switch (FIXME: Mail SVG WG about these)
@@ -94,12 +94,12 @@ static HashSet<AtomicString>& clipperFilterMaskerTags()
static HashSet<AtomicString>& markerTags()
{
- DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
- if (s_tagList.isEmpty()) {
- s_tagList.add(SVGNames::lineTag.localName());
- s_tagList.add(SVGNames::pathTag.localName());
- s_tagList.add(SVGNames::polygonTag.localName());
- s_tagList.add(SVGNames::polylineTag.localName());
+ static NeverDestroyed<HashSet<AtomicString>> s_tagList;
+ if (s_tagList.get().isEmpty()) {
+ s_tagList.get().add(SVGNames::lineTag.localName());
+ s_tagList.get().add(SVGNames::pathTag.localName());
+ s_tagList.get().add(SVGNames::polygonTag.localName());
+ s_tagList.get().add(SVGNames::polylineTag.localName());
}
return s_tagList;
@@ -107,20 +107,20 @@ static HashSet<AtomicString>& markerTags()
static HashSet<AtomicString>& fillAndStrokeTags()
{
- DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
- if (s_tagList.isEmpty()) {
- s_tagList.add(SVGNames::altGlyphTag.localName());
- s_tagList.add(SVGNames::circleTag.localName());
- s_tagList.add(SVGNames::ellipseTag.localName());
- s_tagList.add(SVGNames::lineTag.localName());
- s_tagList.add(SVGNames::pathTag.localName());
- s_tagList.add(SVGNames::polygonTag.localName());
- s_tagList.add(SVGNames::polylineTag.localName());
- s_tagList.add(SVGNames::rectTag.localName());
- s_tagList.add(SVGNames::textTag.localName());
- s_tagList.add(SVGNames::textPathTag.localName());
- s_tagList.add(SVGNames::trefTag.localName());
- s_tagList.add(SVGNames::tspanTag.localName());
+ static NeverDestroyed<HashSet<AtomicString>> s_tagList;
+ if (s_tagList.get().isEmpty()) {
+ s_tagList.get().add(SVGNames::altGlyphTag.localName());
+ s_tagList.get().add(SVGNames::circleTag.localName());
+ s_tagList.get().add(SVGNames::ellipseTag.localName());
+ s_tagList.get().add(SVGNames::lineTag.localName());
+ s_tagList.get().add(SVGNames::pathTag.localName());
+ s_tagList.get().add(SVGNames::polygonTag.localName());
+ s_tagList.get().add(SVGNames::polylineTag.localName());
+ s_tagList.get().add(SVGNames::rectTag.localName());
+ s_tagList.get().add(SVGNames::textTag.localName());
+ s_tagList.get().add(SVGNames::textPathTag.localName());
+ s_tagList.get().add(SVGNames::trefTag.localName());
+ s_tagList.get().add(SVGNames::tspanTag.localName());
}
return s_tagList;
@@ -128,12 +128,12 @@ static HashSet<AtomicString>& fillAndStrokeTags()
static HashSet<AtomicString>& chainableResourceTags()
{
- DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
- if (s_tagList.isEmpty()) {
- s_tagList.add(SVGNames::linearGradientTag.localName());
- s_tagList.add(SVGNames::filterTag.localName());
- s_tagList.add(SVGNames::patternTag.localName());
- s_tagList.add(SVGNames::radialGradientTag.localName());
+ static NeverDestroyed<HashSet<AtomicString>> s_tagList;
+ if (s_tagList.get().isEmpty()) {
+ s_tagList.get().add(SVGNames::linearGradientTag.localName());
+ s_tagList.get().add(SVGNames::filterTag.localName());
+ s_tagList.get().add(SVGNames::patternTag.localName());
+ s_tagList.get().add(SVGNames::radialGradientTag.localName());
}
return s_tagList;
@@ -142,23 +142,21 @@ static HashSet<AtomicString>& chainableResourceTags()
static inline String targetReferenceFromResource(SVGElement& element)
{
String target;
- if (isSVGPatternElement(element))
- target = toSVGPatternElement(element).href();
- else if (isSVGGradientElement(element))
- target = toSVGGradientElement(element).href();
-#if ENABLE(FILTERS)
- else if (isSVGFilterElement(element))
- target = toSVGFilterElement(element).href();
-#endif
+ if (is<SVGPatternElement>(element))
+ target = downcast<SVGPatternElement>(element).href();
+ else if (is<SVGGradientElement>(element))
+ target = downcast<SVGGradientElement>(element).href();
+ else if (is<SVGFilterElement>(element))
+ target = downcast<SVGFilterElement>(element).href();
else
ASSERT_NOT_REACHED();
return SVGURIReference::fragmentIdentifierFromIRIString(target, element.document());
}
-static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document& document, const SVGPaint::SVGPaintType& paintType, const String& paintUri, AtomicString& id, bool& hasPendingResource)
+static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document& document, const SVGPaintType& paintType, const String& paintUri, AtomicString& id, bool& hasPendingResource)
{
- if (paintType != SVGPaint::SVG_PAINTTYPE_URI && paintType != SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR)
+ if (paintType != SVG_PAINTTYPE_URI && paintType != SVG_PAINTTYPE_URI_RGBCOLOR && paintType != SVG_PAINTTYPE_URI_CURRENTCOLOR)
return 0;
id = SVGURIReference::fragmentIdentifierFromIRIString(paintUri, document);
@@ -175,12 +173,12 @@ static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document&
return container;
}
-static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, SVGElement& element)
+static inline void registerPendingResource(SVGDocumentExtensions& extensions, const AtomicString& id, SVGElement& element)
{
- extensions->addPendingResource(id, &element);
+ extensions.addPendingResource(id, &element);
}
-bool SVGResources::buildCachedResources(const RenderElement& renderer, const SVGRenderStyle& svgStyle)
+bool SVGResources::buildCachedResources(const RenderElement& renderer, const RenderStyle& style)
{
ASSERT(renderer.element());
ASSERT_WITH_SECURITY_IMPLICATION(renderer.element()->isSVGElement());
@@ -188,17 +186,18 @@ bool SVGResources::buildCachedResources(const RenderElement& renderer, const SVG
if (!renderer.element())
return false;
- auto& element = toSVGElement(*renderer.element());
+ auto& element = downcast<SVGElement>(*renderer.element());
Document& document = element.document();
- SVGDocumentExtensions* extensions = document.accessSVGExtensions();
- ASSERT(extensions);
+ SVGDocumentExtensions& extensions = document.accessSVGExtensions();
const AtomicString& tagName = element.localName();
if (tagName.isNull())
return false;
+ const SVGRenderStyle& svgStyle = style.svgStyle();
+
bool foundResources = false;
if (clipperFilterMaskerTags().contains(tagName)) {
if (svgStyle.hasClipper()) {
@@ -209,15 +208,20 @@ bool SVGResources::buildCachedResources(const RenderElement& renderer, const SVG
registerPendingResource(extensions, id, element);
}
-#if ENABLE(FILTERS)
- if (svgStyle.hasFilter()) {
- AtomicString id(svgStyle.filterResource());
- if (setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(document, id)))
- foundResources = true;
- else
- registerPendingResource(extensions, id, element);
+ if (style.hasFilter()) {
+ const FilterOperations& filterOperations = style.filter();
+ if (filterOperations.size() == 1) {
+ const FilterOperation& filterOperation = *filterOperations.at(0);
+ if (filterOperation.type() == FilterOperation::REFERENCE) {
+ const auto& referenceFilterOperation = downcast<ReferenceFilterOperation>(filterOperation);
+ AtomicString id = SVGURIReference::fragmentIdentifierFromIRIString(referenceFilterOperation.url(), element.document());
+ if (setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(document, id)))
+ foundResources = true;
+ else
+ registerPendingResource(extensions, id, element);
+ }
+ }
}
-#endif
if (svgStyle.hasMasker()) {
AtomicString id(svgStyle.maskerResource());
@@ -279,7 +283,35 @@ bool SVGResources::buildCachedResources(const RenderElement& renderer, const SVG
return foundResources;
}
-void SVGResources::removeClientFromCache(RenderObject& object, bool markForInvalidation) const
+void SVGResources::layoutDifferentRootIfNeeded(const RenderSVGRoot* svgRoot)
+{
+ if (clipper() && svgRoot != SVGRenderSupport::findTreeRootObject(*clipper()))
+ clipper()->layoutIfNeeded();
+
+ if (masker() && svgRoot != SVGRenderSupport::findTreeRootObject(*masker()))
+ masker()->layoutIfNeeded();
+
+ if (filter() && svgRoot != SVGRenderSupport::findTreeRootObject(*filter()))
+ filter()->layoutIfNeeded();
+
+ if (markerStart() && svgRoot != SVGRenderSupport::findTreeRootObject(*markerStart()))
+ markerStart()->layoutIfNeeded();
+
+ if (markerMid() && svgRoot != SVGRenderSupport::findTreeRootObject(*markerMid()))
+ markerMid()->layoutIfNeeded();
+
+ if (markerEnd() && svgRoot != SVGRenderSupport::findTreeRootObject(*markerEnd()))
+ markerEnd()->layoutIfNeeded();
+}
+
+bool SVGResources::markerReverseStart() const
+{
+ return m_markerData
+ && m_markerData->markerStart
+ && m_markerData->markerStart->markerElement().orientType() == SVGMarkerOrientAutoStartReverse;
+}
+
+void SVGResources::removeClientFromCache(RenderElement& renderer, bool markForInvalidation) const
{
if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
return;
@@ -288,35 +320,33 @@ void SVGResources::removeClientFromCache(RenderObject& object, bool markForInval
ASSERT(!m_clipperFilterMaskerData);
ASSERT(!m_markerData);
ASSERT(!m_fillStrokeData);
- m_linkedResource->removeClientFromCache(object, markForInvalidation);
+ m_linkedResource->removeClientFromCache(renderer, markForInvalidation);
return;
}
if (m_clipperFilterMaskerData) {
if (m_clipperFilterMaskerData->clipper)
- m_clipperFilterMaskerData->clipper->removeClientFromCache(object, markForInvalidation);
-#if ENABLE(FILTERS)
+ m_clipperFilterMaskerData->clipper->removeClientFromCache(renderer, markForInvalidation);
if (m_clipperFilterMaskerData->filter)
- m_clipperFilterMaskerData->filter->removeClientFromCache(object, markForInvalidation);
-#endif
+ m_clipperFilterMaskerData->filter->removeClientFromCache(renderer, markForInvalidation);
if (m_clipperFilterMaskerData->masker)
- m_clipperFilterMaskerData->masker->removeClientFromCache(object, markForInvalidation);
+ m_clipperFilterMaskerData->masker->removeClientFromCache(renderer, markForInvalidation);
}
if (m_markerData) {
if (m_markerData->markerStart)
- m_markerData->markerStart->removeClientFromCache(object, markForInvalidation);
+ m_markerData->markerStart->removeClientFromCache(renderer, markForInvalidation);
if (m_markerData->markerMid)
- m_markerData->markerMid->removeClientFromCache(object, markForInvalidation);
+ m_markerData->markerMid->removeClientFromCache(renderer, markForInvalidation);
if (m_markerData->markerEnd)
- m_markerData->markerEnd->removeClientFromCache(object, markForInvalidation);
+ m_markerData->markerEnd->removeClientFromCache(renderer, markForInvalidation);
}
if (m_fillStrokeData) {
if (m_fillStrokeData->fill)
- m_fillStrokeData->fill->removeClientFromCache(object, markForInvalidation);
+ m_fillStrokeData->fill->removeClientFromCache(renderer, markForInvalidation);
if (m_fillStrokeData->stroke)
- m_fillStrokeData->stroke->removeClientFromCache(object, markForInvalidation);
+ m_fillStrokeData->stroke->removeClientFromCache(renderer, markForInvalidation);
}
}
@@ -374,16 +404,12 @@ void SVGResources::resourceDestroyed(RenderSVGResourceContainer& resource)
}
break;
case FilterResourceType:
-#if ENABLE(FILTERS)
if (!m_clipperFilterMaskerData)
break;
if (m_clipperFilterMaskerData->filter == &resource) {
m_clipperFilterMaskerData->filter->removeAllClientsFromCache();
m_clipperFilterMaskerData->filter = 0;
}
-#else
- ASSERT_NOT_REACHED();
-#endif
break;
case ClipperResourceType:
if (!m_clipperFilterMaskerData)
@@ -414,10 +440,8 @@ void SVGResources::buildSetOfResources(HashSet<RenderSVGResourceContainer*>& set
if (m_clipperFilterMaskerData) {
if (m_clipperFilterMaskerData->clipper)
set.add(m_clipperFilterMaskerData->clipper);
-#if ENABLE(FILTERS)
if (m_clipperFilterMaskerData->filter)
set.add(m_clipperFilterMaskerData->filter);
-#endif
if (m_clipperFilterMaskerData->masker)
set.add(m_clipperFilterMaskerData->masker);
}
@@ -447,7 +471,7 @@ bool SVGResources::setClipper(RenderSVGResourceClipper* clipper)
ASSERT(clipper->resourceType() == ClipperResourceType);
if (!m_clipperFilterMaskerData)
- m_clipperFilterMaskerData = ClipperFilterMaskerData::create();
+ m_clipperFilterMaskerData = std::make_unique<ClipperFilterMaskerData>();
m_clipperFilterMaskerData->clipper = clipper;
return true;
@@ -460,7 +484,6 @@ void SVGResources::resetClipper()
m_clipperFilterMaskerData->clipper = 0;
}
-#if ENABLE(FILTERS)
bool SVGResources::setFilter(RenderSVGResourceFilter* filter)
{
if (!filter)
@@ -469,7 +492,7 @@ bool SVGResources::setFilter(RenderSVGResourceFilter* filter)
ASSERT(filter->resourceType() == FilterResourceType);
if (!m_clipperFilterMaskerData)
- m_clipperFilterMaskerData = ClipperFilterMaskerData::create();
+ m_clipperFilterMaskerData = std::make_unique<ClipperFilterMaskerData>();
m_clipperFilterMaskerData->filter = filter;
return true;
@@ -481,7 +504,6 @@ void SVGResources::resetFilter()
ASSERT(m_clipperFilterMaskerData->filter);
m_clipperFilterMaskerData->filter = 0;
}
-#endif
bool SVGResources::setMarkerStart(RenderSVGResourceMarker* markerStart)
{
@@ -491,7 +513,7 @@ bool SVGResources::setMarkerStart(RenderSVGResourceMarker* markerStart)
ASSERT(markerStart->resourceType() == MarkerResourceType);
if (!m_markerData)
- m_markerData = MarkerData::create();
+ m_markerData = std::make_unique<MarkerData>();
m_markerData->markerStart = markerStart;
return true;
@@ -512,7 +534,7 @@ bool SVGResources::setMarkerMid(RenderSVGResourceMarker* markerMid)
ASSERT(markerMid->resourceType() == MarkerResourceType);
if (!m_markerData)
- m_markerData = MarkerData::create();
+ m_markerData = std::make_unique<MarkerData>();
m_markerData->markerMid = markerMid;
return true;
@@ -533,7 +555,7 @@ bool SVGResources::setMarkerEnd(RenderSVGResourceMarker* markerEnd)
ASSERT(markerEnd->resourceType() == MarkerResourceType);
if (!m_markerData)
- m_markerData = MarkerData::create();
+ m_markerData = std::make_unique<MarkerData>();
m_markerData->markerEnd = markerEnd;
return true;
@@ -554,7 +576,7 @@ bool SVGResources::setMasker(RenderSVGResourceMasker* masker)
ASSERT(masker->resourceType() == MaskerResourceType);
if (!m_clipperFilterMaskerData)
- m_clipperFilterMaskerData = ClipperFilterMaskerData::create();
+ m_clipperFilterMaskerData = std::make_unique<ClipperFilterMaskerData>();
m_clipperFilterMaskerData->masker = masker;
return true;
@@ -577,7 +599,7 @@ bool SVGResources::setFill(RenderSVGResourceContainer* fill)
|| fill->resourceType() == RadialGradientResourceType);
if (!m_fillStrokeData)
- m_fillStrokeData = FillStrokeData::create();
+ m_fillStrokeData = std::make_unique<FillStrokeData>();
m_fillStrokeData->fill = fill;
return true;
@@ -600,7 +622,7 @@ bool SVGResources::setStroke(RenderSVGResourceContainer* stroke)
|| stroke->resourceType() == RadialGradientResourceType);
if (!m_fillStrokeData)
- m_fillStrokeData = FillStrokeData::create();
+ m_fillStrokeData = std::make_unique<FillStrokeData>();
m_fillStrokeData->stroke = stroke;
return true;
@@ -628,7 +650,7 @@ void SVGResources::resetLinkedResource()
m_linkedResource = 0;
}
-#ifndef NDEBUG
+#if ENABLE(TREE_DEBUGGING)
void SVGResources::dump(const RenderObject* object)
{
ASSERT(object);
@@ -642,10 +664,8 @@ void SVGResources::dump(const RenderObject* object)
if (m_clipperFilterMaskerData) {
if (RenderSVGResourceClipper* clipper = m_clipperFilterMaskerData->clipper)
fprintf(stderr, " |-> Clipper : %p (node=%p)\n", clipper, &clipper->clipPathElement());
-#if ENABLE(FILTERS)
if (RenderSVGResourceFilter* filter = m_clipperFilterMaskerData->filter)
fprintf(stderr, " |-> Filter : %p (node=%p)\n", filter, &filter->filterElement());
-#endif
if (RenderSVGResourceMasker* masker = m_clipperFilterMaskerData->masker)
fprintf(stderr, " |-> Masker : %p (node=%p)\n", masker, &masker->maskElement());
}
@@ -672,5 +692,3 @@ void SVGResources::dump(const RenderObject* object)
#endif
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGResources.h b/Source/WebCore/rendering/svg/SVGResources.h
index 240276a1d..e92b76199 100644
--- a/Source/WebCore/rendering/svg/SVGResources.h
+++ b/Source/WebCore/rendering/svg/SVGResources.h
@@ -17,25 +17,25 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGResources_h
-#define SVGResources_h
+#pragma once
-#if ENABLE(SVG)
+#include "RenderSVGResourceMarker.h"
+#include <memory>
#include <wtf/HashSet.h>
#include <wtf/Noncopyable.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
namespace WebCore {
class Document;
class RenderElement;
class RenderObject;
+class RenderStyle;
class RenderSVGResourceClipper;
class RenderSVGResourceContainer;
class RenderSVGResourceFilter;
class RenderSVGResourceMarker;
class RenderSVGResourceMasker;
+class RenderSVGRoot;
class SVGRenderStyle;
// Holds a set of resources associated with a RenderObject
@@ -44,27 +44,21 @@ class SVGResources {
public:
SVGResources();
- bool buildCachedResources(const RenderElement&, const SVGRenderStyle&);
+ bool buildCachedResources(const RenderElement&, const RenderStyle&);
+ void layoutDifferentRootIfNeeded(const RenderSVGRoot*);
// Ordinary resources
- RenderSVGResourceClipper* clipper() const { return m_clipperFilterMaskerData ? m_clipperFilterMaskerData->clipper : 0; }
- RenderSVGResourceMarker* markerStart() const { return m_markerData ? m_markerData->markerStart : 0; }
- RenderSVGResourceMarker* markerMid() const { return m_markerData ? m_markerData->markerMid : 0; }
- RenderSVGResourceMarker* markerEnd() const { return m_markerData ? m_markerData->markerEnd : 0; }
- RenderSVGResourceMasker* masker() const { return m_clipperFilterMaskerData ? m_clipperFilterMaskerData->masker : 0; }
-
- RenderSVGResourceFilter* filter() const
- {
-#if ENABLE(FILTERS)
- if (m_clipperFilterMaskerData)
- return m_clipperFilterMaskerData->filter;
-#endif
- return 0;
- }
+ RenderSVGResourceClipper* clipper() const { return m_clipperFilterMaskerData ? m_clipperFilterMaskerData->clipper : nullptr; }
+ RenderSVGResourceMarker* markerStart() const { return m_markerData ? m_markerData->markerStart : nullptr; }
+ RenderSVGResourceMarker* markerMid() const { return m_markerData ? m_markerData->markerMid : nullptr; }
+ RenderSVGResourceMarker* markerEnd() const { return m_markerData ? m_markerData->markerEnd : nullptr; }
+ bool markerReverseStart() const;
+ RenderSVGResourceMasker* masker() const { return m_clipperFilterMaskerData ? m_clipperFilterMaskerData->masker : nullptr; }
+ RenderSVGResourceFilter* filter() const { return m_clipperFilterMaskerData ? m_clipperFilterMaskerData->filter : nullptr; }
// Paint servers
- RenderSVGResourceContainer* fill() const { return m_fillStrokeData ? m_fillStrokeData->fill : 0; }
- RenderSVGResourceContainer* stroke() const { return m_fillStrokeData ? m_fillStrokeData->stroke : 0; }
+ RenderSVGResourceContainer* fill() const { return m_fillStrokeData ? m_fillStrokeData->fill : nullptr; }
+ RenderSVGResourceContainer* stroke() const { return m_fillStrokeData ? m_fillStrokeData->stroke : nullptr; }
// Chainable resources - linked through xlink:href
RenderSVGResourceContainer* linkedResource() const { return m_linkedResource; }
@@ -72,10 +66,10 @@ public:
void buildSetOfResources(HashSet<RenderSVGResourceContainer*>&);
// Methods operating on all cached resources
- void removeClientFromCache(RenderObject&, bool markForInvalidation = true) const;
+ void removeClientFromCache(RenderElement&, bool markForInvalidation = true) const;
void resourceDestroyed(RenderSVGResourceContainer&);
-#ifndef NDEBUG
+#if ENABLE(TREE_DEBUGGING)
void dump(const RenderObject*);
#endif
@@ -84,9 +78,7 @@ private:
// Only used by SVGResourcesCache cycle detection logic
void resetClipper();
-#if ENABLE(FILTERS)
void resetFilter();
-#endif
void resetMarkerStart();
void resetMarkerMid();
void resetMarkerEnd();
@@ -97,9 +89,7 @@ private:
private:
bool setClipper(RenderSVGResourceClipper*);
-#if ENABLE(FILTERS)
bool setFilter(RenderSVGResourceFilter*);
-#endif
bool setMarkerStart(RenderSVGResourceMarker*);
bool setMarkerMid(RenderSVGResourceMarker*);
bool setMarkerEnd(RenderSVGResourceMarker*);
@@ -118,22 +108,13 @@ private:
public:
ClipperFilterMaskerData()
: clipper(0)
-#if ENABLE(FILTERS)
, filter(0)
-#endif
, masker(0)
{
}
- static PassOwnPtr<ClipperFilterMaskerData> create()
- {
- return adoptPtr(new ClipperFilterMaskerData);
- }
-
RenderSVGResourceClipper* clipper;
-#if ENABLE(FILTERS)
RenderSVGResourceFilter* filter;
-#endif
RenderSVGResourceMasker* masker;
};
@@ -149,11 +130,6 @@ private:
{
}
- static PassOwnPtr<MarkerData> create()
- {
- return adoptPtr(new MarkerData);
- }
-
RenderSVGResourceMarker* markerStart;
RenderSVGResourceMarker* markerMid;
RenderSVGResourceMarker* markerEnd;
@@ -172,22 +148,14 @@ private:
{
}
- static PassOwnPtr<FillStrokeData> create()
- {
- return adoptPtr(new FillStrokeData);
- }
-
RenderSVGResourceContainer* fill;
RenderSVGResourceContainer* stroke;
};
- OwnPtr<ClipperFilterMaskerData> m_clipperFilterMaskerData;
- OwnPtr<MarkerData> m_markerData;
- OwnPtr<FillStrokeData> m_fillStrokeData;
+ std::unique_ptr<ClipperFilterMaskerData> m_clipperFilterMaskerData;
+ std::unique_ptr<MarkerData> m_markerData;
+ std::unique_ptr<FillStrokeData> m_fillStrokeData;
RenderSVGResourceContainer* m_linkedResource;
};
-}
-
-#endif
-#endif
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/SVGResourcesCache.cpp b/Source/WebCore/rendering/svg/SVGResourcesCache.cpp
index fad518a32..83d912eeb 100644
--- a/Source/WebCore/rendering/svg/SVGResourcesCache.cpp
+++ b/Source/WebCore/rendering/svg/SVGResourcesCache.cpp
@@ -20,8 +20,6 @@
#include "config.h"
#include "SVGResourcesCache.h"
-#if ENABLE(SVG)
-#include "HTMLNames.h"
#include "RenderSVGResourceContainer.h"
#include "SVGResources.h"
#include "SVGResourcesCycleSolver.h"
@@ -40,15 +38,13 @@ void SVGResourcesCache::addResourcesFromRenderer(RenderElement& renderer, const
{
ASSERT(!m_cache.contains(&renderer));
- const SVGRenderStyle& svgStyle = style.svgStyle();
-
// Build a list of all resources associated with the passed RenderObject
- OwnPtr<SVGResources> newResources = adoptPtr(new SVGResources);
- if (!newResources->buildCachedResources(renderer, svgStyle))
+ auto newResources = std::make_unique<SVGResources>();
+ if (!newResources->buildCachedResources(renderer, style))
return;
// Put object in cache.
- SVGResources& resources = *m_cache.add(&renderer, newResources.release()).iterator->value;
+ SVGResources& resources = *m_cache.add(&renderer, WTFMove(newResources)).iterator->value;
// Run cycle-detection _afterwards_, so self-references can be caught as well.
SVGResourcesCycleSolver solver(renderer, resources);
@@ -58,13 +54,13 @@ void SVGResourcesCache::addResourcesFromRenderer(RenderElement& renderer, const
HashSet<RenderSVGResourceContainer*> resourceSet;
resources.buildSetOfResources(resourceSet);
- for (auto it = resourceSet.begin(), end = resourceSet.end(); it != end; ++it)
- (*it)->addClient(&renderer);
+ for (auto* resourceContainer : resourceSet)
+ resourceContainer->addClient(renderer);
}
void SVGResourcesCache::removeResourcesFromRenderer(RenderElement& renderer)
{
- OwnPtr<SVGResources> resources = m_cache.take(&renderer);
+ std::unique_ptr<SVGResources> resources = m_cache.take(&renderer);
if (!resources)
return;
@@ -72,29 +68,23 @@ void SVGResourcesCache::removeResourcesFromRenderer(RenderElement& renderer)
HashSet<RenderSVGResourceContainer*> resourceSet;
resources->buildSetOfResources(resourceSet);
- for (auto it = resourceSet.begin(), end = resourceSet.end(); it != end; ++it)
- (*it)->removeClient(&renderer);
+ for (auto* resourceContainer : resourceSet)
+ resourceContainer->removeClient(renderer);
}
-static inline SVGResourcesCache* resourcesCacheFromRenderObject(const RenderObject& renderer)
+static inline SVGResourcesCache& resourcesCacheFromRenderer(const RenderElement& renderer)
{
- SVGDocumentExtensions* extensions = renderer.document().accessSVGExtensions();
- ASSERT(extensions);
-
- SVGResourcesCache* cache = extensions->resourcesCache();
- ASSERT(cache);
-
- return cache;
+ return renderer.document().accessSVGExtensions().resourcesCache();
}
-SVGResources* SVGResourcesCache::cachedResourcesForRenderObject(const RenderObject& renderer)
+SVGResources* SVGResourcesCache::cachedResourcesForRenderer(const RenderElement& renderer)
{
- return resourcesCacheFromRenderObject(renderer)->m_cache.get(&renderer);
+ return resourcesCacheFromRenderer(renderer).m_cache.get(&renderer);
}
void SVGResourcesCache::clientLayoutChanged(RenderElement& renderer)
{
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer);
if (!resources)
return;
@@ -122,15 +112,15 @@ void SVGResourcesCache::clientStyleChanged(RenderElement& renderer, StyleDiffere
// FIXME: Avoid passing in a useless StyleDifference, but instead compare oldStyle/newStyle to see which resources changed
// to be able to selectively rebuild individual resources, instead of all of them.
if (rendererCanHaveResources(renderer)) {
- SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
- cache->removeResourcesFromRenderer(renderer);
- cache->addResourcesFromRenderer(renderer, newStyle);
+ auto& cache = resourcesCacheFromRenderer(renderer);
+ cache.removeResourcesFromRenderer(renderer);
+ cache.addResourcesFromRenderer(renderer, newStyle);
}
RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
if (renderer.element() && !renderer.element()->isSVGElement())
- renderer.element()->setNeedsStyleRecalc(SyntheticStyleChange);
+ renderer.element()->invalidateStyleAndLayerComposition();
}
void SVGResourcesCache::clientWasAddedToTree(RenderObject& renderer)
@@ -142,9 +132,8 @@ void SVGResourcesCache::clientWasAddedToTree(RenderObject& renderer)
if (!rendererCanHaveResources(renderer))
return;
- RenderElement& elementRenderer = toRenderElement(renderer);
- SVGResourcesCache* cache = resourcesCacheFromRenderObject(elementRenderer);
- cache->addResourcesFromRenderer(elementRenderer, elementRenderer.style());
+ RenderElement& elementRenderer = downcast<RenderElement>(renderer);
+ resourcesCacheFromRenderer(elementRenderer).addResourcesFromRenderer(elementRenderer, elementRenderer.style());
}
void SVGResourcesCache::clientWillBeRemovedFromTree(RenderObject& renderer)
@@ -156,40 +145,33 @@ void SVGResourcesCache::clientWillBeRemovedFromTree(RenderObject& renderer)
if (!rendererCanHaveResources(renderer))
return;
- RenderElement& elementRenderer = toRenderElement(renderer);
- SVGResourcesCache* cache = resourcesCacheFromRenderObject(elementRenderer);
- cache->removeResourcesFromRenderer(elementRenderer);
+ RenderElement& elementRenderer = downcast<RenderElement>(renderer);
+ resourcesCacheFromRenderer(elementRenderer).removeResourcesFromRenderer(elementRenderer);
}
void SVGResourcesCache::clientDestroyed(RenderElement& renderer)
{
- SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
- if (resources)
+ if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer))
resources->removeClientFromCache(renderer);
- SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
- cache->removeResourcesFromRenderer(renderer);
+ resourcesCacheFromRenderer(renderer).removeResourcesFromRenderer(renderer);
}
void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer& resource)
{
- SVGResourcesCache* cache = resourcesCacheFromRenderObject(resource);
+ auto& cache = resourcesCacheFromRenderer(resource);
// The resource itself may have clients, that need to be notified.
- cache->removeResourcesFromRenderer(resource);
+ cache.removeResourcesFromRenderer(resource);
- for (auto it = cache->m_cache.begin(), end = cache->m_cache.end(); it != end; ++it) {
- it->value->resourceDestroyed(resource);
+ for (auto& it : cache.m_cache) {
+ it.value->resourceDestroyed(resource);
// Mark users of destroyed resources as pending resolution based on the id of the old resource.
Element& resourceElement = resource.element();
- Element* clientElement = toElement(it->key->node());
- SVGDocumentExtensions* extensions = clientElement->document().accessSVGExtensions();
-
- extensions->addPendingResource(resourceElement.getIdAttribute(), clientElement);
+ Element* clientElement = it.key->element();
+ clientElement->document().accessSVGExtensions().addPendingResource(resourceElement.getIdAttribute(), clientElement);
}
}
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGResourcesCache.h b/Source/WebCore/rendering/svg/SVGResourcesCache.h
index fe6d5e6ed..6983a7f3c 100644
--- a/Source/WebCore/rendering/svg/SVGResourcesCache.h
+++ b/Source/WebCore/rendering/svg/SVGResourcesCache.h
@@ -17,13 +17,12 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGResourcesCache_h
-#define SVGResourcesCache_h
+#pragma once
-#if ENABLE(SVG)
#include "RenderStyleConstants.h"
+#include <memory>
#include <wtf/HashMap.h>
-#include <wtf/OwnPtr.h>
+#include <wtf/Noncopyable.h>
namespace WebCore {
@@ -39,7 +38,7 @@ public:
SVGResourcesCache();
~SVGResourcesCache();
- static SVGResources* cachedResourcesForRenderObject(const RenderObject&);
+ static SVGResources* cachedResourcesForRenderer(const RenderElement&);
// Called from all SVG renderers addChild() methods.
static void clientWasAddedToTree(RenderObject&);
@@ -63,11 +62,8 @@ private:
void addResourcesFromRenderer(RenderElement&, const RenderStyle&);
void removeResourcesFromRenderer(RenderElement&);
- typedef HashMap<const RenderObject*, OwnPtr<SVGResources>> CacheMap;
+ typedef HashMap<const RenderElement*, std::unique_ptr<SVGResources>> CacheMap;
CacheMap m_cache;
};
-}
-
-#endif
-#endif
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.cpp b/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.cpp
index c6776f667..be76c1f9d 100644
--- a/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.cpp
+++ b/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.cpp
@@ -20,12 +20,8 @@
#include "config.h"
#include "SVGResourcesCycleSolver.h"
-// Set to a value > 0, to debug the resource cache.
-#define DEBUG_CYCLE_DETECTION 0
-
-#if ENABLE(SVG)
-#include "RenderElement.h"
-#include "RenderIterator.h"
+#include "Logging.h"
+#include "RenderAncestorIterator.h"
#include "RenderSVGResourceClipper.h"
#include "RenderSVGResourceFilter.h"
#include "RenderSVGResourceMarker.h"
@@ -35,6 +31,15 @@
#include "SVGResources.h"
#include "SVGResourcesCache.h"
+// Set to truthy value to debug the resource cache.
+#define DEBUG_CYCLE_DETECTION 0
+
+#if DEBUG_CYCLE_DETECTION
+#define LOG_DEBUG_CYCLE(...) LOG(SVG, __VA_ARGS__)
+#else
+#define LOG_DEBUG_CYCLE(...) ((void)0)
+#endif
+
namespace WebCore {
SVGResourcesCycleSolver::SVGResourcesCycleSolver(RenderElement& renderer, SVGResources& resources)
@@ -49,43 +54,65 @@ SVGResourcesCycleSolver::~SVGResourcesCycleSolver()
bool SVGResourcesCycleSolver::resourceContainsCycles(RenderElement& renderer) const
{
+ LOG_DEBUG_CYCLE("\n(%p) Check for cycles\n", &renderer);
+
// First operate on the resources of the given renderer.
// <marker id="a"> <path marker-start="url(#b)"/> ...
// <marker id="b" marker-start="url(#a)"/>
- if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer)) {
+ if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) {
HashSet<RenderSVGResourceContainer*> resourceSet;
resources->buildSetOfResources(resourceSet);
- // Walk all resources and check wheter they reference any resource contained in the resources set.
- for (auto resource : resourceSet) {
+ LOG_DEBUG_CYCLE("(%p) Examine our cached resources\n", &renderer);
+
+ // Walk all resources and check whether they reference any resource contained in the resources set.
+ for (auto* resource : resourceSet) {
+ LOG_DEBUG_CYCLE("(%p) Check %p\n", &renderer, resource);
if (m_allResources.contains(resource))
return true;
+
+ // Now check if the resources themselves contain cycles.
+ if (resourceContainsCycles(*resource))
+ return true;
}
}
+ LOG_DEBUG_CYCLE("(%p) Now the children renderers\n", &renderer);
+
// Then operate on the child resources of the given renderer.
// <marker id="a"> <path marker-start="url(#b)"/> ...
// <marker id="b"> <path marker-start="url(#a)"/> ...
for (auto& child : childrenOfType<RenderElement>(renderer)) {
- SVGResources* childResources = SVGResourcesCache::cachedResourcesForRenderObject(child);
- if (!childResources)
- continue;
-
- // A child of the given 'resource' contains resources.
- HashSet<RenderSVGResourceContainer*> childResourceSet;
- childResources->buildSetOfResources(childResourceSet);
-
- // Walk all child resources and check wheter they reference any resource contained in the resources set.
- for (auto& resource : childResourceSet) {
- if (m_allResources.contains(resource))
- return true;
+
+ LOG_DEBUG_CYCLE("(%p) Checking child %p\n", &renderer, &child);
+
+ if (auto* childResources = SVGResourcesCache::cachedResourcesForRenderer(child)) {
+
+ LOG_DEBUG_CYCLE("(%p) Child %p had cached resources. Check them.\n", &renderer, &child);
+
+ // A child of the given 'resource' contains resources.
+ HashSet<RenderSVGResourceContainer*> childResourceSet;
+ childResources->buildSetOfResources(childResourceSet);
+
+ // Walk all child resources and check whether they reference any resource contained in the resources set.
+ for (auto* resource : childResourceSet) {
+ LOG_DEBUG_CYCLE("(%p) Child %p had resource %p\n", &renderer, &child, resource);
+ if (m_allResources.contains(resource))
+ return true;
+ }
}
+ LOG_DEBUG_CYCLE("(%p) Recurse into child %p\n", &renderer, &child);
+
// Walk children recursively, stop immediately if we found a cycle
if (resourceContainsCycles(child))
return true;
+
+ LOG_DEBUG_CYCLE("\n(%p) Child %p was ok\n", &renderer, &child);
}
+ LOG_DEBUG_CYCLE("\n(%p) No cycles found\n", &renderer);
+
return false;
}
@@ -93,8 +120,8 @@ void SVGResourcesCycleSolver::resolveCycles()
{
ASSERT(m_allResources.isEmpty());
-#if DEBUG_CYCLE_DETECTION > 0
- fprintf(stderr, "\nBefore cycle detection:\n");
+#if DEBUG_CYCLE_DETECTION
+ LOG_DEBUG_CYCLE("\nBefore cycle detection:\n");
m_resources.dump(&m_renderer);
#endif
@@ -104,49 +131,52 @@ void SVGResourcesCycleSolver::resolveCycles()
ASSERT(!localResources.isEmpty());
// Add all parent resource containers to the HashSet.
- HashSet<RenderSVGResourceContainer*> parentResources;
- auto parent = m_renderer.parent();
- while (parent) {
- if (parent->isSVGResourceContainer())
- parentResources.add(parent->toRenderSVGResourceContainer());
- parent = parent->parent();
- }
+ HashSet<RenderSVGResourceContainer*> ancestorResources;
+ for (auto& resource : ancestorsOfType<RenderSVGResourceContainer>(m_renderer))
+ ancestorResources.add(&resource);
-#if DEBUG_CYCLE_DETECTION > 0
- fprintf(stderr, "\nDetecting wheter any resources references any of following objects:\n");
+#if DEBUG_CYCLE_DETECTION
+ LOG_DEBUG_CYCLE("\nDetecting whether any resources references any of following objects:\n");
{
- fprintf(stderr, "Local resources:\n");
- for (auto it = localResources.begin(), end = localResources.end(); it != end; ++it)
- fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node());
+ LOG_DEBUG_CYCLE("Local resources:\n");
+ for (RenderObject* resource : localResources)
+ LOG_DEBUG_CYCLE("|> %s : %p (node %p)\n", resource->renderName(), resource, resource->node());
fprintf(stderr, "Parent resources:\n");
- for (auto it = parentResources.begin(), end = parentResources.end(); it != end; ++it)
- fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node());
+ for (RenderObject* resource : ancestorResources)
+ LOG_DEBUG_CYCLE("|> %s : %p (node %p)\n", resource->renderName(), resource, resource->node());
}
#endif
// Build combined set of local and parent resources.
m_allResources = localResources;
- for (auto it = parentResources.begin(), end = parentResources.end(); it != end; ++it)
- m_allResources.add(*it);
+ for (auto* resource : ancestorResources)
+ m_allResources.add(resource);
// If we're a resource, add ourselves to the HashSet.
- if (m_renderer.isSVGResourceContainer())
- m_allResources.add(m_renderer.toRenderSVGResourceContainer());
+ if (is<RenderSVGResourceContainer>(m_renderer))
+ m_allResources.add(&downcast<RenderSVGResourceContainer>(m_renderer));
ASSERT(!m_allResources.isEmpty());
+#if DEBUG_CYCLE_DETECTION
+ LOG_DEBUG_CYCLE("\nAll resources:\n");
+ for (auto* resource : m_allResources)
+ LOG_DEBUG_CYCLE("- %p\n", resource);
+#endif
+
// The job of this function is to determine wheter any of the 'resources' associated with the given 'renderer'
- // references us (or wheter any of its kids references us) -> that's a cycle, we need to find and break it.
- for (auto it = localResources.begin(), end = localResources.end(); it != end; ++it) {
- RenderSVGResourceContainer& resource = **it;
- if (parentResources.contains(&resource) || resourceContainsCycles(resource))
- breakCycle(resource);
+ // references us (or whether any of its kids references us) -> that's a cycle, we need to find and break it.
+ for (auto* resource : localResources) {
+ if (ancestorResources.contains(resource) || resourceContainsCycles(*resource)) {
+ LOG_DEBUG_CYCLE("\n**** Detected a cycle (see the last test in the output above) ****\n");
+ breakCycle(*resource);
+ }
}
-#if DEBUG_CYCLE_DETECTION > 0
- fprintf(stderr, "\nAfter cycle detection:\n");
- m_resources.dump(m_renderer);
+#if DEBUG_CYCLE_DETECTION
+ LOG_DEBUG_CYCLE("\nAfter cycle detection:\n");
+ m_resources.dump(&m_renderer);
#endif
m_allResources.clear();
@@ -183,10 +213,8 @@ void SVGResourcesCycleSolver::breakCycle(RenderSVGResourceContainer& resourceLea
m_resources.resetStroke();
break;
case FilterResourceType:
-#if ENABLE(FILTERS)
ASSERT(&resourceLeadingToCycle == m_resources.filter());
m_resources.resetFilter();
-#endif
break;
case ClipperResourceType:
ASSERT(&resourceLeadingToCycle == m_resources.clipper());
@@ -199,5 +227,3 @@ void SVGResourcesCycleSolver::breakCycle(RenderSVGResourceContainer& resourceLea
}
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.h b/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.h
index fd95a7428..2e666a7ee 100644
--- a/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.h
+++ b/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.h
@@ -17,10 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGResourcesCycleSolver_h
-#define SVGResourcesCycleSolver_h
+#pragma once
-#if ENABLE(SVG)
#include <wtf/HashSet.h>
#include <wtf/Noncopyable.h>
@@ -47,7 +45,4 @@ private:
HashSet<RenderSVGResourceContainer*> m_allResources;
};
-}
-
-#endif
-#endif
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp b/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp
index ec628b168..c6d23f57c 100644
--- a/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp
+++ b/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
- * Copyright (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
* Copyright (C) 2011 Torch Mobile (Beijing) CO. Ltd. All rights reserved.
@@ -24,9 +24,9 @@
#include "config.h"
#include "SVGRootInlineBox.h"
-#if ENABLE(SVG)
#include "GraphicsContext.h"
#include "RenderSVGText.h"
+#include "RenderSVGTextPath.h"
#include "SVGInlineFlowBox.h"
#include "SVGInlineTextBox.h"
#include "SVGNames.h"
@@ -43,48 +43,44 @@ SVGRootInlineBox::SVGRootInlineBox(RenderSVGText& renderSVGText)
RenderSVGText& SVGRootInlineBox::renderSVGText()
{
- return toRenderSVGText(blockFlow());
+ return downcast<RenderSVGText>(blockFlow());
}
-void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit)
+void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
{
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
- ASSERT(!paintInfo.context->paintingDisabled());
+ ASSERT(!paintInfo.context().paintingDisabled());
bool isPrinting = renderSVGText().document().printing();
bool hasSelection = !isPrinting && selectionState() != RenderObject::SelectionNone;
+ bool shouldPaintSelectionHighlight = !(paintInfo.paintBehavior & PaintBehaviorSkipSelectionHighlight);
PaintInfo childPaintInfo(paintInfo);
- if (hasSelection) {
+ if (hasSelection && shouldPaintSelectionHighlight) {
for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
- if (child->isSVGInlineTextBox())
- toSVGInlineTextBox(child)->paintSelectionBackground(childPaintInfo);
- else if (child->isSVGInlineFlowBox())
- toSVGInlineFlowBox(child)->paintSelectionBackground(childPaintInfo);
+ if (is<SVGInlineTextBox>(*child))
+ downcast<SVGInlineTextBox>(*child).paintSelectionBackground(childPaintInfo);
+ else if (is<SVGInlineFlowBox>(*child))
+ downcast<SVGInlineFlowBox>(*child).paintSelectionBackground(childPaintInfo);
}
}
SVGRenderingContext renderingContext(renderSVGText(), paintInfo, SVGRenderingContext::SaveGraphicsContext);
if (renderingContext.isRenderingPrepared()) {
- for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
- if (child->isSVGInlineTextBox())
- SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(&toSVGInlineTextBox(child)->renderer());
-
- child->paint(paintInfo, LayoutPoint(), 0, 0);
- }
+ for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+ child->paint(paintInfo, paintOffset, 0, 0);
}
}
void SVGRootInlineBox::computePerCharacterLayoutInformation()
{
- RenderSVGText* textRoot = toRenderSVGText(&blockFlow());
- ASSERT(textRoot);
+ auto& textRoot = downcast<RenderSVGText>(blockFlow());
- Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot->layoutAttributes();
+ Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot.layoutAttributes();
if (layoutAttributes.isEmpty())
return;
- if (textRoot->needsReordering())
+ if (textRoot.needsReordering())
reorderValueLists(layoutAttributes);
// Perform SVG text layout phase two (see SVGTextLayoutEngine for details).
@@ -104,31 +100,27 @@ void SVGRootInlineBox::computePerCharacterLayoutInformation()
void SVGRootInlineBox::layoutCharactersInTextBoxes(InlineFlowBox* start, SVGTextLayoutEngine& characterLayout)
{
for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) {
- if (child->isSVGInlineTextBox()) {
- ASSERT(child->renderer().isSVGInlineText());
-
- SVGInlineTextBox* textBox = toSVGInlineTextBox(child);
- characterLayout.layoutInlineTextBox(textBox);
+ if (is<SVGInlineTextBox>(*child)) {
+ ASSERT(is<RenderSVGInlineText>(child->renderer()));
+ characterLayout.layoutInlineTextBox(downcast<SVGInlineTextBox>(*child));
} else {
// Skip generated content.
Node* node = child->renderer().node();
if (!node)
continue;
- ASSERT_WITH_SECURITY_IMPLICATION(child->isInlineFlowBox());
-
- SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child);
+ auto& flowBox = downcast<SVGInlineFlowBox>(*child);
bool isTextPath = node->hasTagName(SVGNames::textPathTag);
if (isTextPath) {
// Build text chunks for all <textPath> children, using the line layout algorithm.
// This is needeed as text-anchor is just an additional startOffset for text paths.
SVGTextLayoutEngine lineLayout(characterLayout.layoutAttributes());
- layoutCharactersInTextBoxes(flowBox, lineLayout);
+ layoutCharactersInTextBoxes(&flowBox, lineLayout);
- characterLayout.beginTextPathLayout(&child->renderer(), lineLayout);
+ characterLayout.beginTextPathLayout(downcast<RenderSVGTextPath>(child->renderer()), lineLayout);
}
- layoutCharactersInTextBoxes(flowBox, characterLayout);
+ layoutCharactersInTextBoxes(&flowBox, characterLayout);
if (isTextPath)
characterLayout.endTextPathLayout();
@@ -140,30 +132,28 @@ void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start, FloatRect* childRe
{
for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) {
FloatRect boxRect;
- if (child->isSVGInlineTextBox()) {
- ASSERT(child->renderer().isSVGInlineText());
-
- SVGInlineTextBox* textBox = toSVGInlineTextBox(child);
- boxRect = textBox->calculateBoundaries();
- textBox->setX(boxRect.x());
- textBox->setY(boxRect.y());
- textBox->setLogicalWidth(boxRect.width());
- textBox->setLogicalHeight(boxRect.height());
+ if (is<SVGInlineTextBox>(*child)) {
+ ASSERT(is<RenderSVGInlineText>(child->renderer()));
+
+ auto& textBox = downcast<SVGInlineTextBox>(*child);
+ boxRect = textBox.calculateBoundaries();
+ textBox.setX(boxRect.x());
+ textBox.setY(boxRect.y());
+ textBox.setLogicalWidth(boxRect.width());
+ textBox.setLogicalHeight(boxRect.height());
} else {
// Skip generated content.
if (!child->renderer().node())
continue;
- ASSERT_WITH_SECURITY_IMPLICATION(child->isInlineFlowBox());
-
- SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child);
- layoutChildBoxes(flowBox);
+ auto& flowBox = downcast<SVGInlineFlowBox>(*child);
+ layoutChildBoxes(&flowBox);
- boxRect = flowBox->calculateBoundaries();
- flowBox->setX(boxRect.x());
- flowBox->setY(boxRect.y());
- flowBox->setLogicalWidth(boxRect.width());
- flowBox->setLogicalHeight(boxRect.height());
+ boxRect = flowBox.calculateBoundaries();
+ flowBox.setX(boxRect.x());
+ flowBox.setY(boxRect.y());
+ flowBox.setLogicalWidth(boxRect.width());
+ flowBox.setLogicalHeight(boxRect.height());
}
if (childRect)
childRect->unite(boxRect);
@@ -203,7 +193,7 @@ InlineBox* SVGRootInlineBox::closestLeafChildForPosition(const LayoutPoint& poin
return firstLeaf;
// FIXME: Check for vertical text!
- InlineBox* closestLeaf = 0;
+ InlineBox* closestLeaf = nullptr;
for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChild()) {
if (!leaf->isSVGInlineTextBox())
continue;
@@ -220,6 +210,18 @@ InlineBox* SVGRootInlineBox::closestLeafChildForPosition(const LayoutPoint& poin
return closestLeaf ? closestLeaf : lastLeaf;
}
+bool SVGRootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom, HitTestAction hitTestAction)
+{
+ for (InlineBox* leaf = firstLeafChild(); leaf; leaf = leaf->nextLeafChild()) {
+ if (!leaf->isSVGInlineTextBox())
+ continue;
+ if (leaf->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, lineTop, lineBottom, hitTestAction))
+ return true;
+ }
+
+ return false;
+}
+
static inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes* firstAttributes, SVGTextLayoutAttributes* lastAttributes, unsigned firstPosition, unsigned lastPosition)
{
SVGCharacterDataMap::iterator itFirst = firstAttributes->characterDataMap().find(firstPosition + 1);
@@ -246,8 +248,8 @@ static inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes* firstAtt
static inline void findFirstAndLastAttributesInVector(Vector<SVGTextLayoutAttributes*>& attributes, RenderSVGInlineText* firstContext, RenderSVGInlineText* lastContext,
SVGTextLayoutAttributes*& first, SVGTextLayoutAttributes*& last)
{
- first = 0;
- last = 0;
+ first = nullptr;
+ last = nullptr;
unsigned attributesSize = attributes.size();
for (unsigned i = 0; i < attributesSize; ++i) {
@@ -274,7 +276,7 @@ static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Ve
if (first == last || first == --last)
return;
- if (!(*last)->isSVGInlineTextBox() || !(*first)->isSVGInlineTextBox()) {
+ if (!is<SVGInlineTextBox>(**last) || !is<SVGInlineTextBox>(**first)) {
InlineBox* temp = *first;
*first = *last;
*last = temp;
@@ -282,18 +284,18 @@ static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Ve
continue;
}
- SVGInlineTextBox* firstTextBox = toSVGInlineTextBox(*first);
- SVGInlineTextBox* lastTextBox = toSVGInlineTextBox(*last);
+ auto& firstTextBox = downcast<SVGInlineTextBox>(**first);
+ auto& lastTextBox = downcast<SVGInlineTextBox>(**last);
// Reordering is only necessary for BiDi text that is _absolutely_ positioned.
- if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->len()) {
- RenderSVGInlineText& firstContext = firstTextBox->renderer();
- RenderSVGInlineText& lastContext = lastTextBox->renderer();
+ if (firstTextBox.len() == 1 && firstTextBox.len() == lastTextBox.len()) {
+ RenderSVGInlineText& firstContext = firstTextBox.renderer();
+ RenderSVGInlineText& lastContext = lastTextBox.renderer();
- SVGTextLayoutAttributes* firstAttributes = 0;
- SVGTextLayoutAttributes* lastAttributes = 0;
+ SVGTextLayoutAttributes* firstAttributes = nullptr;
+ SVGTextLayoutAttributes* lastAttributes = nullptr;
findFirstAndLastAttributesInVector(attributes, &firstContext, &lastContext, firstAttributes, lastAttributes);
- swapItemsInLayoutAttributes(firstAttributes, lastAttributes, firstTextBox->start(), lastTextBox->start());
+ swapItemsInLayoutAttributes(firstAttributes, lastAttributes, firstTextBox.start(), lastTextBox.start());
}
InlineBox* temp = *first;
@@ -311,5 +313,3 @@ void SVGRootInlineBox::reorderValueLists(Vector<SVGTextLayoutAttributes*>& attri
}
} // namespace WebCore
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGRootInlineBox.h b/Source/WebCore/rendering/svg/SVGRootInlineBox.h
index 643af3108..bd4455203 100644
--- a/Source/WebCore/rendering/svg/SVGRootInlineBox.h
+++ b/Source/WebCore/rendering/svg/SVGRootInlineBox.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
- * Copyright (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
*
@@ -20,10 +20,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGRootInlineBox_h
-#define SVGRootInlineBox_h
+#pragma once
-#if ENABLE(SVG)
#include "RootInlineBox.h"
#include "SVGRenderSupport.h"
#include "SVGTextLayoutEngine.h"
@@ -39,29 +37,27 @@ public:
RenderSVGText& renderSVGText();
- virtual float virtualLogicalHeight() const override final { return m_logicalHeight; }
+ float virtualLogicalHeight() const override { return m_logicalHeight; }
void setLogicalHeight(float height) { m_logicalHeight = height; }
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override final;
+ void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override;
void computePerCharacterLayoutInformation();
InlineBox* closestLeafChildForPosition(const LayoutPoint&);
+ bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom, HitTestAction) final;
+
private:
- virtual bool isSVGRootInlineBox() const override final { return true; }
+ bool isSVGRootInlineBox() const override { return true; }
void reorderValueLists(Vector<SVGTextLayoutAttributes*>&);
void layoutCharactersInTextBoxes(InlineFlowBox*, SVGTextLayoutEngine&);
- void layoutChildBoxes(InlineFlowBox*, FloatRect* = 0);
+ void layoutChildBoxes(InlineFlowBox*, FloatRect* = nullptr);
void layoutRootBox(const FloatRect&);
float m_logicalHeight;
};
-INLINE_BOX_OBJECT_TYPE_CASTS(SVGRootInlineBox, isSVGRootInlineBox())
-
} // namespace WebCore
-#endif // ENABLE(SVG)
-
-#endif // SVGRootInlineBox_h
+SPECIALIZE_TYPE_TRAITS_INLINE_BOX(SVGRootInlineBox, isSVGRootInlineBox())
diff --git a/Source/WebCore/rendering/svg/SVGSubpathData.h b/Source/WebCore/rendering/svg/SVGSubpathData.h
index cf7901d8d..073afd4ce 100644
--- a/Source/WebCore/rendering/svg/SVGSubpathData.h
+++ b/Source/WebCore/rendering/svg/SVGSubpathData.h
@@ -17,10 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGSubpathData_h
-#define SVGSubpathData_h
+#pragma once
-#if ENABLE(SVG)
#include "Path.h"
#include <wtf/Vector.h>
@@ -30,51 +28,46 @@ class SVGSubpathData {
public:
SVGSubpathData(Vector<FloatPoint>& zeroLengthSubpathLocations)
: m_zeroLengthSubpathLocations(zeroLengthSubpathLocations)
- , m_haveSeenMoveOnly(true)
- , m_pathIsZeroLength(true)
{
- m_lastPoint.set(0, 0);
- m_movePoint.set(0, 0);
}
- static void updateFromPathElement(void* info, const PathElement* element)
+ static void updateFromPathElement(SVGSubpathData& subpathFinder, const PathElement& element)
{
- SVGSubpathData* subpathFinder = static_cast<SVGSubpathData*>(info);
- switch (element->type) {
+ switch (element.type) {
case PathElementMoveToPoint:
- if (subpathFinder->m_pathIsZeroLength && !subpathFinder->m_haveSeenMoveOnly)
- subpathFinder->m_zeroLengthSubpathLocations.append(subpathFinder->m_lastPoint);
- subpathFinder->m_lastPoint = subpathFinder->m_movePoint = element->points[0];
- subpathFinder->m_haveSeenMoveOnly = true;
- subpathFinder->m_pathIsZeroLength = true;
+ if (subpathFinder.m_pathIsZeroLength && !subpathFinder.m_haveSeenMoveOnly)
+ subpathFinder.m_zeroLengthSubpathLocations.append(subpathFinder.m_lastPoint);
+ subpathFinder.m_lastPoint = subpathFinder.m_movePoint = element.points[0];
+ subpathFinder.m_haveSeenMoveOnly = true;
+ subpathFinder.m_pathIsZeroLength = true;
break;
case PathElementAddLineToPoint:
- if (subpathFinder->m_lastPoint != element->points[0]) {
- subpathFinder->m_pathIsZeroLength = false;
- subpathFinder->m_lastPoint = element->points[0];
+ if (subpathFinder.m_lastPoint != element.points[0]) {
+ subpathFinder.m_pathIsZeroLength = false;
+ subpathFinder.m_lastPoint = element.points[0];
}
- subpathFinder->m_haveSeenMoveOnly = false;
+ subpathFinder.m_haveSeenMoveOnly = false;
break;
case PathElementAddQuadCurveToPoint:
- if (subpathFinder->m_lastPoint != element->points[0] || element->points[0] != element->points[1]) {
- subpathFinder->m_pathIsZeroLength = false;
- subpathFinder->m_lastPoint = element->points[1];
+ if (subpathFinder.m_lastPoint != element.points[0] || element.points[0] != element.points[1]) {
+ subpathFinder.m_pathIsZeroLength = false;
+ subpathFinder.m_lastPoint = element.points[1];
}
- subpathFinder->m_haveSeenMoveOnly = false;
+ subpathFinder.m_haveSeenMoveOnly = false;
break;
case PathElementAddCurveToPoint:
- if (subpathFinder->m_lastPoint != element->points[0] || element->points[0] != element->points[1] || element->points[1] != element->points[2]) {
- subpathFinder->m_pathIsZeroLength = false;
- subpathFinder->m_lastPoint = element->points[2];
+ if (subpathFinder.m_lastPoint != element.points[0] || element.points[0] != element.points[1] || element.points[1] != element.points[2]) {
+ subpathFinder.m_pathIsZeroLength = false;
+ subpathFinder.m_lastPoint = element.points[2];
}
- subpathFinder->m_haveSeenMoveOnly = false;
+ subpathFinder.m_haveSeenMoveOnly = false;
break;
case PathElementCloseSubpath:
- if (subpathFinder->m_pathIsZeroLength)
- subpathFinder->m_zeroLengthSubpathLocations.append(subpathFinder->m_lastPoint);
- subpathFinder->m_haveSeenMoveOnly = true; // This is an implicit move for the next element
- subpathFinder->m_pathIsZeroLength = true; // A new sub-path also starts here
- subpathFinder->m_lastPoint = subpathFinder->m_movePoint;
+ if (subpathFinder.m_pathIsZeroLength)
+ subpathFinder.m_zeroLengthSubpathLocations.append(subpathFinder.m_lastPoint);
+ subpathFinder.m_haveSeenMoveOnly = true; // This is an implicit move for the next element
+ subpathFinder.m_pathIsZeroLength = true; // A new sub-path also starts here
+ subpathFinder.m_lastPoint = subpathFinder.m_movePoint;
break;
}
}
@@ -89,12 +82,8 @@ private:
Vector<FloatPoint>& m_zeroLengthSubpathLocations;
FloatPoint m_lastPoint;
FloatPoint m_movePoint;
- bool m_haveSeenMoveOnly;
- bool m_pathIsZeroLength;
+ bool m_haveSeenMoveOnly { false };
+ bool m_pathIsZeroLength { false };
};
-}
-
-#endif // ENABLE(SVG)
-#endif // SVGSubpathData_h
-
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/SVGTextChunk.cpp b/Source/WebCore/rendering/svg/SVGTextChunk.cpp
index b7072753b..17811864e 100644
--- a/Source/WebCore/rendering/svg/SVGTextChunk.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextChunk.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -18,60 +19,102 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGTextChunk.h"
#include "SVGInlineTextBox.h"
namespace WebCore {
-SVGTextChunk::SVGTextChunk(unsigned chunkStyle, float desiredTextLength)
- : m_chunkStyle(chunkStyle)
- , m_desiredTextLength(desiredTextLength)
-{
-}
-
-void SVGTextChunk::calculateLength(float& length, unsigned& characters) const
+SVGTextChunk::SVGTextChunk(const Vector<SVGInlineTextBox*>& lineLayoutBoxes, unsigned first, unsigned limit)
{
- SVGTextFragment* lastFragment = 0;
+ ASSERT(first < limit);
+ ASSERT(limit <= lineLayoutBoxes.size());
+
+ const SVGInlineTextBox* box = lineLayoutBoxes[first];
+ const RenderStyle& style = box->renderer().style();
+ const SVGRenderStyle& svgStyle = style.svgStyle();
+
+ if (!style.isLeftToRightDirection())
+ m_chunkStyle |= SVGTextChunk::RightToLeftText;
+
+ if (style.isVerticalWritingMode())
+ m_chunkStyle |= SVGTextChunk::VerticalText;
+
+ switch (svgStyle.textAnchor()) {
+ case TA_START:
+ break;
+ case TA_MIDDLE:
+ m_chunkStyle |= MiddleAnchor;
+ break;
+ case TA_END:
+ m_chunkStyle |= EndAnchor;
+ break;
+ }
- unsigned boxCount = m_boxes.size();
- for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
- SVGInlineTextBox* textBox = m_boxes.at(boxPosition);
- Vector<SVGTextFragment>& fragments = textBox->textFragments();
+ if (auto* textContentElement = SVGTextContentElement::elementFromRenderer(box->renderer().parent())) {
+ SVGLengthContext lengthContext(textContentElement);
+ m_desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext);
+
+ switch (textContentElement->lengthAdjust()) {
+ case SVGLengthAdjustUnknown:
+ break;
+ case SVGLengthAdjustSpacing:
+ m_chunkStyle |= LengthAdjustSpacing;
+ break;
+ case SVGLengthAdjustSpacingAndGlyphs:
+ m_chunkStyle |= LengthAdjustSpacingAndGlyphs;
+ break;
+ }
+ }
- unsigned size = fragments.size();
- if (!size)
- continue;
+ for (unsigned i = first; i < limit; ++i)
+ m_boxes.append(lineLayoutBoxes[i]);
+}
- for (unsigned i = 0; i < size; ++i) {
- SVGTextFragment& fragment = fragments.at(i);
+unsigned SVGTextChunk::totalCharacters() const
+{
+ unsigned characters = 0;
+ for (auto* box : m_boxes) {
+ for (auto& fragment : box->textFragments())
characters += fragment.length;
+ }
+ return characters;
+}
- if (m_chunkStyle & VerticalText)
- length += fragment.height;
- else
- length += fragment.width;
-
- if (!lastFragment) {
- lastFragment = &fragment;
- continue;
- }
-
- // Resepect gap between chunks.
- if (m_chunkStyle & VerticalText)
- length += fragment.y - (lastFragment->y + lastFragment->height);
- else
- length += fragment.x - (lastFragment->x + lastFragment->width);
+float SVGTextChunk::totalLength() const
+{
+ const SVGTextFragment* firstFragment = nullptr;
+ const SVGTextFragment* lastFragment = nullptr;
+
+ for (auto* box : m_boxes) {
+ auto& fragments = box->textFragments();
+ if (fragments.size()) {
+ firstFragment = &(*fragments.begin());
+ break;
+ }
+ }
- lastFragment = &fragment;
+ for (auto it = m_boxes.rbegin(), end = m_boxes.rend(); it != end; ++it) {
+ auto& fragments = (*it)->textFragments();
+ if (fragments.size()) {
+ lastFragment = &(*fragments.rbegin());
+ break;
}
}
+
+ ASSERT(!firstFragment == !lastFragment);
+ if (!firstFragment)
+ return 0;
+
+ if (m_chunkStyle & VerticalText)
+ return (lastFragment->y + lastFragment->height) - firstFragment->y;
+
+ return (lastFragment->x + lastFragment->width) - firstFragment->x;
}
-float SVGTextChunk::calculateTextAnchorShift(float length) const
+float SVGTextChunk::totalAnchorShift() const
{
+ float length = totalLength();
if (m_chunkStyle & MiddleAnchor)
return -length / 2;
if (m_chunkStyle & EndAnchor)
@@ -79,6 +122,88 @@ float SVGTextChunk::calculateTextAnchorShift(float length) const
return m_chunkStyle & RightToLeftText ? -length : 0;
}
-} // namespace WebCore
+void SVGTextChunk::layout(HashMap<SVGInlineTextBox*, AffineTransform>& textBoxTransformations) const
+{
+ if (hasDesiredTextLength()) {
+ if (hasLengthAdjustSpacing())
+ processTextLengthSpacingCorrection();
+ else {
+ ASSERT(hasLengthAdjustSpacingAndGlyphs());
+ buildBoxTransformations(textBoxTransformations);
+ }
+ }
-#endif // ENABLE(SVG)
+ if (hasTextAnchor())
+ processTextAnchorCorrection();
+}
+
+void SVGTextChunk::processTextLengthSpacingCorrection() const
+{
+ float textLengthShift = (desiredTextLength() - totalLength()) / totalCharacters();
+ bool isVerticalText = m_chunkStyle & VerticalText;
+ unsigned atCharacter = 0;
+
+ for (auto* box : m_boxes) {
+ for (auto& fragment : box->textFragments()) {
+ if (isVerticalText)
+ fragment.y += textLengthShift * atCharacter;
+ else
+ fragment.x += textLengthShift * atCharacter;
+
+ atCharacter += fragment.length;
+ }
+ }
+}
+
+void SVGTextChunk::buildBoxTransformations(HashMap<SVGInlineTextBox*, AffineTransform>& textBoxTransformations) const
+{
+ AffineTransform spacingAndGlyphsTransform;
+ bool foundFirstFragment = false;
+
+ for (auto* box : m_boxes) {
+ if (!foundFirstFragment) {
+ if (!boxSpacingAndGlyphsTransform(box, spacingAndGlyphsTransform))
+ continue;
+ foundFirstFragment = true;
+ }
+
+ textBoxTransformations.set(box, spacingAndGlyphsTransform);
+ }
+}
+
+bool SVGTextChunk::boxSpacingAndGlyphsTransform(const SVGInlineTextBox* box, AffineTransform& spacingAndGlyphsTransform) const
+{
+ auto& fragments = box->textFragments();
+ if (fragments.isEmpty())
+ return false;
+
+ const SVGTextFragment& fragment = fragments.first();
+ float scale = desiredTextLength() / totalLength();
+
+ spacingAndGlyphsTransform.translate(fragment.x, fragment.y);
+
+ if (m_chunkStyle & VerticalText)
+ spacingAndGlyphsTransform.scaleNonUniform(1, scale);
+ else
+ spacingAndGlyphsTransform.scaleNonUniform(scale, 1);
+
+ spacingAndGlyphsTransform.translate(-fragment.x, -fragment.y);
+ return true;
+}
+
+void SVGTextChunk::processTextAnchorCorrection() const
+{
+ float textAnchorShift = totalAnchorShift();
+ bool isVerticalText = m_chunkStyle & VerticalText;
+
+ for (auto* box : m_boxes) {
+ for (auto& fragment : box->textFragments()) {
+ if (isVerticalText)
+ fragment.y += textAnchorShift;
+ else
+ fragment.x += textAnchorShift;
+ }
+ }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/SVGTextChunk.h b/Source/WebCore/rendering/svg/SVGTextChunk.h
index 9618d9fb6..f000f26da 100644
--- a/Source/WebCore/rendering/svg/SVGTextChunk.h
+++ b/Source/WebCore/rendering/svg/SVGTextChunk.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -17,10 +18,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGTextChunk_h
-#define SVGTextChunk_h
+#pragma once
-#if ENABLE(SVG)
#include "SVGRenderStyleDefs.h"
#include "SVGTextContentElement.h"
@@ -41,31 +40,34 @@ public:
LengthAdjustSpacingAndGlyphs = 1 << 6
};
- SVGTextChunk(unsigned chunkStyle, float desiredTextLength);
+ SVGTextChunk(const Vector<SVGInlineTextBox*>&, unsigned first, unsigned limit);
- void calculateLength(float& length, unsigned& characters) const;
- float calculateTextAnchorShift(float length) const;
+ unsigned totalCharacters() const;
+ float totalLength() const;
+ float totalAnchorShift() const;
+ void layout(HashMap<SVGInlineTextBox*, AffineTransform>&) const;
+
+private:
+ void processTextAnchorCorrection() const;
+ void buildBoxTransformations(HashMap<SVGInlineTextBox*, AffineTransform>&) const;
+ void processTextLengthSpacingCorrection() const;
bool isVerticalText() const { return m_chunkStyle & VerticalText; }
float desiredTextLength() const { return m_desiredTextLength; }
- Vector<SVGInlineTextBox*>& boxes() { return m_boxes; }
- const Vector<SVGInlineTextBox*>& boxes() const { return m_boxes; }
-
bool hasDesiredTextLength() const { return m_desiredTextLength > 0 && ((m_chunkStyle & LengthAdjustSpacing) || (m_chunkStyle & LengthAdjustSpacingAndGlyphs)); }
- bool hasTextAnchor() const { return m_chunkStyle & RightToLeftText ? !(m_chunkStyle & EndAnchor) : (m_chunkStyle & MiddleAnchor) || (m_chunkStyle & EndAnchor); }
+ bool hasTextAnchor() const { return m_chunkStyle & RightToLeftText ? !(m_chunkStyle & EndAnchor) : (m_chunkStyle & (MiddleAnchor | EndAnchor)); }
bool hasLengthAdjustSpacing() const { return m_chunkStyle & LengthAdjustSpacing; }
bool hasLengthAdjustSpacingAndGlyphs() const { return m_chunkStyle & LengthAdjustSpacingAndGlyphs; }
+ bool boxSpacingAndGlyphsTransform(const SVGInlineTextBox*, AffineTransform&) const;
+
private:
// Contains all SVGInlineTextBoxes this chunk spans.
Vector<SVGInlineTextBox*> m_boxes;
- unsigned m_chunkStyle;
- float m_desiredTextLength;
+ unsigned m_chunkStyle { DefaultStyle };
+ float m_desiredTextLength { 0 };
};
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp
index 26ab67e25..68b2d4875 100644
--- a/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -18,8 +19,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGTextChunkBuilder.h"
#include "SVGElement.h"
@@ -32,229 +31,71 @@ SVGTextChunkBuilder::SVGTextChunkBuilder()
{
}
-void SVGTextChunkBuilder::transformationForTextBox(SVGInlineTextBox* textBox, AffineTransform& transform) const
+unsigned SVGTextChunkBuilder::totalCharacters() const
{
- DEFINE_STATIC_LOCAL(const AffineTransform, s_identityTransform, ());
- if (!m_textBoxTransformations.contains(textBox)) {
- transform = s_identityTransform;
- return;
- }
-
- transform = m_textBoxTransformations.get(textBox);
+ unsigned characters = 0;
+ for (const auto& chunk : m_textChunks)
+ characters += chunk.totalCharacters();
+ return characters;
}
-void SVGTextChunkBuilder::buildTextChunks(Vector<SVGInlineTextBox*>& lineLayoutBoxes)
+float SVGTextChunkBuilder::totalLength() const
{
- if (lineLayoutBoxes.isEmpty())
- return;
-
- bool foundStart = false;
- unsigned lastChunkStartPosition = 0;
- unsigned boxPosition = 0;
- unsigned boxCount = lineLayoutBoxes.size();
- for (; boxPosition < boxCount; ++boxPosition) {
- SVGInlineTextBox* textBox = lineLayoutBoxes[boxPosition];
- if (!textBox->startsNewTextChunk())
- continue;
-
- if (!foundStart) {
- lastChunkStartPosition = boxPosition;
- foundStart = true;
- } else {
- ASSERT_WITH_SECURITY_IMPLICATION(boxPosition > lastChunkStartPosition);
- addTextChunk(lineLayoutBoxes, lastChunkStartPosition, boxPosition - lastChunkStartPosition);
- lastChunkStartPosition = boxPosition;
- }
- }
-
- if (!foundStart)
- return;
-
- if (boxPosition - lastChunkStartPosition > 0)
- addTextChunk(lineLayoutBoxes, lastChunkStartPosition, boxPosition - lastChunkStartPosition);
+ float length = 0;
+ for (const auto& chunk : m_textChunks)
+ length += chunk.totalLength();
+ return length;
}
-void SVGTextChunkBuilder::layoutTextChunks(Vector<SVGInlineTextBox*>& lineLayoutBoxes)
+float SVGTextChunkBuilder::totalAnchorShift() const
{
- buildTextChunks(lineLayoutBoxes);
- if (m_textChunks.isEmpty())
- return;
-
- unsigned chunkCount = m_textChunks.size();
- for (unsigned i = 0; i < chunkCount; ++i)
- processTextChunk(m_textChunks[i]);
-
- m_textChunks.clear();
+ float anchorShift = 0;
+ for (const auto& chunk : m_textChunks)
+ anchorShift += chunk.totalAnchorShift();
+ return anchorShift;
}
-void SVGTextChunkBuilder::addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxes, unsigned boxStart, unsigned boxCount)
+AffineTransform SVGTextChunkBuilder::transformationForTextBox(SVGInlineTextBox* textBox) const
{
- SVGInlineTextBox* textBox = lineLayoutBoxes[boxStart];
- ASSERT(textBox);
-
- const RenderStyle& style = textBox->renderer().style();
-
- const SVGRenderStyle& svgStyle = style.svgStyle();
-
- // Build chunk style flags.
- unsigned chunkStyle = SVGTextChunk::DefaultStyle;
-
- // Handle 'direction' property.
- if (!style.isLeftToRightDirection())
- chunkStyle |= SVGTextChunk::RightToLeftText;
-
- // Handle 'writing-mode' property.
- if (svgStyle.isVerticalWritingMode())
- chunkStyle |= SVGTextChunk::VerticalText;
-
- // Handle 'text-anchor' property.
- switch (svgStyle.textAnchor()) {
- case TA_START:
- break;
- case TA_MIDDLE:
- chunkStyle |= SVGTextChunk::MiddleAnchor;
- break;
- case TA_END:
- chunkStyle |= SVGTextChunk::EndAnchor;
- break;
- };
-
- // Handle 'lengthAdjust' property.
- float desiredTextLength = 0;
- if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textBox->renderer().parent())) {
- SVGLengthContext lengthContext(textContentElement);
- desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext);
-
- switch (textContentElement->lengthAdjust()) {
- case SVGLengthAdjustUnknown:
- break;
- case SVGLengthAdjustSpacing:
- chunkStyle |= SVGTextChunk::LengthAdjustSpacing;
- break;
- case SVGLengthAdjustSpacingAndGlyphs:
- chunkStyle |= SVGTextChunk::LengthAdjustSpacingAndGlyphs;
- break;
- };
- }
-
- SVGTextChunk chunk(chunkStyle, desiredTextLength);
-
- Vector<SVGInlineTextBox*>& boxes = chunk.boxes();
- for (unsigned i = boxStart; i < boxStart + boxCount; ++i)
- boxes.append(lineLayoutBoxes[i]);
-
- m_textChunks.append(chunk);
+ auto it = m_textBoxTransformations.find(textBox);
+ return it == m_textBoxTransformations.end() ? AffineTransform() : it->value;
}
-void SVGTextChunkBuilder::processTextChunk(const SVGTextChunk& chunk)
+void SVGTextChunkBuilder::buildTextChunks(const Vector<SVGInlineTextBox*>& lineLayoutBoxes)
{
- bool processTextLength = chunk.hasDesiredTextLength();
- bool processTextAnchor = chunk.hasTextAnchor();
- if (!processTextAnchor && !processTextLength)
- return;
-
- const Vector<SVGInlineTextBox*>& boxes = chunk.boxes();
- unsigned boxCount = boxes.size();
- if (!boxCount)
- return;
-
- // Calculate absolute length of whole text chunk (starting from text box 'start', spanning 'length' text boxes).
- float chunkLength = 0;
- unsigned chunkCharacters = 0;
- chunk.calculateLength(chunkLength, chunkCharacters);
-
- bool isVerticalText = chunk.isVerticalText();
- if (processTextLength) {
- if (chunk.hasLengthAdjustSpacing()) {
- float textLengthShift = (chunk.desiredTextLength() - chunkLength) / chunkCharacters;
- unsigned atCharacter = 0;
- for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
- Vector<SVGTextFragment>& fragments = boxes[boxPosition]->textFragments();
- if (fragments.isEmpty())
- continue;
- processTextLengthSpacingCorrection(isVerticalText, textLengthShift, fragments, atCharacter);
- }
- } else {
- ASSERT(chunk.hasLengthAdjustSpacingAndGlyphs());
- float textLengthScale = chunk.desiredTextLength() / chunkLength;
- AffineTransform spacingAndGlyphsTransform;
-
- bool foundFirstFragment = false;
- for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
- SVGInlineTextBox* textBox = boxes[boxPosition];
- Vector<SVGTextFragment>& fragments = textBox->textFragments();
- if (fragments.isEmpty())
- continue;
-
- if (!foundFirstFragment) {
- foundFirstFragment = true;
- buildSpacingAndGlyphsTransform(isVerticalText, textLengthScale, fragments.first(), spacingAndGlyphsTransform);
- }
-
- m_textBoxTransformations.set(textBox, spacingAndGlyphsTransform);
- }
- }
- }
-
- if (!processTextAnchor)
+ if (lineLayoutBoxes.isEmpty())
return;
- // If we previously applied a lengthAdjust="spacing" correction, we have to recalculate the chunk length, to be able to apply the text-anchor shift.
- if (processTextLength && chunk.hasLengthAdjustSpacing()) {
- chunkLength = 0;
- chunkCharacters = 0;
- chunk.calculateLength(chunkLength, chunkCharacters);
- }
+ unsigned limit = lineLayoutBoxes.size();
+ unsigned first = limit;
- float textAnchorShift = chunk.calculateTextAnchorShift(chunkLength);
- for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
- Vector<SVGTextFragment>& fragments = boxes[boxPosition]->textFragments();
- if (fragments.isEmpty())
+ for (unsigned i = 0; i < limit; ++i) {
+ if (!lineLayoutBoxes[i]->startsNewTextChunk())
continue;
- processTextAnchorCorrection(isVerticalText, textAnchorShift, fragments);
- }
-}
-
-void SVGTextChunkBuilder::processTextLengthSpacingCorrection(bool isVerticalText, float textLengthShift, Vector<SVGTextFragment>& fragments, unsigned& atCharacter)
-{
- unsigned fragmentCount = fragments.size();
- for (unsigned i = 0; i < fragmentCount; ++i) {
- SVGTextFragment& fragment = fragments[i];
- if (isVerticalText)
- fragment.y += textLengthShift * atCharacter;
- else
- fragment.x += textLengthShift * atCharacter;
-
- atCharacter += fragment.length;
+ if (first == limit)
+ first = i;
+ else {
+ ASSERT_WITH_SECURITY_IMPLICATION(first != i);
+ m_textChunks.append(SVGTextChunk(lineLayoutBoxes, first, i));
+ first = i;
+ }
}
-}
-void SVGTextChunkBuilder::processTextAnchorCorrection(bool isVerticalText, float textAnchorShift, Vector<SVGTextFragment>& fragments)
-{
- unsigned fragmentCount = fragments.size();
- for (unsigned i = 0; i < fragmentCount; ++i) {
- SVGTextFragment& fragment = fragments[i];
-
- if (isVerticalText)
- fragment.y += textAnchorShift;
- else
- fragment.x += textAnchorShift;
- }
+ if (first != limit)
+ m_textChunks.append(SVGTextChunk(lineLayoutBoxes, first, limit));
}
-void SVGTextChunkBuilder::buildSpacingAndGlyphsTransform(bool isVerticalText, float scale, const SVGTextFragment& fragment, AffineTransform& spacingAndGlyphsTransform)
+void SVGTextChunkBuilder::layoutTextChunks(const Vector<SVGInlineTextBox*>& lineLayoutBoxes)
{
- spacingAndGlyphsTransform.translate(fragment.x, fragment.y);
+ buildTextChunks(lineLayoutBoxes);
+ if (m_textChunks.isEmpty())
+ return;
- if (isVerticalText)
- spacingAndGlyphsTransform.scaleNonUniform(1, scale);
- else
- spacingAndGlyphsTransform.scaleNonUniform(scale, 1);
+ for (const auto& chunk : m_textChunks)
+ chunk.layout(m_textBoxTransformations);
- spacingAndGlyphsTransform.translate(-fragment.x, -fragment.y);
+ m_textChunks.clear();
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGTextChunkBuilder.h b/Source/WebCore/rendering/svg/SVGTextChunkBuilder.h
index 321f3915f..7a7880a87 100644
--- a/Source/WebCore/rendering/svg/SVGTextChunkBuilder.h
+++ b/Source/WebCore/rendering/svg/SVGTextChunkBuilder.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -17,10 +18,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGTextChunkBuilder_h
-#define SVGTextChunkBuilder_h
+#pragma once
-#if ENABLE(SVG)
#include "SVGTextChunk.h"
#include <wtf/Vector.h>
@@ -41,18 +40,13 @@ public:
SVGTextChunkBuilder();
const Vector<SVGTextChunk>& textChunks() const { return m_textChunks; }
- void transformationForTextBox(SVGInlineTextBox*, AffineTransform&) const;
+ unsigned totalCharacters() const;
+ float totalLength() const;
+ float totalAnchorShift() const;
+ AffineTransform transformationForTextBox(SVGInlineTextBox*) const;
- void buildTextChunks(Vector<SVGInlineTextBox*>& lineLayoutBoxes);
- void layoutTextChunks(Vector<SVGInlineTextBox*>& lineLayoutBoxes);
-
-private:
- void addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxes, unsigned boxPosition, unsigned boxCount);
- void processTextChunk(const SVGTextChunk&);
-
- void processTextLengthSpacingCorrection(bool isVerticalText, float textLengthShift, Vector<SVGTextFragment>&, unsigned& atCharacter);
- void processTextAnchorCorrection(bool isVerticalText, float textAnchorShift, Vector<SVGTextFragment>&);
- void buildSpacingAndGlyphsTransform(bool isVerticalText, float scale, const SVGTextFragment&, AffineTransform&);
+ void buildTextChunks(const Vector<SVGInlineTextBox*>& lineLayoutBoxes);
+ void layoutTextChunks(const Vector<SVGInlineTextBox*>& lineLayoutBoxes);
private:
Vector<SVGTextChunk> m_textChunks;
@@ -60,6 +54,3 @@ private:
};
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGTextFragment.h b/Source/WebCore/rendering/svg/SVGTextFragment.h
index a44d0fabc..ad3e9b4c4 100644
--- a/Source/WebCore/rendering/svg/SVGTextFragment.h
+++ b/Source/WebCore/rendering/svg/SVGTextFragment.h
@@ -17,10 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGTextFragment_h
-#define SVGTextFragment_h
+#pragma once
-#if ENABLE(SVG)
#include "AffineTransform.h"
namespace WebCore {
@@ -110,6 +108,3 @@ private:
};
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp
index 05d6cc332..6441272a4 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp
@@ -18,8 +18,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGTextLayoutAttributes.h"
#include <stdio.h>
@@ -74,5 +72,3 @@ void SVGTextLayoutAttributes::dump() const
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h b/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h
index 00d138e53..f72075ea6 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h
@@ -17,10 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGTextLayoutAttributes_h
-#define SVGTextLayoutAttributes_h
+#pragma once
-#if ENABLE(SVG)
#include "SVGTextMetrics.h"
#include <wtf/HashMap.h>
#include <wtf/Noncopyable.h>
@@ -75,6 +73,3 @@ inline SVGCharacterData::SVGCharacterData()
}
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
index 1dbb01fd9..2c068b9c3 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
@@ -18,10 +18,10 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGTextLayoutAttributesBuilder.h"
+#include "RenderChildIterator.h"
+#include "RenderSVGInline.h"
#include "RenderSVGInlineText.h"
#include "RenderSVGText.h"
#include "SVGTextPositioningElement.h"
@@ -35,7 +35,7 @@ SVGTextLayoutAttributesBuilder::SVGTextLayoutAttributesBuilder()
void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer(RenderSVGInlineText& text)
{
- RenderSVGText* textRoot = RenderSVGText::locateRenderSVGTextAncestor(&text);
+ auto* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text);
if (!textRoot)
return;
@@ -43,82 +43,79 @@ void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer(Render
m_characterDataMap.clear();
m_textLength = 0;
- const UChar* lastCharacter = 0;
- collectTextPositioningElements(textRoot, lastCharacter);
+ bool lastCharacterWasSpace = true;
+ collectTextPositioningElements(*textRoot, lastCharacterWasSpace);
if (!m_textLength)
return;
- buildCharacterDataMap(textRoot);
+ buildCharacterDataMap(*textRoot);
}
- m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, &text, m_characterDataMap);
+ m_metricsBuilder.buildMetricsAndLayoutAttributes(*textRoot, &text, m_characterDataMap);
}
-bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesForForSubtree(RenderSVGText* textRoot)
+bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesForForSubtree(RenderSVGText& textRoot)
{
- ASSERT(textRoot);
-
m_characterDataMap.clear();
if (m_textPositions.isEmpty()) {
m_textLength = 0;
- const UChar* lastCharacter = 0;
- collectTextPositioningElements(textRoot, lastCharacter);
+ bool lastCharacterWasSpace = true;
+ collectTextPositioningElements(textRoot, lastCharacterWasSpace);
}
if (!m_textLength)
return false;
buildCharacterDataMap(textRoot);
- m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDataMap);
+ m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, nullptr, m_characterDataMap);
return true;
}
-void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInlineText* text)
+void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInlineText& text)
{
- ASSERT(text);
m_metricsBuilder.measureTextRenderer(text);
}
-static inline void processRenderSVGInlineText(RenderSVGInlineText* text, unsigned& atCharacter, const UChar*& lastCharacter)
+static inline void processRenderSVGInlineText(const RenderSVGInlineText& text, unsigned& atCharacter, bool& lastCharacterWasSpace)
{
- if (text->style().whiteSpace() == PRE) {
- atCharacter += text->textLength();
+ if (text.style().whiteSpace() == PRE) {
+ atCharacter += text.textLength();
return;
}
- const UChar* characters = text->deprecatedCharacters();
- unsigned textLength = text->textLength();
- for (unsigned textPosition = 0; textPosition < textLength; ++textPosition) {
- const UChar* currentCharacter = characters + textPosition;
- if (*currentCharacter == ' ' && (!lastCharacter || *lastCharacter == ' '))
+ for (unsigned textPosition = 0, textLength = text.textLength(); textPosition < textLength; ++textPosition) {
+ const UChar currentCharacter = text[textPosition];
+ if (currentCharacter == ' ' && lastCharacterWasSpace)
continue;
- lastCharacter = currentCharacter;
+ lastCharacterWasSpace = currentCharacter == ' ';
++atCharacter;
}
}
-void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderObject* start, const UChar*& lastCharacter)
+void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderBoxModelObject& start, bool& lastCharacterWasSpace)
{
- ASSERT(!start->isSVGText() || m_textPositions.isEmpty());
+ ASSERT(!is<RenderSVGText>(start) || m_textPositions.isEmpty());
- for (RenderObject* child = start->firstChildSlow(); child; child = child->nextSibling()) {
- if (child->isSVGInlineText()) {
- processRenderSVGInlineText(toRenderSVGInlineText(child), m_textLength, lastCharacter);
+ for (auto& child : childrenOfType<RenderObject>(start)) {
+ if (is<RenderSVGInlineText>(child)) {
+ processRenderSVGInlineText(downcast<RenderSVGInlineText>(child), m_textLength, lastCharacterWasSpace);
continue;
}
- if (!child->isSVGInline())
+ if (!is<RenderSVGInline>(child))
continue;
- SVGTextPositioningElement* element = SVGTextPositioningElement::elementFromRenderer(child);
+ auto& inlineChild = downcast<RenderSVGInline>(child);
+ SVGTextPositioningElement* element = SVGTextPositioningElement::elementFromRenderer(inlineChild);
+
unsigned atPosition = m_textPositions.size();
if (element)
m_textPositions.append(TextPosition(element, m_textLength));
- collectTextPositioningElements(child, lastCharacter);
+ collectTextPositioningElements(inlineChild, lastCharacterWasSpace);
if (!element)
continue;
@@ -130,7 +127,7 @@ void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderObject
}
}
-void SVGTextLayoutAttributesBuilder::buildCharacterDataMap(RenderSVGText* textRoot)
+void SVGTextLayoutAttributesBuilder::buildCharacterDataMap(RenderSVGText& textRoot)
{
SVGTextPositioningElement* outermostTextElement = SVGTextPositioningElement::elementFromRenderer(textRoot);
ASSERT(outermostTextElement);
@@ -160,7 +157,7 @@ void SVGTextLayoutAttributesBuilder::buildCharacterDataMap(RenderSVGText* textRo
fillCharacterDataMap(m_textPositions[i]);
}
-static inline void updateCharacterData(unsigned i, float& lastRotation, SVGCharacterData& data, const SVGLengthContext& lengthContext, const SVGLengthList* xList, const SVGLengthList* yList, const SVGLengthList* dxList, const SVGLengthList* dyList, const SVGNumberList* rotateList)
+static inline void updateCharacterData(unsigned i, float& lastRotation, SVGCharacterData& data, const SVGLengthContext& lengthContext, const SVGLengthListValues* xList, const SVGLengthListValues* yList, const SVGLengthListValues* dxList, const SVGLengthListValues* dyList, const SVGNumberListValues* rotateList)
{
if (xList)
data.x = xList->at(i).value(lengthContext);
@@ -178,11 +175,11 @@ static inline void updateCharacterData(unsigned i, float& lastRotation, SVGChara
void SVGTextLayoutAttributesBuilder::fillCharacterDataMap(const TextPosition& position)
{
- const SVGLengthList& xList = position.element->x();
- const SVGLengthList& yList = position.element->y();
- const SVGLengthList& dxList = position.element->dx();
- const SVGLengthList& dyList = position.element->dy();
- const SVGNumberList& rotateList = position.element->rotate();
+ const auto& xList = position.element->x();
+ const auto& yList = position.element->y();
+ const auto& dxList = position.element->dx();
+ const auto& dyList = position.element->dy();
+ const auto& rotateList = position.element->rotate();
unsigned xListSize = xList.size();
unsigned yListSize = yList.size();
@@ -195,11 +192,11 @@ void SVGTextLayoutAttributesBuilder::fillCharacterDataMap(const TextPosition& po
float lastRotation = SVGTextLayoutAttributes::emptyValue();
SVGLengthContext lengthContext(position.element);
for (unsigned i = 0; i < position.length; ++i) {
- const SVGLengthList* xListPtr = i < xListSize ? &xList : 0;
- const SVGLengthList* yListPtr = i < yListSize ? &yList : 0;
- const SVGLengthList* dxListPtr = i < dxListSize ? &dxList : 0;
- const SVGLengthList* dyListPtr = i < dyListSize ? &dyList : 0;
- const SVGNumberList* rotateListPtr = i < rotateListSize ? &rotateList : 0;
+ const SVGLengthListValues* xListPtr = i < xListSize ? &xList : 0;
+ const SVGLengthListValues* yListPtr = i < yListSize ? &yList : 0;
+ const SVGLengthListValues* dxListPtr = i < dxListSize ? &dxList : 0;
+ const SVGLengthListValues* dyListPtr = i < dyListSize ? &dyList : 0;
+ const SVGNumberListValues* rotateListPtr = i < rotateListSize ? &rotateList : 0;
if (!xListPtr && !yListPtr && !dxListPtr && !dyListPtr && !rotateListPtr)
break;
@@ -232,5 +229,3 @@ void SVGTextLayoutAttributesBuilder::fillCharacterDataMap(const TextPosition& po
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h
index 5aa60e923..99c5f422d 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h
@@ -17,14 +17,13 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGTextLayoutAttributesBuilder_h
-#define SVGTextLayoutAttributesBuilder_h
+#pragma once
-#if ENABLE(SVG)
#include "SVGTextMetricsBuilder.h"
namespace WebCore {
+class RenderBoxModelObject;
class RenderObject;
class RenderSVGInlineText;
class RenderSVGText;
@@ -42,10 +41,10 @@ class SVGTextLayoutAttributesBuilder {
WTF_MAKE_NONCOPYABLE(SVGTextLayoutAttributesBuilder);
public:
SVGTextLayoutAttributesBuilder();
- bool buildLayoutAttributesForForSubtree(RenderSVGText*);
+ bool buildLayoutAttributesForForSubtree(RenderSVGText&);
void buildLayoutAttributesForTextRenderer(RenderSVGInlineText&);
- void rebuildMetricsForTextRenderer(RenderSVGInlineText*);
+ void rebuildMetricsForTextRenderer(RenderSVGInlineText&);
// Invoked whenever the underlying DOM tree changes, so that m_textPositions is rebuild.
void clearTextPositioningElements() { m_textPositions.clear(); }
@@ -65,8 +64,8 @@ private:
unsigned length;
};
- void buildCharacterDataMap(RenderSVGText*);
- void collectTextPositioningElements(RenderObject*, const UChar*& lastCharacter);
+ void buildCharacterDataMap(RenderSVGText&);
+ void collectTextPositioningElements(RenderBoxModelObject&, bool& lastCharacterWasSpace);
void fillCharacterDataMap(const TextPosition&);
private:
@@ -77,6 +76,3 @@ private:
};
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp
index aec25e146..0a0c3cd0b 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp
@@ -18,10 +18,9 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGTextLayoutEngine.h"
+#include "PathTraversalState.h"
#include "RenderSVGTextPath.h"
#include "SVGElement.h"
#include "SVGInlineTextBox.h"
@@ -111,7 +110,7 @@ void SVGTextLayoutEngine::updateRelativePositionAdjustmentsIfNeeded(float dx, fl
m_dy = dy;
}
-void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox, Vector<SVGTextMetrics>& textMetricsValues)
+void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox& textBox, Vector<SVGTextMetrics>& textMetricsValues)
{
ASSERT(!m_currentTextFragment.length);
ASSERT(m_visualMetricsListOffset > 0);
@@ -138,7 +137,7 @@ void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox, Vector<S
}
}
- textBox->textFragments().append(m_currentTextFragment);
+ textBox.textFragments().append(m_currentTextFragment);
m_currentTextFragment = SVGTextFragment();
}
@@ -162,58 +161,39 @@ bool SVGTextLayoutEngine::parentDefinesTextLength(RenderObject* parent) const
return false;
}
-void SVGTextLayoutEngine::beginTextPathLayout(RenderObject* object, SVGTextLayoutEngine& lineLayout)
+void SVGTextLayoutEngine::beginTextPathLayout(RenderSVGTextPath& textPath, SVGTextLayoutEngine& lineLayout)
{
- ASSERT(object);
-
m_inPathLayout = true;
- RenderSVGTextPath* textPath = toRenderSVGTextPath(object);
- m_textPath = textPath->layoutPath();
+ m_textPath = textPath.layoutPath();
if (m_textPath.isEmpty())
return;
- m_textPathStartOffset = textPath->startOffset();
+
+ m_textPathStartOffset = textPath.startOffset();
m_textPathLength = m_textPath.length();
if (m_textPathStartOffset > 0 && m_textPathStartOffset <= 1)
m_textPathStartOffset *= m_textPathLength;
- float totalLength = 0;
- unsigned totalCharacters = 0;
-
lineLayout.m_chunkLayoutBuilder.buildTextChunks(lineLayout.m_lineLayoutBoxes);
- const Vector<SVGTextChunk>& textChunks = lineLayout.m_chunkLayoutBuilder.textChunks();
-
- unsigned size = textChunks.size();
- for (unsigned i = 0; i < size; ++i) {
- const SVGTextChunk& chunk = textChunks.at(i);
-
- float length = 0;
- unsigned characters = 0;
- chunk.calculateLength(length, characters);
-
- // Handle text-anchor as additional start offset for text paths.
- m_textPathStartOffset += chunk.calculateTextAnchorShift(length);
-
- totalLength += length;
- totalCharacters += characters;
- }
+ // Handle text-anchor as additional start offset for text paths.
+ m_textPathStartOffset += lineLayout.m_chunkLayoutBuilder.totalAnchorShift();
m_textPathCurrentOffset = m_textPathStartOffset;
// Eventually handle textLength adjustments.
- SVGLengthAdjustType lengthAdjust = SVGLengthAdjustUnknown;
- float desiredTextLength = 0;
-
- if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textPath)) {
- SVGLengthContext lengthContext(textContentElement);
- lengthAdjust = textContentElement->lengthAdjust();
- desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext);
- }
+ auto* textContentElement = SVGTextContentElement::elementFromRenderer(&textPath);
+ if (!textContentElement)
+ return;
+ SVGLengthContext lengthContext(textContentElement);
+ float desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext);
if (!desiredTextLength)
return;
- if (lengthAdjust == SVGLengthAdjustSpacing)
+ float totalLength = lineLayout.m_chunkLayoutBuilder.totalLength();
+ unsigned totalCharacters = lineLayout.m_chunkLayoutBuilder.totalCharacters();
+
+ if (textContentElement->lengthAdjust() == SVGLengthAdjustSpacing)
m_textPathSpacing = (desiredTextLength - totalLength) / totalCharacters;
else
m_textPathScaling = desiredTextLength / totalLength;
@@ -230,27 +210,25 @@ void SVGTextLayoutEngine::endTextPathLayout()
m_textPathScaling = 1;
}
-void SVGTextLayoutEngine::layoutInlineTextBox(SVGInlineTextBox* textBox)
+void SVGTextLayoutEngine::layoutInlineTextBox(SVGInlineTextBox& textBox)
{
- ASSERT(textBox);
-
- RenderSVGInlineText& text = textBox->renderer();
+ RenderSVGInlineText& text = textBox.renderer();
ASSERT(text.parent());
ASSERT(text.parent()->element());
ASSERT(text.parent()->element()->isSVGElement());
const RenderStyle& style = text.style();
- textBox->clearTextFragments();
- m_isVerticalText = style.svgStyle().isVerticalWritingMode();
- layoutTextOnLineOrPath(textBox, &text, &style);
+ textBox.clearTextFragments();
+ m_isVerticalText = style.isVerticalWritingMode();
+ layoutTextOnLineOrPath(textBox, text, style);
if (m_inPathLayout) {
- m_pathLayoutBoxes.append(textBox);
+ m_pathLayoutBoxes.append(&textBox);
return;
}
- m_lineLayoutBoxes.append(textBox);
+ m_lineLayoutBoxes.append(&textBox);
}
#if DUMP_TEXT_FRAGMENTS > 0
@@ -292,7 +270,7 @@ void SVGTextLayoutEngine::finalizeTransformMatrices(Vector<SVGInlineTextBox*>& b
unsigned fragmentCount = fragments.size();
for (unsigned i = 0; i < fragmentCount; ++i) {
- m_chunkLayoutBuilder.transformationForTextBox(textBox, textBoxTransformation);
+ textBoxTransformation = m_chunkLayoutBuilder.transformationForTextBox(textBox);
if (textBoxTransformation.isIdentity())
continue;
ASSERT(fragments[i].lengthAdjustTransform.isIdentity());
@@ -380,12 +358,12 @@ bool SVGTextLayoutEngine::currentLogicalCharacterMetrics(SVGTextLayoutAttributes
return true;
}
-bool SVGTextLayoutEngine::currentVisualCharacterMetrics(SVGInlineTextBox* textBox, Vector<SVGTextMetrics>& visualMetricsValues, SVGTextMetrics& visualMetrics)
+bool SVGTextLayoutEngine::currentVisualCharacterMetrics(const SVGInlineTextBox& textBox, Vector<SVGTextMetrics>& visualMetricsValues, SVGTextMetrics& visualMetrics)
{
ASSERT(!visualMetricsValues.isEmpty());
unsigned textMetricsSize = visualMetricsValues.size();
- unsigned boxStart = textBox->start();
- unsigned boxLength = textBox->len();
+ unsigned boxStart = textBox.start();
+ unsigned boxLength = textBox.len();
if (m_visualMetricsListOffset == textMetricsSize)
return false;
@@ -420,26 +398,28 @@ void SVGTextLayoutEngine::advanceToNextVisualCharacter(const SVGTextMetrics& vis
m_visualCharacterOffset += visualMetrics.length();
}
-void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, RenderSVGInlineText* text, const RenderStyle* style)
+void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox& textBox, RenderSVGInlineText& text, const RenderStyle& style)
{
if (m_inPathLayout && m_textPath.isEmpty())
return;
- SVGElement* lengthContext = toSVGElement(text->parent()->element());
+ RenderElement* textParent = text.parent();
+ ASSERT(textParent);
+ SVGElement* lengthContext = downcast<SVGElement>(textParent->element());
- RenderObject* textParent = text->parent();
- bool definesTextLength = textParent ? parentDefinesTextLength(textParent) : false;
+ bool definesTextLength = parentDefinesTextLength(textParent);
- const SVGRenderStyle& svgStyle = style->svgStyle();
+ const SVGRenderStyle& svgStyle = style.svgStyle();
m_visualMetricsListOffset = 0;
m_visualCharacterOffset = 0;
- Vector<SVGTextMetrics>& visualMetricsValues = text->layoutAttributes()->textMetricsValues();
+ Vector<SVGTextMetrics>& visualMetricsValues = text.layoutAttributes()->textMetricsValues();
ASSERT(!visualMetricsValues.isEmpty());
- const UChar* characters = text->deprecatedCharacters();
- const Font& font = style->font();
+ auto upconvertedCharacters = StringView(text.text()).upconvertedCharacters();
+ const UChar* characters = upconvertedCharacters;
+ const FontCascade& font = style.fontCascade();
SVGTextLayoutEngineSpacing spacingLayout(font);
SVGTextLayoutEngineBaseline baselineLayout(font);
@@ -448,7 +428,7 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
bool applySpacingToNextCharacter = false;
float lastAngle = 0;
- float baselineShift = baselineLayout.calculateBaselineShift(&svgStyle, lengthContext);
+ float baselineShift = baselineLayout.calculateBaselineShift(svgStyle, lengthContext);
baselineShift -= baselineLayout.calculateAlignmentBaselineShift(m_isVerticalText, text);
// Main layout algorithm.
@@ -481,16 +461,16 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
float x = data.x;
float y = data.y;
- // When we've advanced to the box start offset, determine using the original x/y values,
- // whether this character starts a new text chunk, before doing any further processing.
- if (m_visualCharacterOffset == textBox->start())
- textBox->setStartsNewTextChunk(logicalAttributes->context().characterStartsNewTextChunk(m_logicalCharacterOffset));
+ // When we've advanced to the box start offset, determine using the original x/y values
+ // whether this character starts a new text chunk before doing any further processing.
+ if (m_visualCharacterOffset == textBox.start())
+ textBox.setStartsNewTextChunk(logicalAttributes->context().characterStartsNewTextChunk(m_logicalCharacterOffset));
float angle = data.rotate == SVGTextLayoutAttributes::emptyValue() ? 0 : data.rotate;
// Calculate glyph orientation angle.
const UChar* currentCharacter = characters + m_visualCharacterOffset;
- float orientationAngle = baselineLayout.calculateGlyphOrientationAngle(m_isVerticalText, &svgStyle, *currentCharacter);
+ float orientationAngle = baselineLayout.calculateGlyphOrientationAngle(m_isVerticalText, svgStyle, *currentCharacter);
// Calculate glyph advance & x/y orientation shifts.
float xOrientationShift = 0;
@@ -503,9 +483,6 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
// Apply dx/dy value adjustments to current text position, if needed.
updateRelativePositionAdjustmentsIfNeeded(data.dx, data.dy);
- // Calculate SVG Fonts kerning, if needed.
- float kerning = spacingLayout.calculateSVGKerning(m_isVerticalText, visualMetrics.glyph());
-
// Calculate CSS 'kerning', 'letter-spacing' and 'word-spacing' for next character, if needed.
float spacing = spacingLayout.calculateCSSKerningAndSpacing(&svgStyle, lengthContext, currentCharacter);
@@ -517,7 +494,7 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
if (y != SVGTextLayoutAttributes::emptyValue())
m_textPathCurrentOffset = y + m_textPathStartOffset;
- m_textPathCurrentOffset += m_dy - kerning;
+ m_textPathCurrentOffset += m_dy;
m_dy = 0;
// Apply dx/dy correction and setup translations that move to the glyph midpoint.
@@ -528,7 +505,7 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
if (x != SVGTextLayoutAttributes::emptyValue())
m_textPathCurrentOffset = x + m_textPathStartOffset;
- m_textPathCurrentOffset += m_dx - kerning;
+ m_textPathCurrentOffset += m_dx;
m_dx = 0;
// Apply dx/dy correction and setup translations that move to the glyph midpoint.
@@ -553,27 +530,25 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
if (textPathOffset > m_textPathLength)
break;
- bool ok = false;
- FloatPoint point = m_textPath.pointAtLength(textPathOffset, ok);
- ASSERT(ok);
+ bool success = false;
+ auto traversalState(m_textPath.traversalStateAtLength(textPathOffset, success));
+ ASSERT(success);
+ FloatPoint point = traversalState.current();
x = point.x();
y = point.y();
- angle = m_textPath.normalAngleAtLength(textPathOffset, ok);
- ASSERT(ok);
+
+ angle = traversalState.normalAngle();
// For vertical text on path, the actual angle has to be rotated 90 degrees anti-clockwise, not the orientation angle!
if (m_isVerticalText)
angle -= 90;
} else {
// Apply all previously calculated shift values.
- if (m_isVerticalText) {
+ if (m_isVerticalText)
x += baselineShift;
- y -= kerning;
- } else {
- x -= kerning;
+ else
y -= baselineShift;
- }
x += m_dx;
y += m_dy;
@@ -581,7 +556,7 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
// Determine whether we have to start a new fragment.
bool shouldStartNewFragment = m_dx || m_dy || m_isVerticalText || m_inPathLayout || angle || angle != lastAngle
- || orientationAngle || kerning || applySpacingToNextCharacter || definesTextLength;
+ || orientationAngle || applySpacingToNextCharacter || definesTextLength;
// If we already started a fragment, close it now.
if (didStartTextFragment && shouldStartNewFragment) {
@@ -651,5 +626,3 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutEngine.h b/Source/WebCore/rendering/svg/SVGTextLayoutEngine.h
index c4a926400..3fcfdb4f0 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutEngine.h
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngine.h
@@ -17,10 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGTextLayoutEngine_h
-#define SVGTextLayoutEngine_h
+#pragma once
-#if ENABLE(SVG)
#include "Path.h"
#include "SVGTextChunkBuilder.h"
#include "SVGTextFragment.h"
@@ -31,6 +29,7 @@ namespace WebCore {
class RenderObject;
class RenderStyle;
class RenderSVGInlineText;
+class RenderSVGTextPath;
class SVGElement;
class SVGInlineTextBox;
class SVGRenderStyle;
@@ -51,10 +50,10 @@ public:
Vector<SVGTextLayoutAttributes*>& layoutAttributes() { return m_layoutAttributes; }
SVGTextChunkBuilder& chunkLayoutBuilder() { return m_chunkLayoutBuilder; }
- void beginTextPathLayout(RenderObject*, SVGTextLayoutEngine& lineLayout);
+ void beginTextPathLayout(RenderSVGTextPath&, SVGTextLayoutEngine& lineLayout);
void endTextPathLayout();
- void layoutInlineTextBox(SVGInlineTextBox*);
+ void layoutInlineTextBox(SVGInlineTextBox&);
void finishLayout();
private:
@@ -62,15 +61,15 @@ private:
void updateCurrentTextPosition(float x, float y, float glyphAdvance);
void updateRelativePositionAdjustmentsIfNeeded(float dx, float dy);
- void recordTextFragment(SVGInlineTextBox*, Vector<SVGTextMetrics>&);
+ void recordTextFragment(SVGInlineTextBox&, Vector<SVGTextMetrics>&);
bool parentDefinesTextLength(RenderObject*) const;
- void layoutTextOnLineOrPath(SVGInlineTextBox*, RenderSVGInlineText*, const RenderStyle*);
+ void layoutTextOnLineOrPath(SVGInlineTextBox&, RenderSVGInlineText&, const RenderStyle&);
void finalizeTransformMatrices(Vector<SVGInlineTextBox*>&);
bool currentLogicalCharacterAttributes(SVGTextLayoutAttributes*&);
bool currentLogicalCharacterMetrics(SVGTextLayoutAttributes*&, SVGTextMetrics&);
- bool currentVisualCharacterMetrics(SVGInlineTextBox*, Vector<SVGTextMetrics>&, SVGTextMetrics&);
+ bool currentVisualCharacterMetrics(const SVGInlineTextBox&, Vector<SVGTextMetrics>&, SVGTextMetrics&);
void advanceToNextLogicalCharacter(const SVGTextMetrics&);
void advanceToNextVisualCharacter(const SVGTextMetrics&);
@@ -105,6 +104,3 @@ private:
};
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp
index 0497a3456..e0377167f 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp
@@ -18,11 +18,9 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGTextLayoutEngineBaseline.h"
-#include "Font.h"
+#include "FontCascade.h"
#include "RenderElement.h"
#include "SVGLengthContext.h"
#include "SVGRenderStyle.h"
@@ -30,33 +28,34 @@
namespace WebCore {
-SVGTextLayoutEngineBaseline::SVGTextLayoutEngineBaseline(const Font& font)
+SVGTextLayoutEngineBaseline::SVGTextLayoutEngineBaseline(const FontCascade& font)
: m_font(font)
{
}
-float SVGTextLayoutEngineBaseline::calculateBaselineShift(const SVGRenderStyle* style, SVGElement* contextElement) const
+float SVGTextLayoutEngineBaseline::calculateBaselineShift(const SVGRenderStyle& style, SVGElement* context) const
{
- if (style->baselineShift() == BS_LENGTH) {
- SVGLength baselineShiftValueLength = style->baselineShiftValue();
+ if (style.baselineShift() == BS_LENGTH) {
+ auto baselineShiftValueLength = style.baselineShiftValue();
if (baselineShiftValueLength.unitType() == LengthTypePercentage)
return baselineShiftValueLength.valueAsPercentage() * m_font.pixelSize();
- SVGLengthContext lengthContext(contextElement);
+ SVGLengthContext lengthContext(context);
return baselineShiftValueLength.value(lengthContext);
}
- switch (style->baselineShift()) {
+ switch (style.baselineShift()) {
case BS_BASELINE:
return 0;
case BS_SUB:
return -m_font.fontMetrics().floatHeight() / 2;
case BS_SUPER:
return m_font.fontMetrics().floatHeight() / 2;
- default:
- ASSERT_NOT_REACHED();
- return 0;
+ case BS_LENGTH:
+ break;
}
+ ASSERT_NOT_REACHED();
+ return 0;
}
EAlignmentBaseline SVGTextLayoutEngineBaseline::dominantBaselineToAlignmentBaseline(bool isVerticalText, const RenderObject* textRenderer) const
@@ -104,15 +103,12 @@ EAlignmentBaseline SVGTextLayoutEngineBaseline::dominantBaselineToAlignmentBasel
}
}
-float SVGTextLayoutEngineBaseline::calculateAlignmentBaselineShift(bool isVerticalText, const RenderObject* textRenderer) const
+float SVGTextLayoutEngineBaseline::calculateAlignmentBaselineShift(bool isVerticalText, const RenderObject& textRenderer) const
{
- ASSERT(textRenderer);
- ASSERT(textRenderer->parent());
-
- const RenderObject* textRendererParent = textRenderer->parent();
+ const RenderObject* textRendererParent = textRenderer.parent();
ASSERT(textRendererParent);
- EAlignmentBaseline baseline = textRenderer->style().svgStyle().alignmentBaseline();
+ EAlignmentBaseline baseline = textRenderer.style().svgStyle().alignmentBaseline();
if (baseline == AB_AUTO) {
baseline = dominantBaselineToAlignmentBaseline(isVerticalText, textRendererParent);
ASSERT(baseline != AB_AUTO);
@@ -147,11 +143,9 @@ float SVGTextLayoutEngineBaseline::calculateAlignmentBaselineShift(bool isVertic
}
}
-float SVGTextLayoutEngineBaseline::calculateGlyphOrientationAngle(bool isVerticalText, const SVGRenderStyle* style, const UChar& character) const
+float SVGTextLayoutEngineBaseline::calculateGlyphOrientationAngle(bool isVerticalText, const SVGRenderStyle& style, const UChar& character) const
{
- ASSERT(style);
-
- switch (isVerticalText ? style->glyphOrientationVertical() : style->glyphOrientationHorizontal()) {
+ switch (isVerticalText ? style.glyphOrientationVertical() : style.glyphOrientationHorizontal()) {
case GO_AUTO:
// Spec: Fullwidth ideographic and fullwidth Latin text will be set with a glyph-orientation of 0-degrees.
// Text which is not fullwidth will be set with a glyph-orientation of 90-degrees.
@@ -240,5 +234,3 @@ float SVGTextLayoutEngineBaseline::calculateGlyphAdvanceAndOrientation(bool isVe
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.h b/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.h
index 6794bf3f8..44d7f73d2 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.h
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.h
@@ -17,16 +17,14 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGTextLayoutEngineBaseline_h
-#define SVGTextLayoutEngineBaseline_h
+#pragma once
-#if ENABLE(SVG)
#include "SVGRenderStyleDefs.h"
#include <wtf/Noncopyable.h>
namespace WebCore {
-class Font;
+class FontCascade;
class RenderObject;
class SVGElement;
class SVGRenderStyle;
@@ -36,20 +34,17 @@ class SVGTextMetrics;
class SVGTextLayoutEngineBaseline {
WTF_MAKE_NONCOPYABLE(SVGTextLayoutEngineBaseline);
public:
- SVGTextLayoutEngineBaseline(const Font&);
+ SVGTextLayoutEngineBaseline(const FontCascade&);
- float calculateBaselineShift(const SVGRenderStyle*, SVGElement* lengthContext) const;
- float calculateAlignmentBaselineShift(bool isVerticalText, const RenderObject* textRenderer) const;
- float calculateGlyphOrientationAngle(bool isVerticalText, const SVGRenderStyle*, const UChar& character) const;
+ float calculateBaselineShift(const SVGRenderStyle&, SVGElement* context) const;
+ float calculateAlignmentBaselineShift(bool isVerticalText, const RenderObject& textRenderer) const;
+ float calculateGlyphOrientationAngle(bool isVerticalText, const SVGRenderStyle&, const UChar& character) const;
float calculateGlyphAdvanceAndOrientation(bool isVerticalText, SVGTextMetrics&, float angle, float& xOrientationShift, float& yOrientationShift) const;
private:
EAlignmentBaseline dominantBaselineToAlignmentBaseline(bool isVerticalText, const RenderObject* textRenderer) const;
- const Font& m_font;
+ const FontCascade& m_font;
};
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.cpp
index f0107c4ab..48d80ae99 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.cpp
@@ -18,73 +18,29 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGTextLayoutEngineSpacing.h"
-#include "Font.h"
+#include "FontCascade.h"
#include "SVGLengthContext.h"
#include "SVGRenderStyle.h"
#if ENABLE(SVG_FONTS)
-#include "SVGFontData.h"
#include "SVGFontElement.h"
#include "SVGFontFaceElement.h"
#endif
namespace WebCore {
-SVGTextLayoutEngineSpacing::SVGTextLayoutEngineSpacing(const Font& font)
+SVGTextLayoutEngineSpacing::SVGTextLayoutEngineSpacing(const FontCascade& font)
: m_font(font)
, m_lastCharacter(0)
{
}
-float SVGTextLayoutEngineSpacing::calculateSVGKerning(bool isVerticalText, const SVGTextMetrics::Glyph& currentGlyph)
-{
-#if ENABLE(SVG_FONTS)
- const SimpleFontData* fontData = m_font.primaryFont();
- if (!fontData->isSVGFont()) {
- m_lastGlyph.isValid = false;
- return 0;
- }
-
- ASSERT(fontData->isCustomFont());
- ASSERT(fontData->isSVGFont());
-
- const SVGFontData* svgFontData = static_cast<const SVGFontData*>(fontData->fontData());
- SVGFontFaceElement* svgFontFace = svgFontData->svgFontFaceElement();
- ASSERT(svgFontFace);
-
- SVGFontElement* svgFont = svgFontFace->associatedFontElement();
- if (!svgFont) {
- m_lastGlyph.isValid = false;
- return 0;
- }
-
- float kerning = 0;
- if (m_lastGlyph.isValid) {
- if (isVerticalText)
- kerning = svgFont->verticalKerningForPairOfStringsAndGlyphs(m_lastGlyph.unicodeString, m_lastGlyph.name, currentGlyph.unicodeString, currentGlyph.name);
- else
- kerning = svgFont->horizontalKerningForPairOfStringsAndGlyphs(m_lastGlyph.unicodeString, m_lastGlyph.name, currentGlyph.unicodeString, currentGlyph.name);
- }
-
- m_lastGlyph = currentGlyph;
- m_lastGlyph.isValid = true;
- kerning *= m_font.size() / m_font.fontMetrics().unitsPerEm();
- return kerning;
-#else
- UNUSED_PARAM(isVerticalText);
- UNUSED_PARAM(currentGlyph);
- return false;
-#endif
-}
-
float SVGTextLayoutEngineSpacing::calculateCSSKerningAndSpacing(const SVGRenderStyle* style, SVGElement* contextElement, const UChar* currentCharacter)
{
float kerning = 0;
- SVGLength kerningLength = style->kerning();
+ auto kerningLength = style->kerning();
if (kerningLength.unitType() == LengthTypePercentage)
kerning = kerningLength.valueAsPercentage() * m_font.pixelSize();
else {
@@ -100,7 +56,7 @@ float SVGTextLayoutEngineSpacing::calculateCSSKerningAndSpacing(const SVGRenderS
float spacing = m_font.letterSpacing() + kerning;
if (currentCharacter && lastCharacter && m_font.wordSpacing()) {
- if (Font::treatAsSpace(*currentCharacter) && !Font::treatAsSpace(*lastCharacter))
+ if (FontCascade::treatAsSpace(*currentCharacter) && !FontCascade::treatAsSpace(*lastCharacter))
spacing += m_font.wordSpacing();
}
@@ -108,5 +64,3 @@ float SVGTextLayoutEngineSpacing::calculateCSSKerningAndSpacing(const SVGRenderS
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.h b/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.h
index 71d470737..8e98f2c87 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.h
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.h
@@ -17,15 +17,13 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGTextLayoutEngineSpacing_h
-#define SVGTextLayoutEngineSpacing_h
+#pragma once
-#if ENABLE(SVG)
#include "SVGTextMetrics.h"
namespace WebCore {
-class Font;
+class FontCascade;
class SVGRenderStyle;
class SVGElement;
@@ -33,21 +31,13 @@ class SVGElement;
class SVGTextLayoutEngineSpacing {
WTF_MAKE_NONCOPYABLE(SVGTextLayoutEngineSpacing);
public:
- SVGTextLayoutEngineSpacing(const Font&);
+ SVGTextLayoutEngineSpacing(const FontCascade&);
- float calculateSVGKerning(bool isVerticalText, const SVGTextMetrics::Glyph& currentGlyph);
float calculateCSSKerningAndSpacing(const SVGRenderStyle*, SVGElement* lengthContext, const UChar* currentCharacter);
private:
- const Font& m_font;
+ const FontCascade& m_font;
const UChar* m_lastCharacter;
-
-#if ENABLE(SVG_FONTS)
- SVGTextMetrics::Glyph m_lastGlyph;
-#endif
};
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGTextMetrics.cpp b/Source/WebCore/rendering/svg/SVGTextMetrics.cpp
index 0e6446e31..7627fe553 100644
--- a/Source/WebCore/rendering/svg/SVGTextMetrics.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextMetrics.cpp
@@ -18,12 +18,9 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGTextMetrics.h"
#include "RenderSVGInlineText.h"
-#include "SVGTextRunRenderingContext.h"
#include "WidthIterator.h"
namespace WebCore {
@@ -42,18 +39,18 @@ SVGTextMetrics::SVGTextMetrics(SVGTextMetrics::MetricsType)
{
}
-SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* textRenderer, const TextRun& run)
+SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText& textRenderer, const TextRun& run)
{
- ASSERT(textRenderer);
-
- float scalingFactor = textRenderer->scalingFactor();
+ float scalingFactor = textRenderer.scalingFactor();
ASSERT(scalingFactor);
- const Font& scaledFont = textRenderer->scaledFont();
+ const FontCascade& scaledFont = textRenderer.scaledFont();
int length = 0;
// Calculate width/height using the scaled font, divide this result by the scalingFactor afterwards.
- m_width = scaledFont.width(run, length, m_glyph.name) / scalingFactor;
+ m_width = scaledFont.width(run) / scalingFactor;
+ length = run.length();
+ m_glyph.name = emptyString();
m_height = scaledFont.fontMetrics().floatHeight() / scalingFactor;
m_glyph.unicodeString = run.is8Bit() ? String(run.characters8(), length) : String(run.characters16(), length);
@@ -63,57 +60,40 @@ SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* textRenderer, const TextRun&
m_length = static_cast<unsigned>(length);
}
-TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, const UChar* characters, unsigned position, unsigned length)
+TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText& text, unsigned position, unsigned length)
{
- const RenderStyle& style = text->style();
+ const RenderStyle& style = text.style();
- TextRun run(characters + position
- , length
+ TextRun run(StringView(text.text()).substring(position, length)
, 0 /* xPos, only relevant with allowTabs=true */
, 0 /* padding, only relevant for justified text, not relevant for SVG */
- , TextRun::AllowTrailingExpansion
+ , AllowTrailingExpansion
, style.direction()
, isOverride(style.unicodeBidi()) /* directionalOverride */);
- if (style.font().isSVGFont())
- run.setRenderingContext(SVGTextRunRenderingContext::create(*text));
-
- run.disableRoundingHacks();
-
// We handle letter & word spacing ourselves.
run.disableSpacing();
// Propagate the maximum length of the characters buffer to the TextRun, even when we're only processing a substring.
- run.setCharactersLength(text->textLength() - position);
+ run.setCharactersLength(text.textLength() - position);
ASSERT(run.charactersLength() >= run.length());
return run;
}
-SVGTextMetrics SVGTextMetrics::measureCharacterRange(RenderSVGInlineText* text, unsigned position, unsigned length)
+SVGTextMetrics SVGTextMetrics::measureCharacterRange(RenderSVGInlineText& text, unsigned position, unsigned length)
{
- ASSERT(text);
- return SVGTextMetrics(text, constructTextRun(text, text->deprecatedCharacters(), position, length));
+ return SVGTextMetrics(text, constructTextRun(text, position, length));
}
-SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* text, unsigned position, unsigned length, float width, const String& glyphName)
+SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText& text, unsigned length, float width)
{
- ASSERT(text);
-
- bool needsContext = text->style().font().isSVGFont();
- float scalingFactor = text->scalingFactor();
+ float scalingFactor = text.scalingFactor();
ASSERT(scalingFactor);
m_width = width / scalingFactor;
- m_height = text->scaledFont().fontMetrics().floatHeight() / scalingFactor;
- if (needsContext) {
- m_glyph.isValid = true;
- m_glyph.unicodeString = String(text->deprecatedCharacters() + position, length);
- m_glyph.name = glyphName;
- }
+ m_height = text.scaledFont().fontMetrics().floatHeight() / scalingFactor;
m_length = length;
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGTextMetrics.h b/Source/WebCore/rendering/svg/SVGTextMetrics.h
index ba008c0ef..809629d0f 100644
--- a/Source/WebCore/rendering/svg/SVGTextMetrics.h
+++ b/Source/WebCore/rendering/svg/SVGTextMetrics.h
@@ -17,10 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGTextMetrics_h
-#define SVGTextMetrics_h
+#pragma once
-#if ENABLE(SVG)
#include <wtf/text/WTFString.h>
namespace WebCore {
@@ -31,16 +29,14 @@ class TextRun;
class SVGTextMetrics {
public:
- enum MetricsType {
- SkippedSpaceMetrics
- };
+ enum MetricsType { SkippedSpaceMetrics };
SVGTextMetrics();
- SVGTextMetrics(MetricsType);
- SVGTextMetrics(RenderSVGInlineText*, unsigned position, unsigned length, float width, const String& glyphName);
+ explicit SVGTextMetrics(MetricsType);
+ SVGTextMetrics(RenderSVGInlineText&, unsigned length, float width);
- static SVGTextMetrics measureCharacterRange(RenderSVGInlineText*, unsigned position, unsigned length);
- static TextRun constructTextRun(RenderSVGInlineText*, const UChar* characters, unsigned position, unsigned length);
+ static SVGTextMetrics measureCharacterRange(RenderSVGInlineText&, unsigned position, unsigned length);
+ static TextRun constructTextRun(RenderSVGInlineText&, unsigned position = 0, unsigned length = std::numeric_limits<unsigned>::max());
bool isEmpty() const { return !m_width && !m_height && !m_glyph.isValid && m_length == 1; }
@@ -72,7 +68,7 @@ public:
const Glyph& glyph() const { return m_glyph; }
private:
- SVGTextMetrics(RenderSVGInlineText*, const TextRun&);
+ SVGTextMetrics(RenderSVGInlineText&, const TextRun&);
float m_width;
float m_height;
@@ -81,6 +77,3 @@ private:
};
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp
index 86009e6e9..bb2593d38 100644
--- a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp
@@ -18,19 +18,18 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGTextMetricsBuilder.h"
+#include "RenderChildIterator.h"
+#include "RenderSVGInline.h"
#include "RenderSVGInlineText.h"
#include "RenderSVGText.h"
-#include "SVGTextRunRenderingContext.h"
namespace WebCore {
SVGTextMetricsBuilder::SVGTextMetricsBuilder()
: m_text(0)
- , m_run(static_cast<const UChar*>(0), 0)
+ , m_run(StringView())
, m_textPosition(0)
, m_isComplexText(false)
, m_totalWidth(0)
@@ -39,13 +38,13 @@ SVGTextMetricsBuilder::SVGTextMetricsBuilder()
inline bool SVGTextMetricsBuilder::currentCharacterStartsSurrogatePair() const
{
- return U16_IS_LEAD(m_run[m_textPosition]) && int(m_textPosition + 1) < m_run.charactersLength() && U16_IS_TRAIL(m_run[m_textPosition + 1]);
+ return U16_IS_LEAD(m_run[m_textPosition]) && (m_textPosition + 1) < m_run.charactersLength() && U16_IS_TRAIL(m_run[m_textPosition + 1]);
}
bool SVGTextMetricsBuilder::advance()
{
m_textPosition += m_currentMetrics.length();
- if (int(m_textPosition) >= m_run.charactersLength())
+ if (m_textPosition >= m_run.charactersLength())
return false;
if (m_isComplexText)
@@ -68,18 +67,14 @@ void SVGTextMetricsBuilder::advanceSimpleText()
float currentWidth = m_simpleWidthIterator->runWidthSoFar() - m_totalWidth;
m_totalWidth = m_simpleWidthIterator->runWidthSoFar();
-#if ENABLE(SVG_FONTS)
- m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, m_simpleWidthIterator->lastGlyphName());
-#else
- m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, emptyString());
-#endif
+ m_currentMetrics = SVGTextMetrics(*m_text, metricsLength, currentWidth);
}
void SVGTextMetricsBuilder::advanceComplexText()
{
unsigned metricsLength = currentCharacterStartsSurrogatePair() ? 2 : 1;
- m_currentMetrics = SVGTextMetrics::measureCharacterRange(m_text, m_textPosition, metricsLength);
- m_complexStartToCurrentMetrics = SVGTextMetrics::measureCharacterRange(m_text, 0, m_textPosition + metricsLength);
+ m_currentMetrics = SVGTextMetrics::measureCharacterRange(*m_text, m_textPosition, metricsLength);
+ m_complexStartToCurrentMetrics = SVGTextMetrics::measureCharacterRange(*m_text, 0, m_textPosition + metricsLength);
ASSERT(m_currentMetrics.length() == metricsLength);
// Frequent case for Arabic text: when measuring a single character the arabic isolated form is taken
@@ -93,22 +88,22 @@ void SVGTextMetricsBuilder::advanceComplexText()
m_totalWidth = m_complexStartToCurrentMetrics.width();
}
-void SVGTextMetricsBuilder::initializeMeasurementWithTextRenderer(RenderSVGInlineText* text)
+void SVGTextMetricsBuilder::initializeMeasurementWithTextRenderer(RenderSVGInlineText& text)
{
- m_text = text;
+ m_text = &text;
m_textPosition = 0;
m_currentMetrics = SVGTextMetrics();
m_complexStartToCurrentMetrics = SVGTextMetrics();
m_totalWidth = 0;
- const Font& scaledFont = text->scaledFont();
- m_run = SVGTextMetrics::constructTextRun(text, text->deprecatedCharacters(), 0, text->textLength());
- m_isComplexText = scaledFont.codePath(m_run) == Font::Complex;
+ const FontCascade& scaledFont = text.scaledFont();
+ m_run = SVGTextMetrics::constructTextRun(text);
+ m_isComplexText = scaledFont.codePath(m_run) == FontCascade::Complex;
if (m_isComplexText)
- m_simpleWidthIterator.clear();
+ m_simpleWidthIterator = nullptr;
else
- m_simpleWidthIterator = adoptPtr(new WidthIterator(&scaledFont, m_run));
+ m_simpleWidthIterator = std::make_unique<WidthIterator>(&scaledFont, m_run);
}
struct MeasureTextData {
@@ -122,17 +117,15 @@ struct MeasureTextData {
}
SVGCharacterDataMap* allCharactersMap;
- const UChar* lastCharacter;
+ UChar lastCharacter;
bool processRenderer;
unsigned valueListPosition;
unsigned skippedCharacters;
};
-void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText* text, MeasureTextData* data)
+void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText& text, MeasureTextData* data)
{
- ASSERT(text);
-
- SVGTextLayoutAttributes* attributes = text->layoutAttributes();
+ SVGTextLayoutAttributes* attributes = text.layoutAttributes();
Vector<SVGTextMetrics>* textMetricsValues = &attributes->textMetricsValues();
if (data->processRenderer) {
if (data->allCharactersMap)
@@ -142,12 +135,12 @@ void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText* text, Measu
}
initializeMeasurementWithTextRenderer(text);
- bool preserveWhiteSpace = text->style().whiteSpace() == PRE;
+ bool preserveWhiteSpace = text.style().whiteSpace() == PRE;
int surrogatePairCharacters = 0;
while (advance()) {
- const UChar* currentCharacter = m_run.data16(m_textPosition);
- if (*currentCharacter == ' ' && !preserveWhiteSpace && (!data->lastCharacter || *data->lastCharacter == ' ')) {
+ UChar currentCharacter = m_run[m_textPosition];
+ if (currentCharacter == ' ' && !preserveWhiteSpace && (!data->lastCharacter || data->lastCharacter == ' ')) {
if (data->processRenderer)
textMetricsValues->append(SVGTextMetrics(SVGTextMetrics::SkippedSpaceMetrics));
if (data->allCharactersMap)
@@ -179,10 +172,10 @@ void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText* text, Measu
void SVGTextMetricsBuilder::walkTree(RenderElement& start, RenderSVGInlineText* stopAtLeaf, MeasureTextData* data)
{
- for (auto child = start.firstChild(); child; child = child->nextSibling()) {
- if (child->isSVGInlineText()) {
- RenderSVGInlineText* text = toRenderSVGInlineText(child);
- if (stopAtLeaf && stopAtLeaf != text) {
+ for (auto& child : childrenOfType<RenderObject>(start)) {
+ if (is<RenderSVGInlineText>(child)) {
+ auto& text = downcast<RenderSVGInlineText>(child);
+ if (stopAtLeaf && stopAtLeaf != &text) {
data->processRenderer = false;
measureTextRenderer(text, data);
continue;
@@ -196,32 +189,27 @@ void SVGTextMetricsBuilder::walkTree(RenderElement& start, RenderSVGInlineText*
continue;
}
- if (!child->isSVGInline())
+ if (!is<RenderSVGInline>(child))
continue;
- walkTree(toRenderElement(*child), stopAtLeaf, data);
+ walkTree(downcast<RenderSVGInline>(child), stopAtLeaf, data);
}
}
-void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText* text)
+void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText& text)
{
- ASSERT(text);
-
- RenderSVGText* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text);
+ auto* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text);
if (!textRoot)
return;
- MeasureTextData data(0);
- walkTree(*textRoot, text, &data);
+ MeasureTextData data(nullptr);
+ walkTree(*textRoot, &text, &data);
}
-void SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(RenderSVGText* textRoot, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap)
+void SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(RenderSVGText& textRoot, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap)
{
- ASSERT(textRoot);
MeasureTextData data(&allCharactersMap);
- walkTree(*textRoot, stopAtLeaf, &data);
+ walkTree(textRoot, stopAtLeaf, &data);
}
}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.h b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.h
index 5e0d12951..4f7402523 100644
--- a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.h
+++ b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.h
@@ -17,10 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGTextMetricsBuilder_h
-#define SVGTextMetricsBuilder_h
+#pragma once
-#if ENABLE(SVG)
#include "SVGTextLayoutAttributes.h"
#include "TextRun.h"
#include "WidthIterator.h"
@@ -36,8 +34,8 @@ class SVGTextMetricsBuilder {
WTF_MAKE_NONCOPYABLE(SVGTextMetricsBuilder);
public:
SVGTextMetricsBuilder();
- void measureTextRenderer(RenderSVGInlineText*);
- void buildMetricsAndLayoutAttributes(RenderSVGText*, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap);
+ void measureTextRenderer(RenderSVGInlineText&);
+ void buildMetricsAndLayoutAttributes(RenderSVGText&, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap);
private:
bool advance();
@@ -45,9 +43,9 @@ private:
void advanceComplexText();
bool currentCharacterStartsSurrogatePair() const;
- void initializeMeasurementWithTextRenderer(RenderSVGInlineText*);
+ void initializeMeasurementWithTextRenderer(RenderSVGInlineText&);
void walkTree(RenderElement&, RenderSVGInlineText* stopAtLeaf, MeasureTextData*);
- void measureTextRenderer(RenderSVGInlineText*, MeasureTextData*);
+ void measureTextRenderer(RenderSVGInlineText&, MeasureTextData*);
RenderSVGInlineText* m_text;
TextRun m_run;
@@ -57,13 +55,10 @@ private:
float m_totalWidth;
// Simple text only.
- OwnPtr<WidthIterator> m_simpleWidthIterator;
+ std::unique_ptr<WidthIterator> m_simpleWidthIterator;
// Complex text only.
SVGTextMetrics m_complexStartToCurrentMetrics;
};
} // namespace WebCore
-
-#endif // ENABLE(SVG)
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGTextQuery.cpp b/Source/WebCore/rendering/svg/SVGTextQuery.cpp
index f25dedcad..86e4bf2f3 100644
--- a/Source/WebCore/rendering/svg/SVGTextQuery.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextQuery.cpp
@@ -20,11 +20,11 @@
#include "config.h"
#include "SVGTextQuery.h"
-#if ENABLE(SVG)
#include "FloatConversion.h"
#include "InlineFlowBox.h"
#include "RenderBlockFlow.h"
#include "RenderInline.h"
+#include "RenderSVGText.h"
#include "SVGInlineTextBox.h"
#include "VisiblePosition.h"
@@ -51,12 +51,12 @@ struct SVGTextQuery::Data {
static inline InlineFlowBox* flowBoxForRenderer(RenderObject* renderer)
{
if (!renderer)
- return 0;
+ return nullptr;
- if (renderer->isRenderBlockFlow()) {
+ if (is<RenderBlockFlow>(*renderer)) {
// If we're given a block element, it has to be a RenderSVGText.
- ASSERT(renderer->isSVGText());
- RenderBlockFlow& renderBlock = toRenderBlockFlow(*renderer);
+ ASSERT(is<RenderSVGText>(*renderer));
+ RenderBlockFlow& renderBlock = downcast<RenderBlockFlow>(*renderer);
// RenderSVGText only ever contains a single line box.
auto flowBox = renderBlock.firstRootBox();
@@ -64,9 +64,9 @@ static inline InlineFlowBox* flowBoxForRenderer(RenderObject* renderer)
return flowBox;
}
- if (renderer->isRenderInline()) {
+ if (is<RenderInline>(*renderer)) {
// We're given a RenderSVGInline or objects that derive from it (RenderSVGTSpan / RenderSVGTextPath)
- RenderInline& renderInline = toRenderInline(*renderer);
+ RenderInline& renderInline = downcast<RenderInline>(*renderer);
// RenderSVGInline only ever contains a single line box.
InlineFlowBox* flowBox = renderInline.firstLineBox();
@@ -75,7 +75,7 @@ static inline InlineFlowBox* flowBoxForRenderer(RenderObject* renderer)
}
ASSERT_NOT_REACHED();
- return 0;
+ return nullptr;
}
SVGTextQuery::SVGTextQuery(RenderObject* renderer)
@@ -89,17 +89,17 @@ void SVGTextQuery::collectTextBoxesInFlowBox(InlineFlowBox* flowBox)
return;
for (InlineBox* child = flowBox->firstChild(); child; child = child->nextOnLine()) {
- if (child->isInlineFlowBox()) {
+ if (is<InlineFlowBox>(*child)) {
// Skip generated content.
if (!child->renderer().node())
continue;
- collectTextBoxesInFlowBox(toInlineFlowBox(child));
+ collectTextBoxesInFlowBox(downcast<InlineFlowBox>(child));
continue;
}
- if (child->isSVGInlineTextBox())
- m_textBoxes.append(toSVGInlineTextBox(child));
+ if (is<SVGInlineTextBox>(*child))
+ m_textBoxes.append(downcast<SVGInlineTextBox>(child));
}
}
@@ -115,7 +115,7 @@ bool SVGTextQuery::executeQuery(Data* queryData, ProcessTextFragmentCallback fra
queryData->textBox = m_textBoxes.at(textBoxPosition);
queryData->textRenderer = &queryData->textBox->renderer();
- queryData->isVerticalText = queryData->textRenderer->style().svgStyle().isVerticalWritingMode();
+ queryData->isVerticalText = queryData->textRenderer->style().isVerticalWritingMode();
const Vector<SVGTextFragment>& fragments = queryData->textBox->textFragments();
// Loop over all text fragments in this text box, firing a callback for each.
@@ -134,13 +134,15 @@ bool SVGTextQuery::executeQuery(Data* queryData, ProcessTextFragmentCallback fra
return false;
}
-bool SVGTextQuery::mapStartEndPositionsIntoFragmentCoordinates(Data* queryData, const SVGTextFragment& fragment, int& startPosition, int& endPosition) const
+bool SVGTextQuery::mapStartEndPositionsIntoFragmentCoordinates(Data* queryData, const SVGTextFragment& fragment, unsigned& startPosition, unsigned& endPosition) const
{
// Reuse the same logic used for text selection & painting, to map our query start/length into start/endPositions of the current text fragment.
+ ASSERT(startPosition >= queryData->processedCharacters);
+ ASSERT(endPosition >= queryData->processedCharacters);
startPosition -= queryData->processedCharacters;
endPosition -= queryData->processedCharacters;
- if (startPosition >= endPosition || startPosition < 0 || endPosition < 0)
+ if (startPosition >= endPosition)
return false;
modifyStartEndPositionsRespectingLigatures(queryData, startPosition, endPosition);
@@ -151,7 +153,7 @@ bool SVGTextQuery::mapStartEndPositionsIntoFragmentCoordinates(Data* queryData,
return true;
}
-void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, int& startPosition, int& endPosition) const
+void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, unsigned& startPosition, unsigned& endPosition) const
{
SVGTextLayoutAttributes* layoutAttributes = queryData->textRenderer->layoutAttributes();
Vector<SVGTextMetrics>& textMetricsValues = layoutAttributes->textMetricsValues();
@@ -167,7 +169,7 @@ void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, i
bool alterStartPosition = true;
bool alterEndPosition = true;
- int lastPositionOffset = -1;
+ std::optional<unsigned> lastPositionOffset;
for (; textMetricsOffset < textMetricsSize && positionOffset < positionSize; ++textMetricsOffset) {
SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset];
@@ -182,21 +184,21 @@ void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, i
break;
// If the start position maps to a character in the metrics list, we don't need to modify it.
- if (startPosition == static_cast<int>(positionOffset))
+ if (startPosition == positionOffset)
alterStartPosition = false;
// If the start position maps to a character in the metrics list, we don't need to modify it.
- if (endPosition == static_cast<int>(positionOffset))
+ if (endPosition == positionOffset)
alterEndPosition = false;
// Detect ligatures.
- if (lastPositionOffset != -1 && lastPositionOffset - positionOffset > 1) {
- if (alterStartPosition && startPosition > lastPositionOffset && startPosition < static_cast<int>(positionOffset)) {
- startPosition = lastPositionOffset;
+ if (lastPositionOffset && lastPositionOffset.value() - positionOffset > 1) {
+ if (alterStartPosition && startPosition > lastPositionOffset.value() && startPosition < positionOffset) {
+ startPosition = lastPositionOffset.value();
alterStartPosition = false;
}
- if (alterEndPosition && endPosition > lastPositionOffset && endPosition < static_cast<int>(positionOffset)) {
+ if (alterEndPosition && endPosition > lastPositionOffset.value() && endPosition < positionOffset) {
endPosition = positionOffset;
alterEndPosition = false;
}
@@ -212,16 +214,12 @@ void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, i
if (!alterStartPosition && !alterEndPosition)
return;
- if (lastPositionOffset != -1 && lastPositionOffset - positionOffset > 1) {
- if (alterStartPosition && startPosition > lastPositionOffset && startPosition < static_cast<int>(positionOffset)) {
- startPosition = lastPositionOffset;
- alterStartPosition = false;
- }
+ if (lastPositionOffset && lastPositionOffset.value() - positionOffset > 1) {
+ if (alterStartPosition && startPosition > lastPositionOffset.value() && startPosition < positionOffset)
+ startPosition = lastPositionOffset.value();
- if (alterEndPosition && endPosition > lastPositionOffset && endPosition < static_cast<int>(positionOffset)) {
+ if (alterEndPosition && endPosition > lastPositionOffset.value() && endPosition < positionOffset)
endPosition = positionOffset;
- alterEndPosition = false;
- }
}
}
@@ -288,12 +286,12 @@ bool SVGTextQuery::subStringLengthCallback(Data* queryData, const SVGTextFragmen
{
SubStringLengthData* data = static_cast<SubStringLengthData*>(queryData);
- int startPosition = data->startPosition;
- int endPosition = startPosition + data->length;
+ unsigned startPosition = data->startPosition;
+ unsigned endPosition = startPosition + data->length;
if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
return false;
- SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset + startPosition, endPosition - startPosition);
+ SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(*queryData->textRenderer, fragment.characterOffset + startPosition, endPosition - startPosition);
data->subStringLength += queryData->isVerticalText ? metrics.height() : metrics.width();
return false;
}
@@ -323,15 +321,15 @@ bool SVGTextQuery::startPositionOfCharacterCallback(Data* queryData, const SVGTe
{
StartPositionOfCharacterData* data = static_cast<StartPositionOfCharacterData*>(queryData);
- int startPosition = data->position;
- int endPosition = startPosition + 1;
+ unsigned startPosition = data->position;
+ unsigned endPosition = startPosition + 1;
if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
return false;
data->startPosition = FloatPoint(fragment.x, fragment.y);
if (startPosition) {
- SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset, startPosition);
+ SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(*queryData->textRenderer, fragment.characterOffset, startPosition);
if (queryData->isVerticalText)
data->startPosition.move(0, metrics.height());
else
@@ -347,10 +345,10 @@ bool SVGTextQuery::startPositionOfCharacterCallback(Data* queryData, const SVGTe
return true;
}
-SVGPoint SVGTextQuery::startPositionOfCharacter(unsigned position) const
+FloatPoint SVGTextQuery::startPositionOfCharacter(unsigned position) const
{
if (m_textBoxes.isEmpty())
- return SVGPoint();
+ return { };
StartPositionOfCharacterData data(position);
executeQuery(&data, &SVGTextQuery::startPositionOfCharacterCallback);
@@ -372,14 +370,14 @@ bool SVGTextQuery::endPositionOfCharacterCallback(Data* queryData, const SVGText
{
EndPositionOfCharacterData* data = static_cast<EndPositionOfCharacterData*>(queryData);
- int startPosition = data->position;
- int endPosition = startPosition + 1;
+ unsigned startPosition = data->position;
+ unsigned endPosition = startPosition + 1;
if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
return false;
data->endPosition = FloatPoint(fragment.x, fragment.y);
- SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset, startPosition + 1);
+ SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(*queryData->textRenderer, fragment.characterOffset, startPosition + 1);
if (queryData->isVerticalText)
data->endPosition.move(0, metrics.height());
else
@@ -394,10 +392,10 @@ bool SVGTextQuery::endPositionOfCharacterCallback(Data* queryData, const SVGText
return true;
}
-SVGPoint SVGTextQuery::endPositionOfCharacter(unsigned position) const
+FloatPoint SVGTextQuery::endPositionOfCharacter(unsigned position) const
{
if (m_textBoxes.isEmpty())
- return SVGPoint();
+ return { };
EndPositionOfCharacterData data(position);
executeQuery(&data, &SVGTextQuery::endPositionOfCharacterCallback);
@@ -420,8 +418,8 @@ bool SVGTextQuery::rotationOfCharacterCallback(Data* queryData, const SVGTextFra
{
RotationOfCharacterData* data = static_cast<RotationOfCharacterData*>(queryData);
- int startPosition = data->position;
- int endPosition = startPosition + 1;
+ unsigned startPosition = data->position;
+ unsigned endPosition = startPosition + 1;
if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
return false;
@@ -458,7 +456,7 @@ struct ExtentOfCharacterData : SVGTextQuery::Data {
FloatRect extent;
};
-static inline void calculateGlyphBoundaries(SVGTextQuery::Data* queryData, const SVGTextFragment& fragment, int startPosition, FloatRect& extent)
+static inline void calculateGlyphBoundaries(SVGTextQuery::Data* queryData, const SVGTextFragment& fragment, unsigned startPosition, FloatRect& extent)
{
float scalingFactor = queryData->textRenderer->scalingFactor();
ASSERT(scalingFactor);
@@ -466,14 +464,14 @@ static inline void calculateGlyphBoundaries(SVGTextQuery::Data* queryData, const
extent.setLocation(FloatPoint(fragment.x, fragment.y - queryData->textRenderer->scaledFont().fontMetrics().floatAscent() / scalingFactor));
if (startPosition) {
- SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset, startPosition);
+ SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(*queryData->textRenderer, fragment.characterOffset, startPosition);
if (queryData->isVerticalText)
extent.move(0, metrics.height());
else
extent.move(metrics.width(), 0);
}
- SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset + startPosition, 1);
+ SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(*queryData->textRenderer, fragment.characterOffset + startPosition, 1);
extent.setSize(FloatSize(metrics.width(), metrics.height()));
AffineTransform fragmentTransform;
@@ -488,8 +486,8 @@ bool SVGTextQuery::extentOfCharacterCallback(Data* queryData, const SVGTextFragm
{
ExtentOfCharacterData* data = static_cast<ExtentOfCharacterData*>(queryData);
- int startPosition = data->position;
- int endPosition = startPosition + 1;
+ unsigned startPosition = data->position;
+ unsigned endPosition = startPosition + 1;
if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
return false;
@@ -523,8 +521,8 @@ bool SVGTextQuery::characterNumberAtPositionCallback(Data* queryData, const SVGT
FloatRect extent;
for (unsigned i = 0; i < fragment.length; ++i) {
- int startPosition = data->processedCharacters + i;
- int endPosition = startPosition + 1;
+ unsigned startPosition = data->processedCharacters + i;
+ unsigned endPosition = startPosition + 1;
if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
continue;
@@ -538,7 +536,7 @@ bool SVGTextQuery::characterNumberAtPositionCallback(Data* queryData, const SVGT
return false;
}
-int SVGTextQuery::characterNumberAtPosition(const SVGPoint& position) const
+int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const
{
if (m_textBoxes.isEmpty())
return -1;
@@ -551,5 +549,3 @@ int SVGTextQuery::characterNumberAtPosition(const SVGPoint& position) const
}
}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGTextQuery.h b/Source/WebCore/rendering/svg/SVGTextQuery.h
index bf60a6da6..3f09a76c9 100644
--- a/Source/WebCore/rendering/svg/SVGTextQuery.h
+++ b/Source/WebCore/rendering/svg/SVGTextQuery.h
@@ -17,12 +17,9 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SVGTextQuery_h
-#define SVGTextQuery_h
+#pragma once
-#if ENABLE(SVG)
#include "FloatRect.h"
-#include "SVGPoint.h"
#include "SVGTextFragment.h"
#include <wtf/Vector.h>
@@ -39,11 +36,11 @@ public:
unsigned numberOfCharacters() const;
float textLength() const;
float subStringLength(unsigned startPosition, unsigned length) const;
- SVGPoint startPositionOfCharacter(unsigned position) const;
- SVGPoint endPositionOfCharacter(unsigned position) const;
+ FloatPoint startPositionOfCharacter(unsigned position) const;
+ FloatPoint endPositionOfCharacter(unsigned position) const;
float rotationOfCharacter(unsigned position) const;
FloatRect extentOfCharacter(unsigned position) const;
- int characterNumberAtPosition(const SVGPoint&) const;
+ int characterNumberAtPosition(const FloatPoint&) const;
// Public helper struct. Private classes in SVGTextQuery inherit from it.
struct Data;
@@ -53,8 +50,8 @@ private:
bool executeQuery(Data*, ProcessTextFragmentCallback) const;
void collectTextBoxesInFlowBox(InlineFlowBox*);
- bool mapStartEndPositionsIntoFragmentCoordinates(Data*, const SVGTextFragment&, int& startPosition, int& endPosition) const;
- void modifyStartEndPositionsRespectingLigatures(Data*, int& startPosition, int& endPosition) const;
+ bool mapStartEndPositionsIntoFragmentCoordinates(Data*, const SVGTextFragment&, unsigned& startPosition, unsigned& endPosition) const;
+ void modifyStartEndPositionsRespectingLigatures(Data*, unsigned& startPosition, unsigned& endPosition) const;
private:
bool numberOfCharactersCallback(Data*, const SVGTextFragment&) const;
@@ -70,7 +67,4 @@ private:
Vector<SVGInlineTextBox*> m_textBoxes;
};
-}
-
-#endif
-#endif
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp b/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp
deleted file mode 100644
index 3b2561af8..000000000
--- a/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
- * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
- *
- * 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"
-
-#if ENABLE(SVG_FONTS)
-#include "SVGTextRunRenderingContext.h"
-
-#include "GlyphBuffer.h"
-#include "GraphicsContext.h"
-#include "RenderObject.h"
-#include "RenderSVGInlineText.h"
-#include "RenderSVGResourceSolidColor.h"
-#include "SVGFontData.h"
-#include "SVGFontElement.h"
-#include "SVGFontFaceElement.h"
-#include "SVGGlyphElement.h"
-#include "SVGNames.h"
-#include "WidthIterator.h"
-
-namespace WebCore {
-
-static inline const SVGFontData* svgFontAndFontFaceElementForFontData(const SimpleFontData* fontData, SVGFontFaceElement*& fontFace, SVGFontElement*& font)
-{
- ASSERT(fontData);
- ASSERT(fontData->isCustomFont());
- ASSERT(fontData->isSVGFont());
-
- const SVGFontData* svgFontData = static_cast<const SVGFontData*>(fontData->fontData());
-
- fontFace = svgFontData->svgFontFaceElement();
- ASSERT(fontFace);
-
- font = fontFace->associatedFontElement();
- return svgFontData;
-}
-
-float SVGTextRunRenderingContext::floatWidthUsingSVGFont(const Font& font, const TextRun& run, int& charsConsumed, String& glyphName) const
-{
- WidthIterator it(&font, run);
- GlyphBuffer glyphBuffer;
- charsConsumed += it.advance(run.length(), &glyphBuffer);
- glyphName = it.lastGlyphName();
- return it.runWidthSoFar();
-}
-
-bool SVGTextRunRenderingContext::applySVGKerning(const SimpleFontData* fontData, WidthIterator& iterator, GlyphBuffer* glyphBuffer, int from) const
-{
- ASSERT(glyphBuffer);
- ASSERT(glyphBuffer->size() > 1);
- SVGFontElement* fontElement = 0;
- SVGFontFaceElement* fontFaceElement = 0;
-
- svgFontAndFontFaceElementForFontData(fontData, fontFaceElement, fontElement);
- if (!fontElement || !fontFaceElement)
- return false;
-
- float scale = scaleEmToUnits(fontData->platformData().size(), fontFaceElement->unitsPerEm());
-
- String lastGlyphName;
- String lastUnicodeString;
- int characterOffset = iterator.m_currentCharacter;
- String text = iterator.run().string();
- const int glyphCount = glyphBuffer->size() - from;
- GlyphBufferAdvance* advances = glyphBuffer->advances(from);
-
- for (int i = 0; i < glyphCount; ++i) {
- Glyph glyph = glyphBuffer->glyphAt(from + i);
- if (!glyph)
- continue;
- float kerning = 0;
- SVGGlyph svgGlyph = fontElement->svgGlyphForGlyph(glyph);
- String unicodeString = text.substring(characterOffset, svgGlyph.unicodeStringLength);
- if (i >= 1) {
- // FIXME: Support vertical text.
- kerning = fontElement->horizontalKerningForPairOfStringsAndGlyphs(lastUnicodeString, lastGlyphName, unicodeString, svgGlyph.glyphName);
- advances[i - 1].setWidth(advances[i - 1].width() - kerning * scale);
- }
- lastGlyphName = svgGlyph.glyphName;
- lastUnicodeString = unicodeString;
- characterOffset += svgGlyph.unicodeStringLength;
- }
-
- return true;
-}
-
-void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
-{
- SVGFontElement* fontElement = 0;
- SVGFontFaceElement* fontFaceElement = 0;
-
- const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(fontData, fontFaceElement, fontElement);
- if (!fontElement || !fontFaceElement)
- return;
-
- auto activePaintingResource = this->activePaintingResource();
- if (!activePaintingResource) {
- // TODO: We're only supporting simple filled HTML text so far.
- RenderSVGResourceSolidColor* solidPaintingResource = RenderSVGResource::sharedSolidPaintingResource();
- solidPaintingResource->setColor(context->fillColor());
- activePaintingResource = solidPaintingResource;
- }
-
- auto& elementRenderer = renderer().isRenderElement() ? toRenderElement(renderer()) : *renderer().parent();
- RenderStyle& style = elementRenderer.style();
- bool isVerticalText = style.svgStyle().isVerticalWritingMode();
-
- float scale = scaleEmToUnits(fontData->platformData().size(), fontFaceElement->unitsPerEm());
- ASSERT(activePaintingResource);
-
- FloatPoint glyphOrigin;
- glyphOrigin.setX(svgFontData->horizontalOriginX() * scale);
- glyphOrigin.setY(svgFontData->horizontalOriginY() * scale);
-
- FloatPoint currentPoint = point;
- RenderSVGResourceMode resourceMode = context->textDrawingMode() == TextModeStroke ? ApplyToStrokeMode : ApplyToFillMode;
- for (int i = 0; i < numGlyphs; ++i) {
- Glyph glyph = glyphBuffer.glyphAt(from + i);
- if (!glyph)
- continue;
-
- float advance = glyphBuffer.advanceAt(from + i).width();
- SVGGlyph svgGlyph = fontElement->svgGlyphForGlyph(glyph);
- ASSERT(!svgGlyph.isPartOfLigature);
- ASSERT(svgGlyph.tableEntry == glyph);
-
- SVGGlyphElement::inheritUnspecifiedAttributes(svgGlyph, svgFontData);
-
- // FIXME: Support arbitary SVG content as glyph (currently limited to <glyph d="..."> situations).
- if (svgGlyph.pathData.isEmpty()) {
- if (isVerticalText)
- currentPoint.move(0, advance);
- else
- currentPoint.move(advance, 0);
- continue;
- }
-
- if (isVerticalText) {
- glyphOrigin.setX(svgGlyph.verticalOriginX * scale);
- glyphOrigin.setY(svgGlyph.verticalOriginY * scale);
- }
-
- AffineTransform glyphPathTransform;
- glyphPathTransform.translate(currentPoint.x() + glyphOrigin.x(), currentPoint.y() + glyphOrigin.y());
- glyphPathTransform.scale(scale, -scale);
-
- Path glyphPath = svgGlyph.pathData;
- glyphPath.transform(glyphPathTransform);
-
- if (activePaintingResource->applyResource(elementRenderer, style, context, resourceMode)) {
- float strokeThickness = context->strokeThickness();
- if (renderer().isSVGInlineText())
- context->setStrokeThickness(strokeThickness * toRenderSVGInlineText(renderer()).scalingFactor());
- activePaintingResource->postApplyResource(elementRenderer, context, resourceMode, &glyphPath, 0);
- context->setStrokeThickness(strokeThickness);
- }
-
- if (isVerticalText)
- currentPoint.move(0, advance);
- else
- currentPoint.move(advance, 0);
- }
-}
-
-GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const Font& font, WidthIterator& iterator, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength)
-{
- const SimpleFontData* primaryFont = font.primaryFont();
- ASSERT(primaryFont);
-
- std::pair<GlyphData, GlyphPage*> pair = font.glyphDataAndPageForCharacter(character, mirror, AutoVariant);
- GlyphData glyphData = pair.first;
-
- // Check if we have the missing glyph data, in which case we can just return.
- GlyphData missingGlyphData = primaryFont->missingGlyphData();
- if (glyphData.glyph == missingGlyphData.glyph && glyphData.fontData == missingGlyphData.fontData) {
- ASSERT(glyphData.fontData);
- return glyphData;
- }
-
- // Save data fromt he font fallback list because we may modify it later. Do this before the
- // potential change to glyphData.fontData below.
- FontGlyphs* glyph = font.glyphs();
- ASSERT(glyph);
- FontGlyphs::GlyphPagesStateSaver glyphPagesSaver(*glyph);
-
- // Characters enclosed by an <altGlyph> element, may not be registered in the GlyphPage.
- const SimpleFontData* originalFontData = glyphData.fontData;
- if (glyphData.fontData && !glyphData.fontData->isSVGFont()) {
- auto& elementRenderer = renderer().isRenderElement() ? toRenderElement(renderer()) : *renderer().parent();
- if (Element* parentRendererElement = elementRenderer.element()) {
- if (parentRendererElement->hasTagName(SVGNames::altGlyphTag))
- glyphData.fontData = primaryFont;
- }
- }
-
- const SimpleFontData* fontData = glyphData.fontData;
- if (fontData) {
- if (!fontData->isSVGFont())
- return glyphData;
-
- SVGFontElement* fontElement = 0;
- SVGFontFaceElement* fontFaceElement = 0;
-
- const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(fontData, fontFaceElement, fontElement);
- if (!fontElement || !fontFaceElement)
- return glyphData;
-
- // If we got here, we're dealing with a glyph defined in a SVG Font.
- // The returned glyph by glyphDataAndPageForCharacter() is a glyph stored in the SVG Font glyph table.
- // This doesn't necessarily mean the glyph is suitable for rendering/measuring in this context, its
- // arabic-form/orientation/... may not match, we have to apply SVG Glyph selection to discover that.
- if (svgFontData->applySVGGlyphSelection(iterator, glyphData, mirror, currentCharacter, advanceLength))
- return glyphData;
- }
-
- GlyphPage* page = pair.second;
- ASSERT(page);
-
- // No suitable glyph found that is compatible with the requirments (same language, arabic-form, orientation etc.)
- // Even though our GlyphPage contains an entry for eg. glyph "a", it's not compatible. So we have to temporarily
- // remove the glyph data information from the GlyphPage, and retry the lookup, which handles font fallbacks correctly.
- page->setGlyphDataForCharacter(character, 0, 0);
-
- // Assure that the font fallback glyph selection worked, aka. the fallbackGlyphData font data is not the same as before.
- GlyphData fallbackGlyphData = font.glyphDataForCharacter(character, mirror);
- ASSERT(fallbackGlyphData.fontData != fontData);
-
- // Restore original state of the SVG Font glyph table and the current font fallback list,
- // to assure the next lookup of the same glyph won't immediately return the fallback glyph.
- page->setGlyphDataForCharacter(character, glyphData.glyph, originalFontData);
- ASSERT(fallbackGlyphData.fontData);
- return fallbackGlyphData;
-}
-
-}
-
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h b/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h
deleted file mode 100644
index e1270c19e..000000000
--- a/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) Research In Motion Limited 2011. All rights reserved.
- *
- * 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.
- *
- */
-
-#ifndef SVGTextRunRenderingContext_h
-#define SVGTextRunRenderingContext_h
-
-#include "Font.h"
-#include "TextRun.h"
-
-namespace WebCore {
-
-class RenderObject;
-class RenderSVGResource;
-
-class SVGTextRunRenderingContext final : public TextRun::RenderingContext {
-public:
- static PassRef<SVGTextRunRenderingContext> create(RenderObject& renderer)
- {
- return adoptRef(*new SVGTextRunRenderingContext(renderer));
- }
-
- RenderObject& renderer() const { return m_renderer; }
-
-#if ENABLE(SVG_FONTS)
- RenderSVGResource* activePaintingResource() const { return m_activePaintingResource; }
- void setActivePaintingResource(RenderSVGResource* object) { m_activePaintingResource = object; }
-
- virtual GlyphData glyphDataForCharacter(const Font&, WidthIterator&, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength) override;
- virtual void drawSVGGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const override;
- virtual float floatWidthUsingSVGFont(const Font&, const TextRun&, int& charsConsumed, String& glyphName) const override;
- virtual bool applySVGKerning(const SimpleFontData*, WidthIterator&, GlyphBuffer*, int from) const override;
-#endif
-
-private:
- SVGTextRunRenderingContext(RenderObject& renderer)
- : m_renderer(renderer)
-#if ENABLE(SVG_FONTS)
- , m_activePaintingResource(0)
-#endif
- {
- }
-
- virtual ~SVGTextRunRenderingContext() { }
-
- RenderObject& m_renderer;
-
-#if ENABLE(SVG_FONTS)
- RenderSVGResource* m_activePaintingResource;
-#endif
-};
-
-} // namespace WebCore
-
-#endif // SVGTextRunRenderingContext_h