00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "wtf/Platform.h"
00025 #if ENABLE(SVG)
00026 #include "xml/Document.h"
00027 #include "SVGParserUtilities.h"
00028
00029 #include "ExceptionCode.h"
00030 #include "FloatConversion.h"
00031 #include "FloatPoint.h"
00032 #include "Path.h"
00033 #include "PlatformString.h"
00034 #include "SVGPathSegList.h"
00035 #include "SVGPathSegArc.h"
00036 #include "SVGPathSegClosePath.h"
00037 #include "SVGPathSegCurvetoCubic.h"
00038 #include "SVGPathSegCurvetoCubicSmooth.h"
00039 #include "SVGPathSegCurvetoQuadratic.h"
00040 #include "SVGPathSegCurvetoQuadraticSmooth.h"
00041 #include "SVGPathSegLineto.h"
00042 #include "SVGPathSegLinetoHorizontal.h"
00043 #include "SVGPathSegLinetoVertical.h"
00044 #include "SVGPathSegList.h"
00045 #include "SVGPathSegMoveto.h"
00046 #include "SVGPointList.h"
00047 #include "SVGPathElement.h"
00048 #include <math.h>
00049 #include <wtf/MathExtras.h>
00050
00051 namespace WebCore {
00052
00053
00054
00055
00056
00057 template <typename FloatType> static bool _parseNumber(const UChar*& ptr, const UChar* end, FloatType& number, bool skip)
00058 {
00059 int integer, exponent;
00060 FloatType decimal, frac;
00061 int sign, expsign;
00062 const UChar* start = ptr;
00063
00064 exponent = 0;
00065 integer = 0;
00066 frac = 1;
00067 decimal = 0;
00068 sign = 1;
00069 expsign = 1;
00070
00071
00072 if (ptr < end && *ptr == '+')
00073 ptr++;
00074 else if (ptr < end && *ptr == '-') {
00075 ptr++;
00076 sign = -1;
00077 }
00078
00079 if (ptr == end || ((*ptr < '0' || *ptr > '9') && *ptr != '.'))
00080
00081 return false;
00082
00083
00084 while (ptr < end && *ptr >= '0' && *ptr <= '9')
00085 integer = (integer * 10) + (ptr++)->unicode() - '0';
00086
00087 if (ptr < end && *ptr == '.') {
00088 ptr++;
00089
00090
00091 if (ptr >= end || *ptr < '0' || *ptr > '9')
00092 return false;
00093
00094 while (ptr < end && *ptr >= '0' && *ptr <= '9')
00095 decimal += ((ptr++)->unicode() - '0') * (frac *= static_cast<FloatType>(0.1));
00096 }
00097
00098
00099 if (ptr != start && ptr + 1 < end && (*ptr == 'e' || *ptr == 'E')
00100 && (ptr[1] != 'x' && ptr[1] != 'm')) {
00101 ptr++;
00102
00103
00104 if (*ptr == '+')
00105 ptr++;
00106 else if (*ptr == '-') {
00107 ptr++;
00108 expsign = -1;
00109 }
00110
00111
00112 if (ptr >= end || *ptr < '0' || *ptr > '9')
00113 return false;
00114
00115 while (ptr < end && *ptr >= '0' && *ptr <= '9') {
00116 exponent *= 10;
00117 exponent += ptr->unicode() - '0';
00118 ptr++;
00119 }
00120 }
00121
00122 number = integer + decimal;
00123 number *= sign * static_cast<FloatType>(pow(10.0, expsign * exponent));
00124
00125 if (start == ptr)
00126 return false;
00127
00128 if (skip)
00129 skipOptionalSpacesOrDelimiter(ptr, end);
00130
00131 return true;
00132 }
00133
00134 bool parseNumber(const UChar*& ptr, const UChar* end, float& number, bool skip)
00135 {
00136 return _parseNumber(ptr, end, number, skip);
00137 }
00138
00139
00140 static bool parseNumber(const UChar*& ptr, const UChar* end, double& number, bool skip = true)
00141 {
00142 return _parseNumber(ptr, end, number, skip);
00143 }
00144
00145 bool parseNumberOptionalNumber(const String& s, float& x, float& y)
00146 {
00147 if (s.isEmpty())
00148 return false;
00149 const UChar* cur = s.characters();
00150 const UChar* end = cur + s.length();
00151
00152 if (!parseNumber(cur, end, x))
00153 return false;
00154
00155 if (cur == end)
00156 y = x;
00157 else if (!parseNumber(cur, end, y, false))
00158 return false;
00159
00160 return cur == end;
00161 }
00162
00163 bool pointsListFromSVGData(SVGPointList* pointsList, const String& points)
00164 {
00165 if (points.isEmpty())
00166 return true;
00167 const UChar* cur = points.characters();
00168 const UChar* end = cur + points.length();
00169
00170 skipOptionalSpaces(cur, end);
00171
00172 bool delimParsed = false;
00173 while (cur < end) {
00174 delimParsed = false;
00175 float xPos = 0.0f;
00176 if (!parseNumber(cur, end, xPos))
00177 return false;
00178
00179 float yPos = 0.0f;
00180 if (!parseNumber(cur, end, yPos, false))
00181 return false;
00182
00183 skipOptionalSpaces(cur, end);
00184
00185 if (cur < end && *cur == ',') {
00186 delimParsed = true;
00187 cur++;
00188 }
00189 skipOptionalSpaces(cur, end);
00190
00191 ExceptionCode ec = 0;
00192 pointsList->appendItem(FloatPoint(xPos, yPos), ec);
00193 }
00194 return cur == end && !delimParsed;
00195 }
00196
00208 class SVGPathParser
00209 {
00210 public:
00211 virtual ~SVGPathParser() { }
00212 bool parseSVG(const String& d, bool process = false);
00213
00214 protected:
00215 virtual void svgMoveTo(double x1, double y1, bool closed, bool abs = true) = 0;
00216 virtual void svgLineTo(double x1, double y1, bool abs = true) = 0;
00217 virtual void svgLineToHorizontal(double x, bool abs = true) {}
00218 virtual void svgLineToVertical(double y, bool abs = true) {}
00219 virtual void svgCurveToCubic(double x1, double y1, double x2, double y2, double x, double y, bool abs = true) = 0;
00220 virtual void svgCurveToCubicSmooth(double x, double y, double x2, double y2, bool abs = true) {}
00221 virtual void svgCurveToQuadratic(double x, double y, double x1, double y1, bool abs = true) {}
00222 virtual void svgCurveToQuadraticSmooth(double x, double y, bool abs = true) {}
00223 virtual void svgArcTo(double x, double y, double r1, double r2, double angle, bool largeArcFlag, bool sweepFlag, bool abs = true) {}
00224 virtual void svgClosePath() = 0;
00225 private:
00226 void calculateArc(bool relative, double& curx, double& cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag);
00227 };
00228
00229 bool SVGPathParser::parseSVG(const String& s, bool process)
00230 {
00231 if (s.isEmpty())
00232 return false;
00233
00234 const UChar* ptr = s.characters();
00235 const UChar* end = ptr + s.length();
00236
00237 double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc;
00238 double px1, py1, px2, py2, px3, py3;
00239 bool closed = true;
00240
00241 if (!skipOptionalSpaces(ptr, end))
00242 return false;
00243
00244 char command = (ptr++)->unicode(), lastCommand = ' ';
00245 if (command != 'm' && command != 'M')
00246 return false;
00247
00248 subpathx = subpathy = curx = cury = contrlx = contrly = 0.0;
00249 while (1) {
00250 skipOptionalSpaces(ptr, end);
00251
00252 bool relative = false;
00253
00254 switch(command)
00255 {
00256 case 'm':
00257 relative = true;
00258 case 'M':
00259 {
00260 if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
00261 return false;
00262
00263 if (process) {
00264 subpathx = curx = relative ? curx + tox : tox;
00265 subpathy = cury = relative ? cury + toy : toy;
00266
00267 svgMoveTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury), closed);
00268 } else
00269 svgMoveTo(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), closed, !relative);
00270 closed = false;
00271 break;
00272 }
00273 case 'l':
00274 relative = true;
00275 case 'L':
00276 {
00277 if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
00278 return false;
00279
00280 if (process) {
00281 curx = relative ? curx + tox : tox;
00282 cury = relative ? cury + toy : toy;
00283
00284 svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury));
00285 }
00286 else
00287 svgLineTo(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative);
00288 break;
00289 }
00290 case 'h':
00291 {
00292 if (!parseNumber(ptr, end, tox))
00293 return false;
00294 if (process) {
00295 curx = curx + tox;
00296 svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury));
00297 }
00298 else
00299 svgLineToHorizontal(narrowPrecisionToFloat(tox), false);
00300 break;
00301 }
00302 case 'H':
00303 {
00304 if (!parseNumber(ptr, end, tox))
00305 return false;
00306 if (process) {
00307 curx = tox;
00308 svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury));
00309 }
00310 else
00311 svgLineToHorizontal(narrowPrecisionToFloat(tox));
00312 break;
00313 }
00314 case 'v':
00315 {
00316 if (!parseNumber(ptr, end, toy))
00317 return false;
00318 if (process) {
00319 cury = cury + toy;
00320 svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury));
00321 }
00322 else
00323 svgLineToVertical(narrowPrecisionToFloat(toy), false);
00324 break;
00325 }
00326 case 'V':
00327 {
00328 if (!parseNumber(ptr, end, toy))
00329 return false;
00330 if (process) {
00331 cury = toy;
00332 svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury));
00333 }
00334 else
00335 svgLineToVertical(narrowPrecisionToFloat(toy));
00336 break;
00337 }
00338 case 'z':
00339 case 'Z':
00340 {
00341
00342 if (process) {
00343 curx = subpathx;
00344 cury = subpathy;
00345 }
00346 closed = true;
00347 svgClosePath();
00348 break;
00349 }
00350 case 'c':
00351 relative = true;
00352 case 'C':
00353 {
00354 if (!parseNumber(ptr, end, x1) || !parseNumber(ptr, end, y1) ||
00355 !parseNumber(ptr, end, x2) || !parseNumber(ptr, end, y2) ||
00356 !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
00357 return false;
00358
00359 if (process) {
00360 px1 = relative ? curx + x1 : x1;
00361 py1 = relative ? cury + y1 : y1;
00362 px2 = relative ? curx + x2 : x2;
00363 py2 = relative ? cury + y2 : y2;
00364 px3 = relative ? curx + tox : tox;
00365 py3 = relative ? cury + toy : toy;
00366
00367 svgCurveToCubic(narrowPrecisionToFloat(px1), narrowPrecisionToFloat(py1), narrowPrecisionToFloat(px2),
00368 narrowPrecisionToFloat(py2), narrowPrecisionToFloat(px3), narrowPrecisionToFloat(py3));
00369
00370 contrlx = relative ? curx + x2 : x2;
00371 contrly = relative ? cury + y2 : y2;
00372 curx = relative ? curx + tox : tox;
00373 cury = relative ? cury + toy : toy;
00374 }
00375 else
00376 svgCurveToCubic(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1), narrowPrecisionToFloat(x2),
00377 narrowPrecisionToFloat(y2), narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative);
00378
00379 break;
00380 }
00381 case 's':
00382 relative = true;
00383 case 'S':
00384 {
00385 if (!parseNumber(ptr, end, x2) || !parseNumber(ptr, end, y2) ||
00386 !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
00387 return false;
00388
00389 if (!(lastCommand == 'c' || lastCommand == 'C' ||
00390 lastCommand == 's' || lastCommand == 'S')) {
00391 contrlx = curx;
00392 contrly = cury;
00393 }
00394
00395 if (process) {
00396 px1 = 2 * curx - contrlx;
00397 py1 = 2 * cury - contrly;
00398 px2 = relative ? curx + x2 : x2;
00399 py2 = relative ? cury + y2 : y2;
00400 px3 = relative ? curx + tox : tox;
00401 py3 = relative ? cury + toy : toy;
00402
00403 svgCurveToCubic(narrowPrecisionToFloat(px1), narrowPrecisionToFloat(py1), narrowPrecisionToFloat(px2),
00404 narrowPrecisionToFloat(py2), narrowPrecisionToFloat(px3), narrowPrecisionToFloat(py3));
00405
00406 contrlx = relative ? curx + x2 : x2;
00407 contrly = relative ? cury + y2 : y2;
00408 curx = relative ? curx + tox : tox;
00409 cury = relative ? cury + toy : toy;
00410 }
00411 else
00412 svgCurveToCubicSmooth(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2),
00413 narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative);
00414 break;
00415 }
00416 case 'q':
00417 relative = true;
00418 case 'Q':
00419 {
00420 if (!parseNumber(ptr, end, x1) || !parseNumber(ptr, end, y1) ||
00421 !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
00422 return false;
00423
00424 if (process) {
00425 px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0);
00426 py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0);
00427 px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0);
00428 py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0);
00429 px3 = relative ? curx + tox : tox;
00430 py3 = relative ? cury + toy : toy;
00431
00432 svgCurveToCubic(narrowPrecisionToFloat(px1), narrowPrecisionToFloat(py1), narrowPrecisionToFloat(px2),
00433 narrowPrecisionToFloat(py2), narrowPrecisionToFloat(px3), narrowPrecisionToFloat(py3));
00434
00435 contrlx = relative ? curx + x1 : x1;
00436 contrly = relative ? cury + y1 : y1;
00437 curx = relative ? curx + tox : tox;
00438 cury = relative ? cury + toy : toy;
00439 }
00440 else
00441 svgCurveToQuadratic(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1),
00442 narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative);
00443 break;
00444 }
00445 case 't':
00446 relative = true;
00447 case 'T':
00448 {
00449 if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
00450 return false;
00451 if (!(lastCommand == 'q' || lastCommand == 'Q' ||
00452 lastCommand == 't' || lastCommand == 'T')) {
00453 contrlx = curx;
00454 contrly = cury;
00455 }
00456
00457 if (process) {
00458 xc = 2 * curx - contrlx;
00459 yc = 2 * cury - contrly;
00460
00461 px1 = relative ? (curx + 2 * xc) * (1.0 / 3.0) : (curx + 2 * xc) * (1.0 / 3.0);
00462 py1 = relative ? (cury + 2 * yc) * (1.0 / 3.0) : (cury + 2 * yc) * (1.0 / 3.0);
00463 px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0);
00464 py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0);
00465 px3 = relative ? curx + tox : tox;
00466 py3 = relative ? cury + toy : toy;
00467
00468 svgCurveToCubic(narrowPrecisionToFloat(px1), narrowPrecisionToFloat(py1), narrowPrecisionToFloat(px2),
00469 narrowPrecisionToFloat(py2), narrowPrecisionToFloat(px3), narrowPrecisionToFloat(py3));
00470
00471 contrlx = xc;
00472 contrly = yc;
00473 curx = relative ? curx + tox : tox;
00474 cury = relative ? cury + toy : toy;
00475 }
00476 else
00477 svgCurveToQuadraticSmooth(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative);
00478 break;
00479 }
00480 case 'a':
00481 relative = true;
00482 case 'A':
00483 {
00484 bool largeArc, sweep;
00485 double angle, rx, ry;
00486 if (!parseNumber(ptr, end, rx) || !parseNumber(ptr, end, ry) ||
00487 !parseNumber(ptr, end, angle) || !parseNumber(ptr, end, tox))
00488 return false;
00489 largeArc = tox == 1;
00490 if (!parseNumber(ptr, end, tox))
00491 return false;
00492 sweep = tox == 1;
00493 if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
00494 return false;
00495
00496
00497 rx = fabs(rx);
00498 ry = fabs(ry);
00499
00500 if (process)
00501 calculateArc(relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
00502 else
00503 svgArcTo(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), narrowPrecisionToFloat(rx), narrowPrecisionToFloat(ry),
00504 narrowPrecisionToFloat(angle), largeArc, sweep, !relative);
00505 break;
00506 }
00507 default:
00508
00509 return false;
00510 }
00511 lastCommand = command;
00512
00513 if (ptr >= end)
00514 return true;
00515
00516
00517 if ((*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9')) &&
00518 (command != 'z' && command != 'Z')) {
00519 if (command == 'M')
00520 command = 'L';
00521 else if (command == 'm')
00522 command = 'l';
00523 } else
00524 command = (ptr++)->unicode();
00525
00526 if (lastCommand != 'C' && lastCommand != 'c' &&
00527 lastCommand != 'S' && lastCommand != 's' &&
00528 lastCommand != 'Q' && lastCommand != 'q' &&
00529 lastCommand != 'T' && lastCommand != 't') {
00530 contrlx = curx;
00531 contrly = cury;
00532 }
00533 }
00534
00535 return false;
00536 }
00537
00538
00539
00540
00541
00542 void SVGPathParser::calculateArc(bool relative, double& curx, double& cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag)
00543 {
00544 double sin_th, cos_th;
00545 double a00, a01, a10, a11;
00546 double x0, y0, x1, y1, xc, yc;
00547 double d, sfactor, sfactor_sq;
00548 double th0, th1, th_arc;
00549 int i, n_segs;
00550
00551 sin_th = sin(angle * (piDouble / 180.0));
00552 cos_th = cos(angle * (piDouble / 180.0));
00553
00554 double dx;
00555
00556 if (!relative)
00557 dx = (curx - x) / 2.0;
00558 else
00559 dx = -x / 2.0;
00560
00561 double dy;
00562
00563 if (!relative)
00564 dy = (cury - y) / 2.0;
00565 else
00566 dy = -y / 2.0;
00567
00568 double _x1 = cos_th * dx + sin_th * dy;
00569 double _y1 = -sin_th * dx + cos_th * dy;
00570 double Pr1 = r1 * r1;
00571 double Pr2 = r2 * r2;
00572 double Px = _x1 * _x1;
00573 double Py = _y1 * _y1;
00574
00575
00576 double check = Px / Pr1 + Py / Pr2;
00577 if (check > 1) {
00578 r1 = r1 * sqrt(check);
00579 r2 = r2 * sqrt(check);
00580 }
00581
00582 a00 = cos_th / r1;
00583 a01 = sin_th / r1;
00584 a10 = -sin_th / r2;
00585 a11 = cos_th / r2;
00586
00587 x0 = a00 * curx + a01 * cury;
00588 y0 = a10 * curx + a11 * cury;
00589
00590 if (!relative)
00591 x1 = a00 * x + a01 * y;
00592 else
00593 x1 = a00 * (curx + x) + a01 * (cury + y);
00594
00595 if (!relative)
00596 y1 = a10 * x + a11 * y;
00597 else
00598 y1 = a10 * (curx + x) + a11 * (cury + y);
00599
00600
00601
00602
00603
00604
00605
00606 d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
00607
00608 sfactor_sq = 1.0 / d - 0.25;
00609
00610 if (sfactor_sq < 0)
00611 sfactor_sq = 0;
00612
00613 sfactor = sqrt(sfactor_sq);
00614
00615 if (sweepFlag == largeArcFlag)
00616 sfactor = -sfactor;
00617
00618 xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
00619 yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
00620
00621
00622 th0 = atan2(y0 - yc, x0 - xc);
00623 th1 = atan2(y1 - yc, x1 - xc);
00624
00625 th_arc = th1 - th0;
00626 if (th_arc < 0 && sweepFlag)
00627 th_arc += 2 * piDouble;
00628 else if (th_arc > 0 && !sweepFlag)
00629 th_arc -= 2 * piDouble;
00630
00631 n_segs = (int) (int) ceil(fabs(th_arc / (piDouble * 0.5 + 0.001)));
00632
00633 for(i = 0; i < n_segs; i++) {
00634 double sin_th, cos_th;
00635 double a00, a01, a10, a11;
00636 double x1, y1, x2, y2, x3, y3;
00637 double t;
00638 double th_half;
00639
00640 double _th0 = th0 + i * th_arc / n_segs;
00641 double _th1 = th0 + (i + 1) * th_arc / n_segs;
00642
00643 sin_th = sin(angle * (piDouble / 180.0));
00644 cos_th = cos(angle * (piDouble / 180.0));
00645
00646
00647 a00 = cos_th * r1;
00648 a01 = -sin_th * r2;
00649 a10 = sin_th * r1;
00650 a11 = cos_th * r2;
00651
00652 th_half = 0.5 * (_th1 - _th0);
00653 t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half);
00654 x1 = xc + cos(_th0) - t * sin(_th0);
00655 y1 = yc + sin(_th0) + t * cos(_th0);
00656 x3 = xc + cos(_th1);
00657 y3 = yc + sin(_th1);
00658 x2 = x3 + t * sin(_th1);
00659 y2 = y3 - t * cos(_th1);
00660
00661 svgCurveToCubic(narrowPrecisionToFloat(a00 * x1 + a01 * y1), narrowPrecisionToFloat(a10 * x1 + a11 * y1),
00662 narrowPrecisionToFloat(a00 * x2 + a01 * y2), narrowPrecisionToFloat(a10 * x2 + a11 * y2),
00663 narrowPrecisionToFloat(a00 * x3 + a01 * y3), narrowPrecisionToFloat(a10 * x3 + a11 * y3));
00664 }
00665
00666 if (!relative)
00667 curx = x;
00668 else
00669 curx += x;
00670
00671 if (!relative)
00672 cury = y;
00673 else
00674 cury += y;
00675 }
00676
00677 class PathBuilder : public SVGPathParser
00678 {
00679 public:
00680 bool build(Path* path, const String& d)
00681 {
00682 m_path = path;
00683 return parseSVG(d, true);
00684 }
00685
00686 private:
00687 virtual void svgMoveTo(double x1, double y1, bool closed, bool abs = true)
00688 {
00689 current.setX(narrowPrecisionToFloat(abs ? x1 : current.x() + x1));
00690 current.setY(narrowPrecisionToFloat(abs ? y1 : current.y() + y1));
00691 if (closed)
00692 m_path->closeSubpath();
00693 m_path->moveTo(current);
00694 }
00695 virtual void svgLineTo(double x1, double y1, bool abs = true)
00696 {
00697 current.setX(narrowPrecisionToFloat(abs ? x1 : current.x() + x1));
00698 current.setY(narrowPrecisionToFloat(abs ? y1 : current.y() + y1));
00699 m_path->addLineTo(current);
00700 }
00701 virtual void svgCurveToCubic(double x1, double y1, double x2, double y2, double x, double y, bool abs = true)
00702 {
00703 if (!abs) {
00704 x1 += current.x();
00705 y1 += current.y();
00706 x2 += current.x();
00707 y2 += current.y();
00708 }
00709 current.setX(narrowPrecisionToFloat(abs ? x : current.x() + x));
00710 current.setY(narrowPrecisionToFloat(abs ? y : current.y() + y));
00711 m_path->addBezierCurveTo(FloatPoint::narrowPrecision(x1, y1), FloatPoint::narrowPrecision(x2, y2), current);
00712 }
00713 virtual void svgClosePath()
00714 {
00715 m_path->closeSubpath();
00716 }
00717 Path* m_path;
00718 FloatPoint current;
00719 };
00720
00721 bool pathFromSVGData(Path& path, const String& d)
00722 {
00723 PathBuilder builder;
00724 return builder.build(&path, d);
00725 }
00726
00727 class SVGPathSegListBuilder : public SVGPathParser
00728 {
00729 public:
00730 bool build(SVGPathSegList* segList, const String& d, bool process)
00731 {
00732 m_pathSegList = segList;
00733 return parseSVG(d, process);
00734 }
00735
00736 private:
00737 virtual void svgMoveTo(double x1, double y1, bool, bool abs = true)
00738 {
00739 ExceptionCode ec = 0;
00740
00741 if (abs)
00742 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegMovetoAbs(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1)), ec);
00743 else
00744 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegMovetoRel(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1)), ec);
00745 }
00746 virtual void svgLineTo(double x1, double y1, bool abs = true)
00747 {
00748 ExceptionCode ec = 0;
00749
00750 if (abs)
00751 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoAbs(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1)), ec);
00752 else
00753 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoRel(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1)), ec);
00754 }
00755 virtual void svgLineToHorizontal(double x, bool abs)
00756 {
00757 ExceptionCode ec = 0;
00758
00759 if (abs)
00760 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoHorizontalAbs(narrowPrecisionToFloat(x)), ec);
00761 else
00762 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoHorizontalRel(narrowPrecisionToFloat(x)), ec);
00763 }
00764 virtual void svgLineToVertical(double y, bool abs)
00765 {
00766 ExceptionCode ec = 0;
00767
00768 if (abs)
00769 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoVerticalAbs(narrowPrecisionToFloat(y)), ec);
00770 else
00771 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoVerticalRel(narrowPrecisionToFloat(y)), ec);
00772 }
00773 virtual void svgCurveToCubic(double x1, double y1, double x2, double y2, double x, double y, bool abs = true)
00774 {
00775 ExceptionCode ec = 0;
00776
00777 if (abs)
00778 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoCubicAbs(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y),
00779 narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1),
00780 narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2)), ec);
00781 else
00782 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoCubicRel(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y),
00783 narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1),
00784 narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2)), ec);
00785 }
00786 virtual void svgCurveToCubicSmooth(double x, double y, double x2, double y2, bool abs)
00787 {
00788 ExceptionCode ec = 0;
00789
00790 if (abs)
00791 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoCubicSmoothAbs(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2),
00792 narrowPrecisionToFloat(x), narrowPrecisionToFloat(y)), ec);
00793 else
00794 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoCubicSmoothRel(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2),
00795 narrowPrecisionToFloat(x), narrowPrecisionToFloat(y)), ec);
00796 }
00797 virtual void svgCurveToQuadratic(double x, double y, double x1, double y1, bool abs)
00798 {
00799 ExceptionCode ec = 0;
00800
00801 if (abs)
00802 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoQuadraticAbs(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1),
00803 narrowPrecisionToFloat(x), narrowPrecisionToFloat(y)), ec);
00804 else
00805 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoQuadraticRel(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1),
00806 narrowPrecisionToFloat(x), narrowPrecisionToFloat(y)), ec);
00807 }
00808 virtual void svgCurveToQuadraticSmooth(double x, double y, bool abs)
00809 {
00810 ExceptionCode ec = 0;
00811
00812 if (abs)
00813 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothAbs(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y)), ec);
00814 else
00815 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothRel(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y)), ec);
00816 }
00817 virtual void svgArcTo(double x, double y, double r1, double r2, double angle, bool largeArcFlag, bool sweepFlag, bool abs)
00818 {
00819 ExceptionCode ec = 0;
00820
00821 if (abs)
00822 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegArcAbs(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y),
00823 narrowPrecisionToFloat(r1), narrowPrecisionToFloat(r2),
00824 narrowPrecisionToFloat(angle), largeArcFlag, sweepFlag), ec);
00825 else
00826 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegArcRel(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y),
00827 narrowPrecisionToFloat(r1), narrowPrecisionToFloat(r2),
00828 narrowPrecisionToFloat(angle), largeArcFlag, sweepFlag), ec);
00829 }
00830 virtual void svgClosePath()
00831 {
00832 ExceptionCode ec = 0;
00833 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegClosePath(), ec);
00834 }
00835 SVGPathSegList* m_pathSegList;
00836 };
00837
00838 bool pathSegListFromSVGData(SVGPathSegList* path , const String& d, bool process)
00839 {
00840 SVGPathSegListBuilder builder;
00841 return builder.build(path, d, process);
00842 }
00843
00844 Vector<String> parseDelimitedString(const String& input, const char separator)
00845 {
00846 Vector<String> values;
00847
00848 const UChar* ptr = input.characters();
00849 const UChar* end = ptr + input.length();
00850 skipOptionalSpaces(ptr, end);
00851
00852 while (ptr < end) {
00853
00854 const UChar* inputStart = ptr;
00855 while (ptr < end && *ptr != separator)
00856 ptr++;
00857
00858 if (ptr == inputStart)
00859 break;
00860
00861
00862 const UChar* inputEnd = ptr - 1;
00863 while (inputStart < inputEnd && isWhitespace(*inputEnd))
00864 inputEnd--;
00865
00866 values.append(String(inputStart, inputEnd - inputStart + 1));
00867 skipOptionalSpacesOrDelimiter(ptr, end, separator);
00868 }
00869
00870 return values;
00871 }
00872
00873 }
00874
00875 #endif // ENABLE(SVG)