Index: Source/WebCore/rendering/svg/RenderSVGShape.cpp |
=================================================================== |
--- Source/WebCore/rendering/svg/RenderSVGShape.cpp (revision 118879) |
+++ Source/WebCore/rendering/svg/RenderSVGShape.cpp (working copy) |
@@ -40,7 +40,6 @@ |
#include "RenderSVGResourceMarker.h" |
#include "RenderSVGResourceSolidColor.h" |
#include "SVGPathData.h" |
-#include "SVGPathElement.h" |
#include "SVGRenderingContext.h" |
#include "SVGResources.h" |
#include "SVGResourcesCache.h" |
@@ -72,9 +71,10 @@ |
m_path = adoptPtr(new Path); |
ASSERT(isEmpty()); |
- SVGPathElement* element = static_cast<SVGPathElement*>(node()); |
+ SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); |
updatePathFromGraphicsElement(element, path()); |
processZeroLengthSubpaths(); |
+ processMarkerPositions(); |
} |
bool RenderSVGShape::isEmpty() const |
@@ -177,10 +177,8 @@ |
} |
// Invalidate all resources of this client if our layout changed. |
- if (everHadLayout() && selfNeedsLayout()) { |
+ if (everHadLayout() && selfNeedsLayout()) |
SVGResourcesCache::clientLayoutChanged(this); |
- m_markerLayoutInfo.clear(); |
- } |
// At this point LayoutRepainter already grabbed the old bounds, |
// recalculate them now so repaintAfterLayout() uses the new bounds. |
@@ -204,6 +202,22 @@ |
return style()->svgStyle()->hasStroke() && style()->svgStyle()->capStyle() != ButtCap; |
} |
+bool RenderSVGShape::shouldGenerateMarkerPositions() const |
+{ |
+ if (!style()->svgStyle()->hasMarkers()) |
+ return false; |
+ |
+ SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); |
+ if (!element->supportsMarkers()) |
+ return false; |
+ |
+ SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this); |
+ if (!resources) |
+ return false; |
+ |
+ return resources->markerStart() || resources->markerMid() || resources->markerEnd(); |
+} |
+ |
FloatRect RenderSVGShape::zeroLengthSubpathRect(const FloatPoint& linecapPosition, float strokeWidth) const |
{ |
return FloatRect(linecapPosition.x() - strokeWidth / 2, linecapPosition.y() - strokeWidth / 2, strokeWidth, strokeWidth); |
@@ -337,9 +351,8 @@ |
childPaintInfo.context->setShouldAntialias(false); |
fillAndStrokePath(childPaintInfo.context); |
- |
- if (svgStyle->hasMarkers()) |
- m_markerLayoutInfo.drawMarkers(childPaintInfo); |
+ if (!m_markerPositions.isEmpty()) |
+ drawMarkers(childPaintInfo); |
} |
} |
@@ -384,30 +397,40 @@ |
return false; |
} |
-FloatRect RenderSVGShape::calculateMarkerBoundsIfNeeded() |
+static inline RenderSVGResourceMarker* markerForType(SVGMarkerType type, RenderSVGResourceMarker* markerStart, RenderSVGResourceMarker* markerMid, RenderSVGResourceMarker* markerEnd) |
{ |
- SVGElement* svgElement = static_cast<SVGElement*>(node()); |
- ASSERT(svgElement && svgElement->document()); |
- if (!svgElement->isStyled()) |
- return FloatRect(); |
+ switch (type) { |
+ case StartMarker: |
+ return markerStart; |
+ case MidMarker: |
+ return markerMid; |
+ case EndMarker: |
+ return markerEnd; |
+ } |
- SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); |
- if (!styledElement->supportsMarkers()) |
- return FloatRect(); |
+ ASSERT_NOT_REACHED(); |
+ return 0; |
+} |
- ASSERT(style()->svgStyle()->hasMarkers()); |
+FloatRect RenderSVGShape::markerRect(float strokeWidth) const |
+{ |
+ ASSERT(!m_markerPositions.isEmpty()); |
SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this); |
- if (!resources) |
- return FloatRect(); |
+ ASSERT(resources); |
RenderSVGResourceMarker* markerStart = resources->markerStart(); |
RenderSVGResourceMarker* markerMid = resources->markerMid(); |
RenderSVGResourceMarker* markerEnd = resources->markerEnd(); |
- if (!markerStart && !markerMid && !markerEnd) |
- return FloatRect(); |
+ ASSERT(markerStart || markerMid || markerEnd); |
- return m_markerLayoutInfo.calculateBoundaries(markerStart, markerMid, markerEnd, strokeWidth(), path()); |
+ FloatRect boundaries; |
+ unsigned size = m_markerPositions.size(); |
+ for (unsigned i = 0; i < size; ++i) { |
+ if (RenderSVGResourceMarker* marker = markerForType(m_markerPositions[i].type, markerStart, markerMid, markerEnd)) |
+ boundaries.unite(marker->markerBoundaries(marker->markerTransformation(m_markerPositions[i].origin, m_markerPositions[i].angle, strokeWidth))); |
+ } |
+ return boundaries; |
} |
void RenderSVGShape::updateCachedBoundaries() |
@@ -446,15 +469,33 @@ |
void RenderSVGShape::inflateWithStrokeAndMarkerBounds() |
{ |
const SVGRenderStyle* svgStyle = style()->svgStyle(); |
- FloatRect strokeRect; |
if (svgStyle->hasStroke()) { |
BoundingRectStrokeStyleApplier strokeStyle(this, style()); |
m_strokeAndMarkerBoundingBox.unite(path().strokeBoundingRect(&strokeStyle)); |
} |
- if (svgStyle->hasMarkers()) { |
- FloatRect markerBounds = calculateMarkerBoundsIfNeeded(); |
- if (!markerBounds.isEmpty()) |
- m_strokeAndMarkerBoundingBox.unite(markerBounds); |
+ if (!m_markerPositions.isEmpty()) |
+ m_strokeAndMarkerBoundingBox.unite(markerRect(strokeWidth())); |
+} |
+ |
+void RenderSVGShape::drawMarkers(PaintInfo& paintInfo) |
+{ |
+ ASSERT(!m_markerPositions.isEmpty()); |
+ |
+ SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this); |
+ if (!resources) |
+ return; |
+ |
+ RenderSVGResourceMarker* markerStart = resources->markerStart(); |
+ RenderSVGResourceMarker* markerMid = resources->markerMid(); |
+ RenderSVGResourceMarker* markerEnd = resources->markerEnd(); |
+ if (!markerStart && !markerMid && !markerEnd) |
+ return; |
+ |
+ float strokeWidth = this->strokeWidth(); |
+ unsigned size = m_markerPositions.size(); |
+ for (unsigned i = 0; i < size; ++i) { |
+ if (RenderSVGResourceMarker* marker = markerForType(m_markerPositions[i].type, markerStart, markerMid, markerEnd)) |
+ marker->draw(paintInfo, marker->markerTransformation(m_markerPositions[i].origin, m_markerPositions[i].angle, strokeWidth)); |
} |
} |
@@ -473,6 +514,20 @@ |
subpathData.pathIsDone(); |
} |
+void RenderSVGShape::processMarkerPositions() |
+{ |
+ m_markerPositions.clear(); |
+ |
+ if (!shouldGenerateMarkerPositions()) |
+ return; |
+ |
+ ASSERT(m_path); |
+ |
+ SVGMarkerData markerData(m_markerPositions); |
+ m_path->apply(&markerData, SVGMarkerData::updateFromPathElement); |
+ markerData.pathIsDone(); |
} |
+} |
+ |
#endif // ENABLE(SVG) |