diff options
| author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
|---|---|---|
| committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
| commit | 41386e9cb918eed93b3f13648cbef387e371e451 (patch) | |
| tree | a97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/WebCore/rendering/svg | |
| parent | e15dd966d523731101f70ccf768bba12435a0208 (diff) | |
| download | WebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz | |
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/WebCore/rendering/svg')
107 files changed, 2525 insertions, 2330 deletions
diff --git a/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp b/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp deleted file mode 100644 index 327dd87ec..000000000 --- a/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 "SVGTextRunRenderingContext.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 32f8e3646..953728b01 100644 --- a/Source/WebCore/rendering/svg/RenderSVGBlock.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGBlock.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Inc. + * Copyright (C) 2006 Apple Computer, Inc. * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) Research In Motion Limited 2010. All rights reserved. * @@ -20,6 +20,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGBlock.h" #include "RenderSVGResource.h" @@ -28,8 +30,8 @@ namespace WebCore { -RenderSVGBlock::RenderSVGBlock(SVGGraphicsElement& element, Ref<RenderStyle>&& style) - : RenderBlockFlow(element, WTF::move(style)) +RenderSVGBlock::RenderSVGBlock(SVGGraphicsElement& element, PassRef<RenderStyle> style) + : RenderBlockFlow(element, std::move(style)) { } @@ -83,3 +85,5 @@ 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 ac8b6ad5e..23efff55d 100644 --- a/Source/WebCore/rendering/svg/RenderSVGBlock.h +++ b/Source/WebCore/rendering/svg/RenderSVGBlock.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Inc. + * Copyright (C) 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -20,6 +20,7 @@ #ifndef RenderSVGBlock_h #define RenderSVGBlock_h +#if ENABLE(SVG) #include "RenderBlockFlow.h" #include "SVGGraphicsElement.h" #include "SVGRenderSupport.h" @@ -32,10 +33,10 @@ class RenderSVGBlock : public RenderBlockFlow { public: virtual LayoutRect visualOverflowRect() const override final; - SVGGraphicsElement& graphicsElement() const { return downcast<SVGGraphicsElement>(nodeForNonAnonymous()); } + SVGGraphicsElement& graphicsElement() const { return toSVGGraphicsElement(nodeForNonAnonymous()); } protected: - RenderSVGBlock(SVGGraphicsElement&, Ref<RenderStyle>&&); + RenderSVGBlock(SVGGraphicsElement&, PassRef<RenderStyle>); virtual void willBeDestroyed() override; private: @@ -43,12 +44,13 @@ private: virtual void updateFromStyle() override final; - virtual bool isRenderSVGBlock() const override final { return true; } + virtual bool isRenderSVGBlock() const override final { return true; }; - virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const override; + virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const; virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override final; }; } #endif +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp index 8207df419..71c7bcc00 100644 --- a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp @@ -22,10 +22,11 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGContainer.h" #include "GraphicsContext.h" -#include "HitTestRequest.h" #include "LayoutRepainter.h" #include "RenderIterator.h" #include "RenderSVGResourceFilter.h" @@ -37,8 +38,8 @@ namespace WebCore { -RenderSVGContainer::RenderSVGContainer(SVGElement& element, Ref<RenderStyle>&& style) - : RenderSVGModelObject(element, WTF::move(style)) +RenderSVGContainer::RenderSVGContainer(SVGElement& element, PassRef<RenderStyle> style) + : RenderSVGModelObject(element, std::move(style)) , m_objectBoundingBoxValid(false) , m_needsBoundariesUpdate(true) { @@ -102,7 +103,7 @@ void RenderSVGContainer::removeChild(RenderObject& child) bool RenderSVGContainer::selfWillPaint() { - auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this); return resources && resources->filter(); } @@ -143,11 +144,11 @@ 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 == PaintPhaseSelfOutline && style().outlineWidth() && style().visibility() == VISIBLE) { + if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style().outlineWidth() && style().visibility() == VISIBLE) { IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRect)); paintOutline(paintInfo, paintRectInParent); } @@ -180,14 +181,14 @@ bool RenderSVGContainer::nodeAtFloatPoint(const HitTestRequest& request, HitTest for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) { - updateHitTestResult(result, LayoutPoint(localPoint)); + updateHitTestResult(result, roundedLayoutPoint(localPoint)); return true; } } // Accessibility wants to return SVG containers, if appropriate. if (request.type() & HitTestRequest::AccessibilityHitTest && m_objectBoundingBox.contains(localPoint)) { - updateHitTestResult(result, LayoutPoint(localPoint)); + updateHitTestResult(result, roundedLayoutPoint(localPoint)); return true; } @@ -197,3 +198,5 @@ 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 113c3438e..78d318e99 100644 --- a/Source/WebCore/rendering/svg/RenderSVGContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGContainer.h @@ -23,6 +23,8 @@ #ifndef RenderSVGContainer_h #define RenderSVGContainer_h +#if ENABLE(SVG) + #include "RenderSVGModelObject.h" namespace WebCore { @@ -40,8 +42,9 @@ public: bool isObjectBoundingBoxValid() const { return m_objectBoundingBoxValid; } protected: - RenderSVGContainer(SVGElement&, Ref<RenderStyle>&&); + RenderSVGContainer(SVGElement&, PassRef<RenderStyle>); + virtual bool isSVGContainer() const override final { return true; } virtual const char* renderName() const override { return "RenderSVGContainer"; } virtual bool canHaveChildren() const override final { return true; } @@ -72,8 +75,6 @@ protected: void updateCachedBoundaries(); private: - virtual bool isSVGContainer() const override final { return true; } - FloatRect m_objectBoundingBox; bool m_objectBoundingBoxValid; FloatRect m_strokeBoundingBox; @@ -81,8 +82,9 @@ private: bool m_needsBoundariesUpdate : 1; }; -} // namespace WebCore +RENDER_OBJECT_TYPE_CASTS(RenderSVGContainer, isSVGContainer()) -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGContainer, isSVGContainer()) +} // namespace WebCore +#endif // ENABLE(SVG) #endif // RenderSVGContainer_h diff --git a/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp b/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp index cb6d9c37c..dac2e84ff 100644 --- a/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp @@ -25,6 +25,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGEllipse.h" #include "SVGCircleElement.h" @@ -33,8 +35,8 @@ namespace WebCore { -RenderSVGEllipse::RenderSVGEllipse(SVGGraphicsElement& element, Ref<RenderStyle>&& style) - : RenderSVGShape(element, WTF::move(style)) +RenderSVGEllipse::RenderSVGEllipse(SVGGraphicsElement& element, PassRef<RenderStyle> style) + : RenderSVGShape(element, std::move(style)) , m_usePathFallback(false) { } @@ -52,22 +54,19 @@ void RenderSVGEllipse::updateShapeFromElement() m_center = FloatPoint(); m_radii = FloatSize(); - calculateRadiiAndCenter(); - - // Element is invalid if either dimension is negative. - if (m_radii.width() < 0 || m_radii.height() < 0) + // 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.isEmpty()) { - if (hasNonScalingStroke()) { - // Fallback to RenderSVGShape if shape has a non-scaling stroke. - RenderSVGShape::updateShapeFromElement(); - m_usePathFallback = true; - return; - } - m_usePathFallback = false; - } + if (m_radii.width() <= 0 || m_radii.height() <= 0) + return; 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; @@ -77,20 +76,21 @@ void RenderSVGEllipse::updateShapeFromElement() void RenderSVGEllipse::calculateRadiiAndCenter() { - 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()); + if (isSVGCircleElement(graphicsElement())) { + SVGCircleElement& circle = toSVGCircleElement(graphicsElement()); + SVGLengthContext lengthContext(&circle); + float radius = circle.r().value(lengthContext); m_radii = FloatSize(radius, radius); + m_center = FloatPoint(circle.cx().value(lengthContext), circle.cy().value(lengthContext)); return; } - ASSERT(is<SVGEllipseElement>(graphicsElement())); - m_radii = FloatSize( - lengthContext.valueForLength(style().svgStyle().rx(), LengthModeWidth), - lengthContext.valueForLength(style().svgStyle().ry(), LengthModeHeight)); + 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)); } void RenderSVGEllipse::fillShape(GraphicsContext* context) const @@ -152,10 +152,6 @@ 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 b587d1ab3..4331c1841 100644 --- a/Source/WebCore/rendering/svg/RenderSVGEllipse.h +++ b/Source/WebCore/rendering/svg/RenderSVGEllipse.h @@ -27,25 +27,25 @@ #ifndef RenderSVGEllipse_h #define RenderSVGEllipse_h +#if ENABLE(SVG) #include "RenderSVGShape.h" namespace WebCore { class RenderSVGEllipse final : public RenderSVGShape { public: - RenderSVGEllipse(SVGGraphicsElement&, Ref<RenderStyle>&&); + RenderSVGEllipse(SVGGraphicsElement&, PassRef<RenderStyle>); virtual ~RenderSVGEllipse(); private: - virtual const char* renderName() const override { return "RenderSVGEllipse"; } - - virtual void updateShapeFromElement() override; - virtual bool isEmpty() const override { return m_usePathFallback ? RenderSVGShape::isEmpty() : m_fillBoundingBox.isEmpty(); } - virtual bool isRenderingDisabled() const override; - virtual void fillShape(GraphicsContext*) const override; - virtual void strokeShape(GraphicsContext*) const override; - virtual bool shapeDependentStrokeContains(const FloatPoint&) override; - virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const override; + 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; void calculateRadiiAndCenter(); private: @@ -56,4 +56,5 @@ private: } +#endif // ENABLE(SVG) #endif diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp index 4698907df..4ab82952b 100644 --- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Inc. + * Copyright (C) 2006 Apple Computer, Inc. * Copyright (C) 2009 Google, Inc. * Copyright (C) Research In Motion Limited 2010. All rights reserved. * @@ -20,6 +20,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGForeignObject.h" #include "GraphicsContext.h" @@ -31,13 +33,14 @@ #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, Ref<RenderStyle>&& style) - : RenderSVGBlock(element, WTF::move(style)) +RenderSVGForeignObject::RenderSVGForeignObject(SVGForeignObjectElement& element, PassRef<RenderStyle> style) + : RenderSVGBlock(element, std::move(style)) , m_needsTransformUpdate(true) { } @@ -48,15 +51,13 @@ RenderSVGForeignObject::~RenderSVGForeignObject() SVGForeignObjectElement& RenderSVGForeignObject::foreignObjectElement() const { - return downcast<SVGForeignObjectElement>(RenderSVGBlock::graphicsElement()); + return toSVGForeignObjectElement(RenderSVGBlock::graphicsElement()); } void RenderSVGForeignObject::paint(PaintInfo& paintInfo, const LayoutPoint&) { - if (paintInfo.context->paintingDisabled()) - return; - - if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection) + if (paintInfo.context->paintingDisabled() + || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection)) return; PaintInfo childPaintInfo(paintInfo); @@ -67,30 +68,30 @@ void RenderSVGForeignObject::paint(PaintInfo& paintInfo, const LayoutPoint&) childPaintInfo.context->clip(m_viewport); SVGRenderingContext renderingContext; + bool continueRendering = true; if (paintInfo.phase == PaintPhaseForeground) { renderingContext.prepareToRenderSVGContent(*this, childPaintInfo); - if (!renderingContext.isRenderingPrepared()) - return; + continueRendering = renderingContext.isRenderingPrepared(); } - LayoutPoint childPoint = IntPoint(); - if (paintInfo.phase == PaintPhaseSelection) { - RenderBlock::paint(childPaintInfo, childPoint); - 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); + } } - - // 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 @@ -103,13 +104,6 @@ void RenderSVGForeignObject::computeFloatRectForRepaint(const RenderLayerModelOb SVGRenderSupport::computeFloatRectForRepaint(*this, repaintContainer, repaintRect, fixed); } -void RenderSVGForeignObject::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& repaintRect, bool fixed) const -{ - FloatRect floatRect(repaintRect); - computeFloatRectForRepaint(repaintContainer, floatRect, fixed); - repaintRect = enclosingLayoutRect(floatRect); -} - const AffineTransform& RenderSVGForeignObject::localToParentTransform() const { m_localToParentTransform = localTransform(); @@ -192,7 +186,7 @@ bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, Hit return false; // FOs establish a stacking context, so we need to hit-test all layers. - HitTestLocation hitTestLocation(localPoint); + HitTestLocation hitTestLocation(roundedLayoutPoint(localPoint)); return RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestForeground) || RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestFloat) || RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestChildBlockBackgrounds); @@ -215,3 +209,5 @@ const RenderObject* RenderSVGForeignObject::pushMappingToContainer(const RenderL } } + +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h index 619c49494..b75c373f9 100644 --- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h +++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Inc. + * Copyright (C) 2006 Apple Computer, Inc. * Copyright (C) 2009 Google, Inc. * * This library is free software; you can redistribute it and/or @@ -21,6 +21,7 @@ #ifndef RenderSVGForeignObject_h #define RenderSVGForeignObject_h +#if ENABLE(SVG) #include "AffineTransform.h" #include "FloatPoint.h" #include "FloatRect.h" @@ -32,41 +33,40 @@ class SVGForeignObjectElement; class RenderSVGForeignObject final : public RenderSVGBlock { public: - RenderSVGForeignObject(SVGForeignObjectElement&, Ref<RenderStyle>&&); + RenderSVGForeignObject(SVGForeignObjectElement&, PassRef<RenderStyle>); virtual ~RenderSVGForeignObject(); SVGForeignObjectElement& foreignObjectElement() const; - virtual void paint(PaintInfo&, const LayoutPoint&) override; + virtual void paint(PaintInfo&, const LayoutPoint&); virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const override; virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const override; - virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const override; - virtual bool requiresLayer() const override { return false; } - virtual void layout() override; + virtual bool requiresLayer() const { return false; } + virtual void layout(); - virtual FloatRect objectBoundingBox() const override { return FloatRect(FloatPoint(), m_viewport.size()); } - virtual FloatRect strokeBoundingBox() const override { return FloatRect(FloatPoint(), m_viewport.size()); } - virtual FloatRect repaintRectInLocalCoordinates() const override { return FloatRect(FloatPoint(), m_viewport.size()); } + 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()); } - virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override; + 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; } - virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, 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 setNeedsTransformUpdate() override { m_needsTransformUpdate = true; } + virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } private: - virtual bool isSVGForeignObject() const override { return true; } void graphicsElement() const = delete; virtual const char* renderName() const override { return "RenderSVGForeignObject"; } virtual void updateLogicalWidth() override; virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const override; - virtual const AffineTransform& localToParentTransform() const override; - virtual AffineTransform localTransform() const override { return m_localTransform; } + virtual const AffineTransform& localToParentTransform() const; + virtual AffineTransform localTransform() const { return m_localTransform; } bool m_needsTransformUpdate : 1; FloatRect m_viewport; @@ -77,3 +77,4 @@ private: } #endif +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp b/Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp index 02e6f10d9..6e90d6e01 100644 --- a/Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp @@ -18,6 +18,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGGradientStop.h" #include "RenderSVGResourceContainer.h" @@ -31,8 +33,8 @@ namespace WebCore { using namespace SVGNames; -RenderSVGGradientStop::RenderSVGGradientStop(SVGStopElement& element, Ref<RenderStyle>&& style) - : RenderElement(element, WTF::move(style), 0) +RenderSVGGradientStop::RenderSVGGradientStop(SVGStopElement& element, PassRef<RenderStyle> style) + : RenderElement(element, std::move(style), 0) { } @@ -48,15 +50,17 @@ 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. - const auto* gradient = gradientElement(); + SVGGradientElement* gradient = gradientElement(); if (!gradient) return; - RenderElement* renderer = gradient->renderer(); + RenderObject* renderer = gradient->renderer(); if (!renderer) return; - downcast<RenderSVGResourceContainer>(*renderer).removeAllClientsFromCache(); + ASSERT(renderer->isSVGResourceContainer()); + RenderSVGResourceContainer* container = renderer->toRenderSVGResourceContainer(); + container->removeAllClientsFromCache(); } void RenderSVGGradientStop::layout() @@ -65,11 +69,14 @@ void RenderSVGGradientStop::layout() clearNeedsLayout(); } -SVGGradientElement* RenderSVGGradientStop::gradientElement() +SVGGradientElement* RenderSVGGradientStop::gradientElement() const { - if (is<SVGGradientElement>(element().parentElement())) - return downcast<SVGGradientElement>(element().parentElement()); - return nullptr; + ContainerNode* parentNode = element()->parentNode(); + if (parentNode->hasTagName(linearGradientTag) || parentNode->hasTagName(radialGradientTag)) + return toSVGGradientElement(parentNode); + return 0; } } + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/RenderSVGGradientStop.h b/Source/WebCore/rendering/svg/RenderSVGGradientStop.h index da953ddd4..9428bb85a 100644 --- a/Source/WebCore/rendering/svg/RenderSVGGradientStop.h +++ b/Source/WebCore/rendering/svg/RenderSVGGradientStop.h @@ -1,7 +1,6 @@ /* * 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 @@ -22,46 +21,47 @@ #ifndef RenderSVGGradientStop_h #define RenderSVGGradientStop_h +#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&, Ref<RenderStyle>&&); + RenderSVGGradientStop(SVGStopElement&, PassRef<RenderStyle>); virtual ~RenderSVGGradientStop(); - SVGStopElement& element() const { return downcast<SVGStopElement>(RenderObject::nodeForNonAnonymous()); } + virtual bool isSVGGradientStop() const { return true; } + virtual const char* renderName() const { return "RenderSVGGradientStop"; } -private: - virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override; - - virtual void layout() override; + virtual void layout(); - // These overrides are needed to prevent ASSERTs on <svg><stop /></svg> + // This 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 override { return FloatRect(); } - virtual FloatRect strokeBoundingBox() const override { return FloatRect(); } - virtual FloatRect repaintRectInLocalCoordinates() const override { return FloatRect(); } + 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; } - virtual bool isSVGGradientStop() const override { return true; } - virtual const char* renderName() const override { return "RenderSVGGradientStop"; } +protected: + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); +private: virtual bool canHaveChildren() const override { return false; } - virtual void paint(PaintInfo&, const LayoutPoint&) override { } + virtual void paint(PaintInfo&, const LayoutPoint&) override final { } - SVGGradientElement* gradientElement(); + SVGGradientElement* gradientElement() const; }; -} // namespace WebCore +RENDER_OBJECT_TYPE_CASTS(RenderSVGGradientStop, isSVGGradientStop()) -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGGradientStop, isSVGGradientStop()) +} +#endif // ENABLE(SVG) #endif // RenderSVGGradientStop_h diff --git a/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp index 7721da34c..e874860ca 100644 --- a/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp @@ -18,6 +18,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGHiddenContainer.h" #include "RenderSVGPath.h" @@ -25,8 +27,8 @@ namespace WebCore { -RenderSVGHiddenContainer::RenderSVGHiddenContainer(SVGElement& element, Ref<RenderStyle>&& style) - : RenderSVGContainer(element, WTF::move(style)) +RenderSVGHiddenContainer::RenderSVGHiddenContainer(SVGElement& element, PassRef<RenderStyle> style) + : RenderSVGContainer(element, std::move(style)) { } @@ -54,3 +56,5 @@ 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 f70ac512f..44abca36d 100644 --- a/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.h @@ -20,6 +20,7 @@ #ifndef RenderSVGHiddenContainer_h #define RenderSVGHiddenContainer_h +#if ENABLE(SVG) #include "RenderSVGContainer.h" namespace WebCore { @@ -30,7 +31,7 @@ class SVGElement; // <defs>, <linearGradient>, <radialGradient> are all good examples class RenderSVGHiddenContainer : public RenderSVGContainer { public: - RenderSVGHiddenContainer(SVGElement&, Ref<RenderStyle>&&); + RenderSVGHiddenContainer(SVGElement&, PassRef<RenderStyle>); protected: virtual void layout() override; @@ -48,4 +49,5 @@ private: }; } +#endif // ENABLE(SVG) #endif // RenderSVGHiddenContainer_h diff --git a/Source/WebCore/rendering/svg/RenderSVGImage.cpp b/Source/WebCore/rendering/svg/RenderSVGImage.cpp index 502167981..58dc14597 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 Inc. + * Copyright (C) 2006 Apple Computer, 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,15 +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" @@ -43,8 +45,8 @@ namespace WebCore { -RenderSVGImage::RenderSVGImage(SVGImageElement& element, Ref<RenderStyle>&& style) - : RenderSVGModelObject(element, WTF::move(style)) +RenderSVGImage::RenderSVGImage(SVGImageElement& element, PassRef<RenderStyle> style) + : RenderSVGModelObject(element, std::move(style)) , m_needsBoundariesUpdate(true) , m_needsTransformUpdate(true) , m_imageResource(std::make_unique<RenderImageResource>()) @@ -59,38 +61,22 @@ RenderSVGImage::~RenderSVGImage() SVGImageElement& RenderSVGImage::imageElement() const { - return downcast<SVGImageElement>(RenderSVGModelObject::element()); + return toSVGImageElement(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)); - // 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() == SVGPreserveAspectRatio::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; - } - } - } - - if (oldBoundaries != m_objectBoundingBox) { - if (!updatedViewport) - imageResource().setContainerSizeForRenderer(enclosingIntRect(m_objectBoundingBox).size()); - updatedViewport = true; - m_needsBoundariesUpdate = true; - } + if (oldBoundaries == m_objectBoundingBox) + return false; - return updatedViewport; + imageResource().setContainerSizeForRenderer(enclosingIntRect(m_objectBoundingBox).size()); + m_needsBoundariesUpdate = true; + return true; } void RenderSVGImage::layout() @@ -131,8 +117,7 @@ void RenderSVGImage::layout() void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&) { - if (paintInfo.context->paintingDisabled() || paintInfo.phase != PaintPhaseForeground - || style().visibility() == HIDDEN || !imageResource().hasImage()) + if (paintInfo.context->paintingDisabled() || style().visibility() == HIDDEN || !imageResource().hasImage()) return; FloatRect boundingBox = repaintRectInLocalCoordinates(); @@ -140,22 +125,25 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&) return; PaintInfo childPaintInfo(paintInfo); - GraphicsContextStateSaver stateSaver(*childPaintInfo.context); - childPaintInfo.applyTransform(m_localTransform); + 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 (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 (style().outlineWidth()) - paintOutline(childPaintInfo, IntRect(boundingBox)); + if (drawsOutline) + paintOutline(childPaintInfo, IntRect(boundingBox)); + } } void RenderSVGImage::paintForeground(PaintInfo& paintInfo) @@ -190,7 +178,7 @@ bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& request, HitTestResu if (hitRules.canHitFill) { if (m_objectBoundingBox.contains(localPoint)) { - updateHitTestResult(result, LayoutPoint(localPoint)); + updateHitTestResult(result, roundedLayoutPoint(localPoint)); return true; } } @@ -203,7 +191,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 (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this)) + if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this)) resources->removeClientFromCache(*this); // Eventually notify parent resources, that we've changed. @@ -228,3 +216,5 @@ void RenderSVGImage::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint } } // namespace WebCore + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/RenderSVGImage.h b/Source/WebCore/rendering/svg/RenderSVGImage.h index b36bd218c..bb101cdaa 100644 --- a/Source/WebCore/rendering/svg/RenderSVGImage.h +++ b/Source/WebCore/rendering/svg/RenderSVGImage.h @@ -24,6 +24,7 @@ #ifndef RenderSVGImage_h #define RenderSVGImage_h +#if ENABLE(SVG) #include "AffineTransform.h" #include "FloatRect.h" #include "RenderSVGModelObject.h" @@ -36,15 +37,15 @@ class SVGImageElement; class RenderSVGImage final : public RenderSVGModelObject { public: - RenderSVGImage(SVGImageElement&, Ref<RenderStyle>&&); + RenderSVGImage(SVGImageElement&, PassRef<RenderStyle>); virtual ~RenderSVGImage(); SVGImageElement& imageElement() const; bool updateImageViewport(); - virtual void setNeedsBoundariesUpdate() override { m_needsBoundariesUpdate = true; } + virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; } virtual bool needsBoundariesUpdate() override { return m_needsBoundariesUpdate; } - virtual void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; } + virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } RenderImageResource& imageResource() { return *m_imageResource; } const RenderImageResource& imageResource() const { return *m_imageResource; } @@ -55,29 +56,29 @@ public: private: void element() const = delete; - virtual const char* renderName() const override { return "RenderSVGImage"; } + virtual const char* renderName() const { return "RenderSVGImage"; } virtual bool isSVGImage() const override { return true; } virtual bool canHaveChildren() const override { return false; } - virtual const AffineTransform& localToParentTransform() const override { return m_localTransform; } + virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } - virtual FloatRect objectBoundingBox() const override { return m_objectBoundingBox; } - virtual FloatRect strokeBoundingBox() const override { return m_objectBoundingBox; } - virtual FloatRect repaintRectInLocalCoordinates() const override { return m_repaintBoundingBox; } + 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; } virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) override; - virtual void imageChanged(WrappedImagePtr, const IntRect* = nullptr) override; + virtual void imageChanged(WrappedImagePtr, const IntRect* = 0); - virtual void layout() override; - virtual void paint(PaintInfo&, const LayoutPoint&) override; + virtual void layout(); + virtual void paint(PaintInfo&, const LayoutPoint&); void invalidateBufferedForeground(); - virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override; + virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); - virtual AffineTransform localTransform() const override { return m_localTransform; } + virtual AffineTransform localTransform() const { return m_localTransform; } void calculateImageViewport(); bool m_needsBoundariesUpdate : 1; @@ -90,8 +91,9 @@ private: std::unique_ptr<ImageBuffer> m_bufferedForeground; }; -} // namespace WebCore +RENDER_OBJECT_TYPE_CASTS(RenderSVGImage, isSVGImage()) -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGImage, isSVGImage()) +} // namespace WebCore +#endif // ENABLE(SVG) #endif // RenderSVGImage_h diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.cpp b/Source/WebCore/rendering/svg/RenderSVGInline.cpp index f194702de..f1f384e93 100644 --- a/Source/WebCore/rendering/svg/RenderSVGInline.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGInline.cpp @@ -20,6 +20,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGInline.h" #include "RenderSVGInlineText.h" @@ -30,8 +32,8 @@ namespace WebCore { -RenderSVGInline::RenderSVGInline(SVGGraphicsElement& element, Ref<RenderStyle>&& style) - : RenderInline(element, WTF::move(style)) +RenderSVGInline::RenderSVGInline(SVGGraphicsElement& element, PassRef<RenderStyle> style) + : RenderInline(element, std::move(style)) { setAlwaysCreateLineBoxes(); } @@ -40,29 +42,29 @@ std::unique_ptr<InlineFlowBox> RenderSVGInline::createInlineFlowBox() { auto box = std::make_unique<SVGInlineFlowBox>(*this); box->setHasVirtualLogicalHeight(); - return WTF::move(box); + return std::move(box); } FloatRect RenderSVGInline::objectBoundingBox() const { - if (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this)) - return textAncestor->objectBoundingBox(); + if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this)) + return object->objectBoundingBox(); return FloatRect(); } FloatRect RenderSVGInline::strokeBoundingBox() const { - if (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this)) - return textAncestor->strokeBoundingBox(); + if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this)) + return object->strokeBoundingBox(); return FloatRect(); } FloatRect RenderSVGInline::repaintRectInLocalCoordinates() const { - if (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this)) - return textAncestor->repaintRectInLocalCoordinates(); + if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this)) + return object->repaintRectInLocalCoordinates(); return FloatRect(); } @@ -89,13 +91,13 @@ const RenderObject* RenderSVGInline::pushMappingToContainer(const RenderLayerMod void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const { - auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this); - if (!textAncestor) + const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this); + if (!object) return; - FloatRect textBoundingBox = textAncestor->strokeBoundingBox(); + FloatRect textBoundingBox = object->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()), UseTransforms, wasFixed)); + quads.append(localToAbsoluteQuad(FloatRect(textBoundingBox.x() + box->x(), textBoundingBox.y() + box->y(), box->logicalWidth(), box->logicalHeight()), false, wasFixed)); } void RenderSVGInline::willBeDestroyed() @@ -112,37 +114,30 @@ 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 (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this)) - textAncestor->subtreeChildWasAdded(child); + if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this)) + textRenderer->subtreeChildWasAdded(child); } void RenderSVGInline::removeChild(RenderObject& child) { SVGResourcesCache::clientWillBeRemovedFromTree(child); - auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this); - if (!textAncestor) { + RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this); + if (!textRenderer) { RenderInline::removeChild(child); return; } - Vector<SVGTextLayoutAttributes*, 2> affectedAttributes; - textAncestor->subtreeChildWillBeRemoved(&child, affectedAttributes); + textRenderer->subtreeChildWillBeRemoved(&child, affectedAttributes); RenderInline::removeChild(child); - textAncestor->subtreeChildWasRemoved(affectedAttributes); + textRenderer->subtreeChildWasRemoved(affectedAttributes); } } + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.h b/Source/WebCore/rendering/svg/RenderSVGInline.h index a001f29ff..f6dee80e9 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 Inc. + * Copyright (C) 2006 Apple Computer Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,6 +21,7 @@ #ifndef RenderSVGInline_h #define RenderSVGInline_h +#if ENABLE(SVG) #include "RenderInline.h" #include "SVGGraphicsElement.h" @@ -28,9 +29,9 @@ namespace WebCore { class RenderSVGInline : public RenderInline { public: - RenderSVGInline(SVGGraphicsElement&, Ref<RenderStyle>&&); + RenderSVGInline(SVGGraphicsElement&, PassRef<RenderStyle>); - SVGGraphicsElement& graphicsElement() const { return downcast<SVGGraphicsElement>(nodeForNonAnonymous()); } + SVGGraphicsElement& graphicsElement() const { return toSVGGraphicsElement(nodeForNonAnonymous()); } private: void element() const = delete; @@ -39,8 +40,6 @@ private: virtual bool requiresLayer() const override final { return false; } virtual bool isSVGInline() const override final { return true; } - virtual void updateFromStyle() override 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. @@ -52,7 +51,7 @@ private: 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, bool* wasFixed) 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; @@ -61,12 +60,11 @@ private: virtual void willBeDestroyed() override final; virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override final; - virtual void addChild(RenderObject* child, RenderObject* beforeChild = nullptr) override final; + virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) override final; virtual void removeChild(RenderObject&) override final; }; -} // namespace WebCore - -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGInline, isSVGInline()) +} +#endif // ENABLE(SVG) #endif // !RenderSVGTSpan_H diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp index c3c471b49..0667e8479 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 Inc. + * Copyright (C) 2006 Apple Computer 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,6 +22,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGInlineText.h" #include "CSSFontSelector.h" @@ -77,11 +79,11 @@ String RenderSVGInlineText::originalText() const return textNode().data(); } -void RenderSVGInlineText::setRenderedText(const String& text) +void RenderSVGInlineText::setTextInternal(const String& text) { - RenderText::setRenderedText(text); - if (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this)) - textAncestor->subtreeTextDidChange(this); + RenderText::setTextInternal(text); + if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this)) + textRenderer->subtreeTextDidChange(this); } void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) @@ -105,35 +107,35 @@ void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle return; // The text metrics may be influenced by style changes. - if (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this)) - textAncestor->subtreeStyleDidChange(this); + if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this)) + textRenderer->subtreeStyleDidChange(this); } std::unique_ptr<InlineTextBox> RenderSVGInlineText::createTextBox() { auto box = std::make_unique<SVGInlineTextBox>(*this); box->setHasVirtualLogicalHeight(); - return WTF::move(box); + return std::move(box); } LayoutRect RenderSVGInlineText::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit*) { - if (!is<InlineTextBox>(box)) + if (!box || !box->isInlineTextBox()) return LayoutRect(); - auto& textBox = downcast<InlineTextBox>(*box); - if (static_cast<unsigned>(caretOffset) < textBox.start() || static_cast<unsigned>(caretOffset) > textBox.start() + textBox.len()) + InlineTextBox* textBox = toInlineTextBox(box); + if (static_cast<unsigned>(caretOffset) < textBox->start() || static_cast<unsigned>(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 = textBox.isLeftToRightDirection() ? rect.x() : rect.maxX(); + if (static_cast<unsigned>(caretOffset) < textBox->start() + textBox->len()) { + LayoutRect rect = textBox->localSelectionRect(caretOffset, caretOffset + 1); + LayoutUnit x = box->isLeftToRightDirection() ? rect.x() : rect.maxX(); return LayoutRect(x, rect.y(), caretWidth, rect.height()); } - LayoutRect rect = textBox.localSelectionRect(caretOffset - 1, caretOffset); - LayoutUnit x = textBox.isLeftToRightDirection() ? rect.maxX() : rect.x(); + LayoutRect rect = textBox->localSelectionRect(caretOffset - 1, caretOffset); + LayoutUnit x = box->isLeftToRightDirection() ? rect.maxX() : rect.x(); return LayoutRect(x, rect.y(), caretWidth, rect.height()); } @@ -166,7 +168,7 @@ bool RenderSVGInlineText::characterStartsNewTextChunk(int position) const return it->value.x != SVGTextLayoutAttributes::emptyValue() || it->value.y != SVGTextLayoutAttributes::emptyValue(); } -VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point, const RenderRegion*) +VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point) { if (!firstTextBox() || !textLength()) return createVisiblePosition(0, DOWNSTREAM); @@ -182,16 +184,16 @@ VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point, float closestDistance = std::numeric_limits<float>::max(); float closestDistancePosition = 0; - const SVGTextFragment* closestDistanceFragment = nullptr; - SVGInlineTextBox* closestDistanceBox = nullptr; + const SVGTextFragment* closestDistanceFragment = 0; + SVGInlineTextBox* closestDistanceBox = 0; AffineTransform fragmentTransform; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { - if (!is<SVGInlineTextBox>(*box)) + if (!box->isSVGInlineTextBox()) continue; - auto& textBox = downcast<SVGInlineTextBox>(*box); - Vector<SVGTextFragment>& fragments = textBox.textFragments(); + SVGInlineTextBox* textBox = toSVGInlineTextBox(box); + Vector<SVGTextFragment>& fragments = textBox->textFragments(); unsigned textFragmentsSize = fragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { @@ -206,7 +208,7 @@ VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point, if (distance < closestDistance) { closestDistance = distance; - closestDistanceBox = &textBox; + closestDistanceBox = textBox; closestDistanceFragment = &fragment; closestDistancePosition = fragmentRect.x(); } @@ -222,26 +224,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(const RenderObject& renderer, const RenderStyle& style, float& scalingFactor, FontCascade& scaledFont) +void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, const RenderStyle* style, float& scalingFactor, Font& 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 || style.fontDescription().textRenderingMode() == GeometricPrecision) { + if (scalingFactor == 1 || !scalingFactor || style->fontDescription().textRenderingMode() == GeometricPrecision) { scalingFactor = 1; - scaledFont = style.fontCascade(); + scaledFont = style->font(); return; } - FontDescription fontDescription(style.fontDescription()); + FontDescription 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 = FontCascade(fontDescription, 0, 0); - scaledFont.update(&renderer.document().fontSelector()); + scaledFont = Font(fontDescription, 0, 0); + scaledFont.update(renderer->document().ensureStyleResolver().fontSelector()); } } + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.h b/Source/WebCore/rendering/svg/RenderSVGInlineText.h index 7e349978e..c07228e21 100644 --- a/Source/WebCore/rendering/svg/RenderSVGInlineText.h +++ b/Source/WebCore/rendering/svg/RenderSVGInlineText.h @@ -22,7 +22,8 @@ #ifndef RenderSVGInlineText_h #define RenderSVGInlineText_h -#include "FontCascade.h" +#if ENABLE(SVG) +#include "Font.h" #include "RenderText.h" #include "SVGTextLayoutAttributes.h" #include "Text.h" @@ -35,15 +36,15 @@ class RenderSVGInlineText final : public RenderText { public: RenderSVGInlineText(Text&, const String&); - Text& textNode() const { return downcast<Text>(nodeForNonAnonymous()); } + Text& textNode() const { return toText(nodeForNonAnonymous()); } bool characterStartsNewTextChunk(int position) const; SVGTextLayoutAttributes* layoutAttributes() { return &m_layoutAttributes; } float scalingFactor() const { return m_scalingFactor; } - const FontCascade& scaledFont() const { return m_scaledFont; } + const Font& scaledFont() const { return m_scaledFont; } void updateScaledFont(); - static void computeNewScaledFontForStyle(const RenderObject&, const RenderStyle&, float& scalingFactor, FontCascade& scaledFont); + static void computeNewScaledFontForStyle(RenderObject*, const RenderStyle*, float& scalingFactor, Font& 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; @@ -52,25 +53,26 @@ private: virtual const char* renderName() const override { return "RenderSVGInlineText"; } virtual String originalText() const override; - virtual void setRenderedText(const String&) override; + virtual void setTextInternal(const String&) override; virtual void styleDidChange(StyleDifference, const RenderStyle*) override; virtual FloatRect objectBoundingBox() const override { return floatLinesBoundingBox(); } virtual bool isSVGInlineText() const override { return true; } - virtual VisiblePosition positionForPoint(const LayoutPoint&, const RenderRegion*) override; + 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; float m_scalingFactor; - FontCascade m_scaledFont; + Font m_scaledFont; SVGTextLayoutAttributes m_layoutAttributes; }; -} // namespace WebCore +RENDER_OBJECT_TYPE_CASTS(RenderSVGInlineText, isSVGInlineText()) -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGInlineText, isSVGInlineText()) +} +#endif // ENABLE(SVG) #endif // RenderSVGInlineText_h diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp index 68b20da62..78768eafe 100644 --- a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp @@ -29,6 +29,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGModelObject.h" #include "RenderLayerModelObject.h" @@ -39,8 +41,8 @@ namespace WebCore { -RenderSVGModelObject::RenderSVGModelObject(SVGElement& element, Ref<RenderStyle>&& style) - : RenderElement(element, WTF::move(style), 0) +RenderSVGModelObject::RenderSVGModelObject(SVGElement& element, PassRef<RenderStyle> style) + : RenderElement(element, std::move(style), 0) , m_hasSVGShadow(false) { } @@ -74,7 +76,7 @@ LayoutRect RenderSVGModelObject::outlineBoundsForRepaint(const RenderLayerModelO adjustRectForOutlineAndShadow(box); FloatQuad containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer); - return LayoutRect(snapRectToDevicePixels(LayoutRect(containerRelativeQuad.boundingBox()), document().deviceScaleFactor())); + return containerRelativeQuad.enclosingBoundingBox(); } void RenderSVGModelObject::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const @@ -86,7 +88,7 @@ void RenderSVGModelObject::absoluteRects(Vector<IntRect>& rects, const LayoutPoi void RenderSVGModelObject::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const { - quads.append(localToAbsoluteQuad(strokeBoundingBox(), UseTransforms, wasFixed)); + quads.append(localToAbsoluteQuad(strokeBoundingBox(), 0 /* mode */, wasFixed)); } void RenderSVGModelObject::willBeDestroyed() @@ -124,11 +126,11 @@ static void getElementCTM(SVGElement* element, AffineTransform& transform) Node* current = element; while (current && current->isSVGElement()) { - SVGElement& currentElement = downcast<SVGElement>(*current); - localTransform = currentElement.renderer()->localToParentTransform(); + SVGElement* currentElement = toSVGElement(current); + localTransform = currentElement->renderer()->localToParentTransform(); transform = localTransform.multiply(transform); // For getCTM() computation, stop at the nearest viewport element - if (¤tElement == stopAtElement) + if (currentElement == stopAtElement) break; current = current->parentOrShadowHostNode(); @@ -171,7 +173,7 @@ bool RenderSVGModelObject::checkIntersection(RenderElement* renderer, const Floa if (!isGraphicsElement(*renderer)) return false; AffineTransform ctm; - SVGElement* svgElement = downcast<SVGElement>(renderer->element()); + SVGElement* svgElement = toSVGElement(renderer->element()); getElementCTM(svgElement, ctm); ASSERT(svgElement->renderer()); return intersectsAllowingEmpty(rect, ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates())); @@ -184,10 +186,12 @@ bool RenderSVGModelObject::checkEnclosure(RenderElement* renderer, const FloatRe if (!isGraphicsElement(*renderer)) return false; AffineTransform ctm; - SVGElement* svgElement = downcast<SVGElement>(renderer->element()); + SVGElement* svgElement = toSVGElement(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 00d2f69f3..a7cd417aa 100644 --- a/Source/WebCore/rendering/svg/RenderSVGModelObject.h +++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.h @@ -31,6 +31,8 @@ #ifndef RenderSVGModelObject_h #define RenderSVGModelObject_h +#if ENABLE(SVG) + #include "RenderElement.h" #include "SVGElement.h" #include "SVGRenderSupport.h" @@ -53,7 +55,7 @@ public: virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const override final; virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override; - virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, bool* wasFixed) 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 styleDidChange(StyleDifference, const RenderStyle* oldStyle) override; @@ -64,10 +66,10 @@ public: bool hasSVGShadow() const { return m_hasSVGShadow; } void setHasSVGShadow(bool hasShadow) { m_hasSVGShadow = hasShadow; } - SVGElement& element() const { return downcast<SVGElement>(nodeForNonAnonymous()); } + SVGElement& element() const { return toSVGElement(nodeForNonAnonymous()); } protected: - RenderSVGModelObject(SVGElement&, Ref<RenderStyle>&&); + RenderSVGModelObject(SVGElement&, PassRef<RenderStyle>); virtual void willBeDestroyed() override; @@ -80,8 +82,9 @@ private: bool m_hasSVGShadow; }; -} // namespace WebCore +RENDER_OBJECT_TYPE_CASTS(RenderSVGModelObject, isRenderSVGModelObject()); -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGModelObject, isRenderSVGModelObject()) +} +#endif // ENABLE(SVG) #endif diff --git a/Source/WebCore/rendering/svg/RenderSVGPath.cpp b/Source/WebCore/rendering/svg/RenderSVGPath.cpp index 8e40d8be9..353dd238c 100644 --- a/Source/WebCore/rendering/svg/RenderSVGPath.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGPath.cpp @@ -26,6 +26,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGPath.h" #include "SVGPathElement.h" @@ -33,8 +35,8 @@ namespace WebCore { -RenderSVGPath::RenderSVGPath(SVGGraphicsElement& element, Ref<RenderStyle>&& style) - : RenderSVGShape(element, WTF::move(style)) +RenderSVGPath::RenderSVGPath(SVGGraphicsElement& element, PassRef<RenderStyle> style) + : RenderSVGShape(element, std::move(style)) { } @@ -67,9 +69,9 @@ FloatRect RenderSVGPath::calculateUpdatedStrokeBoundingBox() const static void useStrokeStyleToFill(GraphicsContext* context) { if (Gradient* gradient = context->strokeGradient()) - context->setFillGradient(*gradient); + context->setFillGradient(gradient); else if (Pattern* pattern = context->strokePattern()) - context->setFillPattern(*pattern); + context->setFillPattern(pattern); else context->setFillColor(context->strokeColor(), context->strokeColorSpace()); } @@ -131,7 +133,7 @@ bool RenderSVGPath::shouldStrokeZeroLengthSubpath() const Path* RenderSVGPath::zeroLengthLinecapPath(const FloatPoint& linecapPosition) const { - DEPRECATED_DEFINE_STATIC_LOCAL(Path, tempPath, ()); + DEFINE_STATIC_LOCAL(Path, tempPath, ()); tempPath.clear(); if (style().svgStyle().capStyle() == SquareCap) @@ -155,17 +157,10 @@ void RenderSVGPath::updateZeroLengthSubpaths() return; SVGSubpathData subpathData(m_zeroLengthLinecapLocations); - path().apply([&subpathData](const PathElement& pathElement) { - SVGSubpathData::updateFromPathElement(subpathData, pathElement); - }); + path().apply(&subpathData, SVGSubpathData::updateFromPathElement); 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 08d89119e..5ffd494f4 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 Inc. + * Copyright (C) 2006 Apple Computer, Inc * Copyright (C) 2009 Google, Inc. * Copyright (C) 2011 Renata Hodovan <reni@webkit.org> * Copyright (C) 2011 University of Szeged @@ -26,18 +26,19 @@ #ifndef RenderSVGPath_h #define RenderSVGPath_h +#if ENABLE(SVG) #include "RenderSVGShape.h" namespace WebCore { class RenderSVGPath final : public RenderSVGShape { public: - RenderSVGPath(SVGGraphicsElement&, Ref<RenderStyle>&&); + RenderSVGPath(SVGGraphicsElement&, PassRef<RenderStyle>); virtual ~RenderSVGPath(); private: virtual bool isSVGPath() const override { return true; } - virtual const char* renderName() const override { return "RenderSVGPath"; } + virtual const char* renderName() const { return "RenderSVGPath"; } virtual void updateShapeFromElement() override; FloatRect calculateUpdatedStrokeBoundingBox() const; @@ -50,13 +51,12 @@ private: FloatRect zeroLengthSubpathRect(const FloatPoint&, float) const; void updateZeroLengthSubpaths(); - virtual bool isRenderingDisabled() const override; - Vector<FloatPoint> m_zeroLengthLinecapLocations; }; -} // namespace WebCore +RENDER_OBJECT_TYPE_CASTS(RenderSVGPath, isSVGPath()) -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGPath, isSVGPath()) +} -#endif // RenderSVGPath_h +#endif // ENABLE(SVG) +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGRect.cpp b/Source/WebCore/rendering/svg/RenderSVGRect.cpp index 03fbbb9d5..bfda62f5f 100644 --- a/Source/WebCore/rendering/svg/RenderSVGRect.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGRect.cpp @@ -26,14 +26,16 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGRect.h" #include "SVGNames.h" namespace WebCore { -RenderSVGRect::RenderSVGRect(SVGRectElement& element, Ref<RenderStyle>&& style) - : RenderSVGShape(element, WTF::move(style)) +RenderSVGRect::RenderSVGRect(SVGRectElement& element, PassRef<RenderStyle> style) + : RenderSVGShape(element, std::move(style)) , m_usePathFallback(false) { } @@ -44,7 +46,7 @@ RenderSVGRect::~RenderSVGRect() SVGRectElement& RenderSVGRect::rectElement() const { - return downcast<SVGRectElement>(RenderSVGShape::graphicsElement()); + return toSVGRectElement(RenderSVGShape::graphicsElement()); } void RenderSVGRect::updateShapeFromElement() @@ -56,26 +58,19 @@ void RenderSVGRect::updateShapeFromElement() m_outerStrokeRect = FloatRect(); SVGLengthContext lengthContext(&rectElement()); - FloatSize boundingBoxSize(lengthContext.valueForLength(style().width(), LengthModeWidth), lengthContext.valueForLength(style().height(), LengthModeHeight)); - - // Element is invalid if either dimension is negative. - if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0) + // 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; - - // 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); + m_usePathFallback = false; + FloatSize boundingBoxSize(rectElement().width().value(lengthContext), rectElement().height().value(lengthContext)); + if (boundingBoxSize.isEmpty()) + return; + + m_fillBoundingBox = FloatRect(FloatPoint(rectElement().x().value(lengthContext), rectElement().y().value(lengthContext)), 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. @@ -153,10 +148,6 @@ 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 970301aa7..c305726b8 100644 --- a/Source/WebCore/rendering/svg/RenderSVGRect.h +++ b/Source/WebCore/rendering/svg/RenderSVGRect.h @@ -28,6 +28,7 @@ #ifndef RenderSVGRect_h #define RenderSVGRect_h +#if ENABLE(SVG) #include "RenderSVGPath.h" #include "SVGRectElement.h" @@ -35,7 +36,7 @@ namespace WebCore { class RenderSVGRect final : public RenderSVGShape { public: - RenderSVGRect(SVGRectElement&, Ref<RenderStyle>&&); + RenderSVGRect(SVGRectElement&, PassRef<RenderStyle>); virtual ~RenderSVGRect(); SVGRectElement& rectElement() const; @@ -43,15 +44,14 @@ public: private: void graphicsElement() const = delete; - virtual const char* renderName() const override { return "RenderSVGRect"; } + virtual const char* renderName() const { return "RenderSVGRect"; } - virtual void updateShapeFromElement() override; - virtual bool isEmpty() const override { return m_usePathFallback ? RenderSVGShape::isEmpty() : m_fillBoundingBox.isEmpty(); } - virtual bool isRenderingDisabled() const override; - virtual void fillShape(GraphicsContext*) const override; - virtual void strokeShape(GraphicsContext*) const override; - virtual bool shapeDependentStrokeContains(const FloatPoint&) override; - virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const override; + 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; private: FloatRect m_innerStrokeRect; @@ -61,4 +61,5 @@ private: } +#endif // ENABLE(SVG) #endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResource.cpp b/Source/WebCore/rendering/svg/RenderSVGResource.cpp index 699e54418..d9e1d835e 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResource.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResource.cpp @@ -21,6 +21,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGResource.h" #include "Frame.h" @@ -111,7 +113,7 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m } // If no resources are associated with the given renderer, return the color resource. - auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer); if (!resources) { if (paintType == SVGPaint::SVG_PAINTTYPE_URI_NONE || !inheritColorFromParentStyleIfNeeded(renderer, applyToFill, color)) return nullptr; @@ -154,38 +156,28 @@ RenderSVGResourceSolidColor* RenderSVGResource::sharedSolidPaintingResource() return s_sharedSolidPaintingResource; } -static inline void removeFromCacheAndInvalidateDependencies(RenderElement& renderer, bool needsLayout) +static inline void removeFromCacheAndInvalidateDependencies(RenderObject& object, bool needsLayout) { - if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) { + if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object)) { +#if ENABLE(FILTERS) if (RenderSVGResourceFilter* filter = resources->filter()) - filter->removeClientFromCache(renderer); - + filter->removeClientFromCache(object); +#endif if (RenderSVGResourceMasker* masker = resources->masker()) - masker->removeClientFromCache(renderer); + masker->removeClientFromCache(object); if (RenderSVGResourceClipper* clipper = resources->clipper()) - clipper->removeClientFromCache(renderer); + clipper->removeClientFromCache(object); } - if (!renderer.element() || !renderer.element()->isSVGElement()) + if (!object.node() || !object.node()->isSVGElement()) return; - HashSet<SVGElement*>* dependencies = renderer.document().accessSVGExtensions().setOfElementsReferencingTarget(downcast<SVGElement>(renderer.element())); + HashSet<SVGElement*>* dependencies = object.document().accessSVGExtensions()->setOfElementsReferencingTarget(toSVGElement(object.node())); if (!dependencies) return; - - // 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; - } + for (auto element : *dependencies) { + if (auto renderer = element->renderer()) RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer, needsLayout); - invalidatingDependencies.get().remove(element); - } } } @@ -196,17 +188,16 @@ void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject& if (needsLayout && !object.documentBeingDestroyed()) object.setNeedsLayout(); - if (is<RenderElement>(object)) - removeFromCacheAndInvalidateDependencies(downcast<RenderElement>(object), needsLayout); + removeFromCacheAndInvalidateDependencies(object, needsLayout); // Invalidate resources in ancestor chain, if needed. - auto current = object.parent(); + RenderObject* current = object.parent(); while (current) { removeFromCacheAndInvalidateDependencies(*current, needsLayout); - if (is<RenderSVGResourceContainer>(*current)) { + if (current->isSVGResourceContainer()) { // This will process the rest of the ancestors. - downcast<RenderSVGResourceContainer>(*current).removeAllClientsFromCache(); + current->toRenderSVGResourceContainer()->removeAllClientsFromCache(); break; } @@ -215,3 +206,6 @@ void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject& } } + +#endif + diff --git a/Source/WebCore/rendering/svg/RenderSVGResource.h b/Source/WebCore/rendering/svg/RenderSVGResource.h index ed7a70f50..2c66ffade 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResource.h +++ b/Source/WebCore/rendering/svg/RenderSVGResource.h @@ -20,10 +20,10 @@ #ifndef RenderSVGResource_h #define RenderSVGResource_h +#if ENABLE(SVG) #include "RenderSVGShape.h" #include "RenderStyleConstants.h" #include "SVGDocumentExtensions.h" -#include <wtf/TypeCasts.h> namespace WebCore { @@ -60,7 +60,7 @@ public: virtual ~RenderSVGResource() { } virtual void removeAllClientsFromCache(bool markForInvalidation = true) = 0; - virtual void removeClientFromCache(RenderElement&, bool markForInvalidation = true) = 0; + virtual void removeClientFromCache(RenderObject&, 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,6 +68,15 @@ 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); @@ -78,9 +87,5 @@ public: } -#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() - +#endif #endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp index 65a3e3222..5a6af206d 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp @@ -21,6 +21,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGResourceClipper.h" #include "ElementIterator.h" @@ -40,8 +42,10 @@ namespace WebCore { -RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement& element, Ref<RenderStyle>&& style) - : RenderSVGResourceContainer(element, WTF::move(style)) +RenderSVGResourceType RenderSVGResourceClipper::s_resourceType = ClipperResourceType; + +RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement& element, PassRef<RenderStyle> style) + : RenderSVGResourceContainer(element, std::move(style)) { } @@ -57,7 +61,7 @@ void RenderSVGResourceClipper::removeAllClientsFromCache(bool markForInvalidatio markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourceClipper::removeClientFromCache(RenderElement& client, bool markForInvalidation) +void RenderSVGResourceClipper::removeClientFromCache(RenderObject& client, bool markForInvalidation) { m_clipper.remove(&client); @@ -92,9 +96,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() || !downcast<SVGElement>(*childNode).isSVGGraphicsElement()) + if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGGraphicsElement()) continue; - SVGGraphicsElement& styled = downcast<SVGGraphicsElement>(*childNode); + SVGGraphicsElement* styled = toSVGGraphicsElement(childNode); const RenderStyle& style = renderer->style(); if (style.display() == NONE || style.visibility() != VISIBLE) continue; @@ -104,7 +108,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; @@ -130,29 +134,33 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const bool RenderSVGResourceClipper::applyClippingToContext(RenderElement& renderer, const FloatRect& objectBoundingBox, const FloatRect& repaintRect, GraphicsContext* context) { - ClipperMaskImage& clipperMaskImage = addRendererToClipper(renderer); - bool shouldCreateClipperMaskImage = !clipperMaskImage; + bool missingClipperData = !m_clipper.contains(&renderer); + if (missingClipperData) + m_clipper.set(&renderer, std::make_unique<ClipperData>()); + 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; + } - if (shouldCreateClipperMaskImage && pathOnlyClipping(context, animatedLocalTransform, objectBoundingBox)) - return true; - - AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer); + AffineTransform absoluteTransform; + SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(&renderer, absoluteTransform); - 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, ColorSpaceDeviceRGB, Unaccelerated); - if (!clipperMaskImage) + if (shouldCreateClipData && !repaintRect.isEmpty()) { + if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, clipperData->clipMaskImage, ColorSpaceDeviceRGB, Unaccelerated)) return false; - GraphicsContext* maskContext = clipperMaskImage->context(); + GraphicsContext* maskContext = clipperData->clipMaskImage->context(); ASSERT(maskContext); maskContext->concatCTM(animatedLocalTransform); // clipPath can also be clipped by another clipPath. - auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this); RenderSVGResourceClipper* clipper; bool succeeded; if (resources && (clipper = resources->clipper())) { @@ -161,27 +169,28 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderElement& renderer, c if (!clipper->applyClippingToContext(*this, objectBoundingBox, repaintRect, maskContext)) return false; - succeeded = drawContentIntoMaskImage(clipperMaskImage, objectBoundingBox); + succeeded = drawContentIntoMaskImage(clipperData, objectBoundingBox); // The context restore applies the clipping on non-CG platforms. } else - succeeded = drawContentIntoMaskImage(clipperMaskImage, objectBoundingBox); + succeeded = drawContentIntoMaskImage(clipperData, objectBoundingBox); if (!succeeded) - clipperMaskImage.reset(); + clipperData->clipMaskImage.reset(); } - if (!clipperMaskImage) + if (!clipperData->clipMaskImage) return false; - SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, clipperMaskImage, shouldCreateClipperMaskImage); + SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, clipperData->clipMaskImage, missingClipperData); return true; } -bool RenderSVGResourceClipper::drawContentIntoMaskImage(const ClipperMaskImage& clipperMaskImage, const FloatRect& objectBoundingBox) +bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData, const FloatRect& objectBoundingBox) { - ASSERT(clipperMaskImage); + ASSERT(clipperData); + ASSERT(clipperData->clipMaskImage); - GraphicsContext* maskContext = clipperMaskImage->context(); + GraphicsContext* maskContext = clipperData->clipMaskImage->context(); ASSERT(maskContext); AffineTransform maskContentTransformation; @@ -215,11 +224,11 @@ bool RenderSVGResourceClipper::drawContentIntoMaskImage(const ClipperMaskImage& WindRule newClipRule = style.svgStyle().clipRule(); bool isUseElement = child.hasTagName(SVGNames::useTag); if (isUseElement) { - SVGUseElement& useElement = downcast<SVGUseElement>(child); + SVGUseElement& useElement = toSVGUseElement(child); renderer = useElement.rendererClipChild(); if (!renderer) continue; - if (!useElement.fastHasAttribute(SVGNames::clip_ruleAttr)) + if (!useElement.hasAttribute(SVGNames::clip_ruleAttr)) newClipRule = renderer->style().svgStyle().clipRule(); } @@ -232,7 +241,7 @@ bool RenderSVGResourceClipper::drawContentIntoMaskImage(const ClipperMaskImage& // 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(clipperMaskImage.get(), isUseElement ? *child.renderer() : *renderer, maskContentTransformation); + SVGRenderingContext::renderSubtreeToImageBuffer(clipperData->clipMaskImage.get(), isUseElement ? *child.renderer() : *renderer, maskContentTransformation); } view().frameView().setPaintBehavior(oldBehavior); @@ -256,11 +265,6 @@ 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; @@ -294,10 +298,8 @@ 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()) { - addRendererToClipper(object); + if (selfNeedsLayout()) return object.objectBoundingBox(); - } if (m_clipBoundaries.isEmpty()) calculateClipContentRepaintRect(); @@ -314,3 +316,5 @@ 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 4415b94b1..31c64b8b7 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.h @@ -20,6 +20,7 @@ #ifndef RenderSVGResourceClipper_h #define RenderSVGResourceClipper_h +#if ENABLE(SVG) #include "GraphicsContext.h" #include "ImageBuffer.h" #include "IntSize.h" @@ -31,17 +32,21 @@ namespace WebCore { -typedef std::unique_ptr<ImageBuffer> ClipperMaskImage; +struct ClipperData { + WTF_MAKE_FAST_ALLOCATED; +public: + std::unique_ptr<ImageBuffer> clipMaskImage; +}; class RenderSVGResourceClipper final : public RenderSVGResourceContainer { public: - RenderSVGResourceClipper(SVGClipPathElement&, Ref<RenderStyle>&&); + RenderSVGResourceClipper(SVGClipPathElement&, PassRef<RenderStyle>); virtual ~RenderSVGResourceClipper(); - SVGClipPathElement& clipPathElement() const { return downcast<SVGClipPathElement>(nodeForNonAnonymous()); } + SVGClipPathElement& clipPathElement() const { return toSVGClipPathElement(nodeForNonAnonymous()); } - virtual void removeAllClientsFromCache(bool markForInvalidation = true) override; - virtual void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override; + virtual void removeAllClientsFromCache(bool markForInvalidation = true); + virtual void removeClientFromCache(RenderObject&, bool markForInvalidation = true); virtual 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 @@ -50,31 +55,27 @@ public: bool applyClippingToContext(RenderElement&, const FloatRect&, const FloatRect&, GraphicsContext*); virtual FloatRect resourceBoundingBox(const RenderObject&) override; - virtual RenderSVGResourceType resourceType() const override { return ClipperResourceType; } + virtual RenderSVGResourceType resourceType() const { return ClipperResourceType; } bool hitTestClipContent(const FloatRect&, const FloatPoint&); SVGUnitTypes::SVGUnitType clipPathUnits() const { return clipPathElement().clipPathUnits(); } -protected: - virtual bool selfNeedsClientInvalidation() const override { return (everHadLayout() || m_clipper.size()) && selfNeedsLayout(); } - + static RenderSVGResourceType s_resourceType; private: void element() const = delete; virtual const char* renderName() const override { return "RenderSVGResourceClipper"; } bool pathOnlyClipping(GraphicsContext*, const AffineTransform&, const FloatRect&); - bool drawContentIntoMaskImage(const ClipperMaskImage&, const FloatRect& objectBoundingBox); + bool drawContentIntoMaskImage(ClipperData*, const FloatRect& objectBoundingBox); void calculateClipContentRepaintRect(); - ClipperMaskImage& addRendererToClipper(const RenderObject&); FloatRect m_clipBoundaries; - HashMap<const RenderObject*, ClipperMaskImage> m_clipper; + HashMap<RenderObject*, std::unique_ptr<ClipperData>> m_clipper; }; } -SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourceClipper, ClipperResourceType) - +#endif #endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp index eea2ae3f3..2d8a73138 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp @@ -18,6 +18,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGResourceContainer.h" #include "RenderLayer.h" @@ -31,11 +33,12 @@ namespace WebCore { static inline SVGDocumentExtensions& svgExtensionsFromElement(SVGElement& element) { - return element.document().accessSVGExtensions(); + // FIXME: accessSVGExtensions() should return a reference. + return *element.document().accessSVGExtensions(); } -RenderSVGResourceContainer::RenderSVGResourceContainer(SVGElement& element, Ref<RenderStyle>&& style) - : RenderSVGHiddenContainer(element, WTF::move(style)) +RenderSVGResourceContainer::RenderSVGResourceContainer(SVGElement& element, PassRef<RenderStyle> style) + : RenderSVGHiddenContainer(element, std::move(style)) , m_id(element.getIdAttribute()) , m_registered(false) , m_isInvalidating(false) @@ -52,7 +55,7 @@ void RenderSVGResourceContainer::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; // Invalidate all resources if our layout changed. - if (selfNeedsClientInvalidation()) + if (everHadLayout() && selfNeedsLayout()) RenderSVGRoot::addResourceForClientInvalidation(this); RenderSVGHiddenContainer::layout(); @@ -95,9 +98,9 @@ void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode bool needsLayout = mode == LayoutAndBoundariesInvalidation; bool markForInvalidation = mode != ParentOnlyInvalidation; - for (auto* client : m_clients) { - if (is<RenderSVGResourceContainer>(*client)) { - downcast<RenderSVGResourceContainer>(*client).removeAllClientsFromCache(markForInvalidation); + for (auto client : m_clients) { + if (client->isSVGResourceContainer()) { + client->toRenderSVGResourceContainer()->removeAllClientsFromCache(markForInvalidation); continue; } @@ -114,8 +117,10 @@ void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode void RenderSVGResourceContainer::markAllClientLayersForInvalidation() { - for (auto* clientLayer : m_clientLayers) +#if ENABLE(CSS_FILTERS) + for (auto clientLayer : m_clientLayers) clientLayer->filterNeedsRepaint(); +#endif } void RenderSVGResourceContainer::markClientForInvalidation(RenderObject& client, InvalidationMode mode) @@ -136,15 +141,17 @@ void RenderSVGResourceContainer::markClientForInvalidation(RenderObject& client, } } -void RenderSVGResourceContainer::addClient(RenderElement& client) +void RenderSVGResourceContainer::addClient(RenderObject* client) { - m_clients.add(&client); + ASSERT(client); + m_clients.add(client); } -void RenderSVGResourceContainer::removeClient(RenderElement& client) +void RenderSVGResourceContainer::removeClient(RenderObject* client) { - removeClientFromCache(client, false); - m_clients.remove(&client); + ASSERT(client); + removeClientFromCache(*client, false); + m_clients.remove(client); } void RenderSVGResourceContainer::addClientRenderLayer(RenderLayer* client) @@ -173,10 +180,11 @@ void RenderSVGResourceContainer::registerResource() extensions.addResource(m_id, this); // Update cached resources of pending clients. - for (auto* client : *clients) { - ASSERT(client->hasPendingResources()); - extensions.clearHasPendingResourcesIfPossible(client); - auto* renderer = client->renderer(); + auto end = clients->end(); + for (auto it = clients->begin(); it != end; ++it) { + ASSERT((*it)->hasPendingResources()); + extensions.clearHasPendingResourcesIfPossible(*it); + auto renderer = (*it)->renderer(); if (!renderer) continue; SVGResourcesCache::clientStyleChanged(*renderer, StyleDifferenceLayout, renderer->style()); @@ -184,20 +192,20 @@ void RenderSVGResourceContainer::registerResource() } } -bool RenderSVGResourceContainer::shouldTransformOnTextPainting(const RenderElement& renderer, AffineTransform& resourceTransform) +bool RenderSVGResourceContainer::shouldTransformOnTextPainting(RenderObject* object, 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(renderer.isSVGText() || renderer.isSVGTextPath() || renderer.isSVGInline()); + ASSERT(object->isSVGText() || object->isSVGTextPath() || object->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(renderer); + float scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(object); if (scalingFactor == 1) return false; resourceTransform.scale(scalingFactor); @@ -211,10 +219,12 @@ AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderOb if (!object->isSVGShape()) return resourceTransform; - SVGGraphicsElement* element = downcast<SVGGraphicsElement>(object->node()); + SVGGraphicsElement* element = toSVGGraphicsElement(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 a03706e36..b4045cabe 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h @@ -20,6 +20,7 @@ #ifndef RenderSVGResourceContainer_h #define RenderSVGResourceContainer_h +#if ENABLE(SVG) #include "RenderSVGHiddenContainer.h" #include "RenderSVGResource.h" @@ -36,8 +37,9 @@ public: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override final; virtual bool isSVGResourceContainer() const override final { return true; } + virtual RenderSVGResourceContainer* toRenderSVGResourceContainer() override final { return this; } - static bool shouldTransformOnTextPainting(const RenderElement&, AffineTransform&); + static bool shouldTransformOnTextPainting(RenderObject*, AffineTransform&); static AffineTransform transformOnNonScalingStroke(RenderObject*, const AffineTransform& resourceTransform); void idChanged(); @@ -45,7 +47,7 @@ public: void removeClientRenderLayer(RenderLayer*); protected: - RenderSVGResourceContainer(SVGElement&, Ref<RenderStyle>&&); + RenderSVGResourceContainer(SVGElement&, PassRef<RenderStyle>); enum InvalidationMode { LayoutAndBoundariesInvalidation, @@ -55,16 +57,14 @@ 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(RenderElement&); - void removeClient(RenderElement&); + void addClient(RenderObject*); + void removeClient(RenderObject*); private: virtual void willBeDestroyed() override final; @@ -73,35 +73,31 @@ private: AtomicString m_id; bool m_registered : 1; bool m_isInvalidating : 1; - HashSet<RenderElement*> m_clients; + HashSet<RenderObject*> m_clients; HashSet<RenderLayer*> m_clientLayers; }; inline RenderSVGResourceContainer* getRenderSVGResourceContainerById(Document& document, const AtomicString& id) { if (id.isEmpty()) - return nullptr; + return 0; - if (RenderSVGResourceContainer* renderResource = document.accessSVGExtensions().resourceById(id)) + if (RenderSVGResourceContainer* renderResource = document.accessSVGExtensions()->resourceById(id)) return renderResource; - return nullptr; + return 0; } template<typename Renderer> Renderer* getRenderSVGResourceById(Document& document, const AtomicString& id) { - // 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); + if (RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id)) + return container->cast<Renderer>(); - return nullptr; + return 0; } -} // namespace WebCore - -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGResourceContainer, isSVGResourceContainer()) +} -#endif // RenderSVGResourceContainer_h +#endif +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp index e31865d80..9dd85d6d8 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp @@ -22,6 +22,8 @@ */ #include "config.h" + +#if ENABLE(SVG) && ENABLE(FILTERS) #include "RenderSVGResourceFilter.h" #include "ElementChildIterator.h" @@ -39,12 +41,15 @@ #include "SVGNames.h" #include "SVGRenderingContext.h" #include "Settings.h" +#include "SourceAlpha.h" #include "SourceGraphic.h" namespace WebCore { -RenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement& element, Ref<RenderStyle>&& style) - : RenderSVGResourceContainer(element, WTF::move(style)) +RenderSVGResourceType RenderSVGResourceFilter::s_resourceType = FilterResourceType; + +RenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement& element, PassRef<RenderStyle> style) + : RenderSVGResourceContainer(element, std::move(style)) { } @@ -59,7 +64,7 @@ void RenderSVGResourceFilter::removeAllClientsFromCache(bool markForInvalidation markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourceFilter::removeClientFromCache(RenderElement& client, bool markForInvalidation) +void RenderSVGResourceFilter::removeClientFromCache(RenderObject& client, bool markForInvalidation) { if (FilterData* filterData = m_filter.get(&client)) { if (filterData->savedContext) @@ -71,16 +76,16 @@ void RenderSVGResourceFilter::removeClientFromCache(RenderElement& client, bool markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation); } -std::unique_ptr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter& filter) const +std::unique_ptr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* filter) { static const unsigned maxCountChildNodes = 200; - if (filterElement().countChildNodes() > maxCountChildNodes) + if (filterElement().childNodeCount() > 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)); + auto builder = std::make_unique<SVGFilterBuilder>(SourceGraphic::create(filter), SourceAlpha::create(filter)); for (auto& element : childrenOfType<SVGFilterPrimitiveStandardAttributes>(filterElement())) { RefPtr<FilterEffect> effect = element.build(builder.get(), filter); if (!effect) { @@ -96,6 +101,21 @@ std::unique_ptr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFi 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); @@ -116,7 +136,8 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende return false; // Determine absolute transformation matrix for filter. - AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer); + AffineTransform absoluteTransform; + SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(&renderer, absoluteTransform); if (!absoluteTransform.isInvertible()) return false; @@ -134,7 +155,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); + filterData->builder = buildPrimitives(filterData->filter.get()); if (!filterData->builder) return false; @@ -151,8 +172,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); @@ -162,13 +183,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 (ImageBuffer::sizeNeedsClamping(subRegion.size(), scale)) { + if (!fitsInMaximumImageSize(subRegion.size(), scale)) { filterData->filter->setFilterResolution(scale); - RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(*lastEffect); + RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect); } // If the drawingRegion is empty, we have something like <g filter=".."/>. @@ -176,7 +197,7 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende if (filterData->drawingRegion.isEmpty()) { ASSERT(!m_filter.contains(&renderer)); filterData->savedContext = context; - m_filter.set(&renderer, WTF::move(filterData)); + m_filter.set(&renderer, std::move(filterData)); return false; } @@ -185,13 +206,12 @@ 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; - - auto sourceGraphic = SVGRenderingContext::createImageBuffer(filterData->drawingRegion, effectiveTransform, ColorSpaceLinearRGB, renderingMode); - if (!sourceGraphic) { + if (!SVGRenderingContext::createImageBuffer(filterData->drawingRegion, effectiveTransform, sourceGraphic, ColorSpaceLinearRGB, renderingMode)) { ASSERT(!m_filter.contains(&renderer)); filterData->savedContext = context; - m_filter.set(&renderer, WTF::move(filterData)); + m_filter.set(&renderer, std::move(filterData)); return false; } @@ -201,13 +221,13 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende GraphicsContext* sourceGraphicContext = sourceGraphic->context(); ASSERT(sourceGraphicContext); - filterData->sourceGraphicBuffer = WTF::move(sourceGraphic); + filterData->sourceGraphicBuffer = std::move(sourceGraphic); filterData->savedContext = context; context = sourceGraphicContext; ASSERT(!m_filter.contains(&renderer)); - m_filter.set(&renderer, WTF::move(filterData)); + m_filter.set(&renderer, std::move(filterData)); return true; } @@ -255,7 +275,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(WTF::move(filterData->sourceGraphicBuffer)); + filterData->filter->setSourceImage(std::move(filterData->sourceGraphicBuffer)); // Always true if filterData is just built (filterData->state == FilterData::Built). if (!lastEffect->hasResult()) { @@ -317,3 +337,4 @@ FloatRect RenderSVGResourceFilter::drawingRegion(RenderObject* object) const } } +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h index d6ccfbf86..97e6fdbf9 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h @@ -24,6 +24,7 @@ #ifndef RenderSVGResourceFilter_h #define RenderSVGResourceFilter_h +#if ENABLE(SVG) && ENABLE(FILTERS) #include "ImageBuffer.h" #include "RenderSVGResourceContainer.h" #include "SVGFilter.h" @@ -62,27 +63,28 @@ class GraphicsContext; class RenderSVGResourceFilter final : public RenderSVGResourceContainer { public: - RenderSVGResourceFilter(SVGFilterElement&, Ref<RenderStyle>&&); + RenderSVGResourceFilter(SVGFilterElement&, PassRef<RenderStyle>); virtual ~RenderSVGResourceFilter(); - SVGFilterElement& filterElement() const { return downcast<SVGFilterElement>(RenderSVGResourceContainer::element()); } + SVGFilterElement& filterElement() const { return toSVGFilterElement(RenderSVGResourceContainer::element()); } - virtual void removeAllClientsFromCache(bool markForInvalidation = true) override; - virtual void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override; + 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 void postApplyResource(RenderElement&, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) override; virtual FloatRect resourceBoundingBox(const RenderObject&) override; - std::unique_ptr<SVGFilterBuilder> buildPrimitives(SVGFilter&) const; + std::unique_ptr<SVGFilterBuilder> buildPrimitives(SVGFilter*); SVGUnitTypes::SVGUnitType filterUnits() const { return filterElement().filterUnits(); } SVGUnitTypes::SVGUnitType primitiveUnits() const { return filterElement().primitiveUnits(); } void primitiveAttributeChanged(RenderObject*, const QualifiedName&); - virtual RenderSVGResourceType resourceType() const override { return FilterResourceType; } + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; FloatRect drawingRegion(RenderObject*) const; private: @@ -91,14 +93,14 @@ private: virtual const char* renderName() const override { return "RenderSVGResourceFilter"; } virtual bool isSVGResourceFilter() const override { return true; } + bool fitsInMaximumImageSize(const FloatSize&, FloatSize&); + HashMap<RenderObject*, std::unique_ptr<FilterData>> m_filter; }; -} // namespace WebCore +RENDER_OBJECT_TYPE_CASTS(RenderSVGResourceFilter, isSVGResourceFilter()) -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() +} -#endif // RenderSVGResourceFilter_h +#endif +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp index 473645288..24887b702 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp @@ -26,19 +26,18 @@ */ #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, Ref<RenderStyle>&& style) - : RenderSVGHiddenContainer(filterPrimitiveElement, WTF::move(style)) +RenderSVGResourceFilterPrimitive::RenderSVGResourceFilterPrimitive(SVGFilterPrimitiveStandardAttributes& filterPrimitiveElement, PassRef<RenderStyle> style) + : RenderSVGHiddenContainer(filterPrimitiveElement, std::move(style)) { } @@ -51,65 +50,69 @@ void RenderSVGResourceFilterPrimitive::styleDidChange(StyleDifference diff, cons { RenderSVGHiddenContainer::styleDidChange(diff, oldStyle); - auto* filter = parent(); + RenderObject* filter = parent(); if (!filter) return; + ASSERT(filter->isSVGResourceFilter()); if (diff == StyleDifferenceEqual || !oldStyle) return; const SVGRenderStyle& newStyle = style().svgStyle(); - if (is<SVGFEFloodElement>(filterPrimitiveElement())) { + if (filterPrimitiveElement().hasTagName(SVGNames::feFloodTag)) { if (newStyle.floodColor() != oldStyle->svgStyle().floodColor()) - downcast<RenderSVGResourceFilter>(*filter).primitiveAttributeChanged(this, SVGNames::flood_colorAttr); + toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_colorAttr); if (newStyle.floodOpacity() != oldStyle->svgStyle().floodOpacity()) - downcast<RenderSVGResourceFilter>(*filter).primitiveAttributeChanged(this, SVGNames::flood_opacityAttr); - } else if (is<SVGFEDiffuseLightingElement>(filterPrimitiveElement()) || is<SVGFESpecularLightingElement>(filterPrimitiveElement())) { + toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_opacityAttr); + } else if (filterPrimitiveElement().hasTagName(SVGNames::feDiffuseLightingTag) || filterPrimitiveElement().hasTagName(SVGNames::feSpecularLightingTag)) { if (newStyle.lightingColor() != oldStyle->svgStyle().lightingColor()) - downcast<RenderSVGResourceFilter>(*filter).primitiveAttributeChanged(this, SVGNames::lighting_colorAttr); + toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::lighting_colorAttr); } } -FloatRect RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(FilterEffect& effect) +FloatRect RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(FilterEffect* effect) { - auto& filter = downcast<SVGFilter>(effect.filter()); + SVGFilter* filter = toSVGFilter(effect->filter()); + ASSERT(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 ede92bc0d..f67d61a0f 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h @@ -27,6 +27,8 @@ #ifndef RenderSVGResourceFilterPrimitive_h #define RenderSVGResourceFilterPrimitive_h +#if ENABLE(SVG) && ENABLE(FILTERS) + #include "RenderSVGResourceFilter.h" namespace WebCore { @@ -36,15 +38,16 @@ class SVGFilterPrimitiveStandardAttributes; class RenderSVGResourceFilterPrimitive final : public RenderSVGHiddenContainer { public: - RenderSVGResourceFilterPrimitive(SVGFilterPrimitiveStandardAttributes&, Ref<RenderStyle>&&); + RenderSVGResourceFilterPrimitive(SVGFilterPrimitiveStandardAttributes&, PassRef<RenderStyle>); SVGFilterPrimitiveStandardAttributes& filterPrimitiveElement() const; - virtual void styleDidChange(StyleDifference, const RenderStyle*) override; + virtual void styleDidChange(StyleDifference, const RenderStyle*); - virtual const char* renderName() const override { return "RenderSVGResourceFilterPrimitive"; } + virtual const char* renderName() const { return "RenderSVGResourceFilterPrimitive"; } + virtual bool isSVGResourceFilterPrimitive() const { return true; } // They depend on the RenderObject argument of RenderSVGResourceFilter::applyResource. - static FloatRect determineFilterPrimitiveSubregion(FilterEffect&); + static FloatRect determineFilterPrimitiveSubregion(FilterEffect*); inline void primitiveAttributeChanged(const QualifiedName& attribute) { @@ -54,10 +57,11 @@ public: static_cast<RenderSVGResourceFilter*>(filter)->primitiveAttributeChanged(this, attribute); } private: - virtual 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 7517e24a2..496a7be59 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp @@ -21,6 +21,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGResourceGradient.h" #include "GradientAttributes.h" @@ -30,8 +32,8 @@ namespace WebCore { -RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement& node, Ref<RenderStyle>&& style) - : RenderSVGResourceContainer(node, WTF::move(style)) +RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement& node, PassRef<RenderStyle> style) + : RenderSVGResourceContainer(node, std::move(style)) , m_shouldCollectGradientAttributes(true) #if USE(CG) , m_savedContext(0) @@ -46,7 +48,7 @@ void RenderSVGResourceGradient::removeAllClientsFromCache(bool markForInvalidati markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourceGradient::removeClientFromCache(RenderElement& client, bool markForInvalidation) +void RenderSVGResourceGradient::removeClientFromCache(RenderObject& client, bool markForInvalidation) { m_gradientMap.remove(&client); markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); @@ -55,14 +57,15 @@ void RenderSVGResourceGradient::removeClientFromCache(RenderElement& client, boo #if USE(CG) static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& context, GraphicsContext*& savedContext, std::unique_ptr<ImageBuffer>& imageBuffer, RenderObject* object) { - auto* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(*object); + RenderObject* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(object); ASSERT(textRootBlock); - AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock); - FloatRect repaintRect = textRootBlock->repaintRectInLocalCoordinates(); + AffineTransform absoluteTransform; + SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(textRootBlock, absoluteTransform); - auto maskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, ColorSpaceDeviceRGB, context->renderingMode()); - if (!maskImage) + FloatRect repaintRect = textRootBlock->repaintRectInLocalCoordinates(); + std::unique_ptr<ImageBuffer> maskImage; + if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, maskImage, ColorSpaceDeviceRGB, Unaccelerated)) return false; GraphicsContext* maskImageContext = maskImage->context(); @@ -70,19 +73,19 @@ static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& con ASSERT(maskImage); savedContext = context; context = maskImageContext; - imageBuffer = WTF::move(maskImage); + imageBuffer = std::move(maskImage); return true; } static inline AffineTransform clipToTextMask(GraphicsContext* context, std::unique_ptr<ImageBuffer>& imageBuffer, FloatRect& targetRect, RenderObject* object, bool boundingBoxMode, const AffineTransform& gradientTransform) { - auto* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(*object); + RenderObject* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(object); ASSERT(textRootBlock); - AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock); + AffineTransform absoluteTransform; + SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(textRootBlock, absoluteTransform); targetRect = textRootBlock->repaintRectInLocalCoordinates(); - SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, targetRect, imageBuffer, false); AffineTransform matrix; @@ -119,9 +122,9 @@ bool RenderSVGResourceGradient::applyResource(RenderElement& renderer, const Ren if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty()) return false; - auto& gradientData = m_gradientMap.add(&renderer, nullptr).iterator->value; + OwnPtr<GradientData>& gradientData = m_gradientMap.add(&renderer, nullptr).iterator->value; if (!gradientData) - gradientData = std::make_unique<GradientData>(); + gradientData = adoptPtr(new GradientData); bool isPaintingText = resourceMode & ApplyToTextMode; @@ -149,7 +152,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); @@ -176,13 +179,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); } @@ -208,7 +211,7 @@ void RenderSVGResourceGradient::postApplyResource(RenderElement& renderer, Graph FloatRect targetRect; gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, targetRect, &renderer, gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, gradientTransform)); - context->setFillGradient(*gradientData->gradient); + context->setFillGradient(gradientData->gradient); context->fillRect(targetRect); m_imageBuffer.reset(); @@ -260,3 +263,5 @@ GradientSpreadMethod RenderSVGResourceGradient::platformSpreadMethodFromSVGType( } } + +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h index 78da73adc..c37fc7a5c 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h @@ -22,11 +22,12 @@ #ifndef RenderSVGResourceGradient_h #define RenderSVGResourceGradient_h +#if ENABLE(SVG) #include "Gradient.h" #include "ImageBuffer.h" #include "RenderSVGResourceContainer.h" #include "SVGGradientElement.h" -#include <memory> + #include <wtf/HashMap.h> namespace WebCore { @@ -45,14 +46,14 @@ public: SVGGradientElement& gradientElement() const { return static_cast<SVGGradientElement&>(RenderSVGResourceContainer::element()); } virtual void removeAllClientsFromCache(bool markForInvalidation = true) override final; - virtual void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override final; + virtual void removeClientFromCache(RenderObject&, bool markForInvalidation = true) override 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(); } protected: - RenderSVGResourceGradient(SVGGradientElement&, Ref<RenderStyle>&&); + RenderSVGResourceGradient(SVGGradientElement&, PassRef<RenderStyle>); void element() const = delete; @@ -67,7 +68,7 @@ protected: private: bool m_shouldCollectGradientAttributes : 1; - HashMap<RenderObject*, std::unique_ptr<GradientData>> m_gradientMap; + HashMap<RenderObject*, OwnPtr<GradientData>> m_gradientMap; #if USE(CG) GraphicsContext* m_savedContext; @@ -78,3 +79,4 @@ private: } #endif +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp index 7d57c3fff..c928e5b86 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp @@ -19,13 +19,17 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGResourceLinearGradient.h" namespace WebCore { -RenderSVGResourceLinearGradient::RenderSVGResourceLinearGradient(SVGLinearGradientElement& element, Ref<RenderStyle>&& style) - : RenderSVGResourceGradient(element, WTF::move(style)) +RenderSVGResourceType RenderSVGResourceLinearGradient::s_resourceType = LinearGradientResourceType; + +RenderSVGResourceLinearGradient::RenderSVGResourceLinearGradient(SVGLinearGradientElement& element, PassRef<RenderStyle> style) + : RenderSVGResourceGradient(element, std::move(style)) { } @@ -57,3 +61,5 @@ void RenderSVGResourceLinearGradient::buildGradient(GradientData* gradientData) } } + +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h b/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h index 96348283f..eaec65974 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h @@ -21,6 +21,7 @@ #ifndef RenderSVGResourceLinearGradient_h #define RenderSVGResourceLinearGradient_h +#if ENABLE(SVG) #include "LinearGradientAttributes.h" #include "RenderSVGResourceGradient.h" #include "SVGLinearGradientElement.h" @@ -29,17 +30,18 @@ namespace WebCore { class RenderSVGResourceLinearGradient final : public RenderSVGResourceGradient { public: - RenderSVGResourceLinearGradient(SVGLinearGradientElement&, Ref<RenderStyle>&&); + RenderSVGResourceLinearGradient(SVGLinearGradientElement&, PassRef<RenderStyle>); virtual ~RenderSVGResourceLinearGradient(); - SVGLinearGradientElement& linearGradientElement() const { return downcast<SVGLinearGradientElement>(RenderSVGResourceGradient::gradientElement()); } + SVGLinearGradientElement& linearGradientElement() const { return toSVGLinearGradientElement(RenderSVGResourceGradient::gradientElement()); } - virtual RenderSVGResourceType resourceType() const override { return LinearGradientResourceType; } + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; - virtual SVGUnitTypes::SVGUnitType gradientUnits() const override { return m_attributes.gradientUnits(); } - virtual void calculateGradientTransform(AffineTransform& transform) override { transform = m_attributes.gradientTransform(); } + 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 override; + virtual void buildGradient(GradientData*) const; FloatPoint startPoint(const LinearGradientAttributes&) const; FloatPoint endPoint(const LinearGradientAttributes&) const; @@ -54,6 +56,5 @@ private: } -SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourceLinearGradient, LinearGradientResourceType) - +#endif #endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp index 8c3bdb347..3ea195056 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp @@ -20,6 +20,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGResourceMarker.h" #include "GraphicsContext.h" @@ -28,8 +30,10 @@ namespace WebCore { -RenderSVGResourceMarker::RenderSVGResourceMarker(SVGMarkerElement& element, Ref<RenderStyle>&& style) - : RenderSVGResourceContainer(element, WTF::move(style)) +RenderSVGResourceType RenderSVGResourceMarker::s_resourceType = MarkerResourceType; + +RenderSVGResourceMarker::RenderSVGResourceMarker(SVGMarkerElement& element, PassRef<RenderStyle> style) + : RenderSVGResourceContainer(element, std::move(style)) { } @@ -55,7 +59,7 @@ void RenderSVGResourceMarker::removeAllClientsFromCache(bool markForInvalidation markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourceMarker::removeClientFromCache(RenderElement& client, bool markForInvalidation) +void RenderSVGResourceMarker::removeClientFromCache(RenderObject& client, bool markForInvalidation) { markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation); } @@ -153,3 +157,5 @@ void RenderSVGResourceMarker::calcViewport() } } + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h index 8b8468f78..442cc60d7 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h @@ -20,6 +20,7 @@ #ifndef RenderSVGResourceMarker_h #define RenderSVGResourceMarker_h +#if ENABLE(SVG) #include "RenderSVGResourceContainer.h" #include "SVGMarkerElement.h" @@ -32,24 +33,24 @@ class RenderObject; class RenderSVGResourceMarker final : public RenderSVGResourceContainer { public: - RenderSVGResourceMarker(SVGMarkerElement&, Ref<RenderStyle>&&); + RenderSVGResourceMarker(SVGMarkerElement&, PassRef<RenderStyle>); virtual ~RenderSVGResourceMarker(); - SVGMarkerElement& markerElement() const { return downcast<SVGMarkerElement>(RenderSVGResourceContainer::element()); } + SVGMarkerElement& markerElement() const { return toSVGMarkerElement(RenderSVGResourceContainer::element()); } - virtual void removeAllClientsFromCache(bool markForInvalidation = true) override; - virtual void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override; + virtual void removeAllClientsFromCache(bool markForInvalidation = true); + virtual void removeClientFromCache(RenderObject&, bool markForInvalidation = true); 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&) override; - virtual void layout() override; - virtual void calcViewport() override; + virtual void applyViewportClip(PaintInfo&); + virtual void layout(); + virtual void calcViewport(); - virtual const AffineTransform& localToParentTransform() const override; + virtual const AffineTransform& localToParentTransform() const; AffineTransform markerTransformation(const FloatPoint& origin, float angle, float strokeWidth) const; virtual bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short) override { return false; } @@ -59,7 +60,8 @@ public: float angle() const; SVGMarkerUnitsType markerUnits() const { return markerElement().markerUnits(); } - virtual RenderSVGResourceType resourceType() const override { return MarkerResourceType; } + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; private: void element() const = delete; @@ -77,7 +79,6 @@ private: }; } - -SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourceMarker, MarkerResourceType) +#endif #endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp index 0032e051a..e02fab47b 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp @@ -18,6 +18,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGResourceMasker.h" #include "Element.h" @@ -29,8 +31,10 @@ namespace WebCore { -RenderSVGResourceMasker::RenderSVGResourceMasker(SVGMaskElement& element, Ref<RenderStyle>&& style) - : RenderSVGResourceContainer(element, WTF::move(style)) +RenderSVGResourceType RenderSVGResourceMasker::s_resourceType = MaskerResourceType; + +RenderSVGResourceMasker::RenderSVGResourceMasker(SVGMaskElement& element, PassRef<RenderStyle> style) + : RenderSVGResourceContainer(element, std::move(style)) { } @@ -46,7 +50,7 @@ void RenderSVGResourceMasker::removeAllClientsFromCache(bool markForInvalidation markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourceMasker::removeClientFromCache(RenderElement& client, bool markForInvalidation) +void RenderSVGResourceMasker::removeClientFromCache(RenderObject& client, bool markForInvalidation) { m_masker.remove(&client); @@ -63,19 +67,21 @@ 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); + + AffineTransform absoluteTransform; + SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(&renderer, absoluteTransform); + FloatRect repaintRect = renderer.repaintRectInLocalCoordinates(); if (!maskerData->maskImage && !repaintRect.isEmpty()) { const SVGRenderStyle& svgStyle = style().svgStyle(); ColorSpace colorSpace = svgStyle.colorInterpolation() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB; - // 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) + if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, maskerData->maskImage, colorSpace, Unaccelerated)) return false; - if (!drawContentIntoMaskImage(maskerData, colorSpace, &renderer)) + if (!drawContentIntoMaskImage(maskerData, colorSpace, &renderer)) { maskerData->maskImage.reset(); + } } if (!maskerData->maskImage) @@ -163,3 +169,5 @@ 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 bef2985c3..ecae4332e 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.h @@ -20,6 +20,7 @@ #ifndef RenderSVGResourceMasker_h #define RenderSVGResourceMasker_h +#if ENABLE(SVG) #include "GraphicsContext.h" #include "ImageBuffer.h" #include "IntSize.h" @@ -37,20 +38,21 @@ struct MaskerData { class RenderSVGResourceMasker final : public RenderSVGResourceContainer { public: - RenderSVGResourceMasker(SVGMaskElement&, Ref<RenderStyle>&&); + RenderSVGResourceMasker(SVGMaskElement&, PassRef<RenderStyle>); virtual ~RenderSVGResourceMasker(); - SVGMaskElement& maskElement() const { return downcast<SVGMaskElement>(RenderSVGResourceContainer::element()); } + SVGMaskElement& maskElement() const { return toSVGMaskElement(RenderSVGResourceContainer::element()); } - virtual void removeAllClientsFromCache(bool markForInvalidation = true) override; - virtual void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override; + 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; SVGUnitTypes::SVGUnitType maskUnits() const { return maskElement().maskUnits(); } SVGUnitTypes::SVGUnitType maskContentUnits() const { return maskElement().maskContentUnits(); } - virtual RenderSVGResourceType resourceType() const override { return MaskerResourceType; } + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; private: void element() const = delete; @@ -66,6 +68,5 @@ private: } -SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourceMasker, MaskerResourceType) - +#endif #endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp index 60dc18d0a..4ed8e6a98 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp @@ -19,6 +19,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGResourcePattern.h" #include "ElementIterator.h" @@ -30,15 +32,17 @@ namespace WebCore { -RenderSVGResourcePattern::RenderSVGResourcePattern(SVGPatternElement& element, Ref<RenderStyle>&& style) - : RenderSVGResourceContainer(element, WTF::move(style)) +RenderSVGResourceType RenderSVGResourcePattern::s_resourceType = PatternResourceType; + +RenderSVGResourcePattern::RenderSVGResourcePattern(SVGPatternElement& element, PassRef<RenderStyle> style) + : RenderSVGResourceContainer(element, std::move(style)) , m_shouldCollectPatternAttributes(true) { } SVGPatternElement& RenderSVGResourcePattern::patternElement() const { - return downcast<SVGPatternElement>(RenderSVGResourceContainer::element()); + return toSVGPatternElement(RenderSVGResourceContainer::element()); } void RenderSVGResourcePattern::removeAllClientsFromCache(bool markForInvalidation) @@ -48,15 +52,15 @@ void RenderSVGResourcePattern::removeAllClientsFromCache(bool markForInvalidatio markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourcePattern::removeClientFromCache(RenderElement& client, bool markForInvalidation) +void RenderSVGResourcePattern::removeClientFromCache(RenderObject& client, bool markForInvalidation) { m_patternMap.remove(&client); markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); } -PatternData* RenderSVGResourcePattern::buildPattern(RenderElement& renderer, unsigned short resourceMode, GraphicsContext& context) +PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsigned short resourceMode) { - PatternData* currentData = m_patternMap.get(&renderer); + PatternData* currentData = m_patternMap.get(object); if (currentData && currentData->pattern) return currentData; @@ -70,19 +74,20 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderElement& renderer, uns // If we couldn't determine the pattern content element root, stop here. if (!m_attributes.patternContentElement()) - return nullptr; + return 0; // An empty viewBox disables rendering. if (m_attributes.hasViewBox() && m_attributes.viewBox().isEmpty()) - return nullptr; + return 0; // Compute all necessary transformations to build the tile image & the pattern. FloatRect tileBoundaries; AffineTransform tileImageTransform; - if (!buildTileImageTransform(renderer, m_attributes, patternElement(), tileBoundaries, tileImageTransform)) - return nullptr; + if (!buildTileImageTransform(object, m_attributes, patternElement(), tileBoundaries, tileImageTransform)) + return 0; - AffineTransform absoluteTransformIgnoringRotation = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer); + AffineTransform absoluteTransformIgnoringRotation; + SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransformIgnoringRotation); // Ignore 2D rotation, as it doesn't affect the size of the tile. SVGRenderingContext::clear2DRotation(absoluteTransformIgnoringRotation); @@ -94,16 +99,16 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderElement& renderer, uns static_cast<float>(m_attributes.patternTransform().yScale())); // Build tile image. - auto tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries, context.renderingMode()); + std::unique_ptr<ImageBuffer> tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries); if (!tileImage) - return nullptr; + return 0; RefPtr<Image> copiedImage = tileImage->copyImage(CopyBackingStore); if (!copiedImage) - return nullptr; + return 0; // Build pattern. - auto patternData = std::make_unique<PatternData>(); + OwnPtr<PatternData> patternData = adoptPtr(new PatternData); patternData->pattern = Pattern::create(copiedImage, true, true); // Compute pattern space transformation. @@ -118,7 +123,7 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderElement& renderer, uns // Account for text drawing resetting the context to non-scaled, see SVGInlineTextBox::paintTextWithShadows. if (resourceMode & ApplyToTextMode) { AffineTransform additionalTextTransformation; - if (shouldTransformOnTextPainting(renderer, additionalTextTransformation)) + if (shouldTransformOnTextPainting(object, additionalTextTransformation)) patternData->transform *= additionalTextTransformation; } patternData->pattern->setPatternSpaceTransform(patternData->transform); @@ -126,7 +131,7 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderElement& renderer, uns // 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(&renderer, WTF::move(patternData)).iterator->value.get(); + return m_patternMap.set(object, patternData.release()).iterator->value.get(); } bool RenderSVGResourcePattern::applyResource(RenderElement& renderer, const RenderStyle& style, GraphicsContext*& context, unsigned short resourceMode) @@ -140,7 +145,7 @@ bool RenderSVGResourcePattern::applyResource(RenderElement& renderer, const Rend if (m_attributes.patternUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty()) return false; - PatternData* patternData = buildPattern(renderer, resourceMode, *context); + PatternData* patternData = buildPattern(&renderer, resourceMode); if (!patternData) return false; @@ -151,13 +156,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); } @@ -208,13 +213,15 @@ 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(RenderElement& renderer, +bool RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer, const PatternAttributes& attributes, const SVGPatternElement& patternElement, FloatRect& patternBoundaries, AffineTransform& tileImageTransform) const { - FloatRect objectBoundingBox = renderer.objectBoundingBox(); + ASSERT(renderer); + + FloatRect objectBoundingBox = renderer->objectBoundingBox(); patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement); if (patternBoundaries.width() <= 0 || patternBoundaries.height() <= 0) return false; @@ -230,11 +237,13 @@ bool RenderSVGResourcePattern::buildTileImageTransform(RenderElement& renderer, return true; } -std::unique_ptr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes, const FloatRect& tileBoundaries, const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform, FloatRect& clampedAbsoluteTileBoundaries, RenderingMode renderingMode) const +std::unique_ptr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes, const FloatRect& tileBoundaries, const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform, FloatRect& clampedAbsoluteTileBoundaries) const { - clampedAbsoluteTileBoundaries = ImageBuffer::clampedRect(absoluteTileBoundaries); - auto tileImage = SVGRenderingContext::createImageBuffer(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, ColorSpaceDeviceRGB, renderingMode); - if (!tileImage) + clampedAbsoluteTileBoundaries = SVGRenderingContext::clampedAbsoluteTargetRect(absoluteTileBoundaries); + + std::unique_ptr<ImageBuffer> tileImage; + + if (!SVGRenderingContext::createImageBufferForPattern(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, tileImage, ColorSpaceDeviceRGB, Unaccelerated)) return nullptr; GraphicsContext* tileImageContext = tileImage->context(); @@ -265,3 +274,5 @@ 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 f0cac4652..9eebeefa4 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h @@ -21,13 +21,14 @@ #ifndef RenderSVGResourcePattern_h #define RenderSVGResourcePattern_h +#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 { @@ -41,35 +42,35 @@ public: class RenderSVGResourcePattern final : public RenderSVGResourceContainer { public: - RenderSVGResourcePattern(SVGPatternElement&, Ref<RenderStyle>&&); + RenderSVGResourcePattern(SVGPatternElement&, PassRef<RenderStyle>); SVGPatternElement& patternElement() const; - virtual void removeAllClientsFromCache(bool markForInvalidation = true) override; - virtual void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override; + 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 void postApplyResource(RenderElement&, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) override; virtual FloatRect resourceBoundingBox(const RenderObject&) override { return FloatRect(); } - virtual RenderSVGResourceType resourceType() const override { return PatternResourceType; } + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; private: void element() const = delete; virtual const char* renderName() const override { return "RenderSVGResourcePattern"; } - bool buildTileImageTransform(RenderElement&, const PatternAttributes&, const SVGPatternElement&, FloatRect& patternBoundaries, AffineTransform& tileImageTransform) const; + bool buildTileImageTransform(RenderObject*, 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, RenderingMode) const; + std::unique_ptr<ImageBuffer> createTileImage(const PatternAttributes&, const FloatRect& tileBoundaries, const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform, FloatRect& clampedAbsoluteTileBoundaries) const; - PatternData* buildPattern(RenderElement&, unsigned short resourceMode, GraphicsContext&); + PatternData* buildPattern(RenderObject*, unsigned short resourceMode); bool m_shouldCollectPatternAttributes : 1; PatternAttributes m_attributes; - HashMap<RenderElement*, std::unique_ptr<PatternData>> m_patternMap; + HashMap<RenderObject*, OwnPtr<PatternData>> m_patternMap; }; } -SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourcePattern, PatternResourceType) - +#endif #endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp index 946f0edc2..1f5b8d163 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp @@ -20,12 +20,17 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGResourceRadialGradient.h" + namespace WebCore { -RenderSVGResourceRadialGradient::RenderSVGResourceRadialGradient(SVGRadialGradientElement& element, Ref<RenderStyle>&& style) - : RenderSVGResourceGradient(element, WTF::move(style)) +RenderSVGResourceType RenderSVGResourceRadialGradient::s_resourceType = RadialGradientResourceType; + +RenderSVGResourceRadialGradient::RenderSVGResourceRadialGradient(SVGRadialGradientElement& element, PassRef<RenderStyle> style) + : RenderSVGResourceGradient(element, std::move(style)) { } @@ -72,3 +77,5 @@ void RenderSVGResourceRadialGradient::buildGradient(GradientData* gradientData) } } + +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h b/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h index d1aa57c4f..f1e61a4ee 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h @@ -21,6 +21,7 @@ #ifndef RenderSVGResourceRadialGradient_h #define RenderSVGResourceRadialGradient_h +#if ENABLE(SVG) #include "RadialGradientAttributes.h" #include "RenderSVGResourceGradient.h" #include "SVGRadialGradientElement.h" @@ -31,16 +32,17 @@ class SVGRadialGradientElement; class RenderSVGResourceRadialGradient final : public RenderSVGResourceGradient { public: - RenderSVGResourceRadialGradient(SVGRadialGradientElement&, Ref<RenderStyle>&&); + RenderSVGResourceRadialGradient(SVGRadialGradientElement&, PassRef<RenderStyle>); virtual ~RenderSVGResourceRadialGradient(); - SVGRadialGradientElement& radialGradientElement() const { return downcast<SVGRadialGradientElement>(RenderSVGResourceGradient::gradientElement()); } + SVGRadialGradientElement& radialGradientElement() const { return toSVGRadialGradientElement(RenderSVGResourceGradient::gradientElement()); } - virtual RenderSVGResourceType resourceType() const override { return RadialGradientResourceType; } + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; - virtual SVGUnitTypes::SVGUnitType gradientUnits() const override { return m_attributes.gradientUnits(); } - virtual void calculateGradientTransform(AffineTransform& transform) override { transform = m_attributes.gradientTransform(); } - virtual void buildGradient(GradientData*) const override; + virtual SVGUnitTypes::SVGUnitType gradientUnits() const { return m_attributes.gradientUnits(); } + virtual void calculateGradientTransform(AffineTransform& transform) { transform = m_attributes.gradientTransform(); } + virtual void buildGradient(GradientData*) const; FloatPoint centerPoint(const RadialGradientAttributes&) const; FloatPoint focalPoint(const RadialGradientAttributes&) const; @@ -58,6 +60,5 @@ private: } -SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourceRadialGradient, RadialGradientResourceType) - +#endif #endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp index f501abf44..1d9ada519 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp @@ -18,6 +18,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGResourceSolidColor.h" #include "Frame.h" @@ -28,6 +30,8 @@ namespace WebCore { +RenderSVGResourceType RenderSVGResourceSolidColor::s_resourceType = SolidColorResourceType; + RenderSVGResourceSolidColor::RenderSVGResourceSolidColor() { } @@ -92,3 +96,5 @@ void RenderSVGResourceSolidColor::postApplyResource(RenderElement&, GraphicsCont } } + +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h b/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h index 4bad5b522..80eb45df6 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h @@ -20,25 +20,26 @@ #ifndef RenderSVGResourceSolidColor_h #define RenderSVGResourceSolidColor_h +#if ENABLE(SVG) #include "Color.h" #include "RenderSVGResource.h" namespace WebCore { -class RenderSVGResourceSolidColor final : public RenderSVGResource { - WTF_MAKE_FAST_ALLOCATED; +class RenderSVGResourceSolidColor : public RenderSVGResource { public: RenderSVGResourceSolidColor(); virtual ~RenderSVGResourceSolidColor(); - virtual void removeAllClientsFromCache(bool = true) override { } - virtual void removeClientFromCache(RenderElement&, bool = true) override { } + virtual void removeAllClientsFromCache(bool = true) { } + virtual void removeClientFromCache(RenderObject&, bool = true) { } 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(); } - virtual RenderSVGResourceType resourceType() const override { return SolidColorResourceType; } + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; const Color& color() const { return m_color; } void setColor(const Color& color) { m_color = color; } @@ -49,6 +50,5 @@ private: } -SPECIALIZE_TYPE_TRAITS_RENDER_SVG_RESOURCE(RenderSVGResourceSolidColor, SolidColorResourceType) - +#endif #endif diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp index 64bea0473..6de3aa3c6 100644 --- a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp @@ -22,6 +22,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGRoot.h" #include "Chrome.h" @@ -32,11 +34,6 @@ #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" @@ -48,15 +45,18 @@ #include "TransformState.h" #include <wtf/StackStats.h> +#if ENABLE(FILTERS) +#include "RenderSVGResourceFilter.h" +#endif + namespace WebCore { -RenderSVGRoot::RenderSVGRoot(SVGSVGElement& element, Ref<RenderStyle>&& style) - : RenderReplaced(element, WTF::move(style)) +RenderSVGRoot::RenderSVGRoot(SVGSVGElement& element, PassRef<RenderStyle> style) + : RenderReplaced(element, std::move(style)) , m_objectBoundingBoxValid(false) , m_isLayoutSizeChanged(false) , m_needsBoundariesOrTransformUpdate(true) , m_hasSVGShadow(false) - , m_hasBoxDecorations(false) { } @@ -66,13 +66,20 @@ RenderSVGRoot::~RenderSVGRoot() SVGSVGElement& RenderSVGRoot::svgSVGElement() const { - return downcast<SVGSVGElement>(nodeForNonAnonymous()); + return toSVGSVGElement(nodeForNonAnonymous()); } -void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const +void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) 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 @@ -81,22 +88,33 @@ 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. - intrinsicSize.setWidth(floatValueForLength(svgSVGElement().intrinsicWidth(), 0)); - intrinsicSize.setHeight(floatValueForLength(svgSVGElement().intrinsicHeight(), 0)); - + 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; + } - if (!intrinsicSize.isEmpty()) + // - 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()); - 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()); - } + 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()); } } @@ -114,9 +132,9 @@ bool RenderSVGRoot::isEmbeddedThroughFrameContainingSVGDocument() const return frame().document()->isSVGDocument(); } -static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize) +static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize, RenderView* renderView) { - return valueForLength(length, maxSize) * (length.isFixed() ? scale : 1); + return static_cast<LayoutUnit>(valueForLength(length, maxSize, renderView) * (length.isFixed() ? scale : 1)); } LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const @@ -125,14 +143,15 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(ShouldComputePreferred sho if (!m_containerSize.isEmpty()) return m_containerSize.width(); - if (isEmbeddedThroughFrameContainingSVGDocument()) - return containingBlock()->availableLogicalWidth(); - if (style().logicalWidth().isSpecified() || style().logicalMaxWidth().isSpecified()) return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred); - if (svgSVGElement().hasIntrinsicWidth()) - return resolveLengthAttributeForSVG(svgSVGElement().intrinsicWidth(), style().effectiveZoom(), containingBlock()->availableLogicalWidth()); + 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(); // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG. return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred); @@ -144,14 +163,27 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const if (!m_containerSize.isEmpty()) return m_containerSize.height(); - if (isEmbeddedThroughFrameContainingSVGDocument()) - return containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding); - if (style().logicalHeight().isSpecified() || style().logicalMaxHeight().isSpecified()) return RenderReplaced::computeReplacedLogicalHeight(); - if (svgSVGElement().hasIntrinsicHeight()) - return resolveLengthAttributeForSVG(svgSVGElement().intrinsicHeight(), style().effectiveZoom(), containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding).toFloat()); + 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); // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG. return RenderReplaced::computeReplacedLogicalHeight(); @@ -165,7 +197,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); @@ -195,32 +227,13 @@ void RenderSVGRoot::layout() m_needsBoundariesOrTransformUpdate = false; } - if (!shouldApplyViewportClip()) { - FloatRect contentRepaintRect = repaintRectInLocalCoordinates(); - contentRepaintRect = m_localToBorderBoxTransform.mapRect(contentRepaintRect); - addVisualOverflow(enclosingLayoutRect(contentRepaintRect)); - } - updateLayerTransform(); - m_hasBoxDecorations = isRoot() ? hasBoxDecorationStyle() : hasBoxDecorations(); - 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->isRoot(); -} - void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { // An empty viewport disables rendering. @@ -231,10 +244,6 @@ void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paint 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. // (http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute) if (svgSVGElement().hasEmptyViewBox()) @@ -244,7 +253,7 @@ void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paint // Don't paint if we don't have kids, except if we have filters we should paint those. if (!firstChild()) { - auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this); if (!resources || !resources->filter()) { if (page && paintInfo.phase == PaintPhaseForeground) page->addRelevantUnpaintedObject(this, visualOverflowRect()); @@ -259,9 +268,8 @@ void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paint PaintInfo childPaintInfo(paintInfo); childPaintInfo.context->save(); - // Apply initial viewport clip - if (shouldApplyViewportClip()) - childPaintInfo.context->clip(snappedIntRect(overflowClipRect(paintOffset, currentRenderNamedFlowFragment()))); + // Apply initial viewport clip - not affected by overflow handling + childPaintInfo.context->clip(pixelSnappedIntRect(overflowClipRect(paintOffset, paintInfo.renderRegion))); // Convert from container offsets (html renderers) to a relative transform (svg renderers). // Transform from our paint container's coordinate system to our local coords. @@ -355,16 +363,8 @@ void RenderSVGRoot::computeFloatRectForRepaint(const RenderLayerModelObject* rep if (const ShadowData* shadow = svgStyle.shadow()) shadow->adjustRectForShadow(repaintRect); - // Apply initial viewport clip - if (shouldApplyViewportClip()) - repaintRect.intersect(pixelSnappedBorderBoxRect()); - - 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()); - repaintRect.unite(decoratedRepaintRect); - } + // Apply initial viewport clip - not affected by overflow settings + repaintRect.intersect(pixelSnappedBorderBoxRect()); LayoutRect rect = enclosingIntRect(repaintRect); RenderReplaced::computeRectForRepaint(repaintContainer, rect, fixed); @@ -391,7 +391,7 @@ void RenderSVGRoot::updateCachedBoundaries() { SVGRenderSupport::computeContainerBoundingBoxes(*this, m_objectBoundingBox, m_objectBoundingBoxValid, m_strokeBoundingBox, m_repaintBoundingBoxExcludingShadow); SVGRenderSupport::intersectRepaintRectWithResources(*this, m_repaintBoundingBoxExcludingShadow); - m_repaintBoundingBoxExcludingShadow.inflate(horizontalBorderAndPaddingExtent()); + m_repaintBoundingBoxExcludingShadow.inflate(borderAndPaddingWidth()); m_repaintBoundingBox = m_repaintBoundingBoxExcludingShadow; SVGRenderSupport::intersectRepaintRectWithShadows(*this, m_repaintBoundingBox); @@ -436,17 +436,29 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re bool RenderSVGRoot::hasRelativeDimensions() const { - return svgSVGElement().intrinsicHeight().isPercentOrCalculated() || svgSVGElement().intrinsicWidth().isPercentOrCalculated(); + 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(); } void RenderSVGRoot::addResourceForClientInvalidation(RenderSVGResourceContainer* resource) { - RenderElement* svgRoot = resource->parent(); - while (svgRoot && !is<RenderSVGRoot>(*svgRoot)) + RenderObject* svgRoot = resource->parent(); + while (svgRoot && !svgRoot->isSVGRoot()) svgRoot = svgRoot->parent(); if (!svgRoot) return; - downcast<RenderSVGRoot>(*svgRoot).m_resourcesNeedingToInvalidateClients.add(resource); + toRenderSVGRoot(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 49782eaa4..edebf1cf8 100644 --- a/Source/WebCore/rendering/svg/RenderSVGRoot.h +++ b/Source/WebCore/rendering/svg/RenderSVGRoot.h @@ -23,6 +23,7 @@ #ifndef RenderSVGRoot_h #define RenderSVGRoot_h +#if ENABLE(SVG) #include "FloatRect.h" #include "RenderReplaced.h" @@ -31,12 +32,11 @@ namespace WebCore { class AffineTransform; -class RenderSVGResourceContainer; class SVGSVGElement; class RenderSVGRoot final : public RenderReplaced { public: - RenderSVGRoot(SVGSVGElement&, Ref<RenderStyle>&&); + RenderSVGRoot(SVGSVGElement&, PassRef<RenderStyle>); virtual ~RenderSVGRoot(); SVGSVGElement& svgSVGElement() const; @@ -44,7 +44,7 @@ public: bool isEmbeddedThroughSVGImage() const; bool isEmbeddedThroughFrameContainingSVGDocument() const; - virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const override; + virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const override; bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; } virtual void setNeedsBoundariesUpdate() override { m_needsBoundariesOrTransformUpdate = true; } @@ -55,6 +55,8 @@ public: void setContainerSize(const IntSize& containerSize) { m_containerSize = containerSize; } virtual bool hasRelativeDimensions() const override; + virtual bool hasRelativeIntrinsicLogicalWidth() const override; + virtual bool hasRelativeLogicalHeight() const override; // localToBorderBoxTransform maps local SVG viewport coordinates to local CSS box coordinates. const AffineTransform& localToBorderBoxTransform() const { return m_localToBorderBoxTransform; } @@ -90,20 +92,19 @@ private: virtual FloatRect objectBoundingBox() const override { return m_objectBoundingBox; } virtual FloatRect strokeBoundingBox() const override { return m_strokeBoundingBox; } virtual FloatRect repaintRectInLocalCoordinates() const override { return m_repaintBoundingBox; } - FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const { return m_repaintBoundingBoxExcludingShadow; } + virtual FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const { return m_repaintBoundingBoxExcludingShadow; } virtual 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; - virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, 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 bool canBeSelectionLeaf() const override { return false; } virtual bool canHaveChildren() const override { return true; } - bool shouldApplyViewportClip() const; void updateCachedBoundaries(); void buildLocalToBorderBoxTransform(); @@ -119,11 +120,12 @@ private: bool m_isLayoutSizeChanged : 1; bool m_needsBoundariesOrTransformUpdate : 1; bool m_hasSVGShadow : 1; - bool m_hasBoxDecorations : 1; }; -} // namespace WebCore +template<> inline bool isRendererOfType<const RenderSVGRoot>(const RenderObject& renderer) { return renderer.isSVGRoot(); } +RENDER_OBJECT_TYPE_CASTS(RenderSVGRoot, isSVGRoot()) -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGRoot, isSVGRoot()) +} // namespace WebCore +#endif // ENABLE(SVG) #endif // RenderSVGRoot_h diff --git a/Source/WebCore/rendering/svg/RenderSVGShape.cpp b/Source/WebCore/rendering/svg/RenderSVGShape.cpp index a19cdbb6c..b93a028b5 100644 --- a/Source/WebCore/rendering/svg/RenderSVGShape.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGShape.cpp @@ -26,6 +26,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGShape.h" #include "FloatPoint.h" @@ -63,8 +65,8 @@ private: const RenderSVGShape& m_renderer; }; -RenderSVGShape::RenderSVGShape(SVGGraphicsElement& element, Ref<RenderStyle>&& style) - : RenderSVGModelObject(element, WTF::move(style)) +RenderSVGShape::RenderSVGShape(SVGGraphicsElement& element, PassRef<RenderStyle> style) + : RenderSVGModelObject(element, std::move(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. @@ -77,7 +79,8 @@ RenderSVGShape::~RenderSVGShape() void RenderSVGShape::updateShapeFromElement() { - m_path = std::make_unique<Path>(); + m_path.clear(); + m_path = adoptPtr(new Path); ASSERT(RenderSVGShape::isEmpty()); updatePathFromGraphicsElement(&graphicsElement(), path()); @@ -187,7 +190,7 @@ void RenderSVGShape::layout() Path* RenderSVGShape::nonScalingStrokePath(const Path* path, const AffineTransform& strokeTransform) const { - DEPRECATED_DEFINE_STATIC_LOCAL(Path, tempPath, ()); + DEFINE_STATIC_LOCAL(Path, tempPath, ()); tempPath = *path; tempPath.transform(strokeTransform); @@ -218,7 +221,7 @@ bool RenderSVGShape::shouldGenerateMarkerPositions() const if (!graphicsElement().supportsMarkers()) return false; - auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this); if (!resources) return false; @@ -255,66 +258,55 @@ void RenderSVGShape::strokeShape(const RenderStyle& style, GraphicsContext* cont } } -void RenderSVGShape::strokeShape(GraphicsContext* context) +void RenderSVGShape::fillAndStrokeShape(GraphicsContext* context) { + fillShape(style(), context); + if (!style().svgStyle().hasVisibleStroke()) return; GraphicsContextStateSaver stateSaver(*context, false); + if (hasNonScalingStroke()) { AffineTransform nonScalingTransform = nonScalingStrokeTransform(); if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver)) return; } - strokeShape(style(), context); -} -void RenderSVGShape::fillStrokeMarkers(PaintInfo& childPaintInfo) -{ - auto paintOrder = style().svgStyle().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; - } - } + strokeShape(style(), context); } void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&) { - if (paintInfo.context->paintingDisabled() || paintInfo.phase != PaintPhaseForeground - || style().visibility() == HIDDEN || isEmpty()) + if (paintInfo.context->paintingDisabled() || style().visibility() == HIDDEN || isEmpty()) return; FloatRect boundingBox = repaintRectInLocalCoordinates(); if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo)) return; PaintInfo childPaintInfo(paintInfo); - 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); - - fillStrokeMarkers(childPaintInfo); + 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); + } } - } - if (style().outlineWidth()) - paintOutline(childPaintInfo, IntRect(boundingBox)); + if (drawsOutline) + paintOutline(childPaintInfo, IntRect(boundingBox)); + } } // This method is called from inside paintOutline() since we call paintOutline() @@ -346,7 +338,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, LayoutPoint(localPoint)); + updateHitTestResult(result, roundedLayoutPoint(localPoint)); return true; } } @@ -372,7 +364,7 @@ FloatRect RenderSVGShape::markerRect(float strokeWidth) const { ASSERT(!m_markerPositions.isEmpty()); - auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this); ASSERT(resources); RenderSVGResourceMarker* markerStart = resources->markerStart(); @@ -432,7 +424,7 @@ void RenderSVGShape::updateRepaintBoundingBox() float RenderSVGShape::strokeWidth() const { SVGLengthContext lengthContext(&graphicsElement()); - return lengthContext.valueForLength(style().svgStyle().strokeWidth()); + return style().svgStyle().strokeWidth().value(lengthContext); } bool RenderSVGShape::hasSmoothStroke() const @@ -448,7 +440,7 @@ void RenderSVGShape::drawMarkers(PaintInfo& paintInfo) { ASSERT(!m_markerPositions.isEmpty()); - auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*this); if (!resources) return; @@ -476,10 +468,10 @@ void RenderSVGShape::processMarkerPositions() ASSERT(m_path); SVGMarkerData markerData(m_markerPositions); - m_path->apply([&markerData](const PathElement& pathElement) { - SVGMarkerData::updateFromPathElement(markerData, pathElement); - }); + m_path->apply(&markerData, SVGMarkerData::updateFromPathElement); markerData.pathIsDone(); } } + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/RenderSVGShape.h b/Source/WebCore/rendering/svg/RenderSVGShape.h index 611bfd14b..e27b4b42f 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 Inc. + * Copyright (C) 2006 Apple Computer, Inc * Copyright (C) 2009 Google, Inc. * Copyright (C) 2011 Renata Hodovan <reni@webkit.org> * Copyright (C) 2011 University of Szeged @@ -26,12 +26,13 @@ #ifndef RenderSVGShape_h #define RenderSVGShape_h +#if ENABLE(SVG) #include "AffineTransform.h" #include "FloatRect.h" #include "RenderSVGModelObject.h" #include "SVGGraphicsElement.h" #include "SVGMarkerData.h" -#include <memory> +#include <wtf/OwnPtr.h> #include <wtf/Vector.h> namespace WebCore { @@ -45,10 +46,11 @@ class SVGGraphicsElement; class RenderSVGShape : public RenderSVGModelObject { public: - RenderSVGShape(SVGGraphicsElement&, Ref<RenderStyle>&&); + RenderSVGShape(SVGGraphicsElement&, PassRef<RenderStyle>); + RenderSVGShape(SVGGraphicsElement&, PassRef<RenderStyle>, Path*, bool); virtual ~RenderSVGShape(); - SVGGraphicsElement& graphicsElement() const { return downcast<SVGGraphicsElement>(RenderSVGModelObject::element()); } + SVGGraphicsElement& graphicsElement() const { return toSVGGraphicsElement(RenderSVGModelObject::element()); } void setNeedsShapeUpdate() { m_needsShapeUpdate = true; } virtual void setNeedsBoundariesUpdate() override final { m_needsBoundariesUpdate = true; } @@ -56,7 +58,6 @@ public: virtual void setNeedsTransformUpdate() override 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 @@ -116,15 +117,14 @@ private: void fillShape(const RenderStyle&, GraphicsContext*); void strokeShape(const RenderStyle&, GraphicsContext*); - void strokeShape(GraphicsContext*); - void fillStrokeMarkers(PaintInfo&); + void fillAndStrokeShape(GraphicsContext*); void drawMarkers(PaintInfo&); private: FloatRect m_repaintBoundingBox; FloatRect m_repaintBoundingBoxExcludingShadow; AffineTransform m_localTransform; - std::unique_ptr<Path> m_path; + OwnPtr<Path> m_path; Vector<MarkerPosition> m_markerPositions; bool m_needsBoundariesUpdate : 1; @@ -132,8 +132,9 @@ private: bool m_needsTransformUpdate : 1; }; -} // namespace WebCore +RENDER_OBJECT_TYPE_CASTS(RenderSVGShape, isSVGShape()) -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGShape, isSVGShape()) +} -#endif // RenderSVGShape_h +#endif // ENABLE(SVG) +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGTSpan.h b/Source/WebCore/rendering/svg/RenderSVGTSpan.h index b7a788307..bdd33bbb0 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 Inc. + * Copyright (C) 2006 Apple Computer Inc. * Copyright (C) 2009 Google Inc. * * This library is free software; you can redistribute it and/or @@ -22,14 +22,15 @@ #ifndef RenderSVGTSpan_h #define RenderSVGTSpan_h +#if ENABLE(SVG) #include "RenderSVGInline.h" #include "SVGTextPositioningElement.h" namespace WebCore { class RenderSVGTSpan final : public RenderSVGInline { public: - explicit RenderSVGTSpan(SVGTextPositioningElement& element, Ref<RenderStyle>&& style) - : RenderSVGInline(element, WTF::move(style)) + explicit RenderSVGTSpan(SVGTextPositioningElement& element, PassRef<RenderStyle> style) + : RenderSVGInline(element, std::move(style)) { } @@ -37,8 +38,9 @@ public: private: void graphicsElement() const = delete; - virtual const char* renderName() const override { return "RenderSVGTSpan"; } + virtual const char* renderName() const { return "RenderSVGTSpan"; } }; } +#endif // ENABLE(SVG) #endif // !RenderSVGTSpan_h diff --git a/Source/WebCore/rendering/svg/RenderSVGText.cpp b/Source/WebCore/rendering/svg/RenderSVGText.cpp index 4e08f3f9a..22c1cdaab 100644 --- a/Source/WebCore/rendering/svg/RenderSVGText.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGText.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Inc. + * Copyright (C) 2006 Apple Computer, 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 "Font.h" +#include "FontCache.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" @@ -46,14 +46,15 @@ #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, Ref<RenderStyle>&& style) - : RenderSVGBlock(element, WTF::move(style)) +RenderSVGText::RenderSVGText(SVGTextElement& element, PassRef<RenderStyle> style) + : RenderSVGBlock(element, std::move(style)) , m_needsReordering(false) , m_needsPositioningValuesUpdate(false) , m_needsTransformUpdate(true) @@ -68,7 +69,7 @@ RenderSVGText::~RenderSVGText() SVGTextElement& RenderSVGText::textElement() const { - return downcast<SVGTextElement>(RenderSVGBlock::graphicsElement()); + return toSVGTextElement(RenderSVGBlock::graphicsElement()); } bool RenderSVGText::isChildAllowed(const RenderObject& child, const RenderStyle&) const @@ -76,14 +77,24 @@ bool RenderSVGText::isChildAllowed(const RenderObject& child, const RenderStyle& return child.isInline(); } -RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(RenderObject& start) +RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(RenderObject* start) { - return lineageOfType<RenderSVGText>(start).first(); + ASSERT(start); + while (start && !start->isSVGText()) + start = start->parent(); + if (!start || !start->isSVGText()) + return 0; + return toRenderSVGText(start); } -const RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(const RenderObject& start) +const RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(const RenderObject* start) { - return lineageOfType<RenderSVGText>(start).first(); + ASSERT(start); + while (start && !start->isSVGText()) + start = start->parent(); + if (!start || !start->isSVGText()) + return 0; + return toRenderSVGText(start); } LayoutRect RenderSVGText::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const @@ -116,8 +127,8 @@ 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 (is<RenderSVGInlineText>(*descendant)) - attributes.append(downcast<RenderSVGInlineText>(*descendant).layoutAttributes()); + if (descendant->isSVGInlineText()) + attributes.append(toRenderSVGInlineText(descendant)->layoutAttributes()); } } @@ -127,15 +138,15 @@ static inline bool findPreviousAndNextAttributes(RenderElement* start, RenderSVG ASSERT(locateElement); // FIXME: Make this iterative. for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { - if (is<RenderSVGInlineText>(*child)) { - RenderSVGInlineText& text = downcast<RenderSVGInlineText>(*child); - if (locateElement != &text) { + if (child->isSVGInlineText()) { + RenderSVGInlineText* text = toRenderSVGInlineText(child); + if (locateElement != text) { if (stopAfterNext) { - next = text.layoutAttributes(); + next = text->layoutAttributes(); return true; } - previous = text.layoutAttributes(); + previous = text->layoutAttributes(); continue; } @@ -143,10 +154,10 @@ static inline bool findPreviousAndNextAttributes(RenderElement* start, RenderSVG continue; } - if (!is<RenderSVGInline>(*child)) + if (!child->isSVGInline()) continue; - if (findPreviousAndNextAttributes(downcast<RenderElement>(child), locateElement, stopAfterNext, previous, next)) + if (findPreviousAndNextAttributes(toRenderElement(child), locateElement, stopAfterNext, previous, next)) return true; } @@ -169,6 +180,9 @@ void RenderSVGText::subtreeChildWasAdded(RenderObject* child) if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) 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(); @@ -250,20 +264,21 @@ void RenderSVGText::subtreeChildWillBeRemoved(RenderObject* child, Vector<SVGTex return; // This logic requires that the 'text' child is still inserted in the tree. - auto& text = downcast<RenderSVGInlineText>(*child); + RenderSVGInlineText* text = toRenderSVGInlineText(child); bool stopAfterNext = false; - SVGTextLayoutAttributes* previous = nullptr; - SVGTextLayoutAttributes* next = nullptr; + SVGTextLayoutAttributes* previous = 0; + SVGTextLayoutAttributes* next = 0; if (!documentBeingDestroyed()) - findPreviousAndNextAttributes(this, &text, stopAfterNext, previous, next); + findPreviousAndNextAttributes(this, text, stopAfterNext, previous, next); if (previous) affectedAttributes.append(previous); if (next) affectedAttributes.append(next); - bool removed = m_layoutAttributes.removeFirst(text.layoutAttributes()); - ASSERT_UNUSED(removed, removed); + size_t position = m_layoutAttributes.find(text->layoutAttributes()); + ASSERT(position != notFound); + m_layoutAttributes.remove(position); } void RenderSVGText::subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes) @@ -290,9 +305,10 @@ void RenderSVGText::subtreeStyleDidChange(RenderSVGInlineText* text) // 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 (is<RenderSVGInlineText>(*descendant)) - m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(downcast<RenderSVGInlineText>(*descendant)); + if (descendant->isSVGInlineText()) + m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(toRenderSVGInlineText(descendant)); } } @@ -311,26 +327,29 @@ 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 (is<RenderSVGInlineText>(*descendant)) - m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(downcast<RenderSVGInlineText>(*descendant)); + if (descendant->isSVGInlineText()) + m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(toRenderSVGInlineText(*descendant)); } } -static inline void updateFontInAllDescendants(RenderObject* start, SVGTextLayoutAttributesBuilder* builder = nullptr) +static inline void updateFontInAllDescendants(RenderObject* start, SVGTextLayoutAttributesBuilder* builder = 0) { for (RenderObject* descendant = start; descendant; descendant = descendant->nextInPreOrder(start)) { - if (!is<RenderSVGInlineText>(*descendant)) + if (!descendant->isSVGInlineText()) continue; - auto& text = downcast<RenderSVGInlineText>(*descendant); + RenderSVGInlineText& text = toRenderSVGInlineText(*descendant); text.updateScaledFont(); if (builder) - builder->rebuildMetricsForTextRenderer(text); + builder->rebuildMetricsForTextRenderer(&text); } } @@ -353,7 +372,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; @@ -367,7 +386,7 @@ void RenderSVGText::layout() m_needsTextMetricsUpdate = false; } - m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(*this); + m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(this); m_needsReordering = true; m_needsPositioningValuesUpdate = false; updateCachedBoundariesInParents = true; @@ -390,7 +409,7 @@ void RenderSVGText::layout() ASSERT(!simplifiedLayout()); ASSERT(!scrollsOverflow()); ASSERT(!hasControlClip()); - ASSERT(!multiColumnFlowThread()); + ASSERT(!hasColumns()); ASSERT(!positionedObjects()); ASSERT(!m_overflow); ASSERT(!isAnonymousBlock()); @@ -403,7 +422,7 @@ void RenderSVGText::layout() ASSERT(childrenInline()); LayoutUnit repaintLogicalTop = 0; LayoutUnit repaintLogicalBottom = 0; - rebuildFloatingObjectSetFromIntrudingFloats(); + clearFloats(); layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom); if (m_needsReordering) @@ -428,7 +447,7 @@ std::unique_ptr<RootInlineBox> RenderSVGText::createRootInlineBox() { auto box = std::make_unique<SVGRootInlineBox>(*this); box->setHasVirtualLogicalHeight(); - return WTF::move(box); + return std::move(box); } bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) @@ -457,25 +476,26 @@ bool RenderSVGText::nodeAtPoint(const HitTestRequest&, HitTestResult&, const Hit return false; } -VisiblePosition RenderSVGText::positionForPoint(const LayoutPoint& pointInContents, const RenderRegion* region) +VisiblePosition RenderSVGText::positionForPoint(const LayoutPoint& pointInContents) { RootInlineBox* rootBox = firstRootBox(); if (!rootBox) return createVisiblePosition(0, DOWNSTREAM); + ASSERT_WITH_SECURITY_IMPLICATION(rootBox->isSVGRootInlineBox()); ASSERT(!rootBox->nextRootBox()); ASSERT(childrenInline()); - InlineBox* closestBox = downcast<SVGRootInlineBox>(*rootBox).closestLeafChildForPosition(pointInContents); + InlineBox* closestBox = toSVGRootInlineBox(rootBox)->closestLeafChildForPosition(pointInContents); if (!closestBox) return createVisiblePosition(0, DOWNSTREAM); - return closestBox->renderer().positionForPoint(LayoutPoint(pointInContents.x(), closestBox->y()), region); + return closestBox->renderer().positionForPoint(LayoutPoint(pointInContents.x(), closestBox->y())); } void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const { - quads.append(localToAbsoluteQuad(strokeBoundingBox(), UseTransforms, wasFixed)); + quads.append(localToAbsoluteQuad(strokeBoundingBox(), 0 /* mode */, wasFixed)); } void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint&) @@ -484,6 +504,7 @@ void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint&) return; if (paintInfo.phase != PaintPhaseForeground + && paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseSelection) return; @@ -491,12 +512,6 @@ void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint&) 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 @@ -507,7 +522,7 @@ FloatRect RenderSVGText::strokeBoundingBox() const return strokeBoundaries; SVGLengthContext lengthContext(&textElement()); - strokeBoundaries.inflate(lengthContext.valueForLength(svgStyle.strokeWidth())); + strokeBoundaries.inflate(svgStyle.strokeWidth().value(lengthContext)); return strokeBoundaries; } @@ -535,6 +550,7 @@ void RenderSVGText::removeChild(RenderObject& child) SVGResourcesCache::clientWillBeRemovedFromTree(child); Vector<SVGTextLayoutAttributes*, 2> affectedAttributes; + FontCachePurgePreventer fontCachePurgePreventer; subtreeChildWillBeRemoved(&child, affectedAttributes); RenderSVGBlock::removeChild(child); subtreeChildWasRemoved(affectedAttributes); @@ -554,3 +570,5 @@ void RenderSVGText::updateFirstLetter() } } + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/RenderSVGText.h b/Source/WebCore/rendering/svg/RenderSVGText.h index 462773d21..93ac44246 100644 --- a/Source/WebCore/rendering/svg/RenderSVGText.h +++ b/Source/WebCore/rendering/svg/RenderSVGText.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Inc. + * Copyright (C) 2006 Apple Computer, Inc. * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. * @@ -22,6 +22,7 @@ #ifndef RenderSVGText_h #define RenderSVGText_h +#if ENABLE(SVG) #include "AffineTransform.h" #include "RenderSVGBlock.h" #include "SVGTextLayoutAttributesBuilder.h" @@ -34,20 +35,20 @@ class RenderSVGInlineText; class RenderSVGText final : public RenderSVGBlock { public: - RenderSVGText(SVGTextElement&, Ref<RenderStyle>&&); + RenderSVGText(SVGTextElement&, PassRef<RenderStyle>); virtual ~RenderSVGText(); SVGTextElement& textElement() const; - virtual bool isChildAllowed(const RenderObject&, const RenderStyle&) const override; + virtual bool isChildAllowed(const RenderObject&, const RenderStyle&) const; void setNeedsPositioningValuesUpdate() { m_needsPositioningValuesUpdate = true; } - virtual void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; } + virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } void setNeedsTextMetricsUpdate() { m_needsTextMetricsUpdate = true; } - virtual FloatRect repaintRectInLocalCoordinates() const override; + virtual FloatRect repaintRectInLocalCoordinates() const; - 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; } @@ -58,41 +59,41 @@ public: void subtreeStyleDidChange(RenderSVGInlineText*); void subtreeTextDidChange(RenderSVGInlineText*); - virtual FloatRect objectBoundingBox() const override { return frameRect(); } - virtual FloatRect strokeBoundingBox() const override; - private: void graphicsElement() const = delete; - virtual const char* renderName() const override { return "RenderSVGText"; } - virtual bool isSVGText() const override { return true; } + virtual const char* renderName() const { return "RenderSVGText"; } + virtual bool isSVGText() const { return true; } - virtual void paint(PaintInfo&, const LayoutPoint&) override; + 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) override; - virtual VisiblePosition positionForPoint(const LayoutPoint&, const RenderRegion*) override; + virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); + virtual VisiblePosition positionForPoint(const LayoutPoint&); - virtual bool requiresLayer() const override { return false; } - virtual void layout() override; + virtual bool requiresLayer() const { return false; } + virtual void layout(); - virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override; + virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const; 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; - virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, 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 = nullptr) override; + virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); virtual void removeChild(RenderObject&) override; virtual void willBeDestroyed() override; - virtual const AffineTransform& localToParentTransform() const override { return m_localTransform; } - virtual AffineTransform localTransform() const override { return m_localTransform; } + virtual FloatRect objectBoundingBox() const { return frameRect(); } + virtual FloatRect strokeBoundingBox() const; + + virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } + virtual AffineTransform localTransform() const { return m_localTransform; } virtual std::unique_ptr<RootInlineBox> createRootInlineBox() override; - virtual RenderBlock* firstLineBlock() const override; - virtual void updateFirstLetter() override; + virtual RenderBlock* firstLineBlock() const; + virtual void updateFirstLetter(); bool shouldHandleSubtreeMutations() const; @@ -105,8 +106,9 @@ private: Vector<SVGTextLayoutAttributes*> m_layoutAttributes; }; -} // namespace WebCore +RENDER_OBJECT_TYPE_CASTS(RenderSVGText, isSVGText()) -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGText, isSVGText()) +} -#endif // RenderSVGText_h +#endif // ENABLE(SVG) +#endif diff --git a/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp b/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp index 9671c9b34..12cb6d361 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp @@ -18,6 +18,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGTextPath.h" #include "FloatQuad.h" @@ -32,14 +34,14 @@ namespace WebCore { -RenderSVGTextPath::RenderSVGTextPath(SVGTextPathElement& element, Ref<RenderStyle>&& style) - : RenderSVGInline(element, WTF::move(style)) +RenderSVGTextPath::RenderSVGTextPath(SVGTextPathElement& element, PassRef<RenderStyle> style) + : RenderSVGInline(element, std::move(style)) { } SVGTextPathElement& RenderSVGTextPath::textPathElement() const { - return downcast<SVGTextPathElement>(RenderSVGInline::graphicsElement()); + return toSVGTextPathElement(RenderSVGInline::graphicsElement()); } Path RenderSVGTextPath::layoutPath() const @@ -48,17 +50,17 @@ Path RenderSVGTextPath::layoutPath() const if (!targetElement || !targetElement->hasTagName(SVGNames::pathTag)) return Path(); - SVGPathElement& pathElement = downcast<SVGPathElement>(*targetElement); + SVGPathElement* pathElement = toSVGPathElement(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; } @@ -78,3 +80,5 @@ bool RenderSVGTextPath::stretchMethod() const } } + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/RenderSVGTextPath.h b/Source/WebCore/rendering/svg/RenderSVGTextPath.h index 021555f25..e7e11ad98 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTextPath.h +++ b/Source/WebCore/rendering/svg/RenderSVGTextPath.h @@ -21,13 +21,14 @@ #ifndef RenderSVGTextPath_h #define RenderSVGTextPath_h +#if ENABLE(SVG) #include "RenderSVGInline.h" namespace WebCore { class RenderSVGTextPath final : public RenderSVGInline { public: - RenderSVGTextPath(SVGTextPathElement&, Ref<RenderStyle>&&); + RenderSVGTextPath(SVGTextPathElement&, PassRef<RenderStyle>); SVGTextPathElement& textPathElement() const; @@ -45,8 +46,9 @@ private: Path m_layoutPath; }; -} // namespace WebCore +RENDER_OBJECT_TYPE_CASTS(RenderSVGTextPath, isSVGTextPath()) -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGTextPath, isSVGTextPath()) +} +#endif // ENABLE(SVG) #endif // RenderSVGTextPath_h diff --git a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp index ea64d3cc9..3268b676a 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp @@ -20,6 +20,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "RenderSVGTransformableContainer.h" #include "SVGNames.h" @@ -27,8 +29,8 @@ namespace WebCore { -RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGGraphicsElement& element, Ref<RenderStyle>&& style) - : RenderSVGContainer(element, WTF::move(style)) +RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGGraphicsElement& element, PassRef<RenderStyle> style) + : RenderSVGContainer(element, std::move(style)) , m_needsTransformUpdate(true) , m_didTransformToRootUpdate(false) { @@ -41,13 +43,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 = nullptr; - if (is<SVGUseElement>(element)) - useElement = &downcast<SVGUseElement>(element); - else if (element.isInShadowTree() && is<SVGGElement>(element)) { + SVGUseElement* useElement = 0; + if (isSVGUseElement(element)) + useElement = &toSVGUseElement(element); + else if (element.isInShadowTree() && isSVGGElement(element)) { SVGElement* correspondingElement = element.correspondingElement(); - if (is<SVGUseElement>(correspondingElement)) - useElement = downcast<SVGUseElement>(correspondingElement); + if (correspondingElement && isSVGUseElement(correspondingElement)) + useElement = toSVGUseElement(correspondingElement); } if (useElement) { @@ -69,3 +71,5 @@ bool RenderSVGTransformableContainer::calculateLocalTransform() } } + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h index b9f6c1803..d97eafda0 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h @@ -21,6 +21,7 @@ #ifndef RenderSVGTransformableContainer_h #define RenderSVGTransformableContainer_h +#if ENABLE(SVG) #include "RenderSVGContainer.h" #include "SVGGraphicsElement.h" @@ -29,18 +30,18 @@ namespace WebCore { class SVGGraphicsElement; class RenderSVGTransformableContainer final : public RenderSVGContainer { public: - RenderSVGTransformableContainer(SVGGraphicsElement&, Ref<RenderStyle>&&); - SVGGraphicsElement& graphicsElement() { return downcast<SVGGraphicsElement>(RenderSVGContainer::element()); } + RenderSVGTransformableContainer(SVGGraphicsElement&, PassRef<RenderStyle>); + SVGGraphicsElement& graphicsElement() { return toSVGGraphicsElement(RenderSVGContainer::element()); } - virtual bool isSVGTransformableContainer() const override { return true; } - virtual const AffineTransform& localToParentTransform() const override { return m_localTransform; } - virtual void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; } - virtual bool didTransformToRootUpdate() override { return m_didTransformToRootUpdate; } + 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; } private: void element() const = delete; - virtual bool calculateLocalTransform() override; - virtual AffineTransform localTransform() const override { return m_localTransform; } + virtual bool calculateLocalTransform(); + virtual AffineTransform localTransform() const { return m_localTransform; } bool m_needsTransformUpdate : 1; bool m_didTransformToRootUpdate : 1; @@ -48,8 +49,7 @@ private: FloatSize m_lastTranslation; }; -} // namespace WebCore - -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGTransformableContainer, isSVGTransformableContainer()) +} +#endif // ENABLE(SVG) #endif // RenderSVGTransformableContainer_h diff --git a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp index 02703d3df..f03467c62 100644 --- a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp @@ -21,17 +21,21 @@ */ #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, Ref<RenderStyle>&& style) - : RenderSVGContainer(element, WTF::move(style)) +RenderSVGViewportContainer::RenderSVGViewportContainer(SVGSVGElement& element, PassRef<RenderStyle> style) + : RenderSVGContainer(element, std::move(style)) , m_didTransformToRootUpdate(false) , m_isLayoutSizeChanged(false) , m_needsTransformUpdate(true) @@ -40,7 +44,7 @@ RenderSVGViewportContainer::RenderSVGViewportContainer(SVGSVGElement& element, R SVGSVGElement& RenderSVGViewportContainer::svgSVGElement() const { - return downcast<SVGSVGElement>(RenderSVGContainer::element()); + return toSVGSVGElement(RenderSVGContainer::element()); } void RenderSVGViewportContainer::determineIfLayoutSizeChanged() @@ -56,17 +60,62 @@ void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo) void RenderSVGViewportContainer::calcViewport() { - 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(); + 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(); + } } bool RenderSVGViewportContainer::calculateLocalTransform() @@ -104,3 +153,5 @@ 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 5969aeb67..182431eb5 100644 --- a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h @@ -23,6 +23,7 @@ #ifndef RenderSVGViewportContainer_h #define RenderSVGViewportContainer_h +#if ENABLE(SVG) #include "RenderSVGContainer.h" namespace WebCore { @@ -31,34 +32,34 @@ namespace WebCore { // thus we inherit from RenderSVGContainer instead of RenderSVGTransformableContainer class RenderSVGViewportContainer final : public RenderSVGContainer { public: - RenderSVGViewportContainer(SVGSVGElement&, Ref<RenderStyle>&&); + RenderSVGViewportContainer(SVGSVGElement&, PassRef<RenderStyle>); SVGSVGElement& svgSVGElement() const; FloatRect viewport() const { return m_viewport; } bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; } - virtual bool didTransformToRootUpdate() override { return m_didTransformToRootUpdate; } + virtual bool didTransformToRootUpdate() { return m_didTransformToRootUpdate; } - virtual void determineIfLayoutSizeChanged() override; - virtual void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; } + virtual void determineIfLayoutSizeChanged(); + virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } virtual void paint(PaintInfo&, const LayoutPoint&) override; private: void element() const = delete; - virtual bool isSVGViewportContainer() const override { return true; } - virtual const char* renderName() const override { return "RenderSVGViewportContainer"; } + virtual bool isSVGViewportContainer() const { return true; } + virtual const char* renderName() const { return "RenderSVGViewportContainer"; } AffineTransform viewportTransform() const; - virtual const AffineTransform& localToParentTransform() const override { return m_localToParentTransform; } + virtual const AffineTransform& localToParentTransform() const { return m_localToParentTransform; } - virtual void calcViewport() override; - virtual bool calculateLocalTransform() override; + virtual void calcViewport(); + virtual bool calculateLocalTransform(); - virtual void applyViewportClip(PaintInfo&) override; - virtual bool pointIsInsideViewportClip(const FloatPoint& pointInParent) override; + virtual void applyViewportClip(PaintInfo&); + virtual bool pointIsInsideViewportClip(const FloatPoint& pointInParent); FloatRect m_viewport; mutable AffineTransform m_localToParentTransform; @@ -67,8 +68,9 @@ private: bool m_needsTransformUpdate : 1; }; -} // namespace WebCore +RENDER_OBJECT_TYPE_CASTS(RenderSVGViewportContainer, isSVGViewportContainer()) -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSVGViewportContainer, isSVGViewportContainer()) +} // namespace WebCore +#endif // ENABLE(SVG) #endif // RenderSVGViewportContainer_h diff --git a/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp b/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp index ad345f0c9..db017adba 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 Inc. + * Copyright (C) 2006 Apple Computer Inc. * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) Research In Motion Limited 2010. All rights reserved. * @@ -23,6 +23,7 @@ #include "config.h" #include "SVGInlineFlowBox.h" +#if ENABLE(SVG) #include "DocumentMarkerController.h" #include "GraphicsContext.h" #include "RenderedDocumentMarker.h" @@ -38,14 +39,14 @@ void SVGInlineFlowBox::paintSelectionBackground(PaintInfo& paintInfo) PaintInfo childPaintInfo(paintInfo); for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { - if (is<SVGInlineTextBox>(*child)) - downcast<SVGInlineTextBox>(*child).paintSelectionBackground(childPaintInfo); - else if (is<SVGInlineFlowBox>(*child)) - downcast<SVGInlineFlowBox>(*child).paintSelectionBackground(childPaintInfo); + if (child->isSVGInlineTextBox()) + toSVGInlineTextBox(child)->paintSelectionBackground(childPaintInfo); + else if (child->isSVGInlineFlowBox()) + toSVGInlineFlowBox(child)->paintSelectionBackground(childPaintInfo); } } -void SVGInlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit) +void SVGInlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit) { ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); ASSERT(!paintInfo.context->paintingDisabled()); @@ -53,10 +54,10 @@ void SVGInlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse SVGRenderingContext renderingContext(renderer(), paintInfo, SVGRenderingContext::SaveGraphicsContext); if (renderingContext.isRenderingPrepared()) { for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { - if (is<SVGInlineTextBox>(*child)) - computeTextMatchMarkerRectForRenderer(&downcast<SVGInlineTextBox>(*child).renderer()); + if (child->isSVGInlineTextBox()) + computeTextMatchMarkerRectForRenderer(&(toSVGInlineTextBox(child)->renderer())); - child->paint(paintInfo, paintOffset, 0, 0); + child->paint(paintInfo, LayoutPoint(), 0, 0); } } } @@ -83,21 +84,25 @@ void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText RenderStyle& style = textRenderer->style(); AffineTransform fragmentTransform; - Vector<RenderedDocumentMarker*> markers = textRenderer->document().markers().markersFor(&textNode); - for (auto* marker : markers) { + 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 (!is<SVGInlineTextBox>(*box)) + if (!box->isSVGInlineTextBox()) continue; - auto& textBox = downcast<SVGInlineTextBox>(*box); + 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()); + 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; @@ -105,17 +110,17 @@ void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText int fragmentStartPosition = 0; int fragmentEndPosition = 0; - const Vector<SVGTextFragment>& fragments = textBox.textFragments(); + 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)) + if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition)) continue; - FloatRect fragmentRect = textBox.selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, &style); + FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, &style); fragment.buildFragmentTransform(fragmentTransform); if (!fragmentTransform.isIdentity()) fragmentRect = fragmentTransform.mapRect(fragmentRect); @@ -124,8 +129,10 @@ void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText } } - marker->setRenderedRect(textRenderer->localToAbsoluteQuad(markerRect).enclosingBoundingBox()); + 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 0dccc8f20..88165dfda 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 Inc. + * Copyright (C) 2006 Apple Computer Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,6 +21,7 @@ #ifndef SVGInlineFlowBox_h #define SVGInlineFlowBox_h +#if ENABLE(SVG) #include "InlineFlowBox.h" #include "RenderSVGInline.h" @@ -52,8 +53,10 @@ private: float m_logicalHeight; }; +INLINE_BOX_OBJECT_TYPE_CASTS(SVGInlineFlowBox, isSVGInlineFlowBox()) + } // namespace WebCore -SPECIALIZE_TYPE_TRAITS_INLINE_BOX(SVGInlineFlowBox, isSVGInlineFlowBox()) +#endif // ENABLE(SVG) #endif // SVGInlineFlowBox_h diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp index 83b175dfc..f55976e95 100644 --- a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp +++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp @@ -22,6 +22,8 @@ #include "config.h" #include "SVGInlineTextBox.h" +#if ENABLE(SVG) +#include "FontCache.h" #include "Frame.h" #include "FrameView.h" #include "GraphicsContext.h" @@ -29,14 +31,12 @@ #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 +54,7 @@ SVGInlineTextBox::SVGInlineTextBox(RenderSVGInlineText& renderer) , m_logicalHeight(0) , m_paintingResourceMode(ApplyToDefaultMode) , m_startsNewTextChunk(false) - , m_paintingResource(nullptr) + , m_paintingResource(0) { } @@ -113,10 +113,12 @@ FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment& ASSERT_WITH_SECURITY_IMPLICATION(startPosition < endPosition); ASSERT(style); + FontCachePurgePreventer fontCachePurgePreventer; + float scalingFactor = renderer().scalingFactor(); ASSERT(scalingFactor); - const FontCascade& scaledFont = renderer().scaledFont(); + const Font& scaledFont = renderer().scaledFont(); const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics(); FloatPoint textOrigin(fragment.x, fragment.y); if (scalingFactor != 1) @@ -124,15 +126,12 @@ FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment& textOrigin.move(0, -scaledFontMetrics.floatAscent()); - 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()); + FloatRect selectionRect = scaledFont.selectionRectForText(constructTextRun(style, fragment), textOrigin, fragment.height * scalingFactor, startPosition, endPosition); if (scalingFactor == 1) - return snappedSelectionRect; + return selectionRect; - snappedSelectionRect.scale(1 / scalingFactor); - return snappedSelectionRect; + selectionRect.scale(1 / scalingFactor); + return selectionRect; } LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPosition) const @@ -172,7 +171,7 @@ LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi static inline bool textShouldBePainted(const RenderSVGInlineText& textRenderer) { - // FontCascade::pixelSize(), returns FontDescription::computedPixelSize(), which returns "int(x + 0.5)". + // Font::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(); } @@ -186,7 +185,7 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo) if (renderer().style().visibility() != VISIBLE) return; - auto& parentRenderer = parent()->renderer(); + RenderObject& parentRenderer = parent()->renderer(); ASSERT(!parentRenderer.document().printing()); // Determine whether or not we're selected. @@ -204,6 +203,13 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo) RenderStyle& style = parentRenderer.style(); + RenderStyle* selectionStyle = &style; + if (hasSelection) { + selectionStyle = parentRenderer.getCachedPseudoStyle(SELECTION); + if (!selectionStyle) + selectionStyle = &style; + } + int startPosition, endPosition; selectionStartEnd(startPosition, endPosition); @@ -234,7 +240,7 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo) ASSERT(!m_paintingResource); } -void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit) +void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit) { ASSERT(paintInfo.shouldPaintWithinRoot(renderer())); ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); @@ -246,7 +252,7 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse // 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. - auto& parentRenderer = parent()->renderer(); + RenderObject& parentRenderer = parent()->renderer(); bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; bool hasSelection = !parentRenderer.document().printing() && selectionState() != RenderObject::SelectionNone; @@ -300,24 +306,16 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse if (decorations & TextDecorationOverline) paintDecoration(paintInfo.context, TextDecorationOverline, fragment); - auto paintOrder = style.svgStyle().paintTypesForPaintOrder(); - for (unsigned i = 0; i < paintOrder.size(); ++i) { - switch (paintOrder.at(i)) { - case PaintTypeFill: - if (!hasFill) - continue; - m_paintingResourceMode = ApplyToFillMode | ApplyToTextMode; - paintText(paintInfo.context, &style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly); - break; - case PaintTypeStroke: - if (!hasVisibleStroke) - continue; - m_paintingResourceMode = ApplyToStrokeMode | ApplyToTextMode; - paintText(paintInfo.context, &style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly); - break; - case PaintTypeMarkers: - continue; - } + // 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); } // Spec: Line-through should be drawn after the text is filled and stroked; thus, the line-through is rendered on top of the text. @@ -327,10 +325,6 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse 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); } @@ -373,7 +367,7 @@ void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const { ASSERT(m_paintingResource); - m_paintingResource->postApplyResource(parent()->renderer(), context, m_paintingResourceMode, path, /*RenderSVGShape*/ nullptr); + m_paintingResource->postApplyResource(parent()->renderer(), context, m_paintingResourceMode, path, /*RenderSVGShape*/ 0); m_paintingResource = nullptr; } @@ -388,8 +382,6 @@ bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& c TextRun::RenderingContext* renderingContext = textRun.renderingContext(); if (renderingContext) static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePaintingResource(m_paintingResource); -#else - UNUSED_PARAM(textRun); #endif return true; @@ -397,12 +389,12 @@ bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& c void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*& context, TextRun& textRun) { - releasePaintingResource(context, /* path */nullptr); + releasePaintingResource(context, /* path */0); #if ENABLE(SVG_FONTS) TextRun::RenderingContext* renderingContext = textRun.renderingContext(); if (renderingContext) - static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePaintingResource(nullptr); + static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePaintingResource(0); #else UNUSED_PARAM(textRun); #endif @@ -412,14 +404,15 @@ TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFrag { ASSERT(style); - TextRun run(StringView(renderer().text()).substring(fragment.characterOffset, fragment.length) + TextRun run(renderer().deprecatedCharacters() + fragment.characterOffset + , fragment.length , 0 /* xPos, only relevant with allowTabs=true */ , 0 /* padding, only relevant for justified text, not relevant for SVG */ - , AllowTrailingExpansion + , TextRun::AllowTrailingExpansion , direction() , dirOverride() || style->rtlOrdering() == VisualOrder /* directionalOverride */); - if (style->fontCascade().primaryFont().isSVGFont()) + if (style->font().isSVGFont()) run.setRenderingContext(SVGTextRunRenderingContext::create(renderer())); run.disableRoundingHacks(); @@ -475,7 +468,7 @@ static inline float positionOffsetForDecoration(TextDecoration decoration, const return 0.0f; } -static inline float thicknessForDecoration(TextDecoration, const FontCascade& font) +static inline float thicknessForDecoration(TextDecoration, const Font& font) { // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified. // Compatible with Batik/Opera @@ -535,8 +528,8 @@ void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDe RenderStyle& decorationStyle = decorationRenderer.style(); float scalingFactor = 1; - FontCascade scaledFont; - RenderSVGInlineText::computeNewScaledFontForStyle(decorationRenderer, decorationStyle, scalingFactor, scaledFont); + Font scaledFont; + RenderSVGInlineText::computeNewScaledFontForStyle(&decorationRenderer, &decorationStyle, scalingFactor, scaledFont); ASSERT(scalingFactor); // The initial y value refers to overline position. @@ -570,7 +563,7 @@ void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyl float scalingFactor = renderer().scalingFactor(); ASSERT(scalingFactor); - const FontCascade& scaledFont = renderer().scaledFont(); + const Font& scaledFont = renderer().scaledFont(); const ShadowData* shadow = style->textShadow(); FloatPoint textOrigin(fragment.x, fragment.y); @@ -587,24 +580,27 @@ void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyl if (!prepareGraphicsContextForTextPainting(context, scalingFactor, textRun, style)) break; - { - ShadowApplier shadowApplier(*context, shadow, shadowRect); + FloatSize extraOffset; + if (shadow) + extraOffset = applyShadowToGraphicsContext(context, shadow, shadowRect, false /* stroked */, true /* opaque */, true /* horizontal */); - if (!shadowApplier.didSaveContext()) - context->save(); - context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor)); + context->save(); + context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor)); - scaledFont.drawText(context, textRun, textOrigin + shadowApplier.extraOffset(), startPosition, endPosition); + scaledFont.drawText(context, textRun, textOrigin + extraOffset, startPosition, endPosition); - if (!shadowApplier.didSaveContext()) - context->restore(); - } + context->restore(); restoreGraphicsContextAfterTextPainting(context, textRun); if (!shadow) break; + if (shadow->next()) + context->restore(); + else + context->clearShadow(); + shadow = shadow->next(); } while (shadow); } @@ -671,7 +667,7 @@ FloatRect SVGInlineTextBox::calculateBoundaries() const return textRect; } -bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit, LayoutUnit, HitTestAction) +bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit, LayoutUnit) { // FIXME: integrate with InlineTextBox::nodeAtPoint better. ASSERT(!isLineBreak()); @@ -695,3 +691,5 @@ 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 23c0769fe..97df4d698 100644 --- a/Source/WebCore/rendering/svg/SVGInlineTextBox.h +++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.h @@ -22,6 +22,7 @@ #ifndef SVGInlineTextBox_h #define SVGInlineTextBox_h +#if ENABLE(SVG) #include "InlineTextBox.h" #include "SVGTextLayoutEngine.h" #include "RenderSVGInlineText.h" @@ -35,30 +36,30 @@ class SVGInlineTextBox final : public InlineTextBox { public: explicit SVGInlineTextBox(RenderSVGInlineText&); - RenderSVGInlineText& renderer() const { return downcast<RenderSVGInlineText>(InlineTextBox::renderer()); } + RenderSVGInlineText& renderer() const { return toRenderSVGInlineText(InlineTextBox::renderer()); } - virtual float virtualLogicalHeight() const override { return m_logicalHeight; } + virtual float virtualLogicalHeight() const { return m_logicalHeight; } void setLogicalHeight(float height) { m_logicalHeight = height; } - int selectionTop() { return top(); } - int selectionHeight() { return static_cast<int>(ceilf(m_logicalHeight)); } - virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const override; - virtual float positionForOffset(int offset) const override; + 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; void paintSelectionBackground(PaintInfo&); - virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override; + virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom); virtual LayoutRect localSelectionRect(int startPosition, int endPosition) const override; bool mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment&, int& startPosition, int& endPosition) const; - virtual FloatRect calculateBoundaries() const override; + virtual FloatRect calculateBoundaries() const; void clearTextFragments() { m_textFragments.clear(); } Vector<SVGTextFragment>& textFragments() { return m_textFragments; } const Vector<SVGTextFragment>& textFragments() const { return m_textFragments; } - virtual void dirtyOwnLineBoxes() override; - virtual void dirtyLineBoxes() override; + virtual void dirtyOwnLineBoxes() override final; + virtual void dirtyLineBoxes() override final; bool startsNewTextChunk() const { return m_startsNewTextChunk; } void setStartsNewTextChunk(bool newTextChunk) { m_startsNewTextChunk = newTextChunk; } @@ -82,7 +83,7 @@ private: void paintTextWithShadows(GraphicsContext*, RenderStyle*, TextRun&, const SVGTextFragment&, int startPosition, int endPosition); void paintText(GraphicsContext*, RenderStyle*, RenderStyle* selectionStyle, const SVGTextFragment&, bool hasSelection, bool paintSelectedTextOnly); - virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom, HitTestAction) override; + virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) override; private: float m_logicalHeight; @@ -92,8 +93,9 @@ private: Vector<SVGTextFragment> m_textFragments; }; -} // namespace WebCore +INLINE_BOX_OBJECT_TYPE_CASTS(SVGInlineTextBox, isSVGInlineTextBox()) -SPECIALIZE_TYPE_TRAITS_INLINE_BOX(SVGInlineTextBox, isSVGInlineTextBox()) +} // namespace WebCore +#endif #endif // SVGInlineTextBox_h diff --git a/Source/WebCore/rendering/svg/SVGMarkerData.h b/Source/WebCore/rendering/svg/SVGMarkerData.h index 16b10ebd9..5d5a86d98 100644 --- a/Source/WebCore/rendering/svg/SVGMarkerData.h +++ b/Source/WebCore/rendering/svg/SVGMarkerData.h @@ -20,8 +20,10 @@ #ifndef SVGMarkerData_h #define SVGMarkerData_h +#if ENABLE(SVG) #include "FloatConversion.h" #include "Path.h" +#include <wtf/MathExtras.h> namespace WebCore { @@ -54,20 +56,22 @@ public: { } - static void updateFromPathElement(SVGMarkerData& markerData, const PathElement& element) + static void updateFromPathElement(void* info, 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() @@ -107,11 +111,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,4 +155,5 @@ private: } +#endif // ENABLE(SVG) #endif // SVGMarkerData_h diff --git a/Source/WebCore/rendering/svg/SVGPathData.cpp b/Source/WebCore/rendering/svg/SVGPathData.cpp index 2743f52a9..01ef871f7 100644 --- a/Source/WebCore/rendering/svg/SVGPathData.cpp +++ b/Source/WebCore/rendering/svg/SVGPathData.cpp @@ -20,12 +20,10 @@ #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" @@ -39,42 +37,32 @@ namespace WebCore { static void updatePathFromCircleElement(SVGElement* element, Path& path) { - ASSERT(is<SVGCircleElement>(element)); + ASSERT(isSVGCircleElement(element)); + SVGCircleElement* circle = toSVGCircleElement(element); SVGLengthContext lengthContext(element); - RenderElement* renderer = element->renderer(); - if (!renderer) - return; - RenderStyle& 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)); - } + 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)); } static void updatePathFromEllipseElement(SVGElement* element, Path& path) { - RenderElement* renderer = element->renderer(); - if (!renderer) - return; - RenderStyle& style = renderer->style(); + SVGEllipseElement* ellipse = toSVGEllipseElement(element); + SVGLengthContext lengthContext(element); - float rx = lengthContext.valueForLength(style.svgStyle().rx(), LengthModeWidth); + float rx = ellipse->rx().value(lengthContext); if (rx <= 0) return; - float ry = lengthContext.valueForLength(style.svgStyle().ry(), LengthModeHeight); + float ry = ellipse->ry().value(lengthContext); if (ry <= 0) return; - 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)); + path.addEllipse(FloatRect(ellipse->cx().value(lengthContext) - rx, ellipse->cy().value(lengthContext) - ry, rx * 2, ry * 2)); } static void updatePathFromLineElement(SVGElement* element, Path& path) { - SVGLineElement* line = downcast<SVGLineElement>(element); + SVGLineElement* line = toSVGLineElement(element); SVGLengthContext lengthContext(element); path.moveTo(FloatPoint(line->x1().value(lengthContext), line->y1().value(lengthContext))); @@ -83,12 +71,12 @@ static void updatePathFromLineElement(SVGElement* element, Path& path) static void updatePathFromPathElement(SVGElement* element, Path& path) { - buildPathFromByteStream(downcast<SVGPathElement>(element)->pathByteStream(), path); + buildPathFromByteStream(toSVGPathElement(element)->pathByteStream(), path); } static void updatePathFromPolygonElement(SVGElement* element, Path& path) { - SVGPointList& points = downcast<SVGPolygonElement>(element)->animatedPoints()->values(); + SVGPointList& points = toSVGPolygonElement(element)->animatedPoints()->values(); if (points.isEmpty()) return; @@ -103,7 +91,7 @@ static void updatePathFromPolygonElement(SVGElement* element, Path& path) static void updatePathFromPolylineElement(SVGElement* element, Path& path) { - SVGPointList& points = downcast<SVGPolylineElement>(element)->animatedPoints()->values(); + SVGPointList& points = toSVGPolylineElement(element)->animatedPoints()->values(); if (points.isEmpty()) return; @@ -116,22 +104,19 @@ static void updatePathFromPolylineElement(SVGElement* element, Path& path) static void updatePathFromRectElement(SVGElement* element, Path& path) { - RenderElement* renderer = element->renderer(); - if (!renderer) - return; + SVGRectElement* rect = toSVGRectElement(element); - RenderStyle& style = renderer->style(); SVGLengthContext lengthContext(element); - float width = lengthContext.valueForLength(style.width(), LengthModeWidth); + float width = rect->width().value(lengthContext); if (width <= 0) return; - float height = lengthContext.valueForLength(style.height(), LengthModeHeight); + float height = rect->height().value(lengthContext); if (height <= 0) return; - 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); + float x = rect->x().value(lengthContext); + float y = rect->y().value(lengthContext); + float rx = rect->rx().value(lengthContext); + float ry = rect->ry().value(lengthContext); bool hasRx = rx > 0; bool hasRy = ry > 0; if (hasRx || hasRy) { @@ -172,3 +157,5 @@ 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 4a6289748..1a4b7ba89 100644 --- a/Source/WebCore/rendering/svg/SVGPathData.h +++ b/Source/WebCore/rendering/svg/SVGPathData.h @@ -20,6 +20,7 @@ #ifndef SVGPathData_h #define SVGPathData_h +#if ENABLE(SVG) namespace WebCore { class SVGElement; @@ -29,4 +30,5 @@ void updatePathFromGraphicsElement(SVGElement*, Path&); }; +#endif // ENABLE(SVG) #endif // SVGPathData_h diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp index 2b17b2ccc..9602927f2 100644 --- a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp +++ b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp @@ -23,6 +23,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "SVGRenderSupport.h" #include "NodeRenderStyle.h" @@ -30,14 +32,12 @@ #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 +49,8 @@ FloatRect SVGRenderSupport::repaintRectForRendererInLocalCoordinatesExcludingSVG { // FIXME: Add support for RenderSVGBlock. - if (is<RenderSVGModelObject>(renderer)) - return downcast<RenderSVGModelObject>(renderer).repaintRectInLocalCoordinatesExcludingSVGShadow(); + if (renderer.isSVGShape() || renderer.isSVGImage() || renderer.isSVGContainer()) + return toRenderSVGModelObject(renderer).repaintRectInLocalCoordinatesExcludingSVGShadow(); return renderer.repaintRectInLocalCoordinates(); } @@ -83,27 +83,18 @@ void SVGRenderSupport::computeFloatRectForRepaint(const RenderElement& renderer, renderer.parent()->computeFloatRectForRepaint(repaintContainer, repaintRect, fixed); } -const RenderElement& SVGRenderSupport::localToParentTransform(const RenderElement& renderer, AffineTransform &transform) +void SVGRenderSupport::mapLocalToContainer(const RenderElement& renderer, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool* wasFixed) { + 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. - 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); + // RenderSVGRoot's mapLocalToContainer method expects CSS box coordinates. + if (parent.isSVGRoot()) + transformState.applyTransform(toRenderSVGRoot(parent).localToBorderBoxTransform()); MapCoordinatesFlags mode = UseTransforms; parent.mapLocalToContainer(repaintContainer, transformState, mode, wasFixed); @@ -113,10 +104,19 @@ const RenderElement* SVGRenderSupport::pushMappingToContainer(const RenderElemen { ASSERT_UNUSED(ancestorToStopAt, ancestorToStopAt != &renderer); - AffineTransform transform; - auto& parent = localToParentTransform(renderer, transform); + 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()); - geometryMap.push(&renderer, transform); return &parent; } @@ -127,13 +127,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 !(is<RenderSVGContainer>(parent) && downcast<RenderSVGContainer>(*parent).didTransformToRootUpdate()); + return !(parent && parent->isSVGContainer() && toRenderSVGContainer(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) { - bool otherValid = is<RenderSVGContainer>(*other) ? downcast<RenderSVGContainer>(*other).isObjectBoundingBoxValid() : true; + bool otherValid = other->isSVGContainer() ? toRenderSVGContainer(other)->isObjectBoundingBoxValid() : true; if (!otherValid) return; @@ -159,10 +159,6 @@ void SVGRenderSupport::computeContainerBoundingBoxes(const RenderElement& contai 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(); if (transform.isIdentity()) { updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, current->objectBoundingBox()); @@ -189,36 +185,37 @@ const RenderSVGRoot& SVGRenderSupport::findTreeRootObject(const RenderElement& s return *lineageOfType<RenderSVGRoot>(start).first(); } -static inline void invalidateResourcesOfChildren(RenderElement& renderer) +static inline void invalidateResourcesOfChildren(RenderObject& start) { - ASSERT(!renderer.needsLayout()); - if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) - resources->removeClientFromCache(renderer, false); + ASSERT(!start.needsLayout()); + if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(start)) + resources->removeClientFromCache(start, false); - for (auto& child : childrenOfType<RenderElement>(renderer)) - invalidateResourcesOfChildren(child); + for (RenderObject* child = start.firstChildSlow(); child; child = child->nextSibling()) + invalidateResourcesOfChildren(*child); } static inline bool layoutSizeOfNearestViewportChanged(const RenderElement& renderer) { const RenderElement* start = &renderer; - while (start && !is<RenderSVGRoot>(*start) && !is<RenderSVGViewportContainer>(*start)) + while (start && !start->isSVGRoot() && !start->isSVGViewportContainer()) start = start->parent(); ASSERT(start); - if (is<RenderSVGViewportContainer>(*start)) - return downcast<RenderSVGViewportContainer>(*start).isLayoutSizeChanged(); + ASSERT(start->isSVGRoot() || start->isSVGViewportContainer()); + if (start->isSVGViewportContainer()) + return toRenderSVGViewportContainer(start)->isLayoutSizeChanged(); - return downcast<RenderSVGRoot>(*start).isLayoutSizeChanged(); + return toRenderSVGRoot(start)->isLayoutSizeChanged(); } bool SVGRenderSupport::transformToRootChanged(RenderElement* ancestor) { - while (ancestor && !is<RenderSVGRoot>(*ancestor)) { - if (is<RenderSVGTransformableContainer>(*ancestor)) - return downcast<RenderSVGTransformableContainer>(*ancestor).didTransformToRootUpdate(); - if (is<RenderSVGViewportContainer>(*ancestor)) - return downcast<RenderSVGViewportContainer>(*ancestor).didTransformToRootUpdate(); + while (ancestor && !ancestor->isSVGRoot()) { + if (ancestor->isSVGTransformableContainer()) + return toRenderSVGContainer(ancestor)->didTransformToRootUpdate(); + if (ancestor->isSVGViewportContainer()) + return toRenderSVGViewportContainer(ancestor)->didTransformToRootUpdate(); ancestor = ancestor->parent(); } @@ -231,7 +228,7 @@ void SVGRenderSupport::layoutChildren(RenderElement& start, bool selfNeedsLayout bool transformChanged = transformToRootChanged(&start); bool hasSVGShadow = rendererHasSVGShadow(start); bool needsBoundariesUpdate = start.needsBoundariesUpdate(); - HashSet<RenderElement*> elementsThatDidNotReceiveLayout; + HashSet<RenderObject*> notlayoutedObjects; for (RenderObject* child = start.firstChild(); child; child = child->nextSibling()) { bool needsLayout = selfNeedsLayout; @@ -246,22 +243,21 @@ void SVGRenderSupport::layoutChildren(RenderElement& start, bool selfNeedsLayout if (transformChanged) { // If the transform changed we need to update the text metrics (note: this also happens for layoutSizeChanged=true). - if (is<RenderSVGText>(*child)) - downcast<RenderSVGText>(*child).setNeedsTextMetricsUpdate(); + if (child->isSVGText()) + toRenderSVGText(child)->setNeedsTextMetricsUpdate(); needsLayout = true; } if (layoutSizeChanged) { // When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths - if (SVGElement* element = is<SVGElement>(*child->node()) ? downcast<SVGElement>(child->node()) : nullptr) { + 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 (is<RenderSVGShape>(*child)) - downcast<RenderSVGShape>(*child).setNeedsShapeUpdate(); - else if (is<RenderSVGText>(*child)) { - RenderSVGText& svgText = downcast<RenderSVGText>(*child); - svgText.setNeedsTextMetricsUpdate(); - svgText.setNeedsPositioningValuesUpdate(); + if (child->isSVGShape()) + toRenderSVGShape(child)->setNeedsShapeUpdate(); + else if (child->isSVGText()) { + toRenderSVGText(child)->setNeedsTextMetricsUpdate(); + toRenderSVGText(child)->setNeedsPositioningValuesUpdate(); } needsLayout = true; @@ -273,46 +269,52 @@ void SVGRenderSupport::layoutChildren(RenderElement& start, bool selfNeedsLayout child->setNeedsLayout(MarkOnlyThis); if (child->needsLayout()) { - downcast<RenderElement>(*child).layout(); + toRenderElement(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 && is<RenderElement>(*child)) - elementsThatDidNotReceiveLayout.add(downcast<RenderElement>(child)); + } else if (layoutSizeChanged) + notlayoutedObjects.add(child); ASSERT(!child->needsLayout()); } if (!layoutSizeChanged) { - ASSERT(elementsThatDidNotReceiveLayout.isEmpty()); + ASSERT(notlayoutedObjects.isEmpty()); return; } // If the layout size changed, invalidate all resources of all children that didn't go through the layout() code path. - for (auto* element : elementsThatDidNotReceiveLayout) - invalidateResourcesOfChildren(*element); + for (auto child : notlayoutedObjects) + invalidateResourcesOfChildren(*child); } 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()); - return renderer.style().overflowX() == OHIDDEN || renderer.style().overflowX() == OSCROLL; + return renderer.style().overflowX() == OHIDDEN; } bool SVGRenderSupport::rendererHasSVGShadow(const RenderObject& renderer) { // FIXME: Add support for RenderSVGBlock. - if (is<RenderSVGModelObject>(renderer)) - return downcast<RenderSVGModelObject>(renderer).hasSVGShadow(); + if (renderer.isSVGShape() || renderer.isSVGImage() || renderer.isSVGContainer()) + return toRenderSVGModelObject(renderer).hasSVGShadow(); - if (is<RenderSVGRoot>(renderer)) - return downcast<RenderSVGRoot>(renderer).hasSVGShadow(); + if (renderer.isSVGRoot()) + return toRenderSVGRoot(renderer).hasSVGShadow(); return false; } @@ -321,13 +323,13 @@ void SVGRenderSupport::setRendererHasSVGShadow(RenderObject& renderer, bool hasS { // FIXME: Add support for RenderSVGBlock. - if (is<RenderSVGModelObject>(renderer)) { - downcast<RenderSVGModelObject>(renderer).setHasSVGShadow(hasShadow); + if (renderer.isSVGShape() || renderer.isSVGImage() || renderer.isSVGContainer()) { + toRenderSVGModelObject(renderer).setHasSVGShadow(hasShadow); return; } - if (is<RenderSVGRoot>(renderer)) - downcast<RenderSVGRoot>(renderer).setHasSVGShadow(hasShadow); + if (renderer.isSVGRoot()) + toRenderSVGRoot(renderer).setHasSVGShadow(hasShadow); } void SVGRenderSupport::intersectRepaintRectWithShadows(const RenderElement& renderer, FloatRect& repaintRect) @@ -361,12 +363,14 @@ void SVGRenderSupport::intersectRepaintRectWithShadows(const RenderElement& rend void SVGRenderSupport::intersectRepaintRectWithResources(const RenderElement& renderer, FloatRect& repaintRect) { - auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(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)); @@ -382,7 +386,7 @@ bool SVGRenderSupport::filtersForceContainerLayout(const RenderElement& renderer if (!renderer.normalChildNeedsLayout()) return false; - auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer); if (!resources || !resources->filter()) return false; @@ -393,7 +397,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. - auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer); if (!resources) return true; @@ -411,8 +415,8 @@ void SVGRenderSupport::applyStrokeStyleToContext(GraphicsContext* context, const const SVGRenderStyle& svgStyle = style.svgStyle(); - SVGLengthContext lengthContext(downcast<SVGElement>(renderer.element())); - context->setStrokeThickness(lengthContext.valueForLength(svgStyle.strokeWidth())); + SVGLengthContext lengthContext(toSVGElement(renderer.element())); + context->setStrokeThickness(svgStyle.strokeWidth().value(lengthContext)); context->setLineCap(svgStyle.capStyle()); context->setLineJoin(svgStyle.joinStyle()); if (svgStyle.joinStyle() == MiterJoin) @@ -424,10 +428,10 @@ void SVGRenderSupport::applyStrokeStyleToContext(GraphicsContext* context, const else { DashArray dashArray; dashArray.reserveInitialCapacity(dashes.size()); - for (auto& dash : dashes) - dashArray.uncheckedAppend(dash.value(lengthContext)); + for (unsigned i = 0, size = dashes.size(); i < size; ++i) + dashArray.uncheckedAppend(dashes[i].value(lengthContext)); - context->setLineDash(dashArray, lengthContext.valueForLength(svgStyle.strokeDashOffset())); + context->setLineDash(dashArray, svgStyle.strokeDashOffset().value(lengthContext)); } } @@ -436,40 +440,12 @@ void SVGRenderSupport::childAdded(RenderElement& parent, RenderObject& child) SVGRenderSupport::setRendererHasSVGShadow(child, SVGRenderSupport::rendererHasSVGShadow(parent) || SVGRenderSupport::rendererHasSVGShadow(child)); } -void SVGRenderSupport::styleChanged(RenderElement& renderer, const RenderStyle* oldStyle) +void SVGRenderSupport::styleChanged(RenderElement& renderer) { 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.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 8d7bdb3ce..026c14e7a 100644 --- a/Source/WebCore/rendering/svg/SVGRenderSupport.h +++ b/Source/WebCore/rendering/svg/SVGRenderSupport.h @@ -24,6 +24,7 @@ #ifndef SVGRenderSupport_h #define SVGRenderSupport_h +#if ENABLE(SVG) #include "PaintInfo.h" namespace WebCore { @@ -68,8 +69,7 @@ public: 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 const RenderElement& localToParentTransform(const RenderElement&, AffineTransform &); - static void mapLocalToContainer(const RenderElement&, const RenderLayerModelObject* repaintContainer, TransformState&, bool* wasFixed); + static void mapLocalToContainer(const RenderElement&, const RenderLayerModelObject* repaintContainer, TransformState&, bool* wasFixed = 0); static const RenderElement* pushMappingToContainer(const RenderElement&, const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&); static bool checkForSVGRepaintDuringLayout(const RenderElement&); @@ -84,12 +84,7 @@ public: static void setRendererHasSVGShadow(RenderObject&, bool hasShadow); static void childAdded(RenderElement& parent, RenderObject& child); - static void styleChanged(RenderElement&, const RenderStyle*); - -#if ENABLE(CSS_COMPOSITING) - static bool isolatesBlending(const RenderStyle&); - static void updateMaskedAncestorShouldIsolateBlending(const RenderElement&); -#endif + static void styleChanged(RenderElement&); // FIXME: These methods do not belong here. static const RenderSVGRoot& findTreeRootObject(const RenderElement&); @@ -102,4 +97,5 @@ 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 fc85f23fc..aa6040968 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 INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, 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,13 +27,14 @@ */ #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" @@ -249,17 +250,17 @@ static void writeSVGPaintingResource(TextStream& ts, RenderSVGResource* resource ts << " [id=\"" << element.getIdAttribute() << "\"]"; } -static void writeStyle(TextStream& ts, const RenderElement& renderer) +static void writeStyle(TextStream& ts, const RenderObject& object) { - const RenderStyle& style = renderer.style(); + const RenderStyle& style = object.style(); const SVGRenderStyle& svgStyle = style.svgStyle(); - if (!renderer.localTransform().isIdentity()) - writeNameValuePair(ts, "transform", renderer.localTransform()); + if (!object.localTransform().isIdentity()) + writeNameValuePair(ts, "transform", object.localTransform()); writeIfNotDefault(ts, "image rendering", style.imageRendering(), RenderStyle::initialImageRendering()); writeIfNotDefault(ts, "opacity", style.opacity(), RenderStyle::initialOpacity()); - if (is<RenderSVGShape>(renderer)) { - const auto& shape = downcast<RenderSVGShape>(renderer); + if (object.isSVGShape()) { + const RenderSVGShape& shape = static_cast<const RenderSVGShape&>(object); Color fallbackColor; if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<RenderSVGShape&>(shape), shape.style(), fallbackColor)) { @@ -268,8 +269,8 @@ static void writeStyle(TextStream& ts, const RenderElement& renderer) writeSVGPaintingResource(ts, strokePaintingResource); SVGLengthContext lengthContext(&shape.graphicsElement()); - double dashOffset = lengthContext.valueForLength(svgStyle.strokeDashOffset()); - double strokeWidth = lengthContext.valueForLength(svgStyle.strokeWidth()); + double dashOffset = svgStyle.strokeDashOffset().value(lengthContext); + double strokeWidth = svgStyle.strokeWidth().value(lengthContext); const Vector<SVGLength>& dashes = svgStyle.strokeDashArray(); DashArray dashArray; @@ -306,10 +307,10 @@ static void writeStyle(TextStream& ts, const RenderElement& renderer) writeIfNotEmpty(ts, "end marker", svgStyle.markerEndResource()); } -static TextStream& writePositionAndStyle(TextStream& ts, const RenderElement& renderer) +static TextStream& writePositionAndStyle(TextStream& ts, const RenderObject& object) { - ts << " " << enclosingIntRect(renderer.absoluteClippedOverflowRect()); - writeStyle(ts, renderer); + ts << " " << enclosingIntRect(const_cast<RenderObject&>(object).absoluteClippedOverflowRect()); + writeStyle(ts, object); return ts; } @@ -320,34 +321,34 @@ static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape) SVGGraphicsElement& svgElement = shape.graphicsElement(); SVGLengthContext lengthContext(&svgElement); - if (is<SVGRectElement>(svgElement)) { - const SVGRectElement& element = downcast<SVGRectElement>(svgElement); + if (isSVGRectElement(svgElement)) { + const SVGRectElement& element = toSVGRectElement(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 (is<SVGLineElement>(svgElement)) { - const SVGLineElement& element = downcast<SVGLineElement>(svgElement); + } else if (isSVGLineElement(svgElement)) { + const SVGLineElement& element = toSVGLineElement(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 (is<SVGEllipseElement>(svgElement)) { - const SVGEllipseElement& element = downcast<SVGEllipseElement>(svgElement); + } else if (isSVGEllipseElement(svgElement)) { + const SVGEllipseElement& element = toSVGEllipseElement(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 (is<SVGCircleElement>(svgElement)) { - const SVGCircleElement& element = downcast<SVGCircleElement>(svgElement); + } else if (isSVGCircleElement(svgElement)) { + const SVGCircleElement& element = toSVGCircleElement(svgElement); writeNameValuePair(ts, "cx", element.cx().value(lengthContext)); writeNameValuePair(ts, "cy", element.cy().value(lengthContext)); writeNameValuePair(ts, "r", element.r().value(lengthContext)); - } else if (is<SVGPolyElement>(svgElement)) { - const SVGPolyElement& element = downcast<SVGPolyElement>(svgElement); + } else if (svgElement.hasTagName(SVGNames::polygonTag) || svgElement.hasTagName(SVGNames::polylineTag)) { + const SVGPolyElement& element = toSVGPolyElement(svgElement); writeNameAndQuotedValue(ts, "points", element.pointList().valueAsString()); - } else if (is<SVGPathElement>(svgElement)) { - const SVGPathElement& element = downcast<SVGPathElement>(svgElement); + } else if (isSVGPathElement(svgElement)) { + const SVGPathElement& element = toSVGPathElement(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); @@ -364,7 +365,7 @@ static TextStream& operator<<(TextStream& ts, const RenderSVGRoot& root) static void writeRenderSVGTextBox(TextStream& ts, const RenderSVGText& text) { - auto* box = downcast<SVGRootInlineBox>(text.firstRootBox()); + SVGRootInlineBox* box = toSVGRootInlineBox(text.firstRootBox()); if (!box) return; @@ -434,10 +435,10 @@ 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 (!is<SVGInlineTextBox>(*box)) + if (!box->isSVGInlineTextBox()) continue; - writeSVGInlineTextBox(ts, downcast<SVGInlineTextBox>(box), indent); + writeSVGInlineTextBox(ts, toSVGInlineTextBox(box), indent); } } @@ -450,10 +451,10 @@ static void writeStandardPrefix(TextStream& ts, const RenderObject& object, int ts << " {" << object.node()->nodeName() << "}"; } -static void writeChildren(TextStream& ts, const RenderElement& parent, int indent) +static void writeChildren(TextStream& ts, const RenderObject& object, int indent) { - for (const auto& child : childrenOfType<RenderObject>(parent)) - write(ts, child, indent + 1); + for (RenderObject* child = object.firstChildSlow(); child; child = child->nextSibling()) + write(ts, *child, indent + 1); } static inline void writeCommonGradientProperties(TextStream& ts, SVGSpreadMethodType spreadMethod, const AffineTransform& gradientTransform, SVGUnitTypes::SVGUnitType gradientUnits) @@ -467,50 +468,56 @@ static inline void writeCommonGradientProperties(TextStream& ts, SVGSpreadMethod ts << " [gradientTransform=" << gradientTransform << "]"; } -void writeSVGResourceContainer(TextStream& ts, const RenderSVGResourceContainer& resource, int indent) +void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int indent) { - writeStandardPrefix(ts, resource, indent); + writeStandardPrefix(ts, object, indent); - const AtomicString& id = resource.element().getIdAttribute(); + Element* element = toElement(object.node()); + const AtomicString& id = element->getIdAttribute(); writeNameAndQuotedValue(ts, "id", id); - if (resource.resourceType() == MaskerResourceType) { - const auto& masker = static_cast<const RenderSVGResourceMasker&>(resource); - writeNameValuePair(ts, "maskUnits", masker.maskUnits()); - writeNameValuePair(ts, "maskContentUnits", masker.maskContentUnits()); + 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()); ts << "\n"; - } else if (resource.resourceType() == FilterResourceType) { - const auto& filter = static_cast<const RenderSVGResourceFilter&>(resource); - writeNameValuePair(ts, "filterUnits", filter.filterUnits()); - writeNameValuePair(ts, "primitiveUnits", filter.primitiveUnits()); +#if ENABLE(FILTERS) + } else if (resource->resourceType() == FilterResourceType) { + RenderSVGResourceFilter* filter = static_cast<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)) { + if (auto builder = filter->buildPrimitives(dummyFilter.get())) { if (FilterEffect* lastEffect = builder->lastEffect()) lastEffect->externalRepresentation(ts, indent + 1); } - } else if (resource.resourceType() == ClipperResourceType) { - const auto& clipper = static_cast<const RenderSVGResourceClipper&>(resource); - writeNameValuePair(ts, "clipPathUnits", clipper.clipPathUnits()); +#endif + } else if (resource->resourceType() == ClipperResourceType) { + RenderSVGResourceClipper* clipper = static_cast<RenderSVGResourceClipper*>(resource); + writeNameValuePair(ts, "clipPathUnits", clipper->clipPathUnits()); ts << "\n"; - } else if (resource.resourceType() == MarkerResourceType) { - const auto& marker = static_cast<const RenderSVGResourceMarker&>(resource); - writeNameValuePair(ts, "markerUnits", marker.markerUnits()); - ts << " [ref at " << marker.referencePoint() << "]"; + } else if (resource->resourceType() == MarkerResourceType) { + RenderSVGResourceMarker* marker = static_cast<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) { - const auto& pattern = static_cast<const RenderSVGResourcePattern&>(resource); + ts << marker->angle() << "]\n"; + } else if (resource->resourceType() == PatternResourceType) { + RenderSVGResourcePattern* pattern = static_cast<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->patternElement().collectPatternAttributes(attributes); writeNameValuePair(ts, "patternUnits", attributes.patternUnits()); writeNameValuePair(ts, "patternContentUnits", attributes.patternContentUnits()); @@ -519,37 +526,37 @@ void writeSVGResourceContainer(TextStream& ts, const RenderSVGResourceContainer& if (!transform.isIdentity()) ts << " [patternTransform=" << transform << "]"; ts << "\n"; - } else if (resource.resourceType() == LinearGradientResourceType) { - const auto& gradient = static_cast<const RenderSVGResourceLinearGradient&>(resource); + } else if (resource->resourceType() == LinearGradientResourceType) { + RenderSVGResourceLinearGradient* gradient = static_cast<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) { - const auto& gradient = static_cast<const RenderSVGResourceRadialGradient&>(resource); + ts << " [start=" << gradient->startPoint(attributes) << "] [end=" << gradient->endPoint(attributes) << "]\n"; + } else if (resource->resourceType() == RadialGradientResourceType) { + RenderSVGResourceRadialGradient* gradient = static_cast<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, resource, indent); + writeChildren(ts, object, indent); } -void writeSVGContainer(TextStream& ts, const RenderSVGContainer& container, int indent) +void writeSVGContainer(TextStream& ts, const RenderObject& container, int indent) { // Currently RenderSVGResourceFilterPrimitive has no meaningful output. if (container.isSVGResourceFilterPrimitive()) @@ -580,7 +587,7 @@ void writeSVGText(TextStream& ts, const RenderSVGText& text, int indent) void writeSVGInlineText(TextStream& ts, const RenderSVGInlineText& text, int indent) { writeStandardPrefix(ts, text, indent); - ts << " " << enclosingIntRect(FloatRect(text.firstRunLocation(), text.floatLinesBoundingBox().size())) << "\n"; + ts << " " << enclosingIntRect(FloatRect(text.firstRunOrigin(), text.floatLinesBoundingBox().size())) << "\n"; writeResources(ts, text, indent); writeSVGInlineTextBoxes(ts, text, indent); } @@ -604,18 +611,22 @@ void writeSVGGradientStop(TextStream& ts, const RenderSVGGradientStop& stop, int { writeStandardPrefix(ts, stop, indent); - ts << " [offset=" << stop.element().offset() << "] [color=" << stop.element().stopColorIncludingOpacity() << "]\n"; + SVGStopElement* stopElement = toSVGStopElement(toSVGElement(stop.element())); + ASSERT(stopElement); + + ts << " [offset=" << stopElement->offset() << "] [color=" << stopElement->stopColorIncludingOpacity() << "]\n"; } -void writeResources(TextStream& ts, const RenderObject& renderer, int indent) +void writeResources(TextStream& ts, const RenderObject& object, int indent) { - const RenderStyle& style = renderer.style(); + const RenderStyle& style = object.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>(renderer.document(), svgStyle.maskerResource())) { + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object.document(), svgStyle.maskerResource())) { writeIndent(ts, indent); ts << " "; writeNameAndQuotedValue(ts, "masker", svgStyle.maskerResource()); @@ -625,7 +636,7 @@ void writeResources(TextStream& ts, const RenderObject& renderer, int indent) } } if (!svgStyle.clipperResource().isEmpty()) { - if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(renderer.document(), svgStyle.clipperResource())) { + if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(object.document(), svgStyle.clipperResource())) { writeIndent(ts, indent); ts << " "; writeNameAndQuotedValue(ts, "clipPath", svgStyle.clipperResource()); @@ -634,8 +645,9 @@ void writeResources(TextStream& ts, const RenderObject& renderer, int indent) ts << " " << clipper->resourceBoundingBox(renderer) << "\n"; } } +#if ENABLE(FILTERS) if (!svgStyle.filterResource().isEmpty()) { - if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(renderer.document(), svgStyle.filterResource())) { + if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(object.document(), svgStyle.filterResource())) { writeIndent(ts, indent); ts << " "; writeNameAndQuotedValue(ts, "filter", svgStyle.filterResource()); @@ -644,6 +656,9 @@ void writeResources(TextStream& ts, const RenderObject& renderer, int indent) 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 ebc3932f4..5458c0dd2 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 INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, 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 @@ -26,6 +26,8 @@ #ifndef SVGRenderTreeAsText_h #define SVGRenderTreeAsText_h +#if ENABLE(SVG) + #include "TextStream.h" namespace WebCore { @@ -36,11 +38,9 @@ class FloatSize; class Node; class RenderImage; class RenderObject; -class RenderSVGContainer; class RenderSVGGradientStop; class RenderSVGImage; class RenderSVGInlineText; -class RenderSVGResourceContainer; class RenderSVGShape; class RenderSVGRoot; class RenderSVGText; @@ -51,8 +51,8 @@ class SVGUnitTypes; 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 RenderSVGResourceContainer&, int indent); -void writeSVGContainer(TextStream&, const RenderSVGContainer&, 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); @@ -90,4 +90,6 @@ 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 927a7c1fc..a0ad33016 100644 --- a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp +++ b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp @@ -23,6 +23,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "SVGRenderingContext.h" #include "BasicShapes.h" @@ -35,10 +37,11 @@ #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) @@ -54,12 +57,14 @@ 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; m_paintInfo->rect = m_savedPaintRect; } +#endif if (m_renderingFlags & EndOpacityLayer) m_paintInfo->context->endTransparencyLayer(); @@ -81,7 +86,9 @@ 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) { @@ -95,38 +102,19 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderElement& renderer, Pai // Setup transparency layers before setting up SVG resources! bool isRenderingMask = isRenderingMaskImage(*m_renderer); - // RenderLayer takes care of root opacity. - float opacity = (renderer.isSVGRoot() || isRenderingMask) ? 1 : style.opacity(); + float opacity = isRenderingMask ? 1 : style.opacity(); const ShadowData* shadow = svgStyle.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) { + if (opacity < 1 || shadow) { 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()); + if (opacity < 1) { + m_paintInfo->context->clip(repaintRect); m_paintInfo->context->beginTransparencyLayer(opacity); - - if (hasBlendMode) - m_paintInfo->context->setCompositeOperation(m_paintInfo->context->compositeOperation(), BlendModeNormal); - 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_renderingFlags |= EndShadowLayer; @@ -134,27 +122,17 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderElement& renderer, Pai } ClipPathOperation* clipPathOperation = style.clipPath(); - 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()); + if (clipPathOperation && clipPathOperation->type() == ClipPathOperation::Shape) { + ShapeClipPathOperation* clipPath = static_cast<ShapeClipPathOperation*>(clipPathOperation); + m_paintInfo->context->clipPath(clipPath->pathForReferenceRect(renderer.objectBoundingBox()), clipPath->windRule()); } - auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*m_renderer); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*m_renderer); if (!resources) { +#if ENABLE(FILTERS) if (svgStyle.hasFilter()) return; - +#endif m_renderingFlags |= RenderingPrepared; return; } @@ -172,6 +150,7 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderElement& renderer, Pai return; } +#if ENABLE(FILTERS) if (!isRenderingMask) { m_filter = resources->filter(); if (m_filter) { @@ -190,38 +169,45 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderElement& renderer, Pai m_paintInfo->rect = IntRect(m_filter->drawingRegion(m_renderer)); } } +#endif m_renderingFlags |= RenderingPrepared; } static AffineTransform& currentContentTransformation() { - DEPRECATED_DEFINE_STATIC_LOCAL(AffineTransform, s_currentContentTransformation, ()); + DEFINE_STATIC_LOCAL(AffineTransform, s_currentContentTransformation, ()); return s_currentContentTransformation; } -float SVGRenderingContext::calculateScreenFontSizeScalingFactor(const RenderObject& renderer) +float SVGRenderingContext::calculateScreenFontSizeScalingFactor(const RenderObject* renderer) { - AffineTransform ctm = calculateTransformationToOutermostCoordinateSystem(renderer); + ASSERT(renderer); + + AffineTransform ctm; + calculateTransformationToOutermostCoordinateSystem(renderer, ctm); return narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2)); } -AffineTransform SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject& renderer) +void SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject* renderer, AffineTransform& absoluteTransform) { - AffineTransform absoluteTransform = currentContentTransformation(); + ASSERT(renderer); + absoluteTransform = currentContentTransformation(); + + float deviceScaleFactor = 1; + if (Page* page = renderer->document().page()) + deviceScaleFactor = page->deviceScaleFactor(); - float deviceScaleFactor = renderer.document().deviceScaleFactor(); // Walk up the render tree, accumulating SVG transforms. - const RenderObject* ancestor = &renderer; - while (ancestor) { - absoluteTransform = ancestor->localToParentTransform() * absoluteTransform; - if (ancestor->isSVGRoot()) + while (renderer) { + absoluteTransform = renderer->localToParentTransform() * absoluteTransform; + if (renderer->isSVGRoot()) break; - ancestor = ancestor->parent(); + renderer = renderer->parent(); } // Continue walking up the layer tree, accumulating CSS transforms. - RenderLayer* layer = ancestor ? ancestor->enclosingLayer() : nullptr; + RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0; while (layer) { if (TransformationMatrix* layerTransform = layer->transform()) absoluteTransform = layerTransform->toAffineTransform() * absoluteTransform; @@ -234,53 +220,53 @@ AffineTransform SVGRenderingContext::calculateTransformationToOutermostCoordinat } absoluteTransform.scale(deviceScaleFactor); - return absoluteTransform; } -std::unique_ptr<ImageBuffer> SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, ColorSpace colorSpace, RenderingMode renderingMode) +bool SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, std::unique_ptr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode) { IntRect paintRect = calculateImageBufferRect(targetRect, absoluteTransform); // Don't create empty ImageBuffers. if (paintRect.isEmpty()) - return nullptr; - - FloatSize scale; - FloatSize clampedSize = ImageBuffer::clampedSize(paintRect.size(), scale); - - auto imageBuffer = ImageBuffer::create(clampedSize, renderingMode, 1, colorSpace); - if (!imageBuffer) - return nullptr; + return false; - AffineTransform transform; - transform.scale(scale).translate(-paintRect.location()).multiply(absoluteTransform); + IntSize clampedSize = clampedAbsoluteSize(paintRect.size()); + std::unique_ptr<ImageBuffer> image = ImageBuffer::create(clampedSize, 1, colorSpace, renderingMode); + if (!image) + return false; - GraphicsContext* imageContext = imageBuffer->context(); + GraphicsContext* imageContext = image->context(); ASSERT(imageContext); - imageContext->concatCTM(transform); - return imageBuffer; + 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); + + imageBuffer = std::move(image); + return true; } -std::unique_ptr<ImageBuffer> SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const FloatRect& clampedRect, ColorSpace colorSpace, RenderingMode renderingMode) +bool SVGRenderingContext::createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, std::unique_ptr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode) { - IntSize clampedSize = roundedIntSize(clampedRect.size()); - IntSize unclampedSize = roundedIntSize(targetRect.size()); + IntSize imageSize(roundedIntSize(clampedAbsoluteTargetRect.size())); + IntSize unclampedImageSize(roundedIntSize(absoluteTargetRect.size())); // Don't create empty ImageBuffers. - if (clampedSize.isEmpty()) - return nullptr; + if (imageSize.isEmpty()) + return false; - auto imageBuffer = ImageBuffer::create(clampedSize, renderingMode, 1, colorSpace); - if (!imageBuffer) - return nullptr; + std::unique_ptr<ImageBuffer> image = ImageBuffer::create(imageSize, 1, colorSpace, renderingMode); + if (!image) + return false; - GraphicsContext* imageContext = imageBuffer->context(); + GraphicsContext* imageContext = image->context(); ASSERT(imageContext); // Compensate rounding effects, as the absolute target rect is using floating-point numbers and the image buffer size is integer. - imageContext->scale(FloatSize(unclampedSize.width() / targetRect.width(), unclampedSize.height() / targetRect.height())); + imageContext->scale(FloatSize(unclampedImageSize.width() / absoluteTargetRect.width(), unclampedImageSize.height() / absoluteTargetRect.height())); - return imageBuffer; + imageBuffer = std::move(image); + return true; } void SVGRenderingContext::renderSubtreeToImageBuffer(ImageBuffer* image, RenderElement& item, const AffineTransform& subtreeContentTransformation) @@ -288,7 +274,7 @@ void SVGRenderingContext::renderSubtreeToImageBuffer(ImageBuffer* image, RenderE ASSERT(image); ASSERT(image->context()); - PaintInfo info(image->context(), LayoutRect::infiniteRect(), PaintPhaseForeground, PaintBehaviorNormal); + PaintInfo info(image->context(), IntRect::infiniteRect(), PaintPhaseForeground, PaintBehaviorNormal); AffineTransform& contentTransformation = currentContentTransformation(); AffineTransform savedContentTransformation = contentTransformation; @@ -319,6 +305,18 @@ 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; @@ -330,7 +328,7 @@ void SVGRenderingContext::clear2DRotation(AffineTransform& transform) bool SVGRenderingContext::bufferForeground(std::unique_ptr<ImageBuffer>& imageBuffer) { ASSERT(m_paintInfo); - ASSERT(is<RenderSVGImage>(*m_renderer)); + ASSERT(m_renderer->isSVGImage()); FloatRect boundingBox = m_renderer->objectBoundingBox(); // Invalidate an existing buffer if the scale is not correct. @@ -349,7 +347,7 @@ bool SVGRenderingContext::bufferForeground(std::unique_ptr<ImageBuffer>& imageBu bufferedRenderingContext->translate(-boundingBox.x(), -boundingBox.y()); PaintInfo bufferedInfo(*m_paintInfo); bufferedInfo.context = bufferedRenderingContext; - downcast<RenderSVGImage>(*m_renderer).paintForeground(bufferedInfo); + toRenderSVGImage(m_renderer)->paintForeground(bufferedInfo); } else return false; } @@ -359,3 +357,5 @@ bool SVGRenderingContext::bufferForeground(std::unique_ptr<ImageBuffer>& imageBu } } + +#endif diff --git a/Source/WebCore/rendering/svg/SVGRenderingContext.h b/Source/WebCore/rendering/svg/SVGRenderingContext.h index 9a23c2512..3bf604cc2 100644 --- a/Source/WebCore/rendering/svg/SVGRenderingContext.h +++ b/Source/WebCore/rendering/svg/SVGRenderingContext.h @@ -25,6 +25,7 @@ #ifndef SVGRenderingContext_h #define SVGRenderingContext_h +#if ENABLE(SVG) #include "ImageBuffer.h" #include "PaintInfo.h" @@ -50,7 +51,9 @@ public: , m_renderer(nullptr) , m_paintInfo(nullptr) , m_savedContext(nullptr) +#if ENABLE(FILTERS) , m_filter(nullptr) +#endif { } @@ -59,7 +62,9 @@ public: , m_renderer(nullptr) , m_paintInfo(nullptr) , m_savedContext(nullptr) +#if ENABLE(FILTERS) , m_filter(nullptr) +#endif { prepareToRenderSVGContent(object, paintinfo, needsGraphicsContextSave); } @@ -71,14 +76,17 @@ public: void prepareToRenderSVGContent(RenderElement&, PaintInfo&, NeedsGraphicsContextSave = DontSaveGraphicsContext); bool isRenderingPrepared() const { return m_renderingFlags & RenderingPrepared; } - 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 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 void renderSubtreeToImageBuffer(ImageBuffer*, RenderElement&, const AffineTransform&); static void clipToImageBuffer(GraphicsContext*, const AffineTransform& absoluteTransform, const FloatRect& targetRect, std::unique_ptr<ImageBuffer>&, bool safeToClear); - static float calculateScreenFontSizeScalingFactor(const RenderObject&); - static AffineTransform calculateTransformationToOutermostCoordinateSystem(const RenderObject&); + static float calculateScreenFontSizeScalingFactor(const RenderObject*); + static void calculateTransformationToOutermostCoordinateSystem(const RenderObject*, AffineTransform& absoluteTransform); + static IntSize clampedAbsoluteSize(const IntSize&); + static FloatRect clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect); static void clear2DRotation(AffineTransform&); static IntRect calculateImageBufferRect(const FloatRect& targetRect, const AffineTransform& absoluteTransform) @@ -108,9 +116,12 @@ 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 ab61dd3a2..bdb586b89 100644 --- a/Source/WebCore/rendering/svg/SVGResources.cpp +++ b/Source/WebCore/rendering/svg/SVGResources.cpp @@ -20,6 +20,7 @@ #include "config.h" #include "SVGResources.h" +#if ENABLE(SVG) #include "RenderSVGResourceClipper.h" #include "RenderSVGResourceFilter.h" #include "RenderSVGResourceMarker.h" @@ -31,7 +32,7 @@ #include "SVGRenderStyle.h" #include "SVGURIReference.h" -#if ENABLE(TREE_DEBUGGING) +#ifndef NDEBUG #include <stdio.h> #endif @@ -44,7 +45,7 @@ SVGResources::SVGResources() static HashSet<AtomicString>& clipperFilterMaskerTags() { - DEPRECATED_DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); + DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); if (s_tagList.isEmpty()) { // "container elements": http://www.w3.org/TR/SVG11/intro.html#TermContainerElement // "graphics elements" : http://www.w3.org/TR/SVG11/intro.html#TermGraphicsElement @@ -93,7 +94,7 @@ static HashSet<AtomicString>& clipperFilterMaskerTags() static HashSet<AtomicString>& markerTags() { - DEPRECATED_DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); + DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); if (s_tagList.isEmpty()) { s_tagList.add(SVGNames::lineTag.localName()); s_tagList.add(SVGNames::pathTag.localName()); @@ -106,7 +107,7 @@ static HashSet<AtomicString>& markerTags() static HashSet<AtomicString>& fillAndStrokeTags() { - DEPRECATED_DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); + DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); if (s_tagList.isEmpty()) { s_tagList.add(SVGNames::altGlyphTag.localName()); s_tagList.add(SVGNames::circleTag.localName()); @@ -127,7 +128,7 @@ static HashSet<AtomicString>& fillAndStrokeTags() static HashSet<AtomicString>& chainableResourceTags() { - DEPRECATED_DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); + DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); if (s_tagList.isEmpty()) { s_tagList.add(SVGNames::linearGradientTag.localName()); s_tagList.add(SVGNames::filterTag.localName()); @@ -141,12 +142,14 @@ static HashSet<AtomicString>& chainableResourceTags() static inline String targetReferenceFromResource(SVGElement& element) { String target; - 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(); + 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 else ASSERT_NOT_REACHED(); @@ -172,9 +175,9 @@ 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) @@ -185,11 +188,12 @@ bool SVGResources::buildCachedResources(const RenderElement& renderer, const SVG if (!renderer.element()) return false; - auto& element = downcast<SVGElement>(*renderer.element()); + auto& element = toSVGElement(*renderer.element()); Document& document = element.document(); - SVGDocumentExtensions& extensions = document.accessSVGExtensions(); + SVGDocumentExtensions* extensions = document.accessSVGExtensions(); + ASSERT(extensions); const AtomicString& tagName = element.localName(); if (tagName.isNull()) @@ -205,6 +209,7 @@ 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))) @@ -212,6 +217,7 @@ bool SVGResources::buildCachedResources(const RenderElement& renderer, const SVG else registerPendingResource(extensions, id, element); } +#endif if (svgStyle.hasMasker()) { AtomicString id(svgStyle.maskerResource()); @@ -273,7 +279,7 @@ bool SVGResources::buildCachedResources(const RenderElement& renderer, const SVG return foundResources; } -void SVGResources::removeClientFromCache(RenderElement& renderer, bool markForInvalidation) const +void SVGResources::removeClientFromCache(RenderObject& object, bool markForInvalidation) const { if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource) return; @@ -282,33 +288,35 @@ void SVGResources::removeClientFromCache(RenderElement& renderer, bool markForIn ASSERT(!m_clipperFilterMaskerData); ASSERT(!m_markerData); ASSERT(!m_fillStrokeData); - m_linkedResource->removeClientFromCache(renderer, markForInvalidation); + m_linkedResource->removeClientFromCache(object, markForInvalidation); return; } if (m_clipperFilterMaskerData) { if (m_clipperFilterMaskerData->clipper) - m_clipperFilterMaskerData->clipper->removeClientFromCache(renderer, markForInvalidation); + m_clipperFilterMaskerData->clipper->removeClientFromCache(object, markForInvalidation); +#if ENABLE(FILTERS) if (m_clipperFilterMaskerData->filter) - m_clipperFilterMaskerData->filter->removeClientFromCache(renderer, markForInvalidation); + m_clipperFilterMaskerData->filter->removeClientFromCache(object, markForInvalidation); +#endif if (m_clipperFilterMaskerData->masker) - m_clipperFilterMaskerData->masker->removeClientFromCache(renderer, markForInvalidation); + m_clipperFilterMaskerData->masker->removeClientFromCache(object, markForInvalidation); } if (m_markerData) { if (m_markerData->markerStart) - m_markerData->markerStart->removeClientFromCache(renderer, markForInvalidation); + m_markerData->markerStart->removeClientFromCache(object, markForInvalidation); if (m_markerData->markerMid) - m_markerData->markerMid->removeClientFromCache(renderer, markForInvalidation); + m_markerData->markerMid->removeClientFromCache(object, markForInvalidation); if (m_markerData->markerEnd) - m_markerData->markerEnd->removeClientFromCache(renderer, markForInvalidation); + m_markerData->markerEnd->removeClientFromCache(object, markForInvalidation); } if (m_fillStrokeData) { if (m_fillStrokeData->fill) - m_fillStrokeData->fill->removeClientFromCache(renderer, markForInvalidation); + m_fillStrokeData->fill->removeClientFromCache(object, markForInvalidation); if (m_fillStrokeData->stroke) - m_fillStrokeData->stroke->removeClientFromCache(renderer, markForInvalidation); + m_fillStrokeData->stroke->removeClientFromCache(object, markForInvalidation); } } @@ -366,12 +374,16 @@ 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) @@ -402,8 +414,10 @@ 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); } @@ -433,7 +447,7 @@ bool SVGResources::setClipper(RenderSVGResourceClipper* clipper) ASSERT(clipper->resourceType() == ClipperResourceType); if (!m_clipperFilterMaskerData) - m_clipperFilterMaskerData = std::make_unique<ClipperFilterMaskerData>(); + m_clipperFilterMaskerData = ClipperFilterMaskerData::create(); m_clipperFilterMaskerData->clipper = clipper; return true; @@ -446,6 +460,7 @@ void SVGResources::resetClipper() m_clipperFilterMaskerData->clipper = 0; } +#if ENABLE(FILTERS) bool SVGResources::setFilter(RenderSVGResourceFilter* filter) { if (!filter) @@ -454,7 +469,7 @@ bool SVGResources::setFilter(RenderSVGResourceFilter* filter) ASSERT(filter->resourceType() == FilterResourceType); if (!m_clipperFilterMaskerData) - m_clipperFilterMaskerData = std::make_unique<ClipperFilterMaskerData>(); + m_clipperFilterMaskerData = ClipperFilterMaskerData::create(); m_clipperFilterMaskerData->filter = filter; return true; @@ -466,6 +481,7 @@ void SVGResources::resetFilter() ASSERT(m_clipperFilterMaskerData->filter); m_clipperFilterMaskerData->filter = 0; } +#endif bool SVGResources::setMarkerStart(RenderSVGResourceMarker* markerStart) { @@ -475,7 +491,7 @@ bool SVGResources::setMarkerStart(RenderSVGResourceMarker* markerStart) ASSERT(markerStart->resourceType() == MarkerResourceType); if (!m_markerData) - m_markerData = std::make_unique<MarkerData>(); + m_markerData = MarkerData::create(); m_markerData->markerStart = markerStart; return true; @@ -496,7 +512,7 @@ bool SVGResources::setMarkerMid(RenderSVGResourceMarker* markerMid) ASSERT(markerMid->resourceType() == MarkerResourceType); if (!m_markerData) - m_markerData = std::make_unique<MarkerData>(); + m_markerData = MarkerData::create(); m_markerData->markerMid = markerMid; return true; @@ -517,7 +533,7 @@ bool SVGResources::setMarkerEnd(RenderSVGResourceMarker* markerEnd) ASSERT(markerEnd->resourceType() == MarkerResourceType); if (!m_markerData) - m_markerData = std::make_unique<MarkerData>(); + m_markerData = MarkerData::create(); m_markerData->markerEnd = markerEnd; return true; @@ -538,7 +554,7 @@ bool SVGResources::setMasker(RenderSVGResourceMasker* masker) ASSERT(masker->resourceType() == MaskerResourceType); if (!m_clipperFilterMaskerData) - m_clipperFilterMaskerData = std::make_unique<ClipperFilterMaskerData>(); + m_clipperFilterMaskerData = ClipperFilterMaskerData::create(); m_clipperFilterMaskerData->masker = masker; return true; @@ -561,7 +577,7 @@ bool SVGResources::setFill(RenderSVGResourceContainer* fill) || fill->resourceType() == RadialGradientResourceType); if (!m_fillStrokeData) - m_fillStrokeData = std::make_unique<FillStrokeData>(); + m_fillStrokeData = FillStrokeData::create(); m_fillStrokeData->fill = fill; return true; @@ -584,7 +600,7 @@ bool SVGResources::setStroke(RenderSVGResourceContainer* stroke) || stroke->resourceType() == RadialGradientResourceType); if (!m_fillStrokeData) - m_fillStrokeData = std::make_unique<FillStrokeData>(); + m_fillStrokeData = FillStrokeData::create(); m_fillStrokeData->stroke = stroke; return true; @@ -612,7 +628,7 @@ void SVGResources::resetLinkedResource() m_linkedResource = 0; } -#if ENABLE(TREE_DEBUGGING) +#ifndef NDEBUG void SVGResources::dump(const RenderObject* object) { ASSERT(object); @@ -626,8 +642,10 @@ 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()); } @@ -654,3 +672,5 @@ 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 8db1d4e33..240276a1d 100644 --- a/Source/WebCore/rendering/svg/SVGResources.h +++ b/Source/WebCore/rendering/svg/SVGResources.h @@ -20,9 +20,11 @@ #ifndef SVGResources_h #define SVGResources_h -#include <memory> +#if ENABLE(SVG) #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> namespace WebCore { @@ -53,8 +55,10 @@ public: RenderSVGResourceFilter* filter() const { +#if ENABLE(FILTERS) if (m_clipperFilterMaskerData) return m_clipperFilterMaskerData->filter; +#endif return 0; } @@ -68,10 +72,10 @@ public: void buildSetOfResources(HashSet<RenderSVGResourceContainer*>&); // Methods operating on all cached resources - void removeClientFromCache(RenderElement&, bool markForInvalidation = true) const; + void removeClientFromCache(RenderObject&, bool markForInvalidation = true) const; void resourceDestroyed(RenderSVGResourceContainer&); -#if ENABLE(TREE_DEBUGGING) +#ifndef NDEBUG void dump(const RenderObject*); #endif @@ -80,7 +84,9 @@ private: // Only used by SVGResourcesCache cycle detection logic void resetClipper(); +#if ENABLE(FILTERS) void resetFilter(); +#endif void resetMarkerStart(); void resetMarkerMid(); void resetMarkerEnd(); @@ -91,7 +97,9 @@ private: private: bool setClipper(RenderSVGResourceClipper*); +#if ENABLE(FILTERS) bool setFilter(RenderSVGResourceFilter*); +#endif bool setMarkerStart(RenderSVGResourceMarker*); bool setMarkerMid(RenderSVGResourceMarker*); bool setMarkerEnd(RenderSVGResourceMarker*); @@ -110,13 +118,22 @@ 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; }; @@ -132,6 +149,11 @@ private: { } + static PassOwnPtr<MarkerData> create() + { + return adoptPtr(new MarkerData); + } + RenderSVGResourceMarker* markerStart; RenderSVGResourceMarker* markerMid; RenderSVGResourceMarker* markerEnd; @@ -150,16 +172,22 @@ private: { } + static PassOwnPtr<FillStrokeData> create() + { + return adoptPtr(new FillStrokeData); + } + RenderSVGResourceContainer* fill; RenderSVGResourceContainer* stroke; }; - std::unique_ptr<ClipperFilterMaskerData> m_clipperFilterMaskerData; - std::unique_ptr<MarkerData> m_markerData; - std::unique_ptr<FillStrokeData> m_fillStrokeData; + OwnPtr<ClipperFilterMaskerData> m_clipperFilterMaskerData; + OwnPtr<MarkerData> m_markerData; + OwnPtr<FillStrokeData> m_fillStrokeData; RenderSVGResourceContainer* m_linkedResource; }; } #endif +#endif diff --git a/Source/WebCore/rendering/svg/SVGResourcesCache.cpp b/Source/WebCore/rendering/svg/SVGResourcesCache.cpp index 8556ecde2..fad518a32 100644 --- a/Source/WebCore/rendering/svg/SVGResourcesCache.cpp +++ b/Source/WebCore/rendering/svg/SVGResourcesCache.cpp @@ -20,6 +20,7 @@ #include "config.h" #include "SVGResourcesCache.h" +#if ENABLE(SVG) #include "HTMLNames.h" #include "RenderSVGResourceContainer.h" #include "SVGResources.h" @@ -42,12 +43,12 @@ void SVGResourcesCache::addResourcesFromRenderer(RenderElement& renderer, const const SVGRenderStyle& svgStyle = style.svgStyle(); // Build a list of all resources associated with the passed RenderObject - auto newResources = std::make_unique<SVGResources>(); + OwnPtr<SVGResources> newResources = adoptPtr(new SVGResources); if (!newResources->buildCachedResources(renderer, svgStyle)) return; // Put object in cache. - SVGResources& resources = *m_cache.add(&renderer, WTF::move(newResources)).iterator->value; + SVGResources& resources = *m_cache.add(&renderer, newResources.release()).iterator->value; // Run cycle-detection _afterwards_, so self-references can be caught as well. SVGResourcesCycleSolver solver(renderer, resources); @@ -57,13 +58,13 @@ void SVGResourcesCache::addResourcesFromRenderer(RenderElement& renderer, const HashSet<RenderSVGResourceContainer*> resourceSet; resources.buildSetOfResources(resourceSet); - for (auto* resourceContainer : resourceSet) - resourceContainer->addClient(renderer); + for (auto it = resourceSet.begin(), end = resourceSet.end(); it != end; ++it) + (*it)->addClient(&renderer); } void SVGResourcesCache::removeResourcesFromRenderer(RenderElement& renderer) { - std::unique_ptr<SVGResources> resources = m_cache.take(&renderer); + OwnPtr<SVGResources> resources = m_cache.take(&renderer); if (!resources) return; @@ -71,23 +72,29 @@ void SVGResourcesCache::removeResourcesFromRenderer(RenderElement& renderer) HashSet<RenderSVGResourceContainer*> resourceSet; resources->buildSetOfResources(resourceSet); - for (auto* resourceContainer : resourceSet) - resourceContainer->removeClient(renderer); + for (auto it = resourceSet.begin(), end = resourceSet.end(); it != end; ++it) + (*it)->removeClient(&renderer); } -static inline SVGResourcesCache& resourcesCacheFromRenderer(const RenderElement& renderer) +static inline SVGResourcesCache* resourcesCacheFromRenderObject(const RenderObject& renderer) { - return renderer.document().accessSVGExtensions().resourcesCache(); + SVGDocumentExtensions* extensions = renderer.document().accessSVGExtensions(); + ASSERT(extensions); + + SVGResourcesCache* cache = extensions->resourcesCache(); + ASSERT(cache); + + return cache; } -SVGResources* SVGResourcesCache::cachedResourcesForRenderer(const RenderElement& renderer) +SVGResources* SVGResourcesCache::cachedResourcesForRenderObject(const RenderObject& renderer) { - return resourcesCacheFromRenderer(renderer).m_cache.get(&renderer); + return resourcesCacheFromRenderObject(renderer)->m_cache.get(&renderer); } void SVGResourcesCache::clientLayoutChanged(RenderElement& renderer) { - auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer); + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer); if (!resources) return; @@ -115,9 +122,9 @@ 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)) { - auto& cache = resourcesCacheFromRenderer(renderer); - cache.removeResourcesFromRenderer(renderer); - cache.addResourcesFromRenderer(renderer, newStyle); + SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer); + cache->removeResourcesFromRenderer(renderer); + cache->addResourcesFromRenderer(renderer, newStyle); } RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false); @@ -135,8 +142,9 @@ void SVGResourcesCache::clientWasAddedToTree(RenderObject& renderer) if (!rendererCanHaveResources(renderer)) return; - RenderElement& elementRenderer = downcast<RenderElement>(renderer); - resourcesCacheFromRenderer(elementRenderer).addResourcesFromRenderer(elementRenderer, elementRenderer.style()); + RenderElement& elementRenderer = toRenderElement(renderer); + SVGResourcesCache* cache = resourcesCacheFromRenderObject(elementRenderer); + cache->addResourcesFromRenderer(elementRenderer, elementRenderer.style()); } void SVGResourcesCache::clientWillBeRemovedFromTree(RenderObject& renderer) @@ -148,33 +156,40 @@ void SVGResourcesCache::clientWillBeRemovedFromTree(RenderObject& renderer) if (!rendererCanHaveResources(renderer)) return; - RenderElement& elementRenderer = downcast<RenderElement>(renderer); - resourcesCacheFromRenderer(elementRenderer).removeResourcesFromRenderer(elementRenderer); + RenderElement& elementRenderer = toRenderElement(renderer); + SVGResourcesCache* cache = resourcesCacheFromRenderObject(elementRenderer); + cache->removeResourcesFromRenderer(elementRenderer); } void SVGResourcesCache::clientDestroyed(RenderElement& renderer) { - if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer); + if (resources) resources->removeClientFromCache(renderer); - resourcesCacheFromRenderer(renderer).removeResourcesFromRenderer(renderer); + SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer); + cache->removeResourcesFromRenderer(renderer); } void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer& resource) { - auto& cache = resourcesCacheFromRenderer(resource); + SVGResourcesCache* cache = resourcesCacheFromRenderObject(resource); // The resource itself may have clients, that need to be notified. - cache.removeResourcesFromRenderer(resource); + cache->removeResourcesFromRenderer(resource); - for (auto& it : cache.m_cache) { - it.value->resourceDestroyed(resource); + for (auto it = cache->m_cache.begin(), end = cache->m_cache.end(); it != end; ++it) { + 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 = it.key->element(); - clientElement->document().accessSVGExtensions().addPendingResource(resourceElement.getIdAttribute(), clientElement); + Element* clientElement = toElement(it->key->node()); + SVGDocumentExtensions* extensions = clientElement->document().accessSVGExtensions(); + + extensions->addPendingResource(resourceElement.getIdAttribute(), clientElement); } } } + +#endif diff --git a/Source/WebCore/rendering/svg/SVGResourcesCache.h b/Source/WebCore/rendering/svg/SVGResourcesCache.h index b6d297e56..fe6d5e6ed 100644 --- a/Source/WebCore/rendering/svg/SVGResourcesCache.h +++ b/Source/WebCore/rendering/svg/SVGResourcesCache.h @@ -20,10 +20,10 @@ #ifndef SVGResourcesCache_h #define SVGResourcesCache_h +#if ENABLE(SVG) #include "RenderStyleConstants.h" -#include <memory> #include <wtf/HashMap.h> -#include <wtf/Noncopyable.h> +#include <wtf/OwnPtr.h> namespace WebCore { @@ -39,7 +39,7 @@ public: SVGResourcesCache(); ~SVGResourcesCache(); - static SVGResources* cachedResourcesForRenderer(const RenderElement&); + static SVGResources* cachedResourcesForRenderObject(const RenderObject&); // Called from all SVG renderers addChild() methods. static void clientWasAddedToTree(RenderObject&); @@ -63,10 +63,11 @@ private: void addResourcesFromRenderer(RenderElement&, const RenderStyle&); void removeResourcesFromRenderer(RenderElement&); - typedef HashMap<const RenderElement*, std::unique_ptr<SVGResources>> CacheMap; + typedef HashMap<const RenderObject*, OwnPtr<SVGResources>> CacheMap; CacheMap m_cache; }; } #endif +#endif diff --git a/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.cpp b/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.cpp index be76c1f9d..c6776f667 100644 --- a/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.cpp +++ b/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.cpp @@ -20,8 +20,12 @@ #include "config.h" #include "SVGResourcesCycleSolver.h" -#include "Logging.h" -#include "RenderAncestorIterator.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 "RenderSVGResourceClipper.h" #include "RenderSVGResourceFilter.h" #include "RenderSVGResourceMarker.h" @@ -31,15 +35,6 @@ #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) @@ -54,65 +49,43 @@ 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 (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) { + if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer)) { HashSet<RenderSVGResourceContainer*> resourceSet; resources->buildSetOfResources(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); + // Walk all resources and check wheter they reference any resource contained in the resources set. + for (auto resource : resourceSet) { 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)) { - - 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; - } + 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) 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; } @@ -120,8 +93,8 @@ void SVGResourcesCycleSolver::resolveCycles() { ASSERT(m_allResources.isEmpty()); -#if DEBUG_CYCLE_DETECTION - LOG_DEBUG_CYCLE("\nBefore cycle detection:\n"); +#if DEBUG_CYCLE_DETECTION > 0 + fprintf(stderr, "\nBefore cycle detection:\n"); m_resources.dump(&m_renderer); #endif @@ -131,52 +104,49 @@ void SVGResourcesCycleSolver::resolveCycles() ASSERT(!localResources.isEmpty()); // Add all parent resource containers to the HashSet. - HashSet<RenderSVGResourceContainer*> ancestorResources; - for (auto& resource : ancestorsOfType<RenderSVGResourceContainer>(m_renderer)) - ancestorResources.add(&resource); + HashSet<RenderSVGResourceContainer*> parentResources; + auto parent = m_renderer.parent(); + while (parent) { + if (parent->isSVGResourceContainer()) + parentResources.add(parent->toRenderSVGResourceContainer()); + parent = parent->parent(); + } -#if DEBUG_CYCLE_DETECTION - LOG_DEBUG_CYCLE("\nDetecting whether any resources references any of following objects:\n"); +#if DEBUG_CYCLE_DETECTION > 0 + fprintf(stderr, "\nDetecting wheter any resources references any of following objects:\n"); { - 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, "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()); fprintf(stderr, "Parent resources:\n"); - for (RenderObject* resource : ancestorResources) - LOG_DEBUG_CYCLE("|> %s : %p (node %p)\n", resource->renderName(), resource, resource->node()); + for (auto it = parentResources.begin(), end = parentResources.end(); it != end; ++it) + fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node()); } #endif // Build combined set of local and parent resources. m_allResources = localResources; - for (auto* resource : ancestorResources) - m_allResources.add(resource); + for (auto it = parentResources.begin(), end = parentResources.end(); it != end; ++it) + m_allResources.add(*it); // If we're a resource, add ourselves to the HashSet. - if (is<RenderSVGResourceContainer>(m_renderer)) - m_allResources.add(&downcast<RenderSVGResourceContainer>(m_renderer)); + if (m_renderer.isSVGResourceContainer()) + m_allResources.add(m_renderer.toRenderSVGResourceContainer()); 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 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); - } + // 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); } -#if DEBUG_CYCLE_DETECTION - LOG_DEBUG_CYCLE("\nAfter cycle detection:\n"); - m_resources.dump(&m_renderer); +#if DEBUG_CYCLE_DETECTION > 0 + fprintf(stderr, "\nAfter cycle detection:\n"); + m_resources.dump(m_renderer); #endif m_allResources.clear(); @@ -213,8 +183,10 @@ 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()); @@ -227,3 +199,5 @@ void SVGResourcesCycleSolver::breakCycle(RenderSVGResourceContainer& resourceLea } } + +#endif diff --git a/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.h b/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.h index 691b325cd..fd95a7428 100644 --- a/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.h +++ b/Source/WebCore/rendering/svg/SVGResourcesCycleSolver.h @@ -20,6 +20,7 @@ #ifndef SVGResourcesCycleSolver_h #define SVGResourcesCycleSolver_h +#if ENABLE(SVG) #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> @@ -49,3 +50,4 @@ private: } #endif +#endif diff --git a/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp b/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp index d1a78389a..ec628b168 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 Inc. + * Copyright (C) 2006 Apple Computer 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,10 +43,10 @@ SVGRootInlineBox::SVGRootInlineBox(RenderSVGText& renderSVGText) RenderSVGText& SVGRootInlineBox::renderSVGText() { - return downcast<RenderSVGText>(blockFlow()); + return toRenderSVGText(blockFlow()); } -void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit) +void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit) { ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); ASSERT(!paintInfo.context->paintingDisabled()); @@ -57,33 +57,34 @@ void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse PaintInfo childPaintInfo(paintInfo); if (hasSelection) { for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { - if (is<SVGInlineTextBox>(*child)) - downcast<SVGInlineTextBox>(*child).paintSelectionBackground(childPaintInfo); - else if (is<SVGInlineFlowBox>(*child)) - downcast<SVGInlineFlowBox>(*child).paintSelectionBackground(childPaintInfo); + if (child->isSVGInlineTextBox()) + toSVGInlineTextBox(child)->paintSelectionBackground(childPaintInfo); + else if (child->isSVGInlineFlowBox()) + toSVGInlineFlowBox(child)->paintSelectionBackground(childPaintInfo); } } SVGRenderingContext renderingContext(renderSVGText(), paintInfo, SVGRenderingContext::SaveGraphicsContext); if (renderingContext.isRenderingPrepared()) { for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { - if (is<SVGInlineTextBox>(*child)) - SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(&downcast<SVGInlineTextBox>(*child).renderer()); + if (child->isSVGInlineTextBox()) + SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(&toSVGInlineTextBox(child)->renderer()); - child->paint(paintInfo, paintOffset, 0, 0); + child->paint(paintInfo, LayoutPoint(), 0, 0); } } } void SVGRootInlineBox::computePerCharacterLayoutInformation() { - auto& textRoot = downcast<RenderSVGText>(blockFlow()); + RenderSVGText* textRoot = toRenderSVGText(&blockFlow()); + ASSERT(textRoot); - 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). @@ -103,27 +104,31 @@ void SVGRootInlineBox::computePerCharacterLayoutInformation() void SVGRootInlineBox::layoutCharactersInTextBoxes(InlineFlowBox* start, SVGTextLayoutEngine& characterLayout) { for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) { - if (is<SVGInlineTextBox>(*child)) { - ASSERT(is<RenderSVGInlineText>(child->renderer())); - characterLayout.layoutInlineTextBox(downcast<SVGInlineTextBox>(*child)); + if (child->isSVGInlineTextBox()) { + ASSERT(child->renderer().isSVGInlineText()); + + SVGInlineTextBox* textBox = toSVGInlineTextBox(child); + characterLayout.layoutInlineTextBox(textBox); } else { // Skip generated content. Node* node = child->renderer().node(); if (!node) continue; - auto& flowBox = downcast<SVGInlineFlowBox>(*child); + ASSERT_WITH_SECURITY_IMPLICATION(child->isInlineFlowBox()); + + SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(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(downcast<RenderSVGTextPath>(child->renderer()), lineLayout); + characterLayout.beginTextPathLayout(&child->renderer(), lineLayout); } - layoutCharactersInTextBoxes(&flowBox, characterLayout); + layoutCharactersInTextBoxes(flowBox, characterLayout); if (isTextPath) characterLayout.endTextPathLayout(); @@ -135,28 +140,30 @@ void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start, FloatRect* childRe { for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) { FloatRect boxRect; - 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()); + 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()); } else { // Skip generated content. if (!child->renderer().node()) continue; - auto& flowBox = downcast<SVGInlineFlowBox>(*child); - layoutChildBoxes(&flowBox); + ASSERT_WITH_SECURITY_IMPLICATION(child->isInlineFlowBox()); - boxRect = flowBox.calculateBoundaries(); - flowBox.setX(boxRect.x()); - flowBox.setY(boxRect.y()); - flowBox.setLogicalWidth(boxRect.width()); - flowBox.setLogicalHeight(boxRect.height()); + SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child); + layoutChildBoxes(flowBox); + + boxRect = flowBox->calculateBoundaries(); + flowBox->setX(boxRect.x()); + flowBox->setY(boxRect.y()); + flowBox->setLogicalWidth(boxRect.width()); + flowBox->setLogicalHeight(boxRect.height()); } if (childRect) childRect->unite(boxRect); @@ -196,7 +203,7 @@ InlineBox* SVGRootInlineBox::closestLeafChildForPosition(const LayoutPoint& poin return firstLeaf; // FIXME: Check for vertical text! - InlineBox* closestLeaf = nullptr; + InlineBox* closestLeaf = 0; for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChild()) { if (!leaf->isSVGInlineTextBox()) continue; @@ -239,8 +246,8 @@ static inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes* firstAtt static inline void findFirstAndLastAttributesInVector(Vector<SVGTextLayoutAttributes*>& attributes, RenderSVGInlineText* firstContext, RenderSVGInlineText* lastContext, SVGTextLayoutAttributes*& first, SVGTextLayoutAttributes*& last) { - first = nullptr; - last = nullptr; + first = 0; + last = 0; unsigned attributesSize = attributes.size(); for (unsigned i = 0; i < attributesSize; ++i) { @@ -267,7 +274,7 @@ static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Ve if (first == last || first == --last) return; - if (!is<SVGInlineTextBox>(**last) || !is<SVGInlineTextBox>(**first)) { + if (!(*last)->isSVGInlineTextBox() || !(*first)->isSVGInlineTextBox()) { InlineBox* temp = *first; *first = *last; *last = temp; @@ -275,18 +282,18 @@ static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Ve continue; } - auto& firstTextBox = downcast<SVGInlineTextBox>(**first); - auto& lastTextBox = downcast<SVGInlineTextBox>(**last); + SVGInlineTextBox* firstTextBox = toSVGInlineTextBox(*first); + SVGInlineTextBox* lastTextBox = toSVGInlineTextBox(*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 = nullptr; - SVGTextLayoutAttributes* lastAttributes = nullptr; + SVGTextLayoutAttributes* firstAttributes = 0; + SVGTextLayoutAttributes* lastAttributes = 0; findFirstAndLastAttributesInVector(attributes, &firstContext, &lastContext, firstAttributes, lastAttributes); - swapItemsInLayoutAttributes(firstAttributes, lastAttributes, firstTextBox.start(), lastTextBox.start()); + swapItemsInLayoutAttributes(firstAttributes, lastAttributes, firstTextBox->start(), lastTextBox->start()); } InlineBox* temp = *first; @@ -304,3 +311,5 @@ 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 bca9ffdf2..643af3108 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 Inc. + * Copyright (C) 2006 Apple Computer Inc. * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) Research In Motion Limited 2010. All rights reserved. * @@ -23,6 +23,7 @@ #ifndef SVGRootInlineBox_h #define SVGRootInlineBox_h +#if ENABLE(SVG) #include "RootInlineBox.h" #include "SVGRenderSupport.h" #include "SVGTextLayoutEngine.h" @@ -38,27 +39,29 @@ public: RenderSVGText& renderSVGText(); - virtual float virtualLogicalHeight() const override { return m_logicalHeight; } + virtual float virtualLogicalHeight() const override final { return m_logicalHeight; } void setLogicalHeight(float height) { m_logicalHeight = height; } - virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override; + virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override final; void computePerCharacterLayoutInformation(); InlineBox* closestLeafChildForPosition(const LayoutPoint&); private: - virtual bool isSVGRootInlineBox() const override { return true; } + virtual bool isSVGRootInlineBox() const override final { return true; } void reorderValueLists(Vector<SVGTextLayoutAttributes*>&); void layoutCharactersInTextBoxes(InlineFlowBox*, SVGTextLayoutEngine&); - void layoutChildBoxes(InlineFlowBox*, FloatRect* = nullptr); + void layoutChildBoxes(InlineFlowBox*, FloatRect* = 0); void layoutRootBox(const FloatRect&); float m_logicalHeight; }; +INLINE_BOX_OBJECT_TYPE_CASTS(SVGRootInlineBox, isSVGRootInlineBox()) + } // namespace WebCore -SPECIALIZE_TYPE_TRAITS_INLINE_BOX(SVGRootInlineBox, isSVGRootInlineBox()) +#endif // ENABLE(SVG) #endif // SVGRootInlineBox_h diff --git a/Source/WebCore/rendering/svg/SVGSubpathData.h b/Source/WebCore/rendering/svg/SVGSubpathData.h index 5ae2512cf..cf7901d8d 100644 --- a/Source/WebCore/rendering/svg/SVGSubpathData.h +++ b/Source/WebCore/rendering/svg/SVGSubpathData.h @@ -20,6 +20,7 @@ #ifndef SVGSubpathData_h #define SVGSubpathData_h +#if ENABLE(SVG) #include "Path.h" #include <wtf/Vector.h> @@ -29,46 +30,51 @@ 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(SVGSubpathData& subpathFinder, const PathElement& element) + static void updateFromPathElement(void* info, const PathElement* element) { - switch (element.type) { + SVGSubpathData* subpathFinder = static_cast<SVGSubpathData*>(info); + 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; } } @@ -83,11 +89,12 @@ private: Vector<FloatPoint>& m_zeroLengthSubpathLocations; FloatPoint m_lastPoint; FloatPoint m_movePoint; - bool m_haveSeenMoveOnly { false }; - bool m_pathIsZeroLength { false }; + bool m_haveSeenMoveOnly; + bool m_pathIsZeroLength; }; } +#endif // ENABLE(SVG) #endif // SVGSubpathData_h diff --git a/Source/WebCore/rendering/svg/SVGTextChunk.cpp b/Source/WebCore/rendering/svg/SVGTextChunk.cpp index 999b0821d..b7072753b 100644 --- a/Source/WebCore/rendering/svg/SVGTextChunk.cpp +++ b/Source/WebCore/rendering/svg/SVGTextChunk.cpp @@ -1,6 +1,5 @@ /* * 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 @@ -19,191 +18,67 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "SVGTextChunk.h" #include "SVGInlineTextBox.h" namespace WebCore { -SVGTextChunk::SVGTextChunk(const Vector<SVGInlineTextBox*>& lineLayoutBoxes, unsigned first, unsigned limit) +SVGTextChunk::SVGTextChunk(unsigned chunkStyle, float desiredTextLength) + : m_chunkStyle(chunkStyle) + , m_desiredTextLength(desiredTextLength) { - 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 (svgStyle.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; - } - - 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; - } - } - - for (unsigned i = first; i < limit; ++i) - m_boxes.append(lineLayoutBoxes[i]); } -unsigned SVGTextChunk::totalCharacters() const +void SVGTextChunk::calculateLength(float& length, unsigned& characters) const { - unsigned characters = 0; - for (auto* box : m_boxes) { - for (auto& fragment : box->textFragments()) - characters += fragment.length; - } - return characters; -} + SVGTextFragment* lastFragment = 0; -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; - } - } - - for (auto it = m_boxes.rbegin(), end = m_boxes.rend(); it != end; ++it) { - auto& fragments = (*it)->textFragments(); - if (fragments.size()) { - lastFragment = &(*fragments.rbegin()); - break; - } - } + unsigned boxCount = m_boxes.size(); + for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) { + SVGInlineTextBox* textBox = m_boxes.at(boxPosition); + Vector<SVGTextFragment>& fragments = textBox->textFragments(); - ASSERT(!firstFragment == !lastFragment); - if (!firstFragment) - return 0; + unsigned size = fragments.size(); + if (!size) + continue; - if (m_chunkStyle & VerticalText) - return (lastFragment->y + lastFragment->height) - firstFragment->y; - - return (lastFragment->x + lastFragment->width) - firstFragment->x; -} - -float SVGTextChunk::totalAnchorShift() const -{ - float length = totalLength(); - if (m_chunkStyle & MiddleAnchor) - return -length / 2; - if (m_chunkStyle & EndAnchor) - return m_chunkStyle & RightToLeftText ? 0 : -length; - return m_chunkStyle & RightToLeftText ? -length : 0; -} + for (unsigned i = 0; i < size; ++i) { + SVGTextFragment& fragment = fragments.at(i); + characters += fragment.length; -void SVGTextChunk::layout(HashMap<SVGInlineTextBox*, AffineTransform>& textBoxTransformations) const -{ - if (hasDesiredTextLength()) { - if (hasLengthAdjustSpacing()) - processTextLengthSpacingCorrection(); - else { - ASSERT(hasLengthAdjustSpacingAndGlyphs()); - buildBoxTransformations(textBoxTransformations); - } - } + if (m_chunkStyle & VerticalText) + length += fragment.height; + else + length += fragment.width; - if (hasTextAnchor()) - processTextAnchorCorrection(); -} + if (!lastFragment) { + lastFragment = &fragment; + continue; + } -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; + // Resepect gap between chunks. + if (m_chunkStyle & VerticalText) + length += fragment.y - (lastFragment->y + lastFragment->height); else - fragment.x += textLengthShift * atCharacter; - - atCharacter += fragment.length; - } - } -} + length += fragment.x - (lastFragment->x + lastFragment->width); -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; + lastFragment = &fragment; } - - 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 SVGTextChunk::calculateTextAnchorShift(float length) 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; - } - } + if (m_chunkStyle & MiddleAnchor) + return -length / 2; + if (m_chunkStyle & EndAnchor) + return m_chunkStyle & RightToLeftText ? 0 : -length; + return m_chunkStyle & RightToLeftText ? -length : 0; } } // namespace WebCore + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/SVGTextChunk.h b/Source/WebCore/rendering/svg/SVGTextChunk.h index a0a4c4f9d..9618d9fb6 100644 --- a/Source/WebCore/rendering/svg/SVGTextChunk.h +++ b/Source/WebCore/rendering/svg/SVGTextChunk.h @@ -1,6 +1,5 @@ /* * 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 @@ -21,6 +20,7 @@ #ifndef SVGTextChunk_h #define SVGTextChunk_h +#if ENABLE(SVG) #include "SVGRenderStyleDefs.h" #include "SVGTextContentElement.h" @@ -41,36 +41,31 @@ public: LengthAdjustSpacingAndGlyphs = 1 << 6 }; - SVGTextChunk(const Vector<SVGInlineTextBox*>&, unsigned first, unsigned limit); + SVGTextChunk(unsigned chunkStyle, float desiredTextLength); - 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; + void calculateLength(float& length, unsigned& characters) const; + float calculateTextAnchorShift(float length) 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 | EndAnchor)); } + bool hasTextAnchor() const { return m_chunkStyle & RightToLeftText ? !(m_chunkStyle & EndAnchor) : (m_chunkStyle & MiddleAnchor) || (m_chunkStyle & 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 { DefaultStyle }; - float m_desiredTextLength { 0 }; + unsigned m_chunkStyle; + float m_desiredTextLength; }; } // namespace WebCore +#endif // ENABLE(SVG) #endif diff --git a/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp index 68b2d4875..26ab67e25 100644 --- a/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp +++ b/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp @@ -1,6 +1,5 @@ /* * 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 @@ -19,6 +18,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "SVGTextChunkBuilder.h" #include "SVGElement.h" @@ -31,71 +32,229 @@ SVGTextChunkBuilder::SVGTextChunkBuilder() { } -unsigned SVGTextChunkBuilder::totalCharacters() const +void SVGTextChunkBuilder::transformationForTextBox(SVGInlineTextBox* textBox, AffineTransform& transform) const { - unsigned characters = 0; - for (const auto& chunk : m_textChunks) - characters += chunk.totalCharacters(); - return characters; + DEFINE_STATIC_LOCAL(const AffineTransform, s_identityTransform, ()); + if (!m_textBoxTransformations.contains(textBox)) { + transform = s_identityTransform; + return; + } + + transform = m_textBoxTransformations.get(textBox); } -float SVGTextChunkBuilder::totalLength() const +void SVGTextChunkBuilder::buildTextChunks(Vector<SVGInlineTextBox*>& lineLayoutBoxes) { - float length = 0; - for (const auto& chunk : m_textChunks) - length += chunk.totalLength(); - return length; + 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 SVGTextChunkBuilder::totalAnchorShift() const +void SVGTextChunkBuilder::layoutTextChunks(Vector<SVGInlineTextBox*>& lineLayoutBoxes) { - float anchorShift = 0; - for (const auto& chunk : m_textChunks) - anchorShift += chunk.totalAnchorShift(); - return anchorShift; + 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(); } -AffineTransform SVGTextChunkBuilder::transformationForTextBox(SVGInlineTextBox* textBox) const +void SVGTextChunkBuilder::addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxes, unsigned boxStart, unsigned boxCount) { - auto it = m_textBoxTransformations.find(textBox); - return it == m_textBoxTransformations.end() ? AffineTransform() : it->value; + 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); } -void SVGTextChunkBuilder::buildTextChunks(const Vector<SVGInlineTextBox*>& lineLayoutBoxes) +void SVGTextChunkBuilder::processTextChunk(const SVGTextChunk& chunk) { - if (lineLayoutBoxes.isEmpty()) + 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; - unsigned limit = lineLayoutBoxes.size(); - unsigned first = limit; + // 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); - for (unsigned i = 0; i < limit; ++i) { - if (!lineLayoutBoxes[i]->startsNewTextChunk()) - continue; + 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); + } - if (first == limit) - first = i; - else { - ASSERT_WITH_SECURITY_IMPLICATION(first != i); - m_textChunks.append(SVGTextChunk(lineLayoutBoxes, first, i)); - first = i; + m_textBoxTransformations.set(textBox, spacingAndGlyphsTransform); + } } } - if (first != limit) - m_textChunks.append(SVGTextChunk(lineLayoutBoxes, first, limit)); + if (!processTextAnchor) + 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); + } + + float textAnchorShift = chunk.calculateTextAnchorShift(chunkLength); + for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) { + Vector<SVGTextFragment>& fragments = boxes[boxPosition]->textFragments(); + if (fragments.isEmpty()) + continue; + processTextAnchorCorrection(isVerticalText, textAnchorShift, fragments); + } } -void SVGTextChunkBuilder::layoutTextChunks(const Vector<SVGInlineTextBox*>& lineLayoutBoxes) +void SVGTextChunkBuilder::processTextLengthSpacingCorrection(bool isVerticalText, float textLengthShift, Vector<SVGTextFragment>& fragments, unsigned& atCharacter) { - buildTextChunks(lineLayoutBoxes); - if (m_textChunks.isEmpty()) - return; + unsigned fragmentCount = fragments.size(); + for (unsigned i = 0; i < fragmentCount; ++i) { + SVGTextFragment& fragment = fragments[i]; - for (const auto& chunk : m_textChunks) - chunk.layout(m_textBoxTransformations); + if (isVerticalText) + fragment.y += textLengthShift * atCharacter; + else + fragment.x += textLengthShift * atCharacter; - m_textChunks.clear(); + atCharacter += fragment.length; + } } +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; + } } + +void SVGTextChunkBuilder::buildSpacingAndGlyphsTransform(bool isVerticalText, float scale, const SVGTextFragment& fragment, AffineTransform& spacingAndGlyphsTransform) +{ + spacingAndGlyphsTransform.translate(fragment.x, fragment.y); + + if (isVerticalText) + spacingAndGlyphsTransform.scaleNonUniform(1, scale); + else + spacingAndGlyphsTransform.scaleNonUniform(scale, 1); + + spacingAndGlyphsTransform.translate(-fragment.x, -fragment.y); +} + +} + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/SVGTextChunkBuilder.h b/Source/WebCore/rendering/svg/SVGTextChunkBuilder.h index 6ecf08170..321f3915f 100644 --- a/Source/WebCore/rendering/svg/SVGTextChunkBuilder.h +++ b/Source/WebCore/rendering/svg/SVGTextChunkBuilder.h @@ -1,6 +1,5 @@ /* * 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 @@ -21,6 +20,7 @@ #ifndef SVGTextChunkBuilder_h #define SVGTextChunkBuilder_h +#if ENABLE(SVG) #include "SVGTextChunk.h" #include <wtf/Vector.h> @@ -41,13 +41,18 @@ public: SVGTextChunkBuilder(); const Vector<SVGTextChunk>& textChunks() const { return m_textChunks; } - unsigned totalCharacters() const; - float totalLength() const; - float totalAnchorShift() const; - AffineTransform transformationForTextBox(SVGInlineTextBox*) const; + void transformationForTextBox(SVGInlineTextBox*, AffineTransform&) const; - void buildTextChunks(const Vector<SVGInlineTextBox*>& lineLayoutBoxes); - void layoutTextChunks(const Vector<SVGInlineTextBox*>& lineLayoutBoxes); + 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&); private: Vector<SVGTextChunk> m_textChunks; @@ -56,4 +61,5 @@ private: } // namespace WebCore +#endif // ENABLE(SVG) #endif diff --git a/Source/WebCore/rendering/svg/SVGTextFragment.h b/Source/WebCore/rendering/svg/SVGTextFragment.h index d70dae93e..a44d0fabc 100644 --- a/Source/WebCore/rendering/svg/SVGTextFragment.h +++ b/Source/WebCore/rendering/svg/SVGTextFragment.h @@ -20,6 +20,7 @@ #ifndef SVGTextFragment_h #define SVGTextFragment_h +#if ENABLE(SVG) #include "AffineTransform.h" namespace WebCore { @@ -110,4 +111,5 @@ private: } // namespace WebCore +#endif // ENABLE(SVG) #endif diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp index 6441272a4..05d6cc332 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp +++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp @@ -18,6 +18,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "SVGTextLayoutAttributes.h" #include <stdio.h> @@ -72,3 +74,5 @@ void SVGTextLayoutAttributes::dump() const } } + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h b/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h index 305db1eaf..00d138e53 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h +++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h @@ -20,6 +20,7 @@ #ifndef SVGTextLayoutAttributes_h #define SVGTextLayoutAttributes_h +#if ENABLE(SVG) #include "SVGTextMetrics.h" #include <wtf/HashMap.h> #include <wtf/Noncopyable.h> @@ -75,4 +76,5 @@ 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 16e27cc1f..1dbb01fd9 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp +++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp @@ -18,9 +18,10 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "SVGTextLayoutAttributesBuilder.h" -#include "RenderSVGInline.h" #include "RenderSVGInlineText.h" #include "RenderSVGText.h" #include "SVGTextPositioningElement.h" @@ -34,7 +35,7 @@ SVGTextLayoutAttributesBuilder::SVGTextLayoutAttributesBuilder() void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer(RenderSVGInlineText& text) { - auto* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text); + RenderSVGText* textRoot = RenderSVGText::locateRenderSVGTextAncestor(&text); if (!textRoot) return; @@ -42,79 +43,82 @@ void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer(Render m_characterDataMap.clear(); m_textLength = 0; - bool lastCharacterWasSpace = true; - collectTextPositioningElements(*textRoot, lastCharacterWasSpace); + const UChar* lastCharacter = 0; + collectTextPositioningElements(textRoot, lastCharacter); 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; - bool lastCharacterWasSpace = true; - collectTextPositioningElements(textRoot, lastCharacterWasSpace); + const UChar* lastCharacter = 0; + collectTextPositioningElements(textRoot, lastCharacter); } if (!m_textLength) return false; buildCharacterDataMap(textRoot); - m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, nullptr, m_characterDataMap); + m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDataMap); return true; } -void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInlineText& text) +void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInlineText* text) { + ASSERT(text); m_metricsBuilder.measureTextRenderer(text); } -static inline void processRenderSVGInlineText(const RenderSVGInlineText& text, unsigned& atCharacter, bool& lastCharacterWasSpace) +static inline void processRenderSVGInlineText(RenderSVGInlineText* text, unsigned& atCharacter, const UChar*& lastCharacter) { - if (text.style().whiteSpace() == PRE) { - atCharacter += text.textLength(); + if (text->style().whiteSpace() == PRE) { + atCharacter += text->textLength(); return; } - for (unsigned textPosition = 0, textLength = text.textLength(); textPosition < textLength; ++textPosition) { - const UChar currentCharacter = text[textPosition]; - if (currentCharacter == ' ' && lastCharacterWasSpace) + 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 == ' ')) continue; - lastCharacterWasSpace = currentCharacter == ' '; + lastCharacter = currentCharacter; ++atCharacter; } } -void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderBoxModelObject& start, bool& lastCharacterWasSpace) +void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderObject* start, const UChar*& lastCharacter) { - ASSERT(!is<RenderSVGText>(start) || m_textPositions.isEmpty()); + ASSERT(!start->isSVGText() || m_textPositions.isEmpty()); - for (RenderObject* child = start.firstChild(); child; child = child->nextSibling()) { - if (is<RenderSVGInlineText>(*child)) { - processRenderSVGInlineText(downcast<RenderSVGInlineText>(*child), m_textLength, lastCharacterWasSpace); + for (RenderObject* child = start->firstChildSlow(); child; child = child->nextSibling()) { + if (child->isSVGInlineText()) { + processRenderSVGInlineText(toRenderSVGInlineText(child), m_textLength, lastCharacter); continue; } - if (!is<RenderSVGInline>(*child)) + if (!child->isSVGInline()) continue; - RenderSVGInline& inlineChild = downcast<RenderSVGInline>(*child); - SVGTextPositioningElement* element = SVGTextPositioningElement::elementFromRenderer(inlineChild); - + SVGTextPositioningElement* element = SVGTextPositioningElement::elementFromRenderer(child); unsigned atPosition = m_textPositions.size(); if (element) m_textPositions.append(TextPosition(element, m_textLength)); - collectTextPositioningElements(inlineChild, lastCharacterWasSpace); + collectTextPositioningElements(child, lastCharacter); if (!element) continue; @@ -126,7 +130,7 @@ void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderBoxMod } } -void SVGTextLayoutAttributesBuilder::buildCharacterDataMap(RenderSVGText& textRoot) +void SVGTextLayoutAttributesBuilder::buildCharacterDataMap(RenderSVGText* textRoot) { SVGTextPositioningElement* outermostTextElement = SVGTextPositioningElement::elementFromRenderer(textRoot); ASSERT(outermostTextElement); @@ -228,3 +232,5 @@ 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 df39af8a1..5aa60e923 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h +++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h @@ -20,11 +20,11 @@ #ifndef SVGTextLayoutAttributesBuilder_h #define SVGTextLayoutAttributesBuilder_h +#if ENABLE(SVG) #include "SVGTextMetricsBuilder.h" namespace WebCore { -class RenderBoxModelObject; class RenderObject; class RenderSVGInlineText; class RenderSVGText; @@ -42,10 +42,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 +65,8 @@ private: unsigned length; }; - void buildCharacterDataMap(RenderSVGText&); - void collectTextPositioningElements(RenderBoxModelObject&, bool& lastCharacterWasSpace); + void buildCharacterDataMap(RenderSVGText*); + void collectTextPositioningElements(RenderObject*, const UChar*& lastCharacter); void fillCharacterDataMap(const TextPosition&); private: @@ -78,4 +78,5 @@ private: } // namespace WebCore +#endif // ENABLE(SVG) #endif diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp index 0b1a3183a..aec25e146 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp +++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp @@ -18,9 +18,10 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "SVGTextLayoutEngine.h" -#include "PathTraversalState.h" #include "RenderSVGTextPath.h" #include "SVGElement.h" #include "SVGInlineTextBox.h" @@ -110,7 +111,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); @@ -137,7 +138,7 @@ void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox& textBox, Vector<S } } - textBox.textFragments().append(m_currentTextFragment); + textBox->textFragments().append(m_currentTextFragment); m_currentTextFragment = SVGTextFragment(); } @@ -161,39 +162,58 @@ bool SVGTextLayoutEngine::parentDefinesTextLength(RenderObject* parent) const return false; } -void SVGTextLayoutEngine::beginTextPathLayout(RenderSVGTextPath& textPath, SVGTextLayoutEngine& lineLayout) +void SVGTextLayoutEngine::beginTextPathLayout(RenderObject* object, 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. - auto* textContentElement = SVGTextContentElement::elementFromRenderer(&textPath); - if (!textContentElement) - return; + SVGLengthAdjustType lengthAdjust = SVGLengthAdjustUnknown; + float desiredTextLength = 0; + + if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textPath)) { + SVGLengthContext lengthContext(textContentElement); + lengthAdjust = textContentElement->lengthAdjust(); + desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext); + } - SVGLengthContext lengthContext(textContentElement); - float desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext); if (!desiredTextLength) return; - float totalLength = lineLayout.m_chunkLayoutBuilder.totalLength(); - unsigned totalCharacters = lineLayout.m_chunkLayoutBuilder.totalCharacters(); - - if (textContentElement->lengthAdjust() == SVGLengthAdjustSpacing) + if (lengthAdjust == SVGLengthAdjustSpacing) m_textPathSpacing = (desiredTextLength - totalLength) / totalCharacters; else m_textPathScaling = desiredTextLength / totalLength; @@ -210,25 +230,27 @@ void SVGTextLayoutEngine::endTextPathLayout() m_textPathScaling = 1; } -void SVGTextLayoutEngine::layoutInlineTextBox(SVGInlineTextBox& textBox) +void SVGTextLayoutEngine::layoutInlineTextBox(SVGInlineTextBox* textBox) { - RenderSVGInlineText& text = textBox.renderer(); + ASSERT(textBox); + + RenderSVGInlineText& text = textBox->renderer(); ASSERT(text.parent()); ASSERT(text.parent()->element()); ASSERT(text.parent()->element()->isSVGElement()); const RenderStyle& style = text.style(); - textBox.clearTextFragments(); + textBox->clearTextFragments(); m_isVerticalText = style.svgStyle().isVerticalWritingMode(); - layoutTextOnLineOrPath(textBox, text, style); + 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 @@ -270,7 +292,7 @@ void SVGTextLayoutEngine::finalizeTransformMatrices(Vector<SVGInlineTextBox*>& b unsigned fragmentCount = fragments.size(); for (unsigned i = 0; i < fragmentCount; ++i) { - textBoxTransformation = m_chunkLayoutBuilder.transformationForTextBox(textBox); + m_chunkLayoutBuilder.transformationForTextBox(textBox, textBoxTransformation); if (textBoxTransformation.isIdentity()) continue; ASSERT(fragments[i].lengthAdjustTransform.isIdentity()); @@ -358,12 +380,12 @@ bool SVGTextLayoutEngine::currentLogicalCharacterMetrics(SVGTextLayoutAttributes return true; } -bool SVGTextLayoutEngine::currentVisualCharacterMetrics(const SVGInlineTextBox& textBox, Vector<SVGTextMetrics>& visualMetricsValues, SVGTextMetrics& visualMetrics) +bool SVGTextLayoutEngine::currentVisualCharacterMetrics(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; @@ -398,28 +420,26 @@ 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; - RenderElement* textParent = text.parent(); - ASSERT(textParent); - SVGElement* lengthContext = downcast<SVGElement>(textParent->element()); + SVGElement* lengthContext = toSVGElement(text->parent()->element()); - bool definesTextLength = parentDefinesTextLength(textParent); + RenderObject* textParent = text->parent(); + bool definesTextLength = textParent ? parentDefinesTextLength(textParent) : false; - 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()); - auto upconvertedCharacters = StringView(text.text()).upconvertedCharacters(); - const UChar* characters = upconvertedCharacters; - const FontCascade& font = style.fontCascade(); + const UChar* characters = text->deprecatedCharacters(); + const Font& font = style->font(); SVGTextLayoutEngineSpacing spacingLayout(font); SVGTextLayoutEngineBaseline baselineLayout(font); @@ -428,7 +448,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. @@ -461,16 +481,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; @@ -533,15 +553,14 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox& textBox, Rend if (textPathOffset > m_textPathLength) break; - bool success = false; - auto traversalState(m_textPath.traversalStateAtLength(textPathOffset, success)); - ASSERT(success); + bool ok = false; + FloatPoint point = m_textPath.pointAtLength(textPathOffset, ok); + ASSERT(ok); - FloatPoint point = traversalState.current(); x = point.x(); y = point.y(); - - angle = traversalState.normalAngle(); + angle = m_textPath.normalAngleAtLength(textPathOffset, ok); + ASSERT(ok); // For vertical text on path, the actual angle has to be rotated 90 degrees anti-clockwise, not the orientation angle! if (m_isVerticalText) @@ -632,3 +651,5 @@ 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 e0cbc943e..c4a926400 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutEngine.h +++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngine.h @@ -20,6 +20,7 @@ #ifndef SVGTextLayoutEngine_h #define SVGTextLayoutEngine_h +#if ENABLE(SVG) #include "Path.h" #include "SVGTextChunkBuilder.h" #include "SVGTextFragment.h" @@ -30,7 +31,6 @@ namespace WebCore { class RenderObject; class RenderStyle; class RenderSVGInlineText; -class RenderSVGTextPath; class SVGElement; class SVGInlineTextBox; class SVGRenderStyle; @@ -51,10 +51,10 @@ public: Vector<SVGTextLayoutAttributes*>& layoutAttributes() { return m_layoutAttributes; } SVGTextChunkBuilder& chunkLayoutBuilder() { return m_chunkLayoutBuilder; } - void beginTextPathLayout(RenderSVGTextPath&, SVGTextLayoutEngine& lineLayout); + void beginTextPathLayout(RenderObject*, SVGTextLayoutEngine& lineLayout); void endTextPathLayout(); - void layoutInlineTextBox(SVGInlineTextBox&); + void layoutInlineTextBox(SVGInlineTextBox*); void finishLayout(); private: @@ -62,15 +62,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(const SVGInlineTextBox&, Vector<SVGTextMetrics>&, SVGTextMetrics&); + bool currentVisualCharacterMetrics(SVGInlineTextBox*, Vector<SVGTextMetrics>&, SVGTextMetrics&); void advanceToNextLogicalCharacter(const SVGTextMetrics&); void advanceToNextVisualCharacter(const SVGTextMetrics&); @@ -106,4 +106,5 @@ private: } // namespace WebCore +#endif // ENABLE(SVG) #endif diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp index 378e529b0..0497a3456 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp +++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp @@ -18,9 +18,11 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "SVGTextLayoutEngineBaseline.h" -#include "FontCascade.h" +#include "Font.h" #include "RenderElement.h" #include "SVGLengthContext.h" #include "SVGRenderStyle.h" @@ -28,34 +30,33 @@ namespace WebCore { -SVGTextLayoutEngineBaseline::SVGTextLayoutEngineBaseline(const FontCascade& font) +SVGTextLayoutEngineBaseline::SVGTextLayoutEngineBaseline(const Font& font) : m_font(font) { } -float SVGTextLayoutEngineBaseline::calculateBaselineShift(const SVGRenderStyle& style, SVGElement* context) const +float SVGTextLayoutEngineBaseline::calculateBaselineShift(const SVGRenderStyle* style, SVGElement* contextElement) const { - if (style.baselineShift() == BS_LENGTH) { - SVGLength baselineShiftValueLength = style.baselineShiftValue(); + if (style->baselineShift() == BS_LENGTH) { + SVGLength baselineShiftValueLength = style->baselineShiftValue(); if (baselineShiftValueLength.unitType() == LengthTypePercentage) return baselineShiftValueLength.valueAsPercentage() * m_font.pixelSize(); - SVGLengthContext lengthContext(context); + SVGLengthContext lengthContext(contextElement); 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; - case BS_LENGTH: - break; + default: + ASSERT_NOT_REACHED(); + return 0; } - ASSERT_NOT_REACHED(); - return 0; } EAlignmentBaseline SVGTextLayoutEngineBaseline::dominantBaselineToAlignmentBaseline(bool isVerticalText, const RenderObject* textRenderer) const @@ -103,12 +104,15 @@ EAlignmentBaseline SVGTextLayoutEngineBaseline::dominantBaselineToAlignmentBasel } } -float SVGTextLayoutEngineBaseline::calculateAlignmentBaselineShift(bool isVerticalText, const RenderObject& textRenderer) const +float SVGTextLayoutEngineBaseline::calculateAlignmentBaselineShift(bool isVerticalText, const RenderObject* textRenderer) const { - const RenderObject* textRendererParent = textRenderer.parent(); + ASSERT(textRenderer); + ASSERT(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); @@ -143,9 +147,11 @@ 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 { - switch (isVerticalText ? style.glyphOrientationVertical() : style.glyphOrientationHorizontal()) { + ASSERT(style); + + 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. @@ -234,3 +240,5 @@ 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 4c1581be3..6794bf3f8 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.h +++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.h @@ -20,12 +20,13 @@ #ifndef SVGTextLayoutEngineBaseline_h #define SVGTextLayoutEngineBaseline_h +#if ENABLE(SVG) #include "SVGRenderStyleDefs.h" #include <wtf/Noncopyable.h> namespace WebCore { -class FontCascade; +class Font; class RenderObject; class SVGElement; class SVGRenderStyle; @@ -35,19 +36,20 @@ class SVGTextMetrics; class SVGTextLayoutEngineBaseline { WTF_MAKE_NONCOPYABLE(SVGTextLayoutEngineBaseline); public: - SVGTextLayoutEngineBaseline(const FontCascade&); + SVGTextLayoutEngineBaseline(const Font&); - 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 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 calculateGlyphAdvanceAndOrientation(bool isVerticalText, SVGTextMetrics&, float angle, float& xOrientationShift, float& yOrientationShift) const; private: EAlignmentBaseline dominantBaselineToAlignmentBaseline(bool isVerticalText, const RenderObject* textRenderer) const; - const FontCascade& m_font; + const Font& 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 cb5d07496..f0107c4ab 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.cpp +++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.cpp @@ -18,9 +18,11 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "SVGTextLayoutEngineSpacing.h" -#include "FontCascade.h" +#include "Font.h" #include "SVGLengthContext.h" #include "SVGRenderStyle.h" @@ -32,7 +34,7 @@ namespace WebCore { -SVGTextLayoutEngineSpacing::SVGTextLayoutEngineSpacing(const FontCascade& font) +SVGTextLayoutEngineSpacing::SVGTextLayoutEngineSpacing(const Font& font) : m_font(font) , m_lastCharacter(0) { @@ -41,16 +43,16 @@ SVGTextLayoutEngineSpacing::SVGTextLayoutEngineSpacing(const FontCascade& font) float SVGTextLayoutEngineSpacing::calculateSVGKerning(bool isVerticalText, const SVGTextMetrics::Glyph& currentGlyph) { #if ENABLE(SVG_FONTS) - const Font& font = m_font.primaryFont(); - if (!font.isSVGFont()) { + const SimpleFontData* fontData = m_font.primaryFont(); + if (!fontData->isSVGFont()) { m_lastGlyph.isValid = false; return 0; } - ASSERT(font.isCustomFont()); - ASSERT(font.isSVGFont()); + ASSERT(fontData->isCustomFont()); + ASSERT(fontData->isSVGFont()); - auto* svgFontData = static_cast<const SVGFontData*>(font.svgData()); + const SVGFontData* svgFontData = static_cast<const SVGFontData*>(fontData->fontData()); SVGFontFaceElement* svgFontFace = svgFontData->svgFontFaceElement(); ASSERT(svgFontFace); @@ -98,7 +100,7 @@ float SVGTextLayoutEngineSpacing::calculateCSSKerningAndSpacing(const SVGRenderS float spacing = m_font.letterSpacing() + kerning; if (currentCharacter && lastCharacter && m_font.wordSpacing()) { - if (FontCascade::treatAsSpace(*currentCharacter) && !FontCascade::treatAsSpace(*lastCharacter)) + if (Font::treatAsSpace(*currentCharacter) && !Font::treatAsSpace(*lastCharacter)) spacing += m_font.wordSpacing(); } @@ -106,3 +108,5 @@ 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 d9c18206a..71d470737 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.h +++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.h @@ -20,11 +20,12 @@ #ifndef SVGTextLayoutEngineSpacing_h #define SVGTextLayoutEngineSpacing_h +#if ENABLE(SVG) #include "SVGTextMetrics.h" namespace WebCore { -class FontCascade; +class Font; class SVGRenderStyle; class SVGElement; @@ -32,13 +33,13 @@ class SVGElement; class SVGTextLayoutEngineSpacing { WTF_MAKE_NONCOPYABLE(SVGTextLayoutEngineSpacing); public: - SVGTextLayoutEngineSpacing(const FontCascade&); + SVGTextLayoutEngineSpacing(const Font&); float calculateSVGKerning(bool isVerticalText, const SVGTextMetrics::Glyph& currentGlyph); float calculateCSSKerningAndSpacing(const SVGRenderStyle*, SVGElement* lengthContext, const UChar* currentCharacter); private: - const FontCascade& m_font; + const Font& m_font; const UChar* m_lastCharacter; #if ENABLE(SVG_FONTS) @@ -48,4 +49,5 @@ private: } // namespace WebCore +#endif // ENABLE(SVG) #endif diff --git a/Source/WebCore/rendering/svg/SVGTextMetrics.cpp b/Source/WebCore/rendering/svg/SVGTextMetrics.cpp index 27d4e4859..0e6446e31 100644 --- a/Source/WebCore/rendering/svg/SVGTextMetrics.cpp +++ b/Source/WebCore/rendering/svg/SVGTextMetrics.cpp @@ -18,6 +18,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "SVGTextMetrics.h" #include "RenderSVGInlineText.h" @@ -40,12 +42,14 @@ SVGTextMetrics::SVGTextMetrics(SVGTextMetrics::MetricsType) { } -SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText& textRenderer, const TextRun& run) +SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* textRenderer, const TextRun& run) { - float scalingFactor = textRenderer.scalingFactor(); + ASSERT(textRenderer); + + float scalingFactor = textRenderer->scalingFactor(); ASSERT(scalingFactor); - const FontCascade& scaledFont = textRenderer.scaledFont(); + const Font& scaledFont = textRenderer->scaledFont(); int length = 0; // Calculate width/height using the scaled font, divide this result by the scalingFactor afterwards. @@ -59,19 +63,20 @@ SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText& textRenderer, const TextRun& m_length = static_cast<unsigned>(length); } -TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText& text, unsigned position, unsigned length) +TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, const UChar* characters, unsigned position, unsigned length) { - const RenderStyle& style = text.style(); + const RenderStyle& style = text->style(); - TextRun run(StringView(text.text()).substring(position, length) + TextRun run(characters + position + , length , 0 /* xPos, only relevant with allowTabs=true */ , 0 /* padding, only relevant for justified text, not relevant for SVG */ - , AllowTrailingExpansion + , TextRun::AllowTrailingExpansion , style.direction() , isOverride(style.unicodeBidi()) /* directionalOverride */); - if (style.fontCascade().primaryFont().isSVGFont()) - run.setRenderingContext(SVGTextRunRenderingContext::create(text)); + if (style.font().isSVGFont()) + run.setRenderingContext(SVGTextRunRenderingContext::create(*text)); run.disableRoundingHacks(); @@ -79,27 +84,30 @@ TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText& text, unsigned pos 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) { - return SVGTextMetrics(text, constructTextRun(text, position, length)); + ASSERT(text); + return SVGTextMetrics(text, constructTextRun(text, text->deprecatedCharacters(), position, length)); } -SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText& text, unsigned position, unsigned length, float width, const String& glyphName) +SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* text, unsigned position, unsigned length, float width, const String& glyphName) { - bool needsContext = text.style().fontCascade().primaryFont().isSVGFont(); - float scalingFactor = text.scalingFactor(); + ASSERT(text); + + bool needsContext = text->style().font().isSVGFont(); + float scalingFactor = text->scalingFactor(); ASSERT(scalingFactor); m_width = width / scalingFactor; - m_height = text.scaledFont().fontMetrics().floatHeight() / scalingFactor; + m_height = text->scaledFont().fontMetrics().floatHeight() / scalingFactor; if (needsContext) { m_glyph.isValid = true; - m_glyph.unicodeString = text.text()->substring(position, length); + m_glyph.unicodeString = String(text->deprecatedCharacters() + position, length); m_glyph.name = glyphName; } @@ -107,3 +115,5 @@ SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText& text, unsigned position, uns } } + +#endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/SVGTextMetrics.h b/Source/WebCore/rendering/svg/SVGTextMetrics.h index 61641a2cc..ba008c0ef 100644 --- a/Source/WebCore/rendering/svg/SVGTextMetrics.h +++ b/Source/WebCore/rendering/svg/SVGTextMetrics.h @@ -20,6 +20,7 @@ #ifndef SVGTextMetrics_h #define SVGTextMetrics_h +#if ENABLE(SVG) #include <wtf/text/WTFString.h> namespace WebCore { @@ -30,14 +31,16 @@ class TextRun; class SVGTextMetrics { public: - enum MetricsType { SkippedSpaceMetrics }; + enum MetricsType { + SkippedSpaceMetrics + }; SVGTextMetrics(); - explicit SVGTextMetrics(MetricsType); - SVGTextMetrics(RenderSVGInlineText&, unsigned position, unsigned length, float width, const String& glyphName); + SVGTextMetrics(MetricsType); + SVGTextMetrics(RenderSVGInlineText*, unsigned position, unsigned length, float width, const String& glyphName); - static SVGTextMetrics measureCharacterRange(RenderSVGInlineText&, unsigned position, unsigned length); - static TextRun constructTextRun(RenderSVGInlineText&, unsigned position = 0, unsigned length = std::numeric_limits<unsigned>::max()); + static SVGTextMetrics measureCharacterRange(RenderSVGInlineText*, unsigned position, unsigned length); + static TextRun constructTextRun(RenderSVGInlineText*, const UChar* characters, unsigned position, unsigned length); bool isEmpty() const { return !m_width && !m_height && !m_glyph.isValid && m_length == 1; } @@ -69,7 +72,7 @@ public: const Glyph& glyph() const { return m_glyph; } private: - SVGTextMetrics(RenderSVGInlineText&, const TextRun&); + SVGTextMetrics(RenderSVGInlineText*, const TextRun&); float m_width; float m_height; @@ -79,4 +82,5 @@ private: } // namespace WebCore +#endif // ENABLE(SVG) #endif diff --git a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp index 1447596dd..86009e6e9 100644 --- a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp +++ b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp @@ -18,9 +18,10 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "SVGTextMetricsBuilder.h" -#include "RenderSVGInline.h" #include "RenderSVGInlineText.h" #include "RenderSVGText.h" #include "SVGTextRunRenderingContext.h" @@ -29,7 +30,7 @@ namespace WebCore { SVGTextMetricsBuilder::SVGTextMetricsBuilder() : m_text(0) - , m_run(StringView()) + , m_run(static_cast<const UChar*>(0), 0) , m_textPosition(0) , m_isComplexText(false) , m_totalWidth(0) @@ -38,13 +39,13 @@ SVGTextMetricsBuilder::SVGTextMetricsBuilder() inline bool SVGTextMetricsBuilder::currentCharacterStartsSurrogatePair() const { - return U16_IS_LEAD(m_run[m_textPosition]) && (m_textPosition + 1) < m_run.charactersLength() && U16_IS_TRAIL(m_run[m_textPosition + 1]); + return U16_IS_LEAD(m_run[m_textPosition]) && int(m_textPosition + 1) < m_run.charactersLength() && U16_IS_TRAIL(m_run[m_textPosition + 1]); } bool SVGTextMetricsBuilder::advance() { m_textPosition += m_currentMetrics.length(); - if (m_textPosition >= m_run.charactersLength()) + if (int(m_textPosition) >= m_run.charactersLength()) return false; if (m_isComplexText) @@ -68,17 +69,17 @@ void SVGTextMetricsBuilder::advanceSimpleText() m_totalWidth = m_simpleWidthIterator->runWidthSoFar(); #if ENABLE(SVG_FONTS) - m_currentMetrics = SVGTextMetrics(*m_text, m_textPosition, metricsLength, currentWidth, m_simpleWidthIterator->lastGlyphName()); + m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, m_simpleWidthIterator->lastGlyphName()); #else - m_currentMetrics = SVGTextMetrics(*m_text, m_textPosition, metricsLength, currentWidth, emptyString()); + m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, emptyString()); #endif } 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 @@ -92,22 +93,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 FontCascade& scaledFont = text.scaledFont(); - m_run = SVGTextMetrics::constructTextRun(text); - m_isComplexText = scaledFont.codePath(m_run) == FontCascade::Complex; + const Font& scaledFont = text->scaledFont(); + m_run = SVGTextMetrics::constructTextRun(text, text->deprecatedCharacters(), 0, text->textLength()); + m_isComplexText = scaledFont.codePath(m_run) == Font::Complex; if (m_isComplexText) - m_simpleWidthIterator = nullptr; + m_simpleWidthIterator.clear(); else - m_simpleWidthIterator = std::make_unique<WidthIterator>(&scaledFont, m_run); + m_simpleWidthIterator = adoptPtr(new WidthIterator(&scaledFont, m_run)); } struct MeasureTextData { @@ -121,15 +122,17 @@ struct MeasureTextData { } SVGCharacterDataMap* allCharactersMap; - UChar lastCharacter; + const UChar* lastCharacter; bool processRenderer; unsigned valueListPosition; unsigned skippedCharacters; }; -void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText& text, MeasureTextData* data) +void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText* text, MeasureTextData* data) { - SVGTextLayoutAttributes* attributes = text.layoutAttributes(); + ASSERT(text); + + SVGTextLayoutAttributes* attributes = text->layoutAttributes(); Vector<SVGTextMetrics>* textMetricsValues = &attributes->textMetricsValues(); if (data->processRenderer) { if (data->allCharactersMap) @@ -139,12 +142,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()) { - UChar currentCharacter = m_run[m_textPosition]; - if (currentCharacter == ' ' && !preserveWhiteSpace && (!data->lastCharacter || data->lastCharacter == ' ')) { + const UChar* currentCharacter = m_run.data16(m_textPosition); + if (*currentCharacter == ' ' && !preserveWhiteSpace && (!data->lastCharacter || *data->lastCharacter == ' ')) { if (data->processRenderer) textMetricsValues->append(SVGTextMetrics(SVGTextMetrics::SkippedSpaceMetrics)); if (data->allCharactersMap) @@ -176,10 +179,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 (is<RenderSVGInlineText>(*child)) { - RenderSVGInlineText& text = downcast<RenderSVGInlineText>(*child); - if (stopAtLeaf && stopAtLeaf != &text) { + for (auto child = start.firstChild(); child; child = child->nextSibling()) { + if (child->isSVGInlineText()) { + RenderSVGInlineText* text = toRenderSVGInlineText(child); + if (stopAtLeaf && stopAtLeaf != text) { data->processRenderer = false; measureTextRenderer(text, data); continue; @@ -193,27 +196,32 @@ void SVGTextMetricsBuilder::walkTree(RenderElement& start, RenderSVGInlineText* continue; } - if (!is<RenderSVGInline>(*child)) + if (!child->isSVGInline()) continue; - walkTree(downcast<RenderSVGInline>(*child), stopAtLeaf, data); + walkTree(toRenderElement(*child), stopAtLeaf, data); } } -void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText& text) +void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText* text) { - auto* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text); + ASSERT(text); + + RenderSVGText* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text); if (!textRoot) return; - MeasureTextData data(nullptr); - walkTree(*textRoot, &text, &data); + MeasureTextData data(0); + 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 08e07eeb1..5e0d12951 100644 --- a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.h +++ b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.h @@ -20,6 +20,7 @@ #ifndef SVGTextMetricsBuilder_h #define SVGTextMetricsBuilder_h +#if ENABLE(SVG) #include "SVGTextLayoutAttributes.h" #include "TextRun.h" #include "WidthIterator.h" @@ -35,8 +36,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(); @@ -44,9 +45,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; @@ -56,7 +57,7 @@ private: float m_totalWidth; // Simple text only. - std::unique_ptr<WidthIterator> m_simpleWidthIterator; + OwnPtr<WidthIterator> m_simpleWidthIterator; // Complex text only. SVGTextMetrics m_complexStartToCurrentMetrics; @@ -64,4 +65,5 @@ private: } // namespace WebCore +#endif // ENABLE(SVG) #endif diff --git a/Source/WebCore/rendering/svg/SVGTextQuery.cpp b/Source/WebCore/rendering/svg/SVGTextQuery.cpp index ff3667717..f25dedcad 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 nullptr; + return 0; - if (is<RenderBlockFlow>(*renderer)) { + if (renderer->isRenderBlockFlow()) { // If we're given a block element, it has to be a RenderSVGText. - ASSERT(is<RenderSVGText>(*renderer)); - RenderBlockFlow& renderBlock = downcast<RenderBlockFlow>(*renderer); + ASSERT(renderer->isSVGText()); + RenderBlockFlow& renderBlock = toRenderBlockFlow(*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 (is<RenderInline>(*renderer)) { + if (renderer->isRenderInline()) { // We're given a RenderSVGInline or objects that derive from it (RenderSVGTSpan / RenderSVGTextPath) - RenderInline& renderInline = downcast<RenderInline>(*renderer); + RenderInline& renderInline = toRenderInline(*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 nullptr; + return 0; } SVGTextQuery::SVGTextQuery(RenderObject* renderer) @@ -89,17 +89,17 @@ void SVGTextQuery::collectTextBoxesInFlowBox(InlineFlowBox* flowBox) return; for (InlineBox* child = flowBox->firstChild(); child; child = child->nextOnLine()) { - if (is<InlineFlowBox>(*child)) { + if (child->isInlineFlowBox()) { // Skip generated content. if (!child->renderer().node()) continue; - collectTextBoxesInFlowBox(downcast<InlineFlowBox>(child)); + collectTextBoxesInFlowBox(toInlineFlowBox(child)); continue; } - if (is<SVGInlineTextBox>(*child)) - m_textBoxes.append(downcast<SVGInlineTextBox>(child)); + if (child->isSVGInlineTextBox()) + m_textBoxes.append(toSVGInlineTextBox(child)); } } @@ -213,11 +213,15 @@ void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, i return; if (lastPositionOffset != -1 && lastPositionOffset - positionOffset > 1) { - if (alterStartPosition && startPosition > lastPositionOffset && startPosition < static_cast<int>(positionOffset)) + if (alterStartPosition && startPosition > lastPositionOffset && startPosition < static_cast<int>(positionOffset)) { startPosition = lastPositionOffset; + alterStartPosition = false; + } - if (alterEndPosition && endPosition > lastPositionOffset && endPosition < static_cast<int>(positionOffset)) + if (alterEndPosition && endPosition > lastPositionOffset && endPosition < static_cast<int>(positionOffset)) { endPosition = positionOffset; + alterEndPosition = false; + } } } @@ -289,7 +293,7 @@ bool SVGTextQuery::subStringLengthCallback(Data* queryData, const SVGTextFragmen 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; } @@ -327,7 +331,7 @@ bool SVGTextQuery::startPositionOfCharacterCallback(Data* queryData, const SVGTe 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 @@ -375,7 +379,7 @@ bool SVGTextQuery::endPositionOfCharacterCallback(Data* queryData, const SVGText 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 @@ -462,14 +466,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; @@ -547,3 +551,5 @@ 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 721b2df8e..bf60a6da6 100644 --- a/Source/WebCore/rendering/svg/SVGTextQuery.h +++ b/Source/WebCore/rendering/svg/SVGTextQuery.h @@ -20,6 +20,7 @@ #ifndef SVGTextQuery_h #define SVGTextQuery_h +#if ENABLE(SVG) #include "FloatRect.h" #include "SVGPoint.h" #include "SVGTextFragment.h" @@ -72,3 +73,4 @@ private: } #endif +#endif diff --git a/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp b/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp index dd3f28557..3b2561af8 100644 --- a/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp +++ b/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp @@ -37,22 +37,22 @@ namespace WebCore { -static inline const SVGFontData* svgFontAndFontFaceElementForFontData(const Font* font, SVGFontFaceElement*& svgFontFaceElement, SVGFontElement*& svgFontElement) +static inline const SVGFontData* svgFontAndFontFaceElementForFontData(const SimpleFontData* fontData, SVGFontFaceElement*& fontFace, SVGFontElement*& font) { - ASSERT(font); - ASSERT(font->isCustomFont()); - ASSERT(font->isSVGFont()); + ASSERT(fontData); + ASSERT(fontData->isCustomFont()); + ASSERT(fontData->isSVGFont()); - auto* svgFontData = static_cast<const SVGFontData*>(font->svgData()); + const SVGFontData* svgFontData = static_cast<const SVGFontData*>(fontData->fontData()); - svgFontFaceElement = svgFontData->svgFontFaceElement(); - ASSERT(svgFontFaceElement); + fontFace = svgFontData->svgFontFaceElement(); + ASSERT(fontFace); - svgFontElement = svgFontFaceElement->associatedFontElement(); + font = fontFace->associatedFontElement(); return svgFontData; } -float SVGTextRunRenderingContext::floatWidthUsingSVGFont(const FontCascade& font, const TextRun& run, int& charsConsumed, String& glyphName) const +float SVGTextRunRenderingContext::floatWidthUsingSVGFont(const Font& font, const TextRun& run, int& charsConsumed, String& glyphName) const { WidthIterator it(&font, run); GlyphBuffer glyphBuffer; @@ -61,21 +61,18 @@ float SVGTextRunRenderingContext::floatWidthUsingSVGFont(const FontCascade& font return it.runWidthSoFar(); } -bool SVGTextRunRenderingContext::applySVGKerning(const Font* font, WidthIterator& iterator, GlyphBuffer* glyphBuffer, int from) const +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(font, fontFaceElement, fontElement); + svgFontAndFontFaceElementForFontData(fontData, fontFaceElement, fontElement); if (!fontElement || !fontFaceElement) return false; - if (fontElement->horizontalKerningMapIsEmpty()) - return true; - - float scale = scaleEmToUnits(font->platformData().size(), fontFaceElement->unitsPerEm()); + float scale = scaleEmToUnits(fontData->platformData().size(), fontFaceElement->unitsPerEm()); String lastGlyphName; String lastUnicodeString; @@ -104,166 +101,15 @@ bool SVGTextRunRenderingContext::applySVGKerning(const Font* font, WidthIterator return true; } -class SVGGlyphToPathTranslator final : public GlyphToPathTranslator { -public: - SVGGlyphToPathTranslator(const TextRun* const, const GlyphBuffer&, const FloatPoint&, const SVGFontData&, SVGFontElement&, const int from, const int numGlyphs, float scale, bool isVerticalText); -private: - virtual bool containsMorePaths() override - { - return m_index != m_stoppingPoint; - } - - virtual Path path() override; - virtual std::pair<float, float> extents() override; - virtual GlyphUnderlineType underlineType() override; - virtual void advance() override; - void moveToNextValidGlyph(); - AffineTransform transform(); - - const TextRun* const m_textRun; - const GlyphBuffer& m_glyphBuffer; - const SVGFontData& m_svgFontData; - FloatPoint m_currentPoint; - FloatPoint m_glyphOrigin; - SVGGlyph m_svgGlyph; - int m_index; - Glyph m_glyph; - SVGFontElement& m_fontElement; - const float m_stoppingPoint; - const float m_scale; - const bool m_isVerticalText; -}; - -SVGGlyphToPathTranslator::SVGGlyphToPathTranslator(const TextRun* const textRun, const GlyphBuffer& glyphBuffer, const FloatPoint& point, const SVGFontData& svgFontData, SVGFontElement& fontElement, const int from, const int numGlyphs, float scale, bool isVerticalText) - : m_textRun(textRun) - , m_glyphBuffer(glyphBuffer) - , m_svgFontData(svgFontData) - , m_currentPoint(point) - , m_glyphOrigin(m_svgFontData.horizontalOriginX() * scale, m_svgFontData.horizontalOriginY() * scale) - , m_index(from) - , m_glyph(glyphBuffer.glyphAt(m_index)) - , m_fontElement(fontElement) - , m_stoppingPoint(numGlyphs + from) - , m_scale(scale) - , m_isVerticalText(isVerticalText) -{ - ASSERT(glyphBuffer.size() > m_index); - if (m_glyph) { - m_svgGlyph = m_fontElement.svgGlyphForGlyph(m_glyph); - ASSERT(!m_svgGlyph.isPartOfLigature); - ASSERT(m_svgGlyph.tableEntry == m_glyph); - SVGGlyphElement::inheritUnspecifiedAttributes(m_svgGlyph, &m_svgFontData); - } - moveToNextValidGlyph(); -} - -AffineTransform SVGGlyphToPathTranslator::transform() -{ - AffineTransform glyphPathTransform; - glyphPathTransform.translate(m_currentPoint.x() + m_glyphOrigin.x(), m_currentPoint.y() + m_glyphOrigin.y()); - glyphPathTransform.scale(m_scale, -m_scale); - return glyphPathTransform; -} - -Path SVGGlyphToPathTranslator::path() -{ - Path glyphPath = m_svgGlyph.pathData; - glyphPath.transform(transform()); - return glyphPath; -} - -std::pair<float, float> SVGGlyphToPathTranslator::extents() -{ - AffineTransform glyphPathTransform = transform(); - FloatPoint beginning = glyphPathTransform.mapPoint(m_currentPoint); - FloatSize end = glyphPathTransform.mapSize(FloatSize(m_glyphBuffer.advanceAt(m_index))); - return std::make_pair(beginning.x(), beginning.x() + end.width()); -} - -auto SVGGlyphToPathTranslator::underlineType() -> GlyphUnderlineType -{ - ASSERT(m_textRun); - return computeUnderlineType(*m_textRun, m_glyphBuffer, m_index); -} - -void SVGGlyphToPathTranslator::moveToNextValidGlyph() -{ - if (m_glyph && !m_svgGlyph.pathData.isEmpty()) - return; - advance(); -} - -void SVGGlyphToPathTranslator::advance() -{ - do { - if (m_glyph) { - float advance = m_glyphBuffer.advanceAt(m_index).width(); - if (m_isVerticalText) - m_currentPoint.move(0, advance); - else - m_currentPoint.move(advance, 0); - } - - ++m_index; - if (m_index >= m_stoppingPoint || !m_glyphBuffer.fontAt(m_index)->isSVGFont()) - break; - m_glyph = m_glyphBuffer.glyphAt(m_index); - if (!m_glyph) - continue; - m_svgGlyph = m_fontElement.svgGlyphForGlyph(m_glyph); - ASSERT(!m_svgGlyph.isPartOfLigature); - ASSERT(m_svgGlyph.tableEntry == m_glyph); - SVGGlyphElement::inheritUnspecifiedAttributes(m_svgGlyph, &m_svgFontData); - } while ((!m_glyph || m_svgGlyph.pathData.isEmpty()) && m_index < m_stoppingPoint); - - if (containsMorePaths() && m_isVerticalText) { - m_glyphOrigin.setX(m_svgGlyph.verticalOriginX * m_scale); - m_glyphOrigin.setY(m_svgGlyph.verticalOriginY * m_scale); - } -} - -class DummyGlyphToPathTranslator final : public GlyphToPathTranslator { - virtual bool containsMorePaths() override - { - return false; - } - virtual Path path() override - { - return Path(); - } - virtual std::pair<float, float> extents() override - { - return std::make_pair(0.f, 0.f); - } - virtual GlyphUnderlineType underlineType() override - { - return GlyphUnderlineType::DrawOverGlyph; - } - virtual void advance() override - { - } -}; - -std::unique_ptr<GlyphToPathTranslator> SVGTextRunRenderingContext::createGlyphToPathTranslator(const Font& font, const TextRun* textRun, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const +void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const { - SVGFontElement* fontElement = nullptr; - SVGFontFaceElement* fontFaceElement = nullptr; + SVGFontElement* fontElement = 0; + SVGFontFaceElement* fontFaceElement = 0; - const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(&font, fontFaceElement, fontElement); + const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(fontData, fontFaceElement, fontElement); if (!fontElement || !fontFaceElement) - return std::make_unique<DummyGlyphToPathTranslator>(); - - auto& elementRenderer = is<RenderElement>(renderer()) ? downcast<RenderElement>(renderer()) : *renderer().parent(); - RenderStyle& style = elementRenderer.style(); - bool isVerticalText = style.svgStyle().isVerticalWritingMode(); - - float scale = scaleEmToUnits(font.platformData().size(), fontFaceElement->unitsPerEm()); - - return std::make_unique<SVGGlyphToPathTranslator>(textRun, glyphBuffer, point, *svgFontData, *fontElement, from, numGlyphs, scale, isVerticalText); -} + return; -void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const Font* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const -{ auto activePaintingResource = this->activePaintingResource(); if (!activePaintingResource) { // TODO: We're only supporting simple filled HTML text so far. @@ -272,80 +118,135 @@ void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const F activePaintingResource = solidPaintingResource; } - auto& elementRenderer = is<RenderElement>(renderer()) ? downcast<RenderElement>(renderer()) : *renderer().parent(); + 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 (auto translator = createGlyphToPathTranslator(*font, nullptr, glyphBuffer, from, numGlyphs, point); translator->containsMorePaths(); translator->advance()) { - Path glyphPath = translator->path(); + 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 (is<RenderSVGInlineText>(renderer())) - context->setStrokeThickness(strokeThickness * downcast<RenderSVGInlineText>(renderer()).scalingFactor()); - activePaintingResource->postApplyResource(elementRenderer, context, resourceMode, &glyphPath, nullptr); + 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); } } -static GlyphData missingGlyphForFont(const FontCascade& font) +GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const Font& font, WidthIterator& iterator, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength) { - const Font& primaryFont = font.primaryFont(); - if (!primaryFont.isSVGFont()) - return GlyphData(); - SVGFontElement* fontElement; - SVGFontFaceElement* fontFaceElement; - svgFontAndFontFaceElementForFontData(&primaryFont, fontFaceElement, fontElement); - return GlyphData(fontElement->missingGlyph(), &primaryFont); -} + const SimpleFontData* primaryFont = font.primaryFont(); + ASSERT(primaryFont); -GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const FontCascade& font, WidthIterator& iterator, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength, String& normalizedSpacesStringCache) -{ - GlyphData glyphData = font.glyphDataForCharacter(character, mirror, AutoVariant); - if (!glyphData.glyph) - return missingGlyphForFont(font); + std::pair<GlyphData, GlyphPage*> pair = font.glyphDataAndPageForCharacter(character, mirror, AutoVariant); + GlyphData glyphData = pair.first; - ASSERT(glyphData.font); + // 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. - if (!glyphData.font->isSVGFont()) { - auto& elementRenderer = is<RenderElement>(renderer()) ? downcast<RenderElement>(renderer()) : *renderer().parent(); + 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 (is<SVGAltGlyphElement>(*parentRendererElement)) - glyphData.font = &font.primaryFont(); + if (parentRendererElement->hasTagName(SVGNames::altGlyphTag)) + glyphData.fontData = primaryFont; } } - if (!glyphData.font->isSVGFont()) - return glyphData; + const SimpleFontData* fontData = glyphData.fontData; + if (fontData) { + if (!fontData->isSVGFont()) + return glyphData; - SVGFontElement* fontElement = nullptr; - SVGFontFaceElement* fontFaceElement = nullptr; - const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(glyphData.font, fontFaceElement, fontElement); - if (!svgFontData) - return glyphData; + SVGFontElement* fontElement = 0; + SVGFontFaceElement* fontFaceElement = 0; - // If we got here, we're dealing with a glyph defined in a SVG Font. - // The returned glyph by glyphDataForCharacter() 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, normalizedSpacesStringCache)) - return glyphData; + 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); - GlyphData missingGlyphData = missingGlyphForFont(font); - if (missingGlyphData.glyph) - return missingGlyphData; + // 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); - // SVG font context sensitive selection failed and there is no defined missing glyph. Drop down to a default font. - // The behavior does not seem to be specified. For simplicity we don't try to resolve font fallbacks context-sensitively. - FontDescription fallbackDescription = font.fontDescription(); - fallbackDescription.setFamilies(Vector<AtomicString> { sansSerifFamily }); - FontCascade fallbackFont(fallbackDescription, font.letterSpacing(), font.wordSpacing()); - fallbackFont.update(font.fontSelector()); + // 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); - return fallbackFont.glyphDataForCharacter(character, mirror, AutoVariant); + // 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; } } diff --git a/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h b/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h index 501b9c8ff..e1270c19e 100644 --- a/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h +++ b/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h @@ -21,7 +21,7 @@ #ifndef SVGTextRunRenderingContext_h #define SVGTextRunRenderingContext_h -#include "FontCascade.h" +#include "Font.h" #include "TextRun.h" namespace WebCore { @@ -31,7 +31,7 @@ class RenderSVGResource; class SVGTextRunRenderingContext final : public TextRun::RenderingContext { public: - static Ref<SVGTextRunRenderingContext> create(RenderObject& renderer) + static PassRef<SVGTextRunRenderingContext> create(RenderObject& renderer) { return adoptRef(*new SVGTextRunRenderingContext(renderer)); } @@ -42,10 +42,10 @@ public: RenderSVGResource* activePaintingResource() const { return m_activePaintingResource; } void setActivePaintingResource(RenderSVGResource* object) { m_activePaintingResource = object; } - virtual GlyphData glyphDataForCharacter(const FontCascade&, WidthIterator&, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength, String& normalizedSpacesStringCache) override; - virtual void drawSVGGlyphs(GraphicsContext*, const Font*, const GlyphBuffer&, int from, int to, const FloatPoint&) const override; - virtual float floatWidthUsingSVGFont(const FontCascade&, const TextRun&, int& charsConsumed, String& glyphName) const override; - virtual bool applySVGKerning(const Font*, WidthIterator&, GlyphBuffer*, int from) const override; + 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: @@ -59,10 +59,6 @@ private: virtual ~SVGTextRunRenderingContext() { } -#if ENABLE(SVG_FONTS) - virtual std::unique_ptr<GlyphToPathTranslator> createGlyphToPathTranslator(const Font&, const TextRun*, const GlyphBuffer&, int from, int numGlyphs, const FloatPoint&) const override; -#endif - RenderObject& m_renderer; #if ENABLE(SVG_FONTS) |
