1 /* 2 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 3 * Copyright (C) 2013 Apple Inc. All rights reserved. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 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 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21 #include "config.h" 22 23 #include "core/svg/SVGPathStringSource.h" 24 25 #include "core/svg/SVGParserUtilities.h" 26 #include "platform/geometry/FloatPoint.h" 27 28 namespace blink { 29 30 SVGPathStringSource::SVGPathStringSource(const String& string) 31 : m_string(string) 32 , m_is8BitSource(string.is8Bit()) 33 { 34 ASSERT(!string.isEmpty()); 35 36 if (m_is8BitSource) { 37 m_current.m_character8 = string.characters8(); 38 m_end.m_character8 = m_current.m_character8 + string.length(); 39 } else { 40 m_current.m_character16 = string.characters16(); 41 m_end.m_character16 = m_current.m_character16 + string.length(); 42 } 43 } 44 45 bool SVGPathStringSource::hasMoreData() const 46 { 47 if (m_is8BitSource) 48 return m_current.m_character8 < m_end.m_character8; 49 return m_current.m_character16 < m_end.m_character16; 50 } 51 52 bool SVGPathStringSource::moveToNextToken() 53 { 54 if (m_is8BitSource) 55 return skipOptionalSVGSpaces(m_current.m_character8, m_end.m_character8); 56 return skipOptionalSVGSpaces(m_current.m_character16, m_end.m_character16); 57 } 58 59 template <typename CharacterType> 60 static bool parseSVGSegmentTypeHelper(const CharacterType*& current, SVGPathSegType& pathSegType) 61 { 62 switch (*(current++)) { 63 case 'Z': 64 case 'z': 65 pathSegType = PathSegClosePath; 66 break; 67 case 'M': 68 pathSegType = PathSegMoveToAbs; 69 break; 70 case 'm': 71 pathSegType = PathSegMoveToRel; 72 break; 73 case 'L': 74 pathSegType = PathSegLineToAbs; 75 break; 76 case 'l': 77 pathSegType = PathSegLineToRel; 78 break; 79 case 'C': 80 pathSegType = PathSegCurveToCubicAbs; 81 break; 82 case 'c': 83 pathSegType = PathSegCurveToCubicRel; 84 break; 85 case 'Q': 86 pathSegType = PathSegCurveToQuadraticAbs; 87 break; 88 case 'q': 89 pathSegType = PathSegCurveToQuadraticRel; 90 break; 91 case 'A': 92 pathSegType = PathSegArcAbs; 93 break; 94 case 'a': 95 pathSegType = PathSegArcRel; 96 break; 97 case 'H': 98 pathSegType = PathSegLineToHorizontalAbs; 99 break; 100 case 'h': 101 pathSegType = PathSegLineToHorizontalRel; 102 break; 103 case 'V': 104 pathSegType = PathSegLineToVerticalAbs; 105 break; 106 case 'v': 107 pathSegType = PathSegLineToVerticalRel; 108 break; 109 case 'S': 110 pathSegType = PathSegCurveToCubicSmoothAbs; 111 break; 112 case 's': 113 pathSegType = PathSegCurveToCubicSmoothRel; 114 break; 115 case 'T': 116 pathSegType = PathSegCurveToQuadraticSmoothAbs; 117 break; 118 case 't': 119 pathSegType = PathSegCurveToQuadraticSmoothRel; 120 break; 121 default: 122 pathSegType = PathSegUnknown; 123 } 124 return true; 125 } 126 127 bool SVGPathStringSource::parseSVGSegmentType(SVGPathSegType& pathSegType) 128 { 129 if (m_is8BitSource) 130 return parseSVGSegmentTypeHelper(m_current.m_character8, pathSegType); 131 return parseSVGSegmentTypeHelper(m_current.m_character16, pathSegType); 132 } 133 134 template <typename CharacterType> 135 static bool nextCommandHelper(const CharacterType*& current, SVGPathSegType previousCommand, SVGPathSegType& nextCommand) 136 { 137 // Check for remaining coordinates in the current command. 138 if ((*current == '+' || *current == '-' || *current == '.' || (*current >= '0' && *current <= '9')) 139 && previousCommand != PathSegClosePath) { 140 if (previousCommand == PathSegMoveToAbs) { 141 nextCommand = PathSegLineToAbs; 142 return true; 143 } 144 if (previousCommand == PathSegMoveToRel) { 145 nextCommand = PathSegLineToRel; 146 return true; 147 } 148 nextCommand = previousCommand; 149 return true; 150 } 151 152 return false; 153 } 154 155 SVGPathSegType SVGPathStringSource::nextCommand(SVGPathSegType previousCommand) 156 { 157 SVGPathSegType nextCommand; 158 if (m_is8BitSource) { 159 if (nextCommandHelper(m_current.m_character8, previousCommand, nextCommand)) 160 return nextCommand; 161 } else { 162 if (nextCommandHelper(m_current.m_character16, previousCommand, nextCommand)) 163 return nextCommand; 164 } 165 166 parseSVGSegmentType(nextCommand); 167 return nextCommand; 168 } 169 170 bool SVGPathStringSource::parseMoveToSegment(FloatPoint& targetPoint) 171 { 172 if (m_is8BitSource) 173 return parseFloatPoint(m_current.m_character8, m_end.m_character8, targetPoint); 174 return parseFloatPoint(m_current.m_character16, m_end.m_character16, targetPoint); 175 } 176 177 bool SVGPathStringSource::parseLineToSegment(FloatPoint& targetPoint) 178 { 179 if (m_is8BitSource) 180 return parseFloatPoint(m_current.m_character8, m_end.m_character8, targetPoint); 181 return parseFloatPoint(m_current.m_character16, m_end.m_character16, targetPoint); 182 } 183 184 bool SVGPathStringSource::parseLineToHorizontalSegment(float& x) 185 { 186 if (m_is8BitSource) 187 return parseNumber(m_current.m_character8, m_end.m_character8, x); 188 return parseNumber(m_current.m_character16, m_end.m_character16, x); 189 } 190 191 bool SVGPathStringSource::parseLineToVerticalSegment(float& y) 192 { 193 if (m_is8BitSource) 194 return parseNumber(m_current.m_character8, m_end.m_character8, y); 195 return parseNumber(m_current.m_character16, m_end.m_character16, y); 196 } 197 198 bool SVGPathStringSource::parseCurveToCubicSegment(FloatPoint& point1, FloatPoint& point2, FloatPoint& targetPoint) 199 { 200 if (m_is8BitSource) 201 return parseFloatPoint3(m_current.m_character8, m_end.m_character8, point1, point2, targetPoint); 202 return parseFloatPoint3(m_current.m_character16, m_end.m_character16, point1, point2, targetPoint); 203 } 204 205 bool SVGPathStringSource::parseCurveToCubicSmoothSegment(FloatPoint& point1, FloatPoint& targetPoint) 206 { 207 if (m_is8BitSource) 208 return parseFloatPoint2(m_current.m_character8, m_end.m_character8, point1, targetPoint); 209 return parseFloatPoint2(m_current.m_character16, m_end.m_character16, point1, targetPoint); 210 } 211 212 bool SVGPathStringSource::parseCurveToQuadraticSegment(FloatPoint& point2, FloatPoint& targetPoint) 213 { 214 if (m_is8BitSource) 215 return parseFloatPoint2(m_current.m_character8, m_end.m_character8, point2, targetPoint); 216 return parseFloatPoint2(m_current.m_character16, m_end.m_character16, point2, targetPoint); 217 } 218 219 bool SVGPathStringSource::parseCurveToQuadraticSmoothSegment(FloatPoint& targetPoint) 220 { 221 if (m_is8BitSource) 222 return parseFloatPoint(m_current.m_character8, m_end.m_character8, targetPoint); 223 return parseFloatPoint(m_current.m_character16, m_end.m_character16, targetPoint); 224 } 225 226 template <typename CharacterType> 227 static bool parseArcToSegmentHelper(const CharacterType*& current, const CharacterType* end, float& rx, float& ry, float& angle, bool& largeArc, bool& sweep, FloatPoint& targetPoint) 228 { 229 float toX; 230 float toY; 231 if (!parseNumber(current, end, rx) 232 || !parseNumber(current, end, ry) 233 || !parseNumber(current, end, angle) 234 || !parseArcFlag(current, end, largeArc) 235 || !parseArcFlag(current, end, sweep) 236 || !parseNumber(current, end, toX) 237 || !parseNumber(current, end, toY)) 238 return false; 239 targetPoint = FloatPoint(toX, toY); 240 return true; 241 } 242 243 bool SVGPathStringSource::parseArcToSegment(float& rx, float& ry, float& angle, bool& largeArc, bool& sweep, FloatPoint& targetPoint) 244 { 245 if (m_is8BitSource) 246 return parseArcToSegmentHelper(m_current.m_character8, m_end.m_character8, rx, ry, angle, largeArc, sweep, targetPoint); 247 return parseArcToSegmentHelper(m_current.m_character16, m_end.m_character16, rx, ry, angle, largeArc, sweep, targetPoint); 248 } 249 250 } // namespace blink 251