Chromium Code Reviews| 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; |
| } |
| } |