Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / svg / SVGParserUtilities.cpp
1 /*
2  * Copyright (C) 2002, 2003 The Karbon Developers
3  * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org>
4  * Copyright (C) 2006, 2007 Rob Buis <buis@kde.org>
5  * Copyright (C) 2007, 2009, 2013 Apple Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include "config.h"
24 #include "core/svg/SVGParserUtilities.h"
25
26 #include "core/svg/SVGPointList.h"
27 #include "platform/geometry/FloatRect.h"
28 #include "platform/transforms/AffineTransform.h"
29 #include "wtf/ASCIICType.h"
30 #include "wtf/text/StringHash.h"
31 #include <limits>
32
33 namespace blink {
34
35 template <typename FloatType>
36 static inline bool isValidRange(const FloatType& x)
37 {
38     static const FloatType max = std::numeric_limits<FloatType>::max();
39     return x >= -max && x <= max;
40 }
41
42 // We use this generic parseNumber function to allow the Path parsing code to work
43 // at a higher precision internally, without any unnecessary runtime cost or code
44 // complexity.
45 template <typename CharType, typename FloatType>
46 static bool genericParseNumber(const CharType*& ptr, const CharType* end, FloatType& number, WhitespaceMode mode)
47 {
48     FloatType integer, decimal, frac, exponent;
49     int sign, expsign;
50     const CharType* start = ptr;
51
52     exponent = 0;
53     integer = 0;
54     frac = 1;
55     decimal = 0;
56     sign = 1;
57     expsign = 1;
58
59     if (mode & AllowLeadingWhitespace)
60         skipOptionalSVGSpaces(ptr, end);
61
62     // read the sign
63     if (ptr < end && *ptr == '+')
64         ptr++;
65     else if (ptr < end && *ptr == '-') {
66         ptr++;
67         sign = -1;
68     }
69
70     if (ptr == end || ((*ptr < '0' || *ptr > '9') && *ptr != '.'))
71         // The first character of a number must be one of [0-9+-.]
72         return false;
73
74     // read the integer part, build right-to-left
75     const CharType* ptrStartIntPart = ptr;
76     while (ptr < end && *ptr >= '0' && *ptr <= '9')
77         ++ptr; // Advance to first non-digit.
78
79     if (ptr != ptrStartIntPart) {
80         const CharType* ptrScanIntPart = ptr - 1;
81         FloatType multiplier = 1;
82         while (ptrScanIntPart >= ptrStartIntPart) {
83             integer += multiplier * static_cast<FloatType>(*(ptrScanIntPart--) - '0');
84             multiplier *= 10;
85         }
86         // Bail out early if this overflows.
87         if (!isValidRange(integer))
88             return false;
89     }
90
91     if (ptr < end && *ptr == '.') { // read the decimals
92         ptr++;
93
94         // There must be a least one digit following the .
95         if (ptr >= end || *ptr < '0' || *ptr > '9')
96             return false;
97
98         while (ptr < end && *ptr >= '0' && *ptr <= '9')
99             decimal += (*(ptr++) - '0') * (frac *= static_cast<FloatType>(0.1));
100     }
101
102     // read the exponent part
103     if (ptr != start && ptr + 1 < end && (*ptr == 'e' || *ptr == 'E')
104         && (ptr[1] != 'x' && ptr[1] != 'm')) {
105         ptr++;
106
107         // read the sign of the exponent
108         if (*ptr == '+')
109             ptr++;
110         else if (*ptr == '-') {
111             ptr++;
112             expsign = -1;
113         }
114
115         // There must be an exponent
116         if (ptr >= end || *ptr < '0' || *ptr > '9')
117             return false;
118
119         while (ptr < end && *ptr >= '0' && *ptr <= '9') {
120             exponent *= static_cast<FloatType>(10);
121             exponent += *ptr - '0';
122             ptr++;
123         }
124         // Make sure exponent is valid.
125         if (!isValidRange(exponent) || exponent > std::numeric_limits<FloatType>::max_exponent)
126             return false;
127     }
128
129     number = integer + decimal;
130     number *= sign;
131
132     if (exponent)
133         number *= static_cast<FloatType>(pow(10.0, expsign * static_cast<int>(exponent)));
134
135     // Don't return Infinity() or NaN().
136     if (!isValidRange(number))
137         return false;
138
139     if (start == ptr)
140         return false;
141
142     if (mode & AllowTrailingWhitespace)
143         skipOptionalSVGSpacesOrDelimiter(ptr, end);
144
145     return true;
146 }
147
148 bool parseNumber(const LChar*& ptr, const LChar* end, float& number, WhitespaceMode mode)
149 {
150     return genericParseNumber(ptr, end, number, mode);
151 }
152
153 bool parseNumber(const UChar*& ptr, const UChar* end, float& number, WhitespaceMode mode)
154 {
155     return genericParseNumber(ptr, end, number, mode);
156 }
157
158 // only used to parse largeArcFlag and sweepFlag which must be a "0" or "1"
159 // and might not have any whitespace/comma after it
160 template <typename CharType>
161 bool genericParseArcFlag(const CharType*& ptr, const CharType* end, bool& flag)
162 {
163     if (ptr >= end)
164         return false;
165     const CharType flagChar = *ptr++;
166     if (flagChar == '0')
167         flag = false;
168     else if (flagChar == '1')
169         flag = true;
170     else
171         return false;
172
173     skipOptionalSVGSpacesOrDelimiter(ptr, end);
174
175     return true;
176 }
177
178 bool parseArcFlag(const LChar*& ptr, const LChar* end, bool& flag)
179 {
180     return genericParseArcFlag(ptr, end, flag);
181 }
182
183 bool parseArcFlag(const UChar*& ptr, const UChar* end, bool& flag)
184 {
185     return genericParseArcFlag(ptr, end, flag);
186 }
187
188 template<typename CharType>
189 static bool genericParseNumberOptionalNumber(const CharType*& ptr, const CharType* end, float& x, float& y)
190 {
191     if (!parseNumber(ptr, end, x))
192         return false;
193
194     if (ptr == end)
195         y = x;
196     else if (!parseNumber(ptr, end, y, AllowLeadingAndTrailingWhitespace))
197         return false;
198
199     return ptr == end;
200 }
201
202 bool parseNumberOptionalNumber(const String& string, float& x, float& y)
203 {
204     if (string.isEmpty())
205         return false;
206
207     if (string.is8Bit()) {
208         const LChar* ptr = string.characters8();
209         const LChar* end = ptr + string.length();
210         return genericParseNumberOptionalNumber(ptr, end, x, y);
211     }
212     const UChar* ptr = string.characters16();
213     const UChar* end = ptr + string.length();
214     return genericParseNumberOptionalNumber(ptr, end, x, y);
215 }
216
217 template<typename CharType>
218 bool genericParseNumberOrPercentage(const CharType*& ptr, const CharType* end, float& number)
219 {
220     if (genericParseNumber(ptr, end, number, AllowLeadingWhitespace)) {
221         if (ptr == end)
222             return true;
223
224         bool isPercentage = (*ptr == '%');
225         if (isPercentage)
226             ptr++;
227
228         skipOptionalSVGSpaces(ptr, end);
229
230         if (isPercentage)
231             number /= 100.f;
232
233         return ptr == end;
234     }
235
236     return false;
237 }
238
239 bool parseNumberOrPercentage(const String& string, float& number)
240 {
241     if (string.isEmpty())
242         return false;
243
244     if (string.is8Bit()) {
245         const LChar* ptr = string.characters8();
246         const LChar* end = ptr + string.length();
247         return genericParseNumberOrPercentage(ptr, end, number);
248     }
249     const UChar* ptr = string.characters16();
250     const UChar* end = ptr + string.length();
251     return genericParseNumberOrPercentage(ptr, end, number);
252 }
253
254 template <typename CharType>
255 bool parseFloatPoint(const CharType*& current, const CharType* end, FloatPoint& point)
256 {
257     float x;
258     float y;
259     if (!parseNumber(current, end, x)
260         || !parseNumber(current, end, y))
261         return false;
262     point = FloatPoint(x, y);
263     return true;
264 }
265
266 template bool parseFloatPoint(const LChar*& current, const LChar* end, FloatPoint& point1);
267 template bool parseFloatPoint(const UChar*& current, const UChar* end, FloatPoint& point1);
268
269 template <typename CharType>
270 inline bool parseFloatPoint2(const CharType*& current, const CharType* end, FloatPoint& point1, FloatPoint& point2)
271 {
272     float x1;
273     float y1;
274     float x2;
275     float y2;
276     if (!parseNumber(current, end, x1)
277         || !parseNumber(current, end, y1)
278         || !parseNumber(current, end, x2)
279         || !parseNumber(current, end, y2))
280         return false;
281     point1 = FloatPoint(x1, y1);
282     point2 = FloatPoint(x2, y2);
283     return true;
284 }
285
286 template bool parseFloatPoint2(const LChar*& current, const LChar* end, FloatPoint& point1, FloatPoint& point2);
287 template bool parseFloatPoint2(const UChar*& current, const UChar* end, FloatPoint& point1, FloatPoint& point2);
288
289 template <typename CharType>
290 bool parseFloatPoint3(const CharType*& current, const CharType* end, FloatPoint& point1, FloatPoint& point2, FloatPoint& point3)
291 {
292     float x1;
293     float y1;
294     float x2;
295     float y2;
296     float x3;
297     float y3;
298     if (!parseNumber(current, end, x1)
299         || !parseNumber(current, end, y1)
300         || !parseNumber(current, end, x2)
301         || !parseNumber(current, end, y2)
302         || !parseNumber(current, end, x3)
303         || !parseNumber(current, end, y3))
304         return false;
305     point1 = FloatPoint(x1, y1);
306     point2 = FloatPoint(x2, y2);
307     point3 = FloatPoint(x3, y3);
308     return true;
309 }
310
311 template bool parseFloatPoint3(const LChar*& current, const LChar* end, FloatPoint& point1, FloatPoint& point2, FloatPoint& point3);
312 template bool parseFloatPoint3(const UChar*& current, const UChar* end, FloatPoint& point1, FloatPoint& point2, FloatPoint& point3);
313
314 static const LChar skewXDesc[] =  {'s', 'k', 'e', 'w', 'X'};
315 static const LChar skewYDesc[] =  {'s', 'k', 'e', 'w', 'Y'};
316 static const LChar scaleDesc[] =  {'s', 'c', 'a', 'l', 'e'};
317 static const LChar translateDesc[] =  {'t', 'r', 'a', 'n', 's', 'l', 'a', 't', 'e'};
318 static const LChar rotateDesc[] =  {'r', 'o', 't', 'a', 't', 'e'};
319 static const LChar matrixDesc[] =  {'m', 'a', 't', 'r', 'i', 'x'};
320
321 template<typename CharType>
322 bool parseAndSkipTransformType(const CharType*& ptr, const CharType* end, SVGTransformType& type)
323 {
324     if (ptr >= end)
325         return false;
326
327     if (*ptr == 's') {
328         if (skipString(ptr, end, skewXDesc, WTF_ARRAY_LENGTH(skewXDesc)))
329             type = SVG_TRANSFORM_SKEWX;
330         else if (skipString(ptr, end, skewYDesc, WTF_ARRAY_LENGTH(skewYDesc)))
331             type = SVG_TRANSFORM_SKEWY;
332         else if (skipString(ptr, end, scaleDesc, WTF_ARRAY_LENGTH(scaleDesc)))
333             type = SVG_TRANSFORM_SCALE;
334         else
335             return false;
336     } else if (skipString(ptr, end, translateDesc, WTF_ARRAY_LENGTH(translateDesc)))
337         type = SVG_TRANSFORM_TRANSLATE;
338     else if (skipString(ptr, end, rotateDesc, WTF_ARRAY_LENGTH(rotateDesc)))
339         type = SVG_TRANSFORM_ROTATE;
340     else if (skipString(ptr, end, matrixDesc, WTF_ARRAY_LENGTH(matrixDesc)))
341         type = SVG_TRANSFORM_MATRIX;
342     else
343         return false;
344
345     return true;
346 }
347
348 template bool parseAndSkipTransformType(const UChar*& current, const UChar* end, SVGTransformType&);
349 template bool parseAndSkipTransformType(const LChar*& current, const LChar* end, SVGTransformType&);
350
351 SVGTransformType parseTransformType(const String& string)
352 {
353     if (string.isEmpty())
354         return SVG_TRANSFORM_UNKNOWN;
355     SVGTransformType type = SVG_TRANSFORM_UNKNOWN;
356     if (string.is8Bit()) {
357         const LChar* ptr = string.characters8();
358         const LChar* end = ptr + string.length();
359         parseAndSkipTransformType(ptr, end, type);
360     } else {
361         const UChar* ptr = string.characters16();
362         const UChar* end = ptr + string.length();
363         parseAndSkipTransformType(ptr, end, type);
364     }
365     return type;
366 }
367
368 }