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