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(); |
+} |
+ |
} |