Index: third_party/WebKit/Source/core/svg/SVGPathStringSource.cpp |
diff --git a/third_party/WebKit/Source/core/svg/SVGPathStringSource.cpp b/third_party/WebKit/Source/core/svg/SVGPathStringSource.cpp |
index 9a0142dcbf25fdbb79690877d598fe8f4866df24..b6eaf9f7d2d33d1822b185233a73f23cd5e719bd 100644 |
--- a/third_party/WebKit/Source/core/svg/SVGPathStringSource.cpp |
+++ b/third_party/WebKit/Source/core/svg/SVGPathStringSource.cpp |
@@ -42,13 +42,6 @@ SVGPathStringSource::SVGPathStringSource(const String& string) |
eatWhitespace(); |
} |
-bool SVGPathStringSource::hasMoreData() const |
-{ |
- if (m_is8BitSource) |
- return m_current.m_character8 < m_end.m_character8; |
- return m_current.m_character16 < m_end.m_character16; |
-} |
- |
void SVGPathStringSource::eatWhitespace() |
{ |
if (m_is8BitSource) |
@@ -57,7 +50,7 @@ void SVGPathStringSource::eatWhitespace() |
skipOptionalSVGSpaces(m_current.m_character16, m_end.m_character16); |
} |
-static SVGPathSegType parseSVGSegmentTypeHelper(unsigned lookahead) |
+static SVGPathSegType mapLetterToSegmentType(unsigned lookahead) |
{ |
switch (lookahead) { |
case 'Z': |
@@ -104,23 +97,33 @@ static SVGPathSegType parseSVGSegmentTypeHelper(unsigned lookahead) |
} |
} |
-static bool nextCommandHelper(unsigned lookahead, SVGPathSegType previousCommand, SVGPathSegType& nextCommand) |
+static bool isNumberStart(unsigned lookahead) |
{ |
- // Check for remaining coordinates in the current command. |
- if ((lookahead == '+' || lookahead == '-' || lookahead == '.' || (lookahead >= '0' && lookahead <= '9')) |
- && previousCommand != PathSegClosePath) { |
- if (previousCommand == PathSegMoveToAbs) { |
- nextCommand = PathSegLineToAbs; |
- return true; |
- } |
- if (previousCommand == PathSegMoveToRel) { |
- nextCommand = PathSegLineToRel; |
- return true; |
- } |
- nextCommand = previousCommand; |
+ return (lookahead >= '0' && lookahead <= '9') |
+ || lookahead == '+' |
+ || lookahead == '-' |
+ || lookahead == '.'; |
+} |
+ |
+static bool maybeImplicitCommand(unsigned lookahead, SVGPathSegType previousCommand, SVGPathSegType& nextCommand) |
+{ |
+ // Check if the current lookahead may start a number - in which case it |
+ // could be the start of an implicit command. The 'close' command does not |
+ // have any parameters though and hence can't have an implicit |
+ // 'continuation'. |
+ if (!isNumberStart(lookahead) || previousCommand == PathSegClosePath) |
+ return false; |
+ // Implicit continuations of moveto command translate to linetos. |
+ if (previousCommand == PathSegMoveToAbs) { |
+ nextCommand = PathSegLineToAbs; |
+ return true; |
+ } |
+ if (previousCommand == PathSegMoveToRel) { |
+ nextCommand = PathSegLineToRel; |
return true; |
} |
- return false; |
+ nextCommand = previousCommand; |
+ return true; |
} |
void SVGPathStringSource::setErrorMark(SVGParseStatus status) |
@@ -159,34 +162,27 @@ bool SVGPathStringSource::parseArcFlagWithError() |
return flagValue; |
} |
-SVGPathSegType SVGPathStringSource::peekSegmentType() |
-{ |
- ASSERT(hasMoreData()); |
- // This won't work in all cases because of the state required to "detect" implicit commands. |
- unsigned lookahead = m_is8BitSource ? *m_current.m_character8 : *m_current.m_character16; |
- SVGPathSegType segmentType = parseSVGSegmentTypeHelper(lookahead); |
- // Here we assume that this is only called via SVGPathParser::initialCommandIsMoveTo. |
- // TODO(fs): It ought to be possible to refactor away this entirely, and |
- // just handle this in parseSegment (which we sort of do already...) The |
- // only user is the method mentioned above. |
- if (segmentType != PathSegMoveToAbs && segmentType != PathSegMoveToRel) |
- setErrorMark(SVGParseStatus::ExpectedMoveToCommand); |
- return segmentType; |
-} |
- |
PathSegmentData SVGPathStringSource::parseSegment() |
{ |
ASSERT(hasMoreData()); |
PathSegmentData segment; |
unsigned lookahead = m_is8BitSource ? *m_current.m_character8 : *m_current.m_character16; |
- SVGPathSegType command = parseSVGSegmentTypeHelper(lookahead); |
- if (command == PathSegUnknown) { |
- // Possibly an implicit command. Not allowed if this is the first command. |
- if (m_previousCommand == PathSegUnknown) { |
+ SVGPathSegType command = mapLetterToSegmentType(lookahead); |
+ if (UNLIKELY(m_previousCommand == PathSegUnknown)) { |
+ // First command has to be a moveto. |
+ if (command != PathSegMoveToRel && command != PathSegMoveToAbs) { |
setErrorMark(SVGParseStatus::ExpectedMoveToCommand); |
return segment; |
} |
- if (!nextCommandHelper(lookahead, m_previousCommand, command)) { |
+ // Consume command letter. |
+ if (m_is8BitSource) |
+ m_current.m_character8++; |
+ else |
+ m_current.m_character16++; |
+ } else if (command == PathSegUnknown) { |
+ // Possibly an implicit command. |
+ ASSERT(m_previousCommand != PathSegUnknown); |
+ if (!maybeImplicitCommand(lookahead, m_previousCommand, command)) { |
setErrorMark(SVGParseStatus::ExpectedPathCommand); |
return segment; |
} |