1635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project/* 2dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2002, 2003 The Karbon Developers 3dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org> 4dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2006, 2007 Rob Buis <buis@kde.org> 5dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. 6dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * 7dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * This library is free software; you can redistribute it and/or 8dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * modify it under the terms of the GNU Library General Public 9dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * License as published by the Free Software Foundation; either 10dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * version 2 of the License, or (at your option) any later version. 11dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * 12dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * This library is distributed in the hope that it will be useful, 13dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * but WITHOUT ANY WARRANTY; without even the implied warranty of 14dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Library General Public License for more details. 16dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * 17dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * You should have received a copy of the GNU Library General Public License 18dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * along with this library; see the file COPYING.LIB. If not, write to 19dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Boston, MA 02110-1301, USA. 21dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch */ 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 24967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(SVG) 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGParserUtilities.h" 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 28967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#include "Document.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FloatPoint.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGPointList.h" 31f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 32f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <limits> 3321939df44de1705786c545cd1bf519d47250322dBen Murdoch#include <wtf/ASCIICType.h> 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 374576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangtemplate <typename FloatType> static inline bool isValidRange(const FloatType& x) 384576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang{ 394576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang static const FloatType max = std::numeric_limits<FloatType>::max(); 404576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return x >= -max && x <= max; 414576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang} 424576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang 435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// We use this generic parseNumber function to allow the Path parsing code to work 445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// at a higher precision internally, without any unnecessary runtime cost or code 455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// complexity. 465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsentemplate <typename FloatType> static bool genericParseNumber(const UChar*& ptr, const UChar* end, FloatType& number, bool skip) 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 484576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang FloatType integer, decimal, frac, exponent; 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int sign, expsign; 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* start = ptr; 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project exponent = 0; 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project integer = 0; 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project frac = 1; 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project decimal = 0; 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project sign = 1; 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project expsign = 1; 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // read the sign 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (ptr < end && *ptr == '+') 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr++; 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else if (ptr < end && *ptr == '-') { 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr++; 648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project sign = -1; 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (ptr == end || ((*ptr < '0' || *ptr > '9') && *ptr != '.')) 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The first character of a number must be one of [0-9+-.] 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 71db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block // read the integer part, build right-to-left 72db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block const UChar* ptrStartIntPart = ptr; 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (ptr < end && *ptr >= '0' && *ptr <= '9') 74db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block ++ptr; // Advance to first non-digit. 75db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block 76db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block if (ptr != ptrStartIntPart) { 77db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block const UChar* ptrScanIntPart = ptr - 1; 78db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block FloatType multiplier = 1; 79db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block while (ptrScanIntPart >= ptrStartIntPart) { 80db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block integer += multiplier * static_cast<FloatType>(*(ptrScanIntPart--) - '0'); 81db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block multiplier *= 10; 82db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block } 834576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang // Bail out early if this overflows. 844576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang if (!isValidRange(integer)) 854576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return false; 86db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block } 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (ptr < end && *ptr == '.') { // read the decimals 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr++; 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // There must be a least one digit following the . 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (ptr >= end || *ptr < '0' || *ptr > '9') 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (ptr < end && *ptr >= '0' && *ptr <= '9') 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project decimal += (*(ptr++) - '0') * (frac *= static_cast<FloatType>(0.1)); 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // read the exponent part 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (ptr != start && ptr + 1 < end && (*ptr == 'e' || *ptr == 'E') 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && (ptr[1] != 'x' && ptr[1] != 'm')) { 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr++; 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // read the sign of the exponent 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (*ptr == '+') 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr++; 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else if (*ptr == '-') { 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr++; 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project expsign = -1; 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // There must be an exponent 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (ptr >= end || *ptr < '0' || *ptr > '9') 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (ptr < end && *ptr >= '0' && *ptr <= '9') { 1174576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang exponent *= static_cast<FloatType>(10); 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project exponent += *ptr - '0'; 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr++; 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1214576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang // Make sure exponent is valid. 1224576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang if (!isValidRange(exponent) || exponent > std::numeric_limits<FloatType>::max_exponent) 1234576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return false; 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project number = integer + decimal; 127bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen number *= sign; 128bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 129bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (exponent) 1304576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang number *= static_cast<FloatType>(pow(10.0, expsign * static_cast<int>(exponent))); 1314576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang 1324576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang // Don't return Infinity() or NaN(). 1334576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang if (!isValidRange(number)) 1344576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return false; 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (start == ptr) 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (skip) 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project skipOptionalSpacesOrDelimiter(ptr, end); 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool parseNumber(const UChar*& ptr, const UChar* end, float& number, bool skip) 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen return genericParseNumber(ptr, end, number, skip); 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 150dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block// only used to parse largeArcFlag and sweepFlag which must be a "0" or "1" 151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block// and might not have any whitespace/comma after it 152967717af5423377c967781471ee106e2bb4e11c8Ben Murdochbool parseArcFlag(const UChar*& ptr, const UChar* end, bool& flag) 153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block const UChar flagChar = *ptr++; 155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (flagChar == '0') 156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block flag = false; 157dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else if (flagChar == '1') 158dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block flag = true; 159dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else 160dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return false; 161dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 162dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block skipOptionalSpacesOrDelimiter(ptr, end); 163dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 164dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return true; 165dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 166dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool parseNumberOptionalNumber(const String& s, float& x, float& y) 1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (s.isEmpty()) 1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* cur = s.characters(); 1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* end = cur + s.length(); 1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!parseNumber(cur, end, x)) 1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (cur == end) 1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project y = x; 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else if (!parseNumber(cur, end, y, false)) 1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return cur == end; 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 18528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhubool pointsListFromSVGData(SVGPointList& pointsList, const String& points) 1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (points.isEmpty()) 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* cur = points.characters(); 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* end = cur + points.length(); 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project skipOptionalSpaces(cur, end); 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool delimParsed = false; 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (cur < end) { 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project delimParsed = false; 1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float xPos = 0.0f; 1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!parseNumber(cur, end, xPos)) 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float yPos = 0.0f; 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!parseNumber(cur, end, yPos, false)) 2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project skipOptionalSpaces(cur, end); 2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (cur < end && *cur == ',') { 2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project delimParsed = true; 2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project cur++; 2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project skipOptionalSpaces(cur, end); 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 21328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu pointsList.append(FloatPoint(xPos, yPos)); 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return cur == end && !delimParsed; 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2186c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenbool parseGlyphName(const String& input, HashSet<String>& values) 21921939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 2206c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // FIXME: Parsing error detection is missing. 22121939df44de1705786c545cd1bf519d47250322dBen Murdoch values.clear(); 22221939df44de1705786c545cd1bf519d47250322dBen Murdoch 22321939df44de1705786c545cd1bf519d47250322dBen Murdoch const UChar* ptr = input.characters(); 22421939df44de1705786c545cd1bf519d47250322dBen Murdoch const UChar* end = ptr + input.length(); 22521939df44de1705786c545cd1bf519d47250322dBen Murdoch skipOptionalSpaces(ptr, end); 22621939df44de1705786c545cd1bf519d47250322dBen Murdoch 22721939df44de1705786c545cd1bf519d47250322dBen Murdoch while (ptr < end) { 22821939df44de1705786c545cd1bf519d47250322dBen Murdoch // Leading and trailing white space, and white space before and after separators, will be ignored. 22921939df44de1705786c545cd1bf519d47250322dBen Murdoch const UChar* inputStart = ptr; 23021939df44de1705786c545cd1bf519d47250322dBen Murdoch while (ptr < end && *ptr != ',') 23121939df44de1705786c545cd1bf519d47250322dBen Murdoch ++ptr; 23221939df44de1705786c545cd1bf519d47250322dBen Murdoch 23321939df44de1705786c545cd1bf519d47250322dBen Murdoch if (ptr == inputStart) 23421939df44de1705786c545cd1bf519d47250322dBen Murdoch break; 23521939df44de1705786c545cd1bf519d47250322dBen Murdoch 23621939df44de1705786c545cd1bf519d47250322dBen Murdoch // walk backwards from the ; to ignore any whitespace 23721939df44de1705786c545cd1bf519d47250322dBen Murdoch const UChar* inputEnd = ptr - 1; 23821939df44de1705786c545cd1bf519d47250322dBen Murdoch while (inputStart < inputEnd && isWhitespace(*inputEnd)) 23921939df44de1705786c545cd1bf519d47250322dBen Murdoch --inputEnd; 24021939df44de1705786c545cd1bf519d47250322dBen Murdoch 24121939df44de1705786c545cd1bf519d47250322dBen Murdoch values.add(String(inputStart, inputEnd - inputStart + 1)); 24221939df44de1705786c545cd1bf519d47250322dBen Murdoch skipOptionalSpacesOrDelimiter(ptr, end, ','); 24321939df44de1705786c545cd1bf519d47250322dBen Murdoch } 2446c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 2456c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return true; 24621939df44de1705786c545cd1bf519d47250322dBen Murdoch} 24721939df44de1705786c545cd1bf519d47250322dBen Murdoch 24821939df44de1705786c545cd1bf519d47250322dBen Murdochstatic bool parseUnicodeRange(const UChar* characters, unsigned length, UnicodeRange& range) 24921939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 25021939df44de1705786c545cd1bf519d47250322dBen Murdoch if (length < 2 || characters[0] != 'U' || characters[1] != '+') 25121939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; 25221939df44de1705786c545cd1bf519d47250322dBen Murdoch 25321939df44de1705786c545cd1bf519d47250322dBen Murdoch // Parse the starting hex number (or its prefix). 25421939df44de1705786c545cd1bf519d47250322dBen Murdoch unsigned startRange = 0; 25521939df44de1705786c545cd1bf519d47250322dBen Murdoch unsigned startLength = 0; 25621939df44de1705786c545cd1bf519d47250322dBen Murdoch 25721939df44de1705786c545cd1bf519d47250322dBen Murdoch const UChar* ptr = characters + 2; 25821939df44de1705786c545cd1bf519d47250322dBen Murdoch const UChar* end = characters + length; 25921939df44de1705786c545cd1bf519d47250322dBen Murdoch while (ptr < end) { 26021939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!isASCIIHexDigit(*ptr)) 26121939df44de1705786c545cd1bf519d47250322dBen Murdoch break; 26221939df44de1705786c545cd1bf519d47250322dBen Murdoch ++startLength; 26321939df44de1705786c545cd1bf519d47250322dBen Murdoch if (startLength > 6) 26421939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; 26521939df44de1705786c545cd1bf519d47250322dBen Murdoch startRange = (startRange << 4) | toASCIIHexValue(*ptr); 26621939df44de1705786c545cd1bf519d47250322dBen Murdoch ++ptr; 26721939df44de1705786c545cd1bf519d47250322dBen Murdoch } 26821939df44de1705786c545cd1bf519d47250322dBen Murdoch 26921939df44de1705786c545cd1bf519d47250322dBen Murdoch // Handle the case of ranges separated by "-" sign. 27021939df44de1705786c545cd1bf519d47250322dBen Murdoch if (2 + startLength < length && *ptr == '-') { 27121939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!startLength) 27221939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; 27321939df44de1705786c545cd1bf519d47250322dBen Murdoch 27421939df44de1705786c545cd1bf519d47250322dBen Murdoch // Parse the ending hex number (or its prefix). 27521939df44de1705786c545cd1bf519d47250322dBen Murdoch unsigned endRange = 0; 27621939df44de1705786c545cd1bf519d47250322dBen Murdoch unsigned endLength = 0; 27721939df44de1705786c545cd1bf519d47250322dBen Murdoch ++ptr; 27821939df44de1705786c545cd1bf519d47250322dBen Murdoch while (ptr < end) { 27921939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!isASCIIHexDigit(*ptr)) 28021939df44de1705786c545cd1bf519d47250322dBen Murdoch break; 28121939df44de1705786c545cd1bf519d47250322dBen Murdoch ++endLength; 28221939df44de1705786c545cd1bf519d47250322dBen Murdoch if (endLength > 6) 28321939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; 28421939df44de1705786c545cd1bf519d47250322dBen Murdoch endRange = (endRange << 4) | toASCIIHexValue(*ptr); 28521939df44de1705786c545cd1bf519d47250322dBen Murdoch ++ptr; 28621939df44de1705786c545cd1bf519d47250322dBen Murdoch } 28721939df44de1705786c545cd1bf519d47250322dBen Murdoch 28821939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!endLength) 28921939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; 29021939df44de1705786c545cd1bf519d47250322dBen Murdoch 29121939df44de1705786c545cd1bf519d47250322dBen Murdoch range.first = startRange; 29221939df44de1705786c545cd1bf519d47250322dBen Murdoch range.second = endRange; 29321939df44de1705786c545cd1bf519d47250322dBen Murdoch return true; 29421939df44de1705786c545cd1bf519d47250322dBen Murdoch } 29521939df44de1705786c545cd1bf519d47250322dBen Murdoch 29621939df44de1705786c545cd1bf519d47250322dBen Murdoch // Handle the case of a number with some optional trailing question marks. 29721939df44de1705786c545cd1bf519d47250322dBen Murdoch unsigned endRange = startRange; 29821939df44de1705786c545cd1bf519d47250322dBen Murdoch while (ptr < end) { 29921939df44de1705786c545cd1bf519d47250322dBen Murdoch if (*ptr != '?') 30021939df44de1705786c545cd1bf519d47250322dBen Murdoch break; 30121939df44de1705786c545cd1bf519d47250322dBen Murdoch ++startLength; 30221939df44de1705786c545cd1bf519d47250322dBen Murdoch if (startLength > 6) 30321939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; 30421939df44de1705786c545cd1bf519d47250322dBen Murdoch startRange <<= 4; 30521939df44de1705786c545cd1bf519d47250322dBen Murdoch endRange = (endRange << 4) | 0xF; 30621939df44de1705786c545cd1bf519d47250322dBen Murdoch ++ptr; 30721939df44de1705786c545cd1bf519d47250322dBen Murdoch } 30821939df44de1705786c545cd1bf519d47250322dBen Murdoch 30921939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!startLength) 31021939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; 31121939df44de1705786c545cd1bf519d47250322dBen Murdoch 31221939df44de1705786c545cd1bf519d47250322dBen Murdoch range.first = startRange; 31321939df44de1705786c545cd1bf519d47250322dBen Murdoch range.second = endRange; 31421939df44de1705786c545cd1bf519d47250322dBen Murdoch return true; 31521939df44de1705786c545cd1bf519d47250322dBen Murdoch} 31621939df44de1705786c545cd1bf519d47250322dBen Murdoch 3176c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenbool parseKerningUnicodeString(const String& input, UnicodeRanges& rangeList, HashSet<String>& stringList) 31821939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 3196c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // FIXME: Parsing error detection is missing. 32021939df44de1705786c545cd1bf519d47250322dBen Murdoch const UChar* ptr = input.characters(); 32121939df44de1705786c545cd1bf519d47250322dBen Murdoch const UChar* end = ptr + input.length(); 32221939df44de1705786c545cd1bf519d47250322dBen Murdoch 32321939df44de1705786c545cd1bf519d47250322dBen Murdoch while (ptr < end) { 32421939df44de1705786c545cd1bf519d47250322dBen Murdoch const UChar* inputStart = ptr; 32521939df44de1705786c545cd1bf519d47250322dBen Murdoch while (ptr < end && *ptr != ',') 32621939df44de1705786c545cd1bf519d47250322dBen Murdoch ++ptr; 32721939df44de1705786c545cd1bf519d47250322dBen Murdoch 32821939df44de1705786c545cd1bf519d47250322dBen Murdoch if (ptr == inputStart) 32921939df44de1705786c545cd1bf519d47250322dBen Murdoch break; 33021939df44de1705786c545cd1bf519d47250322dBen Murdoch 33121939df44de1705786c545cd1bf519d47250322dBen Murdoch // Try to parse unicode range first 33221939df44de1705786c545cd1bf519d47250322dBen Murdoch UnicodeRange range; 33321939df44de1705786c545cd1bf519d47250322dBen Murdoch if (parseUnicodeRange(inputStart, ptr - inputStart, range)) 33421939df44de1705786c545cd1bf519d47250322dBen Murdoch rangeList.append(range); 33521939df44de1705786c545cd1bf519d47250322dBen Murdoch else 33621939df44de1705786c545cd1bf519d47250322dBen Murdoch stringList.add(String(inputStart, ptr - inputStart)); 33721939df44de1705786c545cd1bf519d47250322dBen Murdoch ++ptr; 33821939df44de1705786c545cd1bf519d47250322dBen Murdoch } 3396c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 3406c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return true; 34121939df44de1705786c545cd1bf519d47250322dBen Murdoch} 34221939df44de1705786c545cd1bf519d47250322dBen Murdoch 3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVector<String> parseDelimitedString(const String& input, const char seperator) 3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<String> values; 3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* ptr = input.characters(); 3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* end = ptr + input.length(); 3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project skipOptionalSpaces(ptr, end); 3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (ptr < end) { 3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Leading and trailing white space, and white space before and after semicolon separators, will be ignored. 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* inputStart = ptr; 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (ptr < end && *ptr != seperator) // careful not to ignore whitespace inside inputs 3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr++; 3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (ptr == inputStart) 3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // walk backwards from the ; to ignore any whitespace 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* inputEnd = ptr - 1; 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (inputStart < inputEnd && isWhitespace(*inputEnd)) 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project inputEnd--; 3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project values.append(String(inputStart, inputEnd - inputStart + 1)); 3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project skipOptionalSpacesOrDelimiter(ptr, end, seperator); 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return values; 3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif // ENABLE(SVG) 375