Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1284)

Unified Diff: Source/core/svg/SVGPathParser.cpp

Issue 1023993002: Rework the SVGPathSource interface (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Blender fixups. Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/svg/SVGPathParser.h ('k') | Source/core/svg/SVGPathSeg.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/svg/SVGPathParser.cpp
diff --git a/Source/core/svg/SVGPathParser.cpp b/Source/core/svg/SVGPathParser.cpp
index 859eb7454f115d9426d9722a022437005681226e..fc63a809e00d117e7605c2176e3347b68c9a2e48 100644
--- a/Source/core/svg/SVGPathParser.cpp
+++ b/Source/core/svg/SVGPathParser.cpp
@@ -36,109 +36,85 @@ DEFINE_TRACE(SVGPathParser)
visitor->trace(m_consumer);
}
-void SVGPathParser::parseClosePathSegment()
+bool SVGPathParser::initialCommandIsMoveTo()
{
- // Reset m_currentPoint for the next path.
- if (m_pathParsingMode == NormalizedParsing)
- m_currentPoint = m_subPathPoint;
- m_consumer->closePath();
+ // If the path is empty it is still valid, so return true.
+ if (!m_source->hasMoreData())
+ return true;
+
+ SVGPathSegType command = m_source->peekSegmentType();
+ // Path must start with moveTo.
+ return command == PathSegMoveToAbs || command == PathSegMoveToRel;
}
-bool SVGPathParser::parseMoveToSegment()
+void SVGPathParser::emitMoveToSegment(PathSegmentData& segment)
{
- FloatPoint targetPoint;
- if (!m_source->parseMoveToSegment(targetPoint))
- return false;
-
if (m_pathParsingMode == UnalteredParsing) {
- m_consumer->moveTo(targetPoint, m_mode);
- return true;
+ m_consumer->moveTo(segment.targetPoint, m_mode);
+ return;
}
if (m_mode == RelativeCoordinates)
- m_currentPoint += targetPoint;
+ m_currentPoint += segment.targetPoint;
else
- m_currentPoint = targetPoint;
+ m_currentPoint = segment.targetPoint;
m_subPathPoint = m_currentPoint;
m_consumer->moveTo(m_currentPoint, AbsoluteCoordinates);
- return true;
}
-bool SVGPathParser::parseLineToSegment()
+void SVGPathParser::emitLineToSegment(PathSegmentData& segment)
{
- FloatPoint targetPoint;
- if (!m_source->parseLineToSegment(targetPoint))
- return false;
-
if (m_pathParsingMode == UnalteredParsing) {
- m_consumer->lineTo(targetPoint, m_mode);
- return true;
+ m_consumer->lineTo(segment.targetPoint, m_mode);
+ return;
}
if (m_mode == RelativeCoordinates)
- m_currentPoint += targetPoint;
+ m_currentPoint += segment.targetPoint;
else
- m_currentPoint = targetPoint;
+ m_currentPoint = segment.targetPoint;
m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates);
- return true;
}
-bool SVGPathParser::parseLineToHorizontalSegment()
+void SVGPathParser::emitLineToHorizontalSegment(PathSegmentData& segment)
{
- float toX;
- if (!m_source->parseLineToHorizontalSegment(toX))
- return false;
-
if (m_pathParsingMode == UnalteredParsing) {
- m_consumer->lineToHorizontal(toX, m_mode);
- return true;
+ m_consumer->lineToHorizontal(segment.targetPoint.x(), m_mode);
+ return;
}
if (m_mode == RelativeCoordinates)
- m_currentPoint.move(toX, 0);
+ m_currentPoint += segment.targetPoint;
else
- m_currentPoint.setX(toX);
+ m_currentPoint.setX(segment.targetPoint.x());
m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates);
- return true;
}
-bool SVGPathParser::parseLineToVerticalSegment()
+void SVGPathParser::emitLineToVerticalSegment(PathSegmentData& segment)
{
- float toY;
- if (!m_source->parseLineToVerticalSegment(toY))
- return false;
-
if (m_pathParsingMode == UnalteredParsing) {
- m_consumer->lineToVertical(toY, m_mode);
- return true;
+ m_consumer->lineToVertical(segment.targetPoint.y(), m_mode);
+ return;
}
if (m_mode == RelativeCoordinates)
- m_currentPoint.move(0, toY);
+ m_currentPoint += segment.targetPoint;
else
- m_currentPoint.setY(toY);
+ m_currentPoint.setY(segment.targetPoint.y());
m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates);
- return true;
}
-bool SVGPathParser::parseCurveToCubicSegment()
+void SVGPathParser::emitCurveToCubicSegment(PathSegmentData& segment)
{
- FloatPoint point1;
- FloatPoint point2;
- FloatPoint targetPoint;
- if (!m_source->parseCurveToCubicSegment(point1, point2, targetPoint))
- return false;
-
if (m_pathParsingMode == UnalteredParsing) {
- m_consumer->curveToCubic(point1, point2, targetPoint, m_mode);
- return true;
+ m_consumer->curveToCubic(segment.point1, segment.point2, segment.targetPoint, m_mode);
+ return;
}
if (m_mode == RelativeCoordinates) {
- point1 += m_currentPoint;
- point2 += m_currentPoint;
- targetPoint += m_currentPoint;
+ segment.point1 += m_currentPoint;
+ segment.point2 += m_currentPoint;
+ segment.targetPoint += m_currentPoint;
}
- m_consumer->curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates);
+ m_consumer->curveToCubic(segment.point1, segment.point2, segment.targetPoint, AbsoluteCoordinates);
- m_controlPoint = point2;
- m_currentPoint = targetPoint;
- return true;
+ m_controlPoint = segment.point2;
+ m_currentPoint = segment.targetPoint;
}
static FloatPoint reflectedPoint(const FloatPoint& reflectIn, const FloatPoint& pointToReflect)
@@ -146,16 +122,11 @@ static FloatPoint reflectedPoint(const FloatPoint& reflectIn, const FloatPoint&
return FloatPoint(2 * reflectIn.x() - pointToReflect.x(), 2 * reflectIn.y() - pointToReflect.y());
}
-bool SVGPathParser::parseCurveToCubicSmoothSegment()
+void SVGPathParser::emitCurveToCubicSmoothSegment(PathSegmentData& segment)
{
- FloatPoint point2;
- FloatPoint targetPoint;
- if (!m_source->parseCurveToCubicSmoothSegment(point2, targetPoint))
- return false;
-
if (m_pathParsingMode == UnalteredParsing) {
- m_consumer->curveToCubicSmooth(point2, targetPoint, m_mode);
- return true;
+ m_consumer->curveToCubicSmooth(segment.point2, segment.targetPoint, m_mode);
+ return;
}
if (m_lastCommand != PathSegCurveToCubicAbs
&& m_lastCommand != PathSegCurveToCubicRel
@@ -165,15 +136,14 @@ bool SVGPathParser::parseCurveToCubicSmoothSegment()
FloatPoint point1 = reflectedPoint(m_currentPoint, m_controlPoint);
if (m_mode == RelativeCoordinates) {
- point2 += m_currentPoint;
- targetPoint += m_currentPoint;
+ segment.point2 += m_currentPoint;
+ segment.targetPoint += m_currentPoint;
}
- m_consumer->curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates);
+ m_consumer->curveToCubic(point1, segment.point2, segment.targetPoint, AbsoluteCoordinates);
- m_controlPoint = point2;
- m_currentPoint = targetPoint;
- return true;
+ m_controlPoint = segment.point2;
+ m_currentPoint = segment.targetPoint;
}
// Blend the points with a ratio (1/3):(2/3).
@@ -183,41 +153,31 @@ static FloatPoint blendPoints(const FloatPoint& p1, const FloatPoint& p2)
return FloatPoint((p1.x() + 2 * p2.x()) * oneOverThree, (p1.y() + 2 * p2.y()) * oneOverThree);
}
-bool SVGPathParser::parseCurveToQuadraticSegment()
+void SVGPathParser::emitCurveToQuadraticSegment(PathSegmentData& segment)
{
- FloatPoint point1;
- FloatPoint targetPoint;
- if (!m_source->parseCurveToQuadraticSegment(point1, targetPoint))
- return false;
-
if (m_pathParsingMode == UnalteredParsing) {
- m_consumer->curveToQuadratic(point1, targetPoint, m_mode);
- return true;
+ m_consumer->curveToQuadratic(segment.point1, segment.targetPoint, m_mode);
+ return;
}
- m_controlPoint = point1;
+ m_controlPoint = segment.point1;
if (m_mode == RelativeCoordinates) {
m_controlPoint += m_currentPoint;
- targetPoint += m_currentPoint;
+ segment.targetPoint += m_currentPoint;
}
- point1 = blendPoints(m_currentPoint, m_controlPoint);
- FloatPoint point2 = blendPoints(targetPoint, m_controlPoint);
+ segment.point1 = blendPoints(m_currentPoint, m_controlPoint);
+ FloatPoint point2 = blendPoints(segment.targetPoint, m_controlPoint);
- m_consumer->curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates);
+ m_consumer->curveToCubic(segment.point1, point2, segment.targetPoint, AbsoluteCoordinates);
- m_currentPoint = targetPoint;
- return true;
+ m_currentPoint = segment.targetPoint;
}
-bool SVGPathParser::parseCurveToQuadraticSmoothSegment()
+void SVGPathParser::emitCurveToQuadraticSmoothSegment(PathSegmentData& segment)
{
- FloatPoint targetPoint;
- if (!m_source->parseCurveToQuadraticSmoothSegment(targetPoint))
- return false;
-
if (m_pathParsingMode == UnalteredParsing) {
- m_consumer->curveToQuadraticSmooth(targetPoint, m_mode);
- return true;
+ m_consumer->curveToQuadraticSmooth(segment.targetPoint, m_mode);
+ return;
}
if (m_lastCommand != PathSegCurveToQuadraticAbs
&& m_lastCommand != PathSegCurveToQuadraticRel
@@ -226,53 +186,45 @@ bool SVGPathParser::parseCurveToQuadraticSmoothSegment()
m_controlPoint = m_currentPoint;
if (m_mode == RelativeCoordinates)
- targetPoint += m_currentPoint;
+ segment.targetPoint += m_currentPoint;
m_controlPoint = reflectedPoint(m_currentPoint, m_controlPoint);
FloatPoint point1 = blendPoints(m_currentPoint, m_controlPoint);
- FloatPoint point2 = blendPoints(targetPoint, m_controlPoint);
+ FloatPoint point2 = blendPoints(segment.targetPoint, m_controlPoint);
- m_consumer->curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates);
+ m_consumer->curveToCubic(point1, point2, segment.targetPoint, AbsoluteCoordinates);
- m_currentPoint = targetPoint;
- return true;
+ m_currentPoint = segment.targetPoint;
}
-bool SVGPathParser::parseArcToSegment()
+void SVGPathParser::emitArcToSegment(PathSegmentData& segment)
{
- float rx;
- float ry;
- float angle;
- bool largeArc;
- bool sweep;
- FloatPoint targetPoint;
- if (!m_source->parseArcToSegment(rx, ry, angle, largeArc, sweep, targetPoint))
- return false;
-
if (m_pathParsingMode == UnalteredParsing) {
- m_consumer->arcTo(rx, ry, angle, largeArc, sweep, targetPoint, m_mode);
- return true;
+ m_consumer->arcTo(segment.arcRadii().x(), segment.arcRadii().y(), segment.arcAngle(), segment.arcLarge, segment.arcSweep, segment.targetPoint, m_mode);
+ return;
}
// If rx = 0 or ry = 0 then this arc is treated as a straight line segment (a "lineto") joining the endpoints.
// http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters
// If the current point and target point for the arc are identical, it should be treated as a zero length
// path. This ensures continuity in animations.
- rx = fabsf(rx);
- ry = fabsf(ry);
+ float rx = fabsf(segment.arcRadii().x());
+ float ry = fabsf(segment.arcRadii().y());
if (m_mode == RelativeCoordinates)
- targetPoint += m_currentPoint;
+ segment.targetPoint += m_currentPoint;
- if (!rx || !ry || targetPoint == m_currentPoint) {
- m_consumer->lineTo(targetPoint, AbsoluteCoordinates);
- m_currentPoint = targetPoint;
- return true;
+ if (!rx || !ry || segment.targetPoint == m_currentPoint) {
+ m_consumer->lineTo(segment.targetPoint, AbsoluteCoordinates);
+ m_currentPoint = segment.targetPoint;
+ return;
}
+ float angle = segment.arcAngle();
FloatPoint point1 = m_currentPoint;
- m_currentPoint = targetPoint;
- return decomposeArcToCubic(angle, rx, ry, point1, targetPoint, largeArc, sweep);
+ m_currentPoint = segment.targetPoint;
+ if (!decomposeArcToCubic(angle, rx, ry, point1, segment.targetPoint, segment.arcLarge, segment.arcSweep))
+ m_consumer->lineTo(segment.targetPoint, AbsoluteCoordinates);
}
bool SVGPathParser::parsePathDataFromSource(PathParsingMode pathParsingMode, bool checkForInitialMoveTo)
@@ -286,92 +238,76 @@ bool SVGPathParser::parsePathDataFromSource(PathParsingMode pathParsingMode, boo
m_currentPoint = FloatPoint();
m_subPathPoint = FloatPoint();
- // Skip any leading spaces.
- if (!m_source->moveToNextToken())
- return true;
+ if (checkForInitialMoveTo && !initialCommandIsMoveTo())
+ return false;
- SVGPathSegType command;
- m_source->parseSVGSegmentType(command);
m_lastCommand = PathSegUnknown;
+ while (m_source->hasMoreData()) {
+ PathSegmentData segment = m_source->parseSegment();
+ if (segment.command == PathSegUnknown)
+ return false;
- // Path must start with moveto.
- if (checkForInitialMoveTo && command != PathSegMoveToAbs && command != PathSegMoveToRel)
- return false;
-
- while (true) {
- // Skip spaces between command and first coordinate.
- m_source->moveToNextToken();
m_mode = AbsoluteCoordinates;
- switch (command) {
+
+ switch (segment.command) {
case PathSegMoveToRel:
m_mode = RelativeCoordinates;
case PathSegMoveToAbs:
- if (!parseMoveToSegment())
- return false;
+ emitMoveToSegment(segment);
break;
case PathSegLineToRel:
m_mode = RelativeCoordinates;
case PathSegLineToAbs:
- if (!parseLineToSegment())
- return false;
+ emitLineToSegment(segment);
break;
case PathSegLineToHorizontalRel:
m_mode = RelativeCoordinates;
case PathSegLineToHorizontalAbs:
- if (!parseLineToHorizontalSegment())
- return false;
+ emitLineToHorizontalSegment(segment);
break;
case PathSegLineToVerticalRel:
m_mode = RelativeCoordinates;
case PathSegLineToVerticalAbs:
- if (!parseLineToVerticalSegment())
- return false;
+ emitLineToVerticalSegment(segment);
break;
case PathSegClosePath:
- parseClosePathSegment();
+ m_consumer->closePath();
+ // Reset m_currentPoint for the next path.
+ if (m_pathParsingMode == NormalizedParsing)
+ m_currentPoint = m_subPathPoint;
break;
case PathSegCurveToCubicRel:
m_mode = RelativeCoordinates;
case PathSegCurveToCubicAbs:
- if (!parseCurveToCubicSegment())
- return false;
+ emitCurveToCubicSegment(segment);
break;
case PathSegCurveToCubicSmoothRel:
m_mode = RelativeCoordinates;
case PathSegCurveToCubicSmoothAbs:
- if (!parseCurveToCubicSmoothSegment())
- return false;
+ emitCurveToCubicSmoothSegment(segment);
break;
case PathSegCurveToQuadraticRel:
m_mode = RelativeCoordinates;
case PathSegCurveToQuadraticAbs:
- if (!parseCurveToQuadraticSegment())
- return false;
+ emitCurveToQuadraticSegment(segment);
break;
case PathSegCurveToQuadraticSmoothRel:
m_mode = RelativeCoordinates;
case PathSegCurveToQuadraticSmoothAbs:
- if (!parseCurveToQuadraticSmoothSegment())
- return false;
+ emitCurveToQuadraticSmoothSegment(segment);
break;
case PathSegArcRel:
m_mode = RelativeCoordinates;
case PathSegArcAbs:
- if (!parseArcToSegment())
- return false;
+ emitArcToSegment(segment);
break;
default:
- return false;
+ ASSERT_NOT_REACHED();
}
if (!m_consumer->continueConsuming())
return true;
- m_lastCommand = command;
-
- if (!m_source->hasMoreData())
- return true;
-
- command = m_source->nextCommand(command);
+ m_lastCommand = segment.command;
if (m_lastCommand != PathSegCurveToCubicAbs
&& m_lastCommand != PathSegCurveToCubicRel
@@ -383,10 +319,10 @@ bool SVGPathParser::parsePathDataFromSource(PathParsingMode pathParsingMode, boo
&& m_lastCommand != PathSegCurveToQuadraticSmoothRel)
m_controlPoint = m_currentPoint;
- m_consumer->incrementPathSegmentCount();
+ if (m_source->hasMoreData())
+ m_consumer->incrementPathSegmentCount();
}
-
- return false;
+ return true;
}
// This works by converting the SVG arc to "simple" beziers.
« no previous file with comments | « Source/core/svg/SVGPathParser.h ('k') | Source/core/svg/SVGPathSeg.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698