summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/svg
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-07-18 13:59:13 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-07-18 13:59:28 +0200
commit4d6084feccab99c0a7b3ecef26bb49c41dd50201 (patch)
treefd1195897f551eee6d5a15d07ff5733b15aa2a5c /Source/WebCore/rendering/svg
parentae901828d4689ab9e89113f6b6ea8042b37a9fda (diff)
downloadqtwebkit-4d6084feccab99c0a7b3ecef26bb49c41dd50201.tar.gz
Imported WebKit commit ff52235a78888e5cb8e286a828a8698042200e67 (http://svn.webkit.org/repository/webkit/trunk@122948)
New snapshot that should fix the rendering issues recently introduced
Diffstat (limited to 'Source/WebCore/rendering/svg')
-rwxr-xr-xSource/WebCore/rendering/svg/RenderSVGPath.cpp118
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGPath.h13
-rwxr-xr-xSource/WebCore/rendering/svg/RenderSVGShape.cpp131
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGShape.h21
4 files changed, 165 insertions, 118 deletions
diff --git a/Source/WebCore/rendering/svg/RenderSVGPath.cpp b/Source/WebCore/rendering/svg/RenderSVGPath.cpp
index edad43945..cf658359d 100755
--- a/Source/WebCore/rendering/svg/RenderSVGPath.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGPath.cpp
@@ -32,6 +32,7 @@
#include "SVGPathElement.h"
#include "SVGStyledTransformableElement.h"
+#include "SVGSubpathData.h"
namespace WebCore {
@@ -44,6 +45,123 @@ RenderSVGPath::~RenderSVGPath()
{
}
+void RenderSVGPath::updateShapeFromElement()
+{
+ RenderSVGShape::updateShapeFromElement();
+ updateZeroLengthSubpaths();
+
+ m_strokeBoundingBox = calculateUpdatedStrokeBoundingBox();
+}
+
+FloatRect RenderSVGPath::calculateUpdatedStrokeBoundingBox() const
+{
+ FloatRect strokeBoundingBox = m_strokeBoundingBox;
+
+ if (style()->svgStyle()->hasStroke()) {
+ // FIXME: zero-length subpaths do not respect vector-effect = non-scaling-stroke.
+ float strokeWidth = this->strokeWidth();
+ for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i)
+ strokeBoundingBox.unite(zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeWidth));
+ }
+
+ 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(), context->strokeColorSpace());
+}
+
+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))
+ return true;
+
+ const SVGRenderStyle* svgStyle = style()->svgStyle();
+ for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) {
+ ASSERT(svgStyle->hasStroke());
+ float strokeWidth = this->strokeWidth();
+ if (svgStyle->capStyle() == SquareCap) {
+ if (zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeWidth).contains(point))
+ return true;
+ } else {
+ ASSERT(svgStyle->capStyle() == RoundCap);
+ FloatPoint radiusVector(point.x() - m_zeroLengthLinecapLocations[i].x(), point.y() - m_zeroLengthLinecapLocations[i].y());
+ if (radiusVector.lengthSquared() < strokeWidth * strokeWidth * .25f)
+ return true;
+ }
+ }
+ return false;
+}
+
+bool RenderSVGPath::shouldStrokeZeroLengthSubpath() const
+{
+ // Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-linecap" property has a value of butt
+ // but shall be stroked if the "stroke-linecap" property has a value of round or square
+ return style()->svgStyle()->hasStroke() && style()->svgStyle()->capStyle() != ButtCap;
+}
+
+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
+{
+ return FloatRect(linecapPosition.x() - strokeWidth / 2, linecapPosition.y() - strokeWidth / 2, strokeWidth, strokeWidth);
+}
+
+void RenderSVGPath::updateZeroLengthSubpaths()
+{
+ m_zeroLengthLinecapLocations.clear();
+
+ if (!strokeWidth() || !shouldStrokeZeroLengthSubpath())
+ return;
+
+ SVGSubpathData subpathData(m_zeroLengthLinecapLocations);
+ path().apply(&subpathData, SVGSubpathData::updateFromPathElement);
+ subpathData.pathIsDone();
+}
+
}
#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGPath.h b/Source/WebCore/rendering/svg/RenderSVGPath.h
index 77e99e5be..ab1cf1c0b 100644
--- a/Source/WebCore/rendering/svg/RenderSVGPath.h
+++ b/Source/WebCore/rendering/svg/RenderSVGPath.h
@@ -39,6 +39,19 @@ public:
private:
virtual bool isSVGPath() const { return true; }
virtual const char* renderName() const { return "RenderSVGPath"; }
+
+ virtual void updateShapeFromElement() OVERRIDE;
+ FloatRect calculateUpdatedStrokeBoundingBox() const;
+
+ virtual void strokeShape(GraphicsContext*) const OVERRIDE;
+ virtual bool shapeDependentStrokeContains(const FloatPoint&) OVERRIDE;
+
+ bool shouldStrokeZeroLengthSubpath() const;
+ Path* zeroLengthLinecapPath(const FloatPoint&) const;
+ FloatRect zeroLengthSubpathRect(const FloatPoint&, float) const;
+ void updateZeroLengthSubpaths();
+
+ Vector<FloatPoint> m_zeroLengthLinecapLocations;
};
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGShape.cpp b/Source/WebCore/rendering/svg/RenderSVGShape.cpp
index 282c50a0b..62a8c99ba 100755
--- a/Source/WebCore/rendering/svg/RenderSVGShape.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGShape.cpp
@@ -44,7 +44,6 @@
#include "SVGResources.h"
#include "SVGResourcesCache.h"
#include "SVGStyledTransformableElement.h"
-#include "SVGSubpathData.h"
#include "SVGTransformList.h"
#include "SVGURIReference.h"
#include "StrokeStyleApplier.h"
@@ -72,7 +71,6 @@ void RenderSVGShape::updateShapeFromElement()
SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
updatePathFromGraphicsElement(element, path());
- processZeroLengthSubpaths();
processMarkerPositions();
m_fillBoundingBox = calculateObjectBoundingBox();
@@ -91,8 +89,13 @@ void RenderSVGShape::fillShape(GraphicsContext* context) const
void RenderSVGShape::strokeShape(GraphicsContext* context) const
{
- if (style()->svgStyle()->hasVisibleStroke())
- context->strokePath(path());
+ ASSERT(m_path);
+ Path* usePath = m_path.get();
+
+ if (hasNonScalingStroke())
+ usePath = nonScalingStrokePath(usePath, nonScalingStrokeTransform());
+
+ context->strokePath(*usePath);
}
bool RenderSVGShape::shapeDependentStrokeContains(const FloatPoint& point)
@@ -136,20 +139,6 @@ bool RenderSVGShape::strokeContains(const FloatPoint& point, bool requiresStroke
if (requiresStroke && !RenderSVGResource::strokePaintingResource(this, style(), fallbackColor))
return false;
- for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) {
- ASSERT(style()->svgStyle()->hasStroke());
- float strokeWidth = this->strokeWidth();
- if (style()->svgStyle()->capStyle() == SquareCap) {
- if (zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeWidth).contains(point))
- return true;
- } else {
- ASSERT(style()->svgStyle()->capStyle() == RoundCap);
- FloatPoint radiusVector(point.x() - m_zeroLengthLinecapLocations[i].x(), point.y() - m_zeroLengthLinecapLocations[i].y());
- if (radiusVector.lengthSquared() < strokeWidth * strokeWidth * .25f)
- return true;
- }
- }
-
return shapeDependentStrokeContains(point);
}
@@ -212,13 +201,6 @@ AffineTransform RenderSVGShape::nonScalingStrokeTransform() const
return element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
}
-bool RenderSVGShape::shouldStrokeZeroLengthSubpath() const
-{
- // Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-linecap" property has a value of butt
- // but shall be stroked if the "stroke-linecap" property has a value of round or square
- return style()->svgStyle()->hasStroke() && style()->svgStyle()->capStyle() != ButtCap;
-}
-
bool RenderSVGShape::shouldGenerateMarkerPositions() const
{
if (!style()->svgStyle()->hasMarkers())
@@ -235,94 +217,55 @@ bool RenderSVGShape::shouldGenerateMarkerPositions() const
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);
-}
-
-Path* RenderSVGShape::zeroLengthLinecapPath(const FloatPoint& linecapPosition)
-{
- // Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-linecap" property has a value of butt
- // but shall be stroked if the "stroke-linecap" property has a value of round or square
- DEFINE_STATIC_LOCAL(Path, tempPath, ());
-
- tempPath.clear();
- float strokeWidth = this->strokeWidth();
- if (style()->svgStyle()->capStyle() == SquareCap)
- tempPath.addRect(zeroLengthSubpathRect(linecapPosition, strokeWidth));
- else
- tempPath.addEllipse(zeroLengthSubpathRect(linecapPosition, strokeWidth));
-
- return &tempPath;
-}
-
-void RenderSVGShape::fillShape(RenderStyle* style, GraphicsContext* context, Path* path, RenderSVGShape* shape)
+void RenderSVGShape::fillShape(RenderStyle* style, GraphicsContext* context)
{
Color fallbackColor;
if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(this, style, fallbackColor)) {
if (fillPaintingResource->applyResource(this, style, context, ApplyToFillMode))
- fillPaintingResource->postApplyResource(this, context, ApplyToFillMode, path, shape);
+ fillPaintingResource->postApplyResource(this, context, ApplyToFillMode, 0, this);
else if (fallbackColor.isValid()) {
RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
fallbackResource->setColor(fallbackColor);
if (fallbackResource->applyResource(this, style, context, ApplyToFillMode))
- fallbackResource->postApplyResource(this, context, ApplyToFillMode, path, shape);
+ fallbackResource->postApplyResource(this, context, ApplyToFillMode, 0, this);
}
}
}
-void RenderSVGShape::strokePath(RenderStyle* style, GraphicsContext* context, Path* path, RenderSVGResource* strokePaintingResource,
- const Color& fallbackColor, int applyMode)
+void RenderSVGShape::strokeShape(RenderStyle* style, GraphicsContext* context)
{
- if (!style->svgStyle()->hasVisibleStroke())
- return;
-
- if (strokePaintingResource->applyResource(this, style, context, applyMode)) {
- strokePaintingResource->postApplyResource(this, context, applyMode, path, this);
- return;
+ Color fallbackColor;
+ if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(this, style, fallbackColor)) {
+ if (strokePaintingResource->applyResource(this, style, context, ApplyToStrokeMode))
+ strokePaintingResource->postApplyResource(this, context, ApplyToStrokeMode, 0, this);
+ else if (fallbackColor.isValid()) {
+ RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
+ fallbackResource->setColor(fallbackColor);
+ if (fallbackResource->applyResource(this, style, context, ApplyToStrokeMode))
+ fallbackResource->postApplyResource(this, context, ApplyToStrokeMode, 0, this);
+ }
}
-
- if (!fallbackColor.isValid())
- return;
-
- RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
- fallbackResource->setColor(fallbackColor);
- if (fallbackResource->applyResource(this, style, context, applyMode))
- fallbackResource->postApplyResource(this, context, applyMode, path, this);
}
-void RenderSVGShape::fillAndStrokePath(GraphicsContext* context)
+void RenderSVGShape::fillAndStrokeShape(GraphicsContext* context)
{
RenderStyle* style = this->style();
- fillShape(style, context, 0, this);
+ fillShape(style, context);
- Color fallbackColor = Color();
- RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(this, style, fallbackColor);
- if (!strokePaintingResource)
+ if (!style->svgStyle()->hasVisibleStroke())
return;
- Path* usePath = m_path.get();
GraphicsContextStateSaver stateSaver(*context, false);
AffineTransform nonScalingTransform;
if (hasNonScalingStroke()) {
- nonScalingTransform = nonScalingStrokeTransform();
+ AffineTransform nonScalingTransform = nonScalingStrokeTransform();
if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
return;
- usePath = nonScalingStrokePath(usePath, nonScalingTransform);
}
- strokePath(style, context, usePath, strokePaintingResource, fallbackColor, ApplyToStrokeMode);
-
- // Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-linecap" property has a value of butt
- // but shall be stroked if the "stroke-linecap" property has a value of round or square
- for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) {
- Path* usePath = zeroLengthLinecapPath(m_zeroLengthLinecapLocations[i]);
- if (hasNonScalingStroke())
- usePath = nonScalingStrokePath(usePath, nonScalingTransform);
- strokePath(style, context, usePath, strokePaintingResource, fallbackColor, ApplyToFillMode);
- }
+ strokeShape(style, context);
}
void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&)
@@ -347,7 +290,7 @@ void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&)
if (svgStyle->shapeRendering() == SR_CRISPEDGES)
childPaintInfo.context->setShouldAntialias(false);
- fillAndStrokePath(childPaintInfo.context);
+ fillAndStrokeShape(childPaintInfo.context);
if (!m_markerPositions.isEmpty())
drawMarkers(childPaintInfo);
}
@@ -453,11 +396,6 @@ FloatRect RenderSVGShape::calculateStrokeBoundingBox() const
}
} else
strokeBoundingBox.unite(path().strokeBoundingRect(&strokeStyle));
-
- // FIXME: zero-length subpaths do not respect vector-effect = non-scaling-stroke.
- float strokeWidth = this->strokeWidth();
- for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i)
- strokeBoundingBox.unite(zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeWidth));
}
if (!m_markerPositions.isEmpty())
@@ -510,21 +448,6 @@ void RenderSVGShape::drawMarkers(PaintInfo& paintInfo)
}
}
-void RenderSVGShape::processZeroLengthSubpaths()
-{
- m_zeroLengthLinecapLocations.clear();
-
- float strokeWidth = this->strokeWidth();
- if (!strokeWidth || !shouldStrokeZeroLengthSubpath())
- return;
-
- ASSERT(m_path);
-
- SVGSubpathData subpathData(m_zeroLengthLinecapLocations);
- m_path->apply(&subpathData, SVGSubpathData::updateFromPathElement);
- subpathData.pathIsDone();
-}
-
void RenderSVGShape::processMarkerPositions()
{
m_markerPositions.clear();
diff --git a/Source/WebCore/rendering/svg/RenderSVGShape.h b/Source/WebCore/rendering/svg/RenderSVGShape.h
index 81c6b370c..4796e8c31 100644
--- a/Source/WebCore/rendering/svg/RenderSVGShape.h
+++ b/Source/WebCore/rendering/svg/RenderSVGShape.h
@@ -89,9 +89,12 @@ protected:
virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
float strokeWidth() const;
bool hasPath() const { return m_path.get(); }
- bool hasNonScalingStroke() const { return style()->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE; }
bool hasSmoothStroke() const;
+ bool hasNonScalingStroke() const { return style()->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE; }
+ AffineTransform nonScalingStrokeTransform() const;
+ Path* nonScalingStrokePath(const Path*, const AffineTransform&) const;
+
FloatRect m_fillBoundingBox;
FloatRect m_strokeBoundingBox;
@@ -115,35 +118,25 @@ private:
virtual FloatRect objectBoundingBox() const { return m_fillBoundingBox; }
virtual FloatRect strokeBoundingBox() const { return m_strokeBoundingBox; }
-
FloatRect calculateObjectBoundingBox() const;
FloatRect calculateStrokeBoundingBox() const;
void updateRepaintBoundingBox();
- AffineTransform nonScalingStrokeTransform() const;
bool setupNonScalingStrokeContext(AffineTransform&, GraphicsContextStateSaver&);
- Path* nonScalingStrokePath(const Path*, const AffineTransform&) const;
-
- Path* zeroLengthLinecapPath(const FloatPoint&);
- bool shouldStrokeZeroLengthSubpath() const;
- FloatRect zeroLengthSubpathRect(const FloatPoint&, float) const;
- void processZeroLengthSubpaths();
bool shouldGenerateMarkerPositions() const;
FloatRect markerRect(float strokeWidth) const;
void processMarkerPositions();
- void fillShape(RenderStyle*, GraphicsContext*, Path*, RenderSVGShape*);
- void strokePath(RenderStyle*, GraphicsContext*, Path*, RenderSVGResource*,
- const Color&, int);
- void fillAndStrokePath(GraphicsContext*);
+ void fillShape(RenderStyle*, GraphicsContext*);
+ void strokeShape(RenderStyle*, GraphicsContext*);
+ void fillAndStrokeShape(GraphicsContext*);
void drawMarkers(PaintInfo&);
private:
FloatRect m_repaintBoundingBox;
AffineTransform m_localTransform;
OwnPtr<Path> m_path;
- Vector<FloatPoint> m_zeroLengthLinecapLocations;
Vector<MarkerPosition> m_markerPositions;
bool m_needsBoundariesUpdate : 1;