Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 2 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
| 3 * Copyright (C) 2013 Apple Inc. All rights reserved. | 3 * Copyright (C) 2013 Apple Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
| 6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
| 7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
| 8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
| 9 * | 9 * |
| 10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
| 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 * Library General Public License for more details. | 13 * Library General Public License for more details. |
| 14 * | 14 * |
| 15 * You should have received a copy of the GNU Library General Public License | 15 * You should have received a copy of the GNU Library General Public License |
| 16 * along with this library; see the file COPYING.LIB. If not, write to | 16 * along with this library; see the file COPYING.LIB. If not, write to |
| 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 18 * Boston, MA 02110-1301, USA. | 18 * Boston, MA 02110-1301, USA. |
| 19 */ | 19 */ |
| 20 | 20 |
| 21 #include "core/svg/SVGPathStringSource.h" | 21 #include "core/svg/SVGPathStringSource.h" |
| 22 | 22 |
| 23 #include "core/svg/SVGParserUtilities.h" | 23 #include "core/svg/SVGParserUtilities.h" |
| 24 #include "platform/geometry/FloatPoint.h" | 24 #include "platform/geometry/FloatPoint.h" |
| 25 | 25 |
| 26 namespace blink { | 26 namespace blink { |
| 27 | 27 |
| 28 SVGPathStringSource::SVGPathStringSource(const String& string) | 28 SVGPathStringSource::SVGPathStringSource(const String& string) |
| 29 : m_string(string) | 29 : m_is8BitSource(string.is8Bit()) |
| 30 , m_is8BitSource(string.is8Bit()) | |
| 31 , m_seenError(false) | |
| 32 , m_previousCommand(PathSegUnknown) | 30 , m_previousCommand(PathSegUnknown) |
| 31 , m_string(string) | |
| 33 { | 32 { |
| 34 ASSERT(!string.isNull()); | 33 ASSERT(!string.isNull()); |
| 35 | 34 |
| 36 if (m_is8BitSource) { | 35 if (m_is8BitSource) { |
| 37 m_current.m_character8 = string.characters8(); | 36 m_current.m_character8 = string.characters8(); |
| 38 m_end.m_character8 = m_current.m_character8 + string.length(); | 37 m_end.m_character8 = m_current.m_character8 + string.length(); |
| 39 } else { | 38 } else { |
| 40 m_current.m_character16 = string.characters16(); | 39 m_current.m_character16 = string.characters16(); |
| 41 m_end.m_character16 = m_current.m_character16 + string.length(); | 40 m_end.m_character16 = m_current.m_character16 + string.length(); |
| 42 } | 41 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 117 if (previousCommand == PathSegMoveToRel) { | 116 if (previousCommand == PathSegMoveToRel) { |
| 118 nextCommand = PathSegLineToRel; | 117 nextCommand = PathSegLineToRel; |
| 119 return true; | 118 return true; |
| 120 } | 119 } |
| 121 nextCommand = previousCommand; | 120 nextCommand = previousCommand; |
| 122 return true; | 121 return true; |
| 123 } | 122 } |
| 124 return false; | 123 return false; |
| 125 } | 124 } |
| 126 | 125 |
| 126 void SVGPathStringSource::setErrorMark(SVGParseStatus status) | |
| 127 { | |
| 128 if (m_error.status() != SVGParseStatus::NoError) | |
| 129 return; | |
| 130 size_t locus = m_is8BitSource | |
| 131 ? m_current.m_character8 - m_string.characters8() | |
| 132 : m_current.m_character16 - m_string.characters16(); | |
| 133 m_error = SVGParsingError(status, locus); | |
| 134 } | |
| 135 | |
| 127 float SVGPathStringSource::parseNumberWithError() | 136 float SVGPathStringSource::parseNumberWithError() |
| 128 { | 137 { |
| 129 float numberValue = 0; | 138 float numberValue = 0; |
| 139 bool error; | |
| 130 if (m_is8BitSource) | 140 if (m_is8BitSource) |
| 131 m_seenError |= !parseNumber(m_current.m_character8, m_end.m_character8, numberValue); | 141 error = !parseNumber(m_current.m_character8, m_end.m_character8, numberV alue); |
| 132 else | 142 else |
| 133 m_seenError |= !parseNumber(m_current.m_character16, m_end.m_character16 , numberValue); | 143 error = !parseNumber(m_current.m_character16, m_end.m_character16, numbe rValue); |
| 144 if (UNLIKELY(error)) | |
| 145 setErrorMark(SVGParseStatus::ExpectedNumber); | |
| 134 return numberValue; | 146 return numberValue; |
| 135 } | 147 } |
| 136 | 148 |
| 137 bool SVGPathStringSource::parseArcFlagWithError() | 149 bool SVGPathStringSource::parseArcFlagWithError() |
| 138 { | 150 { |
| 139 bool flagValue = false; | 151 bool flagValue = false; |
| 152 bool error; | |
| 140 if (m_is8BitSource) | 153 if (m_is8BitSource) |
| 141 m_seenError |= !parseArcFlag(m_current.m_character8, m_end.m_character8, flagValue); | 154 error = !parseArcFlag(m_current.m_character8, m_end.m_character8, flagVa lue); |
| 142 else | 155 else |
| 143 m_seenError |= !parseArcFlag(m_current.m_character16, m_end.m_character1 6, flagValue); | 156 error = !parseArcFlag(m_current.m_character16, m_end.m_character16, flag Value); |
| 157 if (UNLIKELY(error)) | |
| 158 setErrorMark(SVGParseStatus::ExpectedArcFlag); | |
| 144 return flagValue; | 159 return flagValue; |
| 145 } | 160 } |
| 146 | 161 |
| 147 SVGPathSegType SVGPathStringSource::peekSegmentType() | 162 SVGPathSegType SVGPathStringSource::peekSegmentType() |
| 148 { | 163 { |
| 149 ASSERT(hasMoreData()); | 164 ASSERT(hasMoreData()); |
| 150 // This won't work in all cases because of the state required to "detect" im plicit commands. | 165 // This won't work in all cases because of the state required to "detect" im plicit commands. |
| 151 unsigned lookahead = m_is8BitSource ? *m_current.m_character8 : *m_current.m _character16; | 166 unsigned lookahead = m_is8BitSource ? *m_current.m_character8 : *m_current.m _character16; |
| 152 return parseSVGSegmentTypeHelper(lookahead); | 167 SVGPathSegType segmentType = parseSVGSegmentTypeHelper(lookahead); |
| 168 // Here we assume that this is only called via SVGPathParser::initialCommand IsMoveTo. | |
| 169 // TODO(fs): It ought to be possible to refactor away this entirely, and | |
| 170 // just handle this in parseSegment (which we sort of do already...) The | |
| 171 // only user is the method mentioned above. | |
|
f(malita)
2016/01/27 14:51:13
Yeah, it would be nice to get rid of this assumpti
fs
2016/01/27 14:57:56
I have some sort of (outline of a) plan for this [
| |
| 172 if (segmentType != PathSegMoveToAbs && segmentType != PathSegMoveToRel) | |
| 173 setErrorMark(SVGParseStatus::ExpectedMoveToCommand); | |
| 174 return segmentType; | |
| 153 } | 175 } |
| 154 | 176 |
| 155 PathSegmentData SVGPathStringSource::parseSegment() | 177 PathSegmentData SVGPathStringSource::parseSegment() |
| 156 { | 178 { |
| 157 ASSERT(hasMoreData()); | 179 ASSERT(hasMoreData()); |
| 158 PathSegmentData segment; | 180 PathSegmentData segment; |
| 159 unsigned lookahead = m_is8BitSource ? *m_current.m_character8 : *m_current.m _character16; | 181 unsigned lookahead = m_is8BitSource ? *m_current.m_character8 : *m_current.m _character16; |
| 160 SVGPathSegType command = parseSVGSegmentTypeHelper(lookahead); | 182 SVGPathSegType command = parseSVGSegmentTypeHelper(lookahead); |
| 161 if (command == PathSegUnknown) { | 183 if (command == PathSegUnknown) { |
| 162 // Possibly an implicit command. Not allowed if this is the first comman d. | 184 // Possibly an implicit command. Not allowed if this is the first comman d. |
| 163 if (m_previousCommand == PathSegUnknown) | 185 if (m_previousCommand == PathSegUnknown) { |
| 186 setErrorMark(SVGParseStatus::ExpectedMoveToCommand); | |
| 164 return segment; | 187 return segment; |
| 165 if (!nextCommandHelper(lookahead, m_previousCommand, command)) | 188 } |
| 189 if (!nextCommandHelper(lookahead, m_previousCommand, command)) { | |
| 190 setErrorMark(SVGParseStatus::ExpectedPathCommand); | |
| 166 return segment; | 191 return segment; |
| 192 } | |
| 167 } else { | 193 } else { |
| 168 // Valid explicit command. | 194 // Valid explicit command. |
| 169 if (m_is8BitSource) | 195 if (m_is8BitSource) |
| 170 m_current.m_character8++; | 196 m_current.m_character8++; |
| 171 else | 197 else |
| 172 m_current.m_character16++; | 198 m_current.m_character16++; |
| 173 } | 199 } |
| 174 | 200 |
| 175 segment.command = m_previousCommand = command; | 201 segment.command = m_previousCommand = command; |
| 176 | 202 |
| 177 ASSERT(!m_seenError); | 203 ASSERT(m_error.status() == SVGParseStatus::NoError); |
| 178 | 204 |
| 179 switch (segment.command) { | 205 switch (segment.command) { |
| 180 case PathSegCurveToCubicRel: | 206 case PathSegCurveToCubicRel: |
| 181 case PathSegCurveToCubicAbs: | 207 case PathSegCurveToCubicAbs: |
| 182 segment.point1.setX(parseNumberWithError()); | 208 segment.point1.setX(parseNumberWithError()); |
| 183 segment.point1.setY(parseNumberWithError()); | 209 segment.point1.setY(parseNumberWithError()); |
| 184 /* fall through */ | 210 /* fall through */ |
| 185 case PathSegCurveToCubicSmoothRel: | 211 case PathSegCurveToCubicSmoothRel: |
| 186 case PathSegCurveToCubicSmoothAbs: | 212 case PathSegCurveToCubicSmoothAbs: |
| 187 segment.point2.setX(parseNumberWithError()); | 213 segment.point2.setX(parseNumberWithError()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 segment.setArcAngle(parseNumberWithError()); | 247 segment.setArcAngle(parseNumberWithError()); |
| 222 segment.arcLarge = parseArcFlagWithError(); | 248 segment.arcLarge = parseArcFlagWithError(); |
| 223 segment.arcSweep = parseArcFlagWithError(); | 249 segment.arcSweep = parseArcFlagWithError(); |
| 224 segment.targetPoint.setX(parseNumberWithError()); | 250 segment.targetPoint.setX(parseNumberWithError()); |
| 225 segment.targetPoint.setY(parseNumberWithError()); | 251 segment.targetPoint.setY(parseNumberWithError()); |
| 226 break; | 252 break; |
| 227 case PathSegUnknown: | 253 case PathSegUnknown: |
| 228 ASSERT_NOT_REACHED(); | 254 ASSERT_NOT_REACHED(); |
| 229 } | 255 } |
| 230 | 256 |
| 231 if (UNLIKELY(m_seenError)) | 257 if (UNLIKELY(m_error.status() != SVGParseStatus::NoError)) |
| 232 segment.command = PathSegUnknown; | 258 segment.command = PathSegUnknown; |
| 233 return segment; | 259 return segment; |
| 234 } | 260 } |
| 235 | 261 |
| 236 } // namespace blink | 262 } // namespace blink |
| OLD | NEW |