diff options
Diffstat (limited to 'third_party/WebKit/Source')
6 files changed, 210 insertions, 10 deletions
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); |