summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfmalita <fmalita@chromium.org>2016-01-25 15:16:47 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-25 23:17:33 +0000
commit7003bed16de3861e47d6bb0287ba4d6bffcfea04 (patch)
tree2f17cb95c20e25d50a7b32c33d434f5062a268b6
parentbf571b6dcf58bd8a28fdd5e15b4428e5c2a0b44f (diff)
downloadchromium_src-7003bed16de3861e47d6bb0287ba4d6bffcfea04.zip
chromium_src-7003bed16de3861e47d6bb0287ba4d6bffcfea04.tar.gz
chromium_src-7003bed16de3861e47d6bb0287ba4d6bffcfea04.tar.bz2
[SVG] Paint unnormalized paths
The SkPath API supports all SVG path verbs, so there's no need to normalize paths when converting to the Skia representation. Switch buildPathFromString() and buildPathFromByteStream() to unaltered parsing, and expand SVGPathBuilder to handle the full path vocabulary. This yields a more natural verb conversion (arcTo, in particular, is no longer decomposed into cubics), with correctness and perf implications. BUG=453040 R=fs@opera.com,caryclark@google.com Review URL: https://codereview.chromium.org/1623073003 Cr-Commit-Position: refs/heads/master@{#371345}
-rw-r--r--third_party/WebKit/LayoutTests/TestExpectations29
-rw-r--r--third_party/WebKit/Source/core/layout/svg/SVGMarkerData.h3
-rw-r--r--third_party/WebKit/Source/core/svg/SVGPathBuilder.cpp177
-rw-r--r--third_party/WebKit/Source/core/svg/SVGPathBuilder.h25
-rw-r--r--third_party/WebKit/Source/core/svg/SVGPathUtilities.cpp4
-rw-r--r--third_party/WebKit/Source/platform/graphics/Path.cpp10
-rw-r--r--third_party/WebKit/Source/platform/graphics/Path.h1
7 files changed, 235 insertions, 14 deletions
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 8b501ae..e747e0e 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -131,7 +131,8 @@ crbug.com/463358 [ Mac Linux Debug ] fast/backgrounds/transformed-body-html-back
crbug.com/463358 [ Mac Linux Debug ] css3/masking/clip-path-polygon-nonzero.html [ Failure ]
crbug.com/463358 [ Mac Linux ] fast/transforms/transformed-caret.html [ Pass Failure ]
crbug.com/463358 [ Mac Linux Debug ] fast/backgrounds/transformed-body-background.html [ Failure ]
-crbug.com/463358 [ Mac Linux Debug ] svg/W3C-SVG-1.1/paths-data-02-t.svg [ Failure ]
+# TODO(fmalita): Re-enable after https://codereview.chromium.org/1623073003/
+# crbug.com/463358 [ Mac Linux Debug ] svg/W3C-SVG-1.1/paths-data-02-t.svg [ Failure ]
crbug.com/463358 [ Mac Linux Debug ] css3/masking/clip-path-polygon.html [ Failure ]
crbug.com/267206 [ Mac ] virtual/rootlayerscrolls/fast/scrolling/scrollbar-tickmarks-hittest.html [ Timeout ]
@@ -1250,8 +1251,6 @@ crbug.com/521730 [ Win10 ] media/track/track-cue-rendering-vertical.html [ Failu
crbug.com/521730 [ Win10 ] fast/css/line-height-determined-by-primary-font.html [ Failure ]
crbug.com/521730 [ Win10 ] fast/forms/month/month-appearance-l10n.html [ Failure ]
crbug.com/521730 [ Win10 ] fast/forms/month/month-appearance-pseudo-elements.html [ Failure ]
-# TODO(fmalita): re-enable after http://crrev.com/1410733003
-# crbug.com/521730 [ Win10 ] fast/forms/search/search-appearance-basic.html [ Failure ]
crbug.com/521730 [ Win10 ] fast/inline/justify-emphasis-inline-box.html [ Failure ]
crbug.com/521730 [ Win10 ] fast/ruby/nested-ruby.html [ Failure ]
crbug.com/521730 [ Win10 ] fast/text-autosizing/display-type-change.html [ Failure ]
@@ -1442,7 +1441,6 @@ crbug.com/568778 [ XP ] media/video-overlay-cast-light-rendering.html [ Failure
crbug.com/568778 [ XP ] media/video-transformed.html [ Failure ]
crbug.com/568778 [ XP ] svg/wicd/test-rightsizing-a.xhtml [ Failure ]
crbug.com/568778 [ XP ] svg/zoom/page/zoom-hixie-mixed-009.xml [ Failure ]
-crbug.com/568778 [ XP ] svg/zoom/page/zoom-img-preserveAspectRatio-support-1.html [ Failure ]
crbug.com/568778 [ XP ] svg/zoom/page/zoom-replaced-intrinsic-ratio-001.htm [ Failure ]
crbug.com/568778 [ XP ] svg/zoom/page/zoom-svg-through-object-with-auto-size.html [ Failure ]
crbug.com/568778 [ XP ] svg/zoom/page/zoom-svg-through-object-with-huge-size.xhtml [ Failure ]
@@ -1553,6 +1551,29 @@ crbug.com/568559 [ Android Linux Win ] fast/text/international/bidi-menulist.htm
crbug.com/568559 [ Android Linux Win ] fast/text/international/pop-up-button-text-alignment-and-direction.html [ NeedsRebaseline ]
crbug.com/568559 [ Android Linux Win ] fast/forms/select-popup/popup-menu-appearance-texttransform.html [ NeedsRebaseline ]
+# https://codereview.chromium.org/1623073003/
+crbug.com/453040 svg/W3C-SVG-1.1/animate-elem-37-t.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/W3C-SVG-1.1/animate-elem-40-t.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/W3C-SVG-1.1/animate-elem-83-t.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/W3C-SVG-1.1/coords-viewattr-03-b.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/W3C-SVG-1.1/extend-namespace-01-f.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/W3C-SVG-1.1/fonts-elem-03-b.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/W3C-SVG-1.1/fonts-elem-04-b.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/W3C-SVG-1.1/fonts-elem-07-b.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/W3C-SVG-1.1/painting-marker-03-f.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/W3C-SVG-1.1/paths-data-02-t.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/W3C-SVG-1.1/paths-data-03-f.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/as-background-image/background-image-preserveaspectRatio-support.html [ NeedsRebaseline ]
+crbug.com/453040 svg/as-background-image/svg-as-background-6.html [ NeedsRebaseline ]
+crbug.com/453040 svg/as-image/img-preserveAspectRatio-support-1.html [ NeedsRebaseline ]
+crbug.com/453040 svg/carto.net/tabgroup.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/custom/control-points-for-S-and-T.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/custom/relative-sized-inner-svg.xhtml [ NeedsRebaseline ]
+crbug.com/453040 svg/custom/relative-sized-use-on-symbol.xhtml [ NeedsRebaseline ]
+crbug.com/453040 svg/custom/relative-sized-use-without-attributes-on-symbol.xhtml [ NeedsRebaseline ]
+crbug.com/453040 svg/custom/use-on-symbol-inside-pattern.svg [ NeedsRebaseline ]
+crbug.com/453040 svg/zoom/page/zoom-img-preserveAspectRatio-support-1.html [ NeedsRebaseline ]
+
crbug.com/569950 svg/batik/filters/feTile.svg [ NeedsRebaseline ]
crbug.com/569950 svg/filters/feTile.svg [ NeedsRebaseline ]
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGMarkerData.h b/third_party/WebKit/Source/core/layout/svg/SVGMarkerData.h
index 878c45b..5dec45f 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGMarkerData.h
+++ b/third_party/WebKit/Source/core/layout/svg/SVGMarkerData.h
@@ -137,7 +137,8 @@ private:
switch (element->type) {
case PathElementAddQuadCurveToPoint:
- // FIXME: https://bugs.webkit.org/show_bug.cgi?id=33115 (PathElementAddQuadCurveToPoint not handled for <marker>)
+ m_inslopePoints[0] = points[0];
+ m_inslopePoints[1] = points[1];
m_origin = points[1];
break;
case PathElementAddCurveToPoint:
diff --git a/third_party/WebKit/Source/core/svg/SVGPathBuilder.cpp b/third_party/WebKit/Source/core/svg/SVGPathBuilder.cpp
index 32e47dd..0fcd338 100644
--- a/third_party/WebKit/Source/core/svg/SVGPathBuilder.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGPathBuilder.cpp
@@ -23,29 +23,194 @@
#include "core/svg/SVGPathBuilder.h"
-#include "core/svg/SVGPathData.h"
#include "platform/graphics/Path.h"
namespace blink {
+FloatPoint SVGPathBuilder::smoothControl(bool isCompatibleSegment) const
+{
+ // The control point is assumed to be the reflection of the control point on
+ // the previous command relative to the current point. If there is no previous
+ // command or if the previous command was not a [quad/cubic], assume the control
+ // point is coincident with the current point.
+ // [https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands]
+ // [https://www.w3.org/TR/SVG/paths.html#PathDataQuadraticBezierCommands]
+ FloatPoint controlPoint = m_currentPoint;
+ if (isCompatibleSegment)
+ controlPoint += m_currentPoint - m_lastControlPoint;
+
+ return controlPoint;
+}
+
+void SVGPathBuilder::emitClose()
+{
+ m_path.closeSubpath();
+
+ // At the end of the [closepath] command, the new current
+ // point is set to the initial point of the current subpath.
+ // [https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand]
+ m_currentPoint = m_subpathPoint;
+}
+
+void SVGPathBuilder::emitMoveTo(const FloatPoint& p)
+{
+ m_path.moveTo(p);
+
+ // If a "closepath" is followed immediately by a "moveto", then
+ // the "moveto" identifies the start point of the next subpath.
+ // [https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand]
+ if (m_lastCommand == PathSegClosePath)
+ m_subpathPoint = p;
+
+ m_currentPoint = p;
+}
+
+void SVGPathBuilder::emitLineTo(const FloatPoint& p)
+{
+ m_path.addLineTo(p);
+ m_currentPoint = p;
+}
+
+void SVGPathBuilder::emitQuadTo(const FloatPoint& c0, const FloatPoint& p)
+{
+ m_path.addQuadCurveTo(c0, p);
+ m_lastControlPoint = c0;
+ m_currentPoint = p;
+}
+
+void SVGPathBuilder::emitSmoothQuadTo(const FloatPoint& p)
+{
+ bool lastWasQuadratic = m_lastCommand == PathSegCurveToQuadraticAbs
+ || m_lastCommand == PathSegCurveToQuadraticRel
+ || m_lastCommand == PathSegCurveToQuadraticSmoothAbs
+ || m_lastCommand == PathSegCurveToQuadraticSmoothRel;
+
+ emitQuadTo(smoothControl(lastWasQuadratic), p);
+}
+
+void SVGPathBuilder::emitCubicTo(const FloatPoint& c0, const FloatPoint& c1, const FloatPoint& p)
+{
+ m_path.addBezierCurveTo(c0, c1, p);
+ m_lastControlPoint = c1;
+ m_currentPoint = p;
+}
+
+void SVGPathBuilder::emitSmoothCubicTo(const FloatPoint& c1, const FloatPoint& p)
+{
+ bool lastWasCubic = m_lastCommand == PathSegCurveToCubicAbs
+ || m_lastCommand == PathSegCurveToCubicRel
+ || m_lastCommand == PathSegCurveToCubicSmoothAbs
+ || m_lastCommand == PathSegCurveToCubicSmoothRel;
+
+ emitCubicTo(smoothControl(lastWasCubic), c1, p);
+}
+
+void SVGPathBuilder::emitArcTo(const FloatPoint& p, const FloatSize& r, float rotate,
+ bool largeArc, bool sweep)
+{
+ m_path.addArcTo(p, r, rotate, largeArc, sweep);
+ m_currentPoint = p;
+}
+
void SVGPathBuilder::emitSegment(const PathSegmentData& segment)
{
switch (segment.command) {
+ case PathSegClosePath:
+ emitClose();
+ break;
case PathSegMoveToAbs:
- m_path.moveTo(segment.targetPoint);
+ emitMoveTo(
+ segment.targetPoint);
+ break;
+ case PathSegMoveToRel:
+ emitMoveTo(
+ m_currentPoint + segment.targetPoint);
break;
case PathSegLineToAbs:
- m_path.addLineTo(segment.targetPoint);
+ emitLineTo(
+ segment.targetPoint);
break;
- case PathSegClosePath:
- m_path.closeSubpath();
+ case PathSegLineToRel:
+ emitLineTo(
+ m_currentPoint + segment.targetPoint);
+ break;
+ case PathSegLineToHorizontalAbs:
+ emitLineTo(
+ FloatPoint(segment.targetPoint.x(), m_currentPoint.y()));
+ break;
+ case PathSegLineToHorizontalRel:
+ emitLineTo(
+ m_currentPoint + FloatSize(segment.targetPoint.x(), 0));
+ break;
+ case PathSegLineToVerticalAbs:
+ emitLineTo(
+ FloatPoint(m_currentPoint.x(), segment.targetPoint.y()));
+ break;
+ case PathSegLineToVerticalRel:
+ emitLineTo(
+ m_currentPoint + FloatSize(0, segment.targetPoint.y()));
+ break;
+ case PathSegCurveToQuadraticAbs:
+ emitQuadTo(
+ segment.point1,
+ segment.targetPoint);
+ break;
+ case PathSegCurveToQuadraticRel:
+ emitQuadTo(
+ m_currentPoint + segment.point1,
+ m_currentPoint + segment.targetPoint);
+ break;
+ case PathSegCurveToQuadraticSmoothAbs:
+ emitSmoothQuadTo(
+ segment.targetPoint);
+ break;
+ case PathSegCurveToQuadraticSmoothRel:
+ emitSmoothQuadTo(
+ m_currentPoint + segment.targetPoint);
break;
case PathSegCurveToCubicAbs:
- m_path.addBezierCurveTo(segment.point1, segment.point2, segment.targetPoint);
+ emitCubicTo(
+ segment.point1,
+ segment.point2,
+ segment.targetPoint);
+ break;
+ case PathSegCurveToCubicRel:
+ emitCubicTo(
+ m_currentPoint + segment.point1,
+ m_currentPoint + segment.point2,
+ m_currentPoint + segment.targetPoint);
+ break;
+ case PathSegCurveToCubicSmoothAbs:
+ emitSmoothCubicTo(
+ segment.point2,
+ segment.targetPoint);
+ break;
+ case PathSegCurveToCubicSmoothRel:
+ emitSmoothCubicTo(
+ m_currentPoint + segment.point2,
+ m_currentPoint + segment.targetPoint);
+ break;
+ case PathSegArcAbs:
+ emitArcTo(
+ segment.targetPoint,
+ toFloatSize(segment.arcRadii()),
+ segment.arcAngle(),
+ segment.largeArcFlag(),
+ segment.sweepFlag());
+ break;
+ case PathSegArcRel:
+ emitArcTo(
+ m_currentPoint + segment.targetPoint,
+ toFloatSize(segment.arcRadii()),
+ segment.arcAngle(),
+ segment.largeArcFlag(),
+ segment.sweepFlag());
break;
default:
ASSERT_NOT_REACHED();
}
+
+ m_lastCommand = segment.command;
}
} // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGPathBuilder.h b/third_party/WebKit/Source/core/svg/SVGPathBuilder.h
index 6cbe279..522bee4 100644
--- a/third_party/WebKit/Source/core/svg/SVGPathBuilder.h
+++ b/third_party/WebKit/Source/core/svg/SVGPathBuilder.h
@@ -25,19 +25,42 @@
#define SVGPathBuilder_h
#include "core/svg/SVGPathConsumer.h"
+#include "core/svg/SVGPathData.h"
+#include "platform/geometry/FloatPoint.h"
namespace blink {
+class FloatSize;
class Path;
class SVGPathBuilder final : public SVGPathConsumer {
public:
- SVGPathBuilder(Path& path) : m_path(path) { }
+ SVGPathBuilder(Path& path)
+ : m_path(path)
+ // Starting in ClosePath state ensures correct handling of the first moveTo.
+ , m_lastCommand(PathSegClosePath)
+ { }
private:
void emitSegment(const PathSegmentData&) override;
+ void emitClose();
+ void emitMoveTo(const FloatPoint&);
+ void emitLineTo(const FloatPoint&);
+ void emitQuadTo(const FloatPoint&, const FloatPoint&);
+ void emitSmoothQuadTo(const FloatPoint&);
+ void emitCubicTo(const FloatPoint&, const FloatPoint&, const FloatPoint&);
+ void emitSmoothCubicTo(const FloatPoint&, const FloatPoint&);
+ void emitArcTo(const FloatPoint&, const FloatSize&, float, bool largeArc, bool sweep);
+
+ FloatPoint smoothControl(bool isSmooth) const;
+
Path& m_path;
+
+ SVGPathSegType m_lastCommand;
+ FloatPoint m_subpathPoint;
+ FloatPoint m_currentPoint;
+ FloatPoint m_lastControlPoint;
};
} // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGPathUtilities.cpp b/third_party/WebKit/Source/core/svg/SVGPathUtilities.cpp
index a4b9ddb..259bf0e 100644
--- a/third_party/WebKit/Source/core/svg/SVGPathUtilities.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGPathUtilities.cpp
@@ -36,7 +36,7 @@ bool buildPathFromString(const String& d, Path& result)
SVGPathBuilder builder(result);
SVGPathStringSource source(d);
SVGPathParser parser(&source, &builder);
- return parser.parsePathDataFromSource(NormalizedParsing);
+ return parser.parsePathDataFromSource(UnalteredParsing);
}
bool buildPathFromByteStream(const SVGPathByteStream& stream, Path& result)
@@ -47,7 +47,7 @@ bool buildPathFromByteStream(const SVGPathByteStream& stream, Path& result)
SVGPathBuilder builder(result);
SVGPathByteStreamSource source(stream);
SVGPathParser parser(&source, &builder);
- return parser.parsePathDataFromSource(NormalizedParsing);
+ return parser.parsePathDataFromSource(UnalteredParsing);
}
String buildStringFromByteStream(const SVGPathByteStream& stream)
diff --git a/third_party/WebKit/Source/platform/graphics/Path.cpp b/third_party/WebKit/Source/platform/graphics/Path.cpp
index c54308e..f18b2f2 100644
--- a/third_party/WebKit/Source/platform/graphics/Path.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Path.cpp
@@ -331,6 +331,16 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
m_path.arcTo(p1.data(), p2.data(), WebCoreFloatToSkScalar(radius));
}
+void Path::addArcTo(const FloatPoint& p, const FloatSize& r, float xRotate, bool largeArc, bool sweep)
+{
+ m_path.arcTo(
+ WebCoreFloatToSkScalar(r.width()), WebCoreFloatToSkScalar(r.height()),
+ WebCoreFloatToSkScalar(xRotate),
+ largeArc ? SkPath::kLarge_ArcSize : SkPath::kSmall_ArcSize,
+ sweep ? SkPath::kCW_Direction : SkPath::kCCW_Direction,
+ WebCoreFloatToSkScalar(p.x()), WebCoreFloatToSkScalar(p.y()));
+}
+
void Path::closeSubpath()
{
m_path.close();
diff --git a/third_party/WebKit/Source/platform/graphics/Path.h b/third_party/WebKit/Source/platform/graphics/Path.h
index f2a4f72..c46b5ac 100644
--- a/third_party/WebKit/Source/platform/graphics/Path.h
+++ b/third_party/WebKit/Source/platform/graphics/Path.h
@@ -122,6 +122,7 @@ public:
void addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& endPoint);
void addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& endPoint);
void addArcTo(const FloatPoint&, const FloatPoint&, float radius);
+ void addArcTo(const FloatPoint&, const FloatSize& r, float xRotate, bool largeArc, bool sweep);
void closeSubpath();
void addArc(const FloatPoint&, float radius, float startAngle, float endAngle, bool anticlockwise);