| Index: Source/core/rendering/svg/RenderSVGPath.cpp
|
| diff --git a/Source/core/rendering/svg/RenderSVGPath.cpp b/Source/core/rendering/svg/RenderSVGPath.cpp
|
| index 8ea008e5432f82b61a6a5ab772c3f9eda3c46dd8..a6344ec8aeae9892b7eb8c974b7cec8464798d1b 100644
|
| --- a/Source/core/rendering/svg/RenderSVGPath.cpp
|
| +++ b/Source/core/rendering/svg/RenderSVGPath.cpp
|
| @@ -29,8 +29,11 @@
|
|
|
| #include "core/rendering/svg/RenderSVGPath.h"
|
|
|
| +#include "core/rendering/svg/RenderSVGResourceMarker.h"
|
| +#include "core/rendering/svg/SVGResources.h"
|
| +#include "core/rendering/svg/SVGResourcesCache.h"
|
| #include "core/rendering/svg/SVGSubpathData.h"
|
| -#include "platform/graphics/GraphicsContextStateSaver.h"
|
| +#include "core/svg/SVGGraphicsElement.h"
|
|
|
| namespace blink {
|
|
|
| @@ -55,6 +58,9 @@ FloatRect RenderSVGPath::calculateUpdatedStrokeBoundingBox() const
|
| {
|
| FloatRect strokeBoundingBox = m_strokeBoundingBox;
|
|
|
| + if (!m_markerPositions.isEmpty())
|
| + strokeBoundingBox.unite(markerRect(strokeWidth()));
|
| +
|
| if (style()->svgStyle().hasStroke()) {
|
| // FIXME: zero-length subpaths do not respect vector-effect = non-scaling-stroke.
|
| float strokeWidth = this->strokeWidth();
|
| @@ -65,42 +71,6 @@ FloatRect RenderSVGPath::calculateUpdatedStrokeBoundingBox() const
|
| return strokeBoundingBox;
|
| }
|
|
|
| -static void useStrokeStyleToFill(GraphicsContext* context)
|
| -{
|
| - if (Gradient* gradient = context->strokeGradient())
|
| - context->setFillGradient(gradient);
|
| - else if (Pattern* pattern = context->strokePattern())
|
| - context->setFillPattern(pattern);
|
| - else
|
| - context->setFillColor(context->strokeColor());
|
| -}
|
| -
|
| -void RenderSVGPath::strokeShape(GraphicsContext* context) const
|
| -{
|
| - if (!style()->svgStyle().hasVisibleStroke())
|
| - return;
|
| -
|
| - RenderSVGShape::strokeShape(context);
|
| -
|
| - if (m_zeroLengthLinecapLocations.isEmpty())
|
| - return;
|
| -
|
| - Path* usePath;
|
| - AffineTransform nonScalingTransform;
|
| -
|
| - if (hasNonScalingStroke())
|
| - nonScalingTransform = nonScalingStrokeTransform();
|
| -
|
| - GraphicsContextStateSaver stateSaver(*context, true);
|
| - useStrokeStyleToFill(context);
|
| - for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) {
|
| - usePath = zeroLengthLinecapPath(m_zeroLengthLinecapLocations[i]);
|
| - if (hasNonScalingStroke())
|
| - usePath = nonScalingStrokePath(usePath, nonScalingTransform);
|
| - context->fillPath(*usePath);
|
| - }
|
| -}
|
| -
|
| bool RenderSVGPath::shapeDependentStrokeContains(const FloatPoint& point)
|
| {
|
| if (RenderSVGShape::shapeDependentStrokeContains(point))
|
| @@ -130,20 +100,7 @@ bool RenderSVGPath::shouldStrokeZeroLengthSubpath() const
|
| return style()->svgStyle().hasStroke() && style()->svgStyle().capStyle() != ButtCap;
|
| }
|
|
|
| -Path* RenderSVGPath::zeroLengthLinecapPath(const FloatPoint& linecapPosition) const
|
| -{
|
| - DEFINE_STATIC_LOCAL(Path, tempPath, ());
|
| -
|
| - tempPath.clear();
|
| - if (style()->svgStyle().capStyle() == SquareCap)
|
| - tempPath.addRect(zeroLengthSubpathRect(linecapPosition, this->strokeWidth()));
|
| - else
|
| - tempPath.addEllipse(zeroLengthSubpathRect(linecapPosition, this->strokeWidth()));
|
| -
|
| - return &tempPath;
|
| -}
|
| -
|
| -FloatRect RenderSVGPath::zeroLengthSubpathRect(const FloatPoint& linecapPosition, float strokeWidth) const
|
| +FloatRect RenderSVGPath::zeroLengthSubpathRect(const FloatPoint& linecapPosition, float strokeWidth)
|
| {
|
| return FloatRect(linecapPosition.x() - strokeWidth / 2, linecapPosition.y() - strokeWidth / 2, strokeWidth, strokeWidth);
|
| }
|
| @@ -160,4 +117,57 @@ void RenderSVGPath::updateZeroLengthSubpaths()
|
| subpathData.pathIsDone();
|
| }
|
|
|
| +FloatRect RenderSVGPath::markerRect(float strokeWidth) const
|
| +{
|
| + ASSERT(!m_markerPositions.isEmpty());
|
| +
|
| + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
|
| + ASSERT(resources);
|
| +
|
| + RenderSVGResourceMarker* markerStart = resources->markerStart();
|
| + RenderSVGResourceMarker* markerMid = resources->markerMid();
|
| + RenderSVGResourceMarker* markerEnd = resources->markerEnd();
|
| + ASSERT(markerStart || markerMid || markerEnd);
|
| +
|
| + FloatRect boundaries;
|
| + unsigned size = m_markerPositions.size();
|
| + for (unsigned i = 0; i < size; ++i) {
|
| + if (RenderSVGResourceMarker* marker = SVGMarkerData::markerForType(m_markerPositions[i].type, markerStart, markerMid, markerEnd))
|
| + boundaries.unite(marker->markerBoundaries(marker->markerTransformation(m_markerPositions[i].origin, m_markerPositions[i].angle, strokeWidth)));
|
| + }
|
| + return boundaries;
|
| +}
|
| +
|
| +bool RenderSVGPath::shouldGenerateMarkerPositions() const
|
| +{
|
| + if (!style()->svgStyle().hasMarkers())
|
| + return false;
|
| +
|
| + if (!SVGResources::supportsMarkers(*toSVGGraphicsElement(element())))
|
| + return false;
|
| +
|
| + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
|
| + if (!resources)
|
| + return false;
|
| +
|
| + return resources->markerStart() || resources->markerMid() || resources->markerEnd();
|
| +}
|
| +
|
| +void RenderSVGPath::processMarkerPositions()
|
| +{
|
| + m_markerPositions.clear();
|
| +
|
| + if (!shouldGenerateMarkerPositions())
|
| + return;
|
| +
|
| + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
|
| + ASSERT(resources);
|
| +
|
| + RenderSVGResourceMarker* markerStart = resources->markerStart();
|
| +
|
| + SVGMarkerData markerData(m_markerPositions, markerStart ? markerStart->orientType() == SVGMarkerOrientAutoStartReverse : false);
|
| + path().apply(&markerData, SVGMarkerData::updateFromPathElement);
|
| + markerData.pathIsDone();
|
| +}
|
| +
|
| }
|
|
|