Index: third_party/WebKit/Source/core/svg/SVGPathBuilder.cpp |
diff --git a/third_party/WebKit/Source/core/svg/SVGPathBuilder.cpp b/third_party/WebKit/Source/core/svg/SVGPathBuilder.cpp |
index acbce1d157bfbfd9be74f0a519449046e57aff21..5bfc63ba4f6c42ac6eba0b42accc7762401c1655 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 isSmooth) const |
fs
2016/01/25 19:17:40
isSmooth -> isCompatibleSegment or something? (To
f(malita)
2016/01/25 19:37:06
Done.
|
+{ |
+ // 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 (isSmooth) |
+ 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_initialPoint; |
+} |
+ |
+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_initialPoint = 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 isSmooth = m_lastCommand == PathSegCurveToQuadraticAbs |
fs
2016/01/25 19:17:40
isSmooth -> isQuadratic/lastWasQuadratic per above
f(malita)
2016/01/25 19:37:06
Done.
|
+ || m_lastCommand == PathSegCurveToQuadraticRel |
+ || m_lastCommand == PathSegCurveToQuadraticSmoothAbs |
+ || m_lastCommand == PathSegCurveToQuadraticSmoothRel; |
+ |
+ emitQuadTo(smoothControl(isSmooth), 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 isSmooth = m_lastCommand == PathSegCurveToCubicAbs |
fs
2016/01/25 19:17:40
Analogue to the quad case.
f(malita)
2016/01/25 19:37:06
Done.
|
+ || m_lastCommand == PathSegCurveToCubicRel |
+ || m_lastCommand == PathSegCurveToCubicSmoothAbs |
+ || m_lastCommand == PathSegCurveToCubicSmoothRel; |
+ |
+ emitCubicTo(smoothControl(isSmooth), 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; |
} |
} |