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#if ENABLE(SVG) 24#include "SVGPathStringSource.h" 25 26#include "FloatPoint.h" 27#include "SVGParserUtilities.h" 28 29namespace WebCore { 30 31SVGPathStringSource::SVGPathStringSource(const String& string) 32 : m_string(string) 33 , m_is8BitSource(string.is8Bit()) 34{ 35 ASSERT(!string.isEmpty()); 36 37 if (m_is8BitSource) { 38 m_current.m_character8 = string.characters8(); 39 m_end.m_character8 = m_current.m_character8 + string.length(); 40 } else { 41 m_current.m_character16 = string.characters16(); 42 m_end.m_character16 = m_current.m_character16 + string.length(); 43 } 44} 45 46bool SVGPathStringSource::hasMoreData() const 47{ 48 if (m_is8BitSource) 49 return m_current.m_character8 < m_end.m_character8; 50 return m_current.m_character16 < m_end.m_character16; 51} 52 53bool SVGPathStringSource::moveToNextToken() 54{ 55 if (m_is8BitSource) 56 return skipOptionalSVGSpaces(m_current.m_character8, m_end.m_character8); 57 return skipOptionalSVGSpaces(m_current.m_character16, m_end.m_character16); 58} 59 60template <typename CharacterType> 61static bool parseSVGSegmentTypeHelper(const CharacterType*& current, SVGPathSegType& pathSegType) 62{ 63 switch (*(current++)) { 64 case 'Z': 65 case 'z': 66 pathSegType = PathSegClosePath; 67 break; 68 case 'M': 69 pathSegType = PathSegMoveToAbs; 70 break; 71 case 'm': 72 pathSegType = PathSegMoveToRel; 73 break; 74 case 'L': 75 pathSegType = PathSegLineToAbs; 76 break; 77 case 'l': 78 pathSegType = PathSegLineToRel; 79 break; 80 case 'C': 81 pathSegType = PathSegCurveToCubicAbs; 82 break; 83 case 'c': 84 pathSegType = PathSegCurveToCubicRel; 85 break; 86 case 'Q': 87 pathSegType = PathSegCurveToQuadraticAbs; 88 break; 89 case 'q': 90 pathSegType = PathSegCurveToQuadraticRel; 91 break; 92 case 'A': 93 pathSegType = PathSegArcAbs; 94 break; 95 case 'a': 96 pathSegType = PathSegArcRel; 97 break; 98 case 'H': 99 pathSegType = PathSegLineToHorizontalAbs; 100 break; 101 case 'h': 102 pathSegType = PathSegLineToHorizontalRel; 103 break; 104 case 'V': 105 pathSegType = PathSegLineToVerticalAbs; 106 break; 107 case 'v': 108 pathSegType = PathSegLineToVerticalRel; 109 break; 110 case 'S': 111 pathSegType = PathSegCurveToCubicSmoothAbs; 112 break; 113 case 's': 114 pathSegType = PathSegCurveToCubicSmoothRel; 115 break; 116 case 'T': 117 pathSegType = PathSegCurveToQuadraticSmoothAbs; 118 break; 119 case 't': 120 pathSegType = PathSegCurveToQuadraticSmoothRel; 121 break; 122 default: 123 pathSegType = PathSegUnknown; 124 } 125 return true; 126} 127 128bool SVGPathStringSource::parseSVGSegmentType(SVGPathSegType& pathSegType) 129{ 130 if (m_is8BitSource) 131 return parseSVGSegmentTypeHelper(m_current.m_character8, pathSegType); 132 return parseSVGSegmentTypeHelper(m_current.m_character16, pathSegType); 133} 134 135template <typename CharacterType> 136static bool nextCommandHelper(const CharacterType*& current, SVGPathSegType previousCommand, SVGPathSegType& nextCommand) 137{ 138 // Check for remaining coordinates in the current command. 139 if ((*current == '+' || *current == '-' || *current == '.' || (*current >= '0' && *current <= '9')) 140 && previousCommand != PathSegClosePath) { 141 if (previousCommand == PathSegMoveToAbs) { 142 nextCommand = PathSegLineToAbs; 143 return true; 144 } 145 if (previousCommand == PathSegMoveToRel) { 146 nextCommand = PathSegLineToRel; 147 return true; 148 } 149 nextCommand = previousCommand; 150 return true; 151 } 152 153 return false; 154} 155 156SVGPathSegType SVGPathStringSource::nextCommand(SVGPathSegType previousCommand) 157{ 158 SVGPathSegType nextCommand; 159 if (m_is8BitSource) { 160 if (nextCommandHelper(m_current.m_character8, previousCommand, nextCommand)) 161 return nextCommand; 162 } else { 163 if (nextCommandHelper(m_current.m_character16, previousCommand, nextCommand)) 164 return nextCommand; 165 } 166 167 parseSVGSegmentType(nextCommand); 168 return nextCommand; 169} 170 171bool SVGPathStringSource::parseMoveToSegment(FloatPoint& targetPoint) 172{ 173 if (m_is8BitSource) 174 return parseFloatPoint(m_current.m_character8, m_end.m_character8, targetPoint); 175 return parseFloatPoint(m_current.m_character16, m_end.m_character16, targetPoint); 176} 177 178bool SVGPathStringSource::parseLineToSegment(FloatPoint& targetPoint) 179{ 180 if (m_is8BitSource) 181 return parseFloatPoint(m_current.m_character8, m_end.m_character8, targetPoint); 182 return parseFloatPoint(m_current.m_character16, m_end.m_character16, targetPoint); 183} 184 185bool SVGPathStringSource::parseLineToHorizontalSegment(float& x) 186{ 187 if (m_is8BitSource) 188 return parseNumber(m_current.m_character8, m_end.m_character8, x); 189 return parseNumber(m_current.m_character16, m_end.m_character16, x); 190} 191 192bool SVGPathStringSource::parseLineToVerticalSegment(float& y) 193{ 194 if (m_is8BitSource) 195 return parseNumber(m_current.m_character8, m_end.m_character8, y); 196 return parseNumber(m_current.m_character16, m_end.m_character16, y); 197} 198 199bool SVGPathStringSource::parseCurveToCubicSegment(FloatPoint& point1, FloatPoint& point2, FloatPoint& targetPoint) 200{ 201 if (m_is8BitSource) 202 return parseFloatPoint3(m_current.m_character8, m_end.m_character8, point1, point2, targetPoint); 203 return parseFloatPoint3(m_current.m_character16, m_end.m_character16, point1, point2, targetPoint); 204} 205 206bool SVGPathStringSource::parseCurveToCubicSmoothSegment(FloatPoint& point1, FloatPoint& targetPoint) 207{ 208 if (m_is8BitSource) 209 return parseFloatPoint2(m_current.m_character8, m_end.m_character8, point1, targetPoint); 210 return parseFloatPoint2(m_current.m_character16, m_end.m_character16, point1, targetPoint); 211} 212 213bool SVGPathStringSource::parseCurveToQuadraticSegment(FloatPoint& point2, FloatPoint& targetPoint) 214{ 215 if (m_is8BitSource) 216 return parseFloatPoint2(m_current.m_character8, m_end.m_character8, point2, targetPoint); 217 return parseFloatPoint2(m_current.m_character16, m_end.m_character16, point2, targetPoint); 218} 219 220bool SVGPathStringSource::parseCurveToQuadraticSmoothSegment(FloatPoint& targetPoint) 221{ 222 if (m_is8BitSource) 223 return parseFloatPoint(m_current.m_character8, m_end.m_character8, targetPoint); 224 return parseFloatPoint(m_current.m_character16, m_end.m_character16, targetPoint); 225} 226 227template <typename CharacterType> 228static bool parseArcToSegmentHelper(const CharacterType*& current, const CharacterType* end, float& rx, float& ry, float& angle, bool& largeArc, bool& sweep, FloatPoint& targetPoint) 229{ 230 float toX; 231 float toY; 232 if (!parseNumber(current, end, rx) 233 || !parseNumber(current, end, ry) 234 || !parseNumber(current, end, angle) 235 || !parseArcFlag(current, end, largeArc) 236 || !parseArcFlag(current, end, sweep) 237 || !parseNumber(current, end, toX) 238 || !parseNumber(current, end, toY)) 239 return false; 240 targetPoint = FloatPoint(toX, toY); 241 return true; 242} 243 244bool SVGPathStringSource::parseArcToSegment(float& rx, float& ry, float& angle, bool& largeArc, bool& sweep, FloatPoint& targetPoint) 245{ 246 if (m_is8BitSource) 247 return parseArcToSegmentHelper(m_current.m_character8, m_end.m_character8, rx, ry, angle, largeArc, sweep, targetPoint); 248 return parseArcToSegmentHelper(m_current.m_character16, m_end.m_character16, rx, ry, angle, largeArc, sweep, targetPoint); 249} 250 251} // namespace WebKit 252 253#endif // ENABLE(SVG) 254