~ubuntu-branches/ubuntu/maverick/webkit/maverick

« back to all changes in this revision

Viewing changes to WebCore/ksvg2/svg/SVGParserUtilities.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mike Hommey
  • Date: 2007-08-19 15:54:12 UTC
  • Revision ID: james.westby@ubuntu.com-20070819155412-uxxg1h9plpghmtbi
Tags: upstream-0~svn25144
ImportĀ upstreamĀ versionĀ 0~svn25144

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of the KDE project
 
2
   Copyright (C) 2002, 2003 The Karbon Developers
 
3
                 2006       Alexander Kellett <lypanov@kde.org>
 
4
                 2006, 2007 Rob Buis <buis@kde.org>
 
5
 
 
6
   This library is free software; you can redistribute it and/or
 
7
   modify it under the terms of the GNU Library General Public
 
8
   License as published by the Free Software Foundation; either
 
9
   version 2 of the License, or (at your option) any later version.
 
10
 
 
11
   This library is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
   Library General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU Library General Public License
 
17
   along with this library; see the file COPYING.LIB.  If not, write to
 
18
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
19
   Boston, MA 02111-1307, USA.
 
20
*/
 
21
 
 
22
#include "config.h"
 
23
#if ENABLE(SVG)
 
24
#include "SVGParserUtilities.h"
 
25
 
 
26
#include "FloatConversion.h"
 
27
#include "PlatformString.h"
 
28
#include <math.h>
 
29
#include <wtf/MathExtras.h>
 
30
 
 
31
namespace WebCore {
 
32
 
 
33
bool parseNumber(const UChar*& ptr, const UChar* end, double& number, bool skip)
 
34
{
 
35
    int integer, exponent;
 
36
    double decimal, frac;
 
37
    int sign, expsign;
 
38
    const UChar* start = ptr;
 
39
 
 
40
    exponent = 0;
 
41
    integer = 0;
 
42
    frac = 1.0;
 
43
    decimal = 0;
 
44
    sign = 1;
 
45
    expsign = 1;
 
46
 
 
47
    // read the sign
 
48
    if (ptr < end && *ptr == '+')
 
49
        ptr++;
 
50
    else if (ptr < end && *ptr == '-') {
 
51
        ptr++;
 
52
        sign = -1;
 
53
    }
 
54
    // read the integer part
 
55
    while (ptr < end && *ptr >= '0' && *ptr <= '9')
 
56
        integer = (integer * 10) + *(ptr++) - '0';
 
57
 
 
58
    if (ptr < end && *ptr == '.') { // read the decimals
 
59
        ptr++;
 
60
        while(ptr < end && *ptr >= '0' && *ptr <= '9')
 
61
            decimal += (*(ptr++) - '0') * (frac *= 0.1);
 
62
    }
 
63
 
 
64
    if (ptr < end && (*ptr == 'e' || *ptr == 'E')) { // read the exponent part
 
65
        ptr++;
 
66
 
 
67
        // read the sign of the exponent
 
68
        if (ptr < end && *ptr == '+')
 
69
            ptr++;
 
70
        else if (ptr < end && *ptr == '-') {
 
71
            ptr++;
 
72
            expsign = -1;
 
73
        }
 
74
 
 
75
        while (ptr < end && *ptr >= '0' && *ptr <= '9') {
 
76
            exponent *= 10;
 
77
            exponent += *ptr - '0';
 
78
            ptr++;
 
79
        }
 
80
    }
 
81
 
 
82
    number = integer + decimal;
 
83
    number *= sign * pow(10.0, expsign * exponent);
 
84
 
 
85
    if (start == ptr)
 
86
        return false;
 
87
 
 
88
    if (skip)
 
89
        skipOptionalSpacesOrDelimiter(ptr, end);
 
90
 
 
91
    return true;
 
92
}
 
93
 
 
94
bool parseNumberOptionalNumber(const String& s, double& x, double& y)
 
95
{
 
96
    if (s.isEmpty())
 
97
        return false;
 
98
    const UChar* cur = s.characters();
 
99
    const UChar* end = cur + s.length();
 
100
 
 
101
    if (!parseNumber(cur, end, x))
 
102
        return false;
 
103
 
 
104
    if (cur == end)
 
105
        y = x;
 
106
    else if (!parseNumber(cur, end, y, false))
 
107
        return false;
 
108
 
 
109
    return cur == end;
 
110
}
 
111
 
 
112
bool SVGPolyParser::parsePoints(const String& s) const
 
113
{
 
114
    if (s.isEmpty())
 
115
        return true;
 
116
    const UChar* cur = s.characters();
 
117
    const UChar* end = cur + s.length();
 
118
 
 
119
    skipOptionalSpaces(cur, end);
 
120
 
 
121
    bool delimParsed = false;
 
122
    int segmentNum = 0;
 
123
    while (cur < end) {
 
124
        delimParsed = false;
 
125
        double xPos = 0;
 
126
        if (!parseNumber(cur, end, xPos))
 
127
           return false;
 
128
 
 
129
        double yPos = 0;
 
130
        if (!parseNumber(cur, end, yPos, false))
 
131
            return false;
 
132
 
 
133
        skipOptionalSpaces(cur, end);
 
134
 
 
135
        if (cur < end && *cur == ',') {
 
136
            delimParsed = true;
 
137
            cur++;
 
138
        }
 
139
        skipOptionalSpaces(cur, end);
 
140
 
 
141
        svgPolyTo(xPos, yPos, segmentNum++);
 
142
    }
 
143
    return cur == end && !delimParsed;
 
144
}
 
145
 
 
146
bool SVGPathParser::parseSVG(const String& s, bool process)
 
147
{
 
148
    if (s.isEmpty())
 
149
        return false;
 
150
 
 
151
    const UChar* ptr = s.characters();
 
152
    const UChar* end = ptr + s.length();
 
153
 
 
154
    double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc;
 
155
    double px1, py1, px2, py2, px3, py3;
 
156
    bool closed = true;
 
157
    
 
158
    if (!skipOptionalSpaces(ptr, end)) // skip any leading spaces
 
159
        return false;
 
160
    
 
161
    char command = *(ptr++), lastCommand = ' ';
 
162
    if (command != 'm' && command != 'M') // path must start with moveto
 
163
        return false;
 
164
 
 
165
    subpathx = subpathy = curx = cury = contrlx = contrly = 0.0;
 
166
    while (1) {
 
167
        skipOptionalSpaces(ptr, end); // skip spaces between command and first coord
 
168
 
 
169
        bool relative = false;
 
170
 
 
171
        switch(command)
 
172
        {
 
173
            case 'm':
 
174
                relative = true;
 
175
            case 'M':
 
176
            {
 
177
                if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
 
178
                    return false;
 
179
 
 
180
                if (process) {
 
181
                    subpathx = curx = relative ? curx + tox : tox;
 
182
                    subpathy = cury = relative ? cury + toy : toy;
 
183
 
 
184
                    svgMoveTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury), closed);
 
185
                } else
 
186
                    svgMoveTo(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), closed, !relative);
 
187
                closed = false;
 
188
                break;
 
189
            }
 
190
            case 'l':
 
191
                relative = true;
 
192
            case 'L':
 
193
            {
 
194
                if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
 
195
                    return false;
 
196
 
 
197
                if (process) {
 
198
                    curx = relative ? curx + tox : tox;
 
199
                    cury = relative ? cury + toy : toy;
 
200
 
 
201
                    svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury));
 
202
                }
 
203
                else
 
204
                    svgLineTo(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative);
 
205
                break;
 
206
            }
 
207
            case 'h':
 
208
            {
 
209
                if (!parseNumber(ptr, end, tox))
 
210
                    return false;
 
211
                if (process) {
 
212
                    curx = curx + tox;
 
213
                    svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury));
 
214
                }
 
215
                else
 
216
                    svgLineToHorizontal(narrowPrecisionToFloat(tox), false);
 
217
                break;
 
218
            }
 
219
            case 'H':
 
220
            {
 
221
                if (!parseNumber(ptr, end, tox))
 
222
                    return false;
 
223
                if (process) {
 
224
                    curx = tox;
 
225
                    svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury));
 
226
                }
 
227
                else
 
228
                    svgLineToHorizontal(narrowPrecisionToFloat(tox));
 
229
                break;
 
230
            }
 
231
            case 'v':
 
232
            {
 
233
                if (!parseNumber(ptr, end, toy))
 
234
                    return false;
 
235
                if (process) {
 
236
                    cury = cury + toy;
 
237
                    svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury));
 
238
                }
 
239
                else
 
240
                    svgLineToVertical(narrowPrecisionToFloat(toy), false);
 
241
                break;
 
242
            }
 
243
            case 'V':
 
244
            {
 
245
                if (!parseNumber(ptr, end, toy))
 
246
                    return false;
 
247
                if (process) {
 
248
                    cury = toy;
 
249
                    svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury));
 
250
                }
 
251
                else
 
252
                    svgLineToVertical(narrowPrecisionToFloat(toy));
 
253
                break;
 
254
            }
 
255
            case 'z':
 
256
            case 'Z':
 
257
            {
 
258
                // reset curx, cury for next path
 
259
                if (process) {
 
260
                    curx = subpathx;
 
261
                    cury = subpathy;
 
262
                }
 
263
                closed = true;
 
264
                svgClosePath();
 
265
                break;
 
266
            }
 
267
            case 'c':
 
268
                relative = true;
 
269
            case 'C':
 
270
            {
 
271
                if (!parseNumber(ptr, end, x1)  || !parseNumber(ptr, end, y1) ||
 
272
                    !parseNumber(ptr, end, x2)  || !parseNumber(ptr, end, y2) ||
 
273
                    !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
 
274
                    return false;
 
275
 
 
276
                if (process) {
 
277
                    px1 = relative ? curx + x1 : x1;
 
278
                    py1 = relative ? cury + y1 : y1;
 
279
                    px2 = relative ? curx + x2 : x2;
 
280
                    py2 = relative ? cury + y2 : y2;
 
281
                    px3 = relative ? curx + tox : tox;
 
282
                    py3 = relative ? cury + toy : toy;
 
283
 
 
284
                    svgCurveToCubic(narrowPrecisionToFloat(px1), narrowPrecisionToFloat(py1), narrowPrecisionToFloat(px2), 
 
285
                                    narrowPrecisionToFloat(py2), narrowPrecisionToFloat(px3), narrowPrecisionToFloat(py3));
 
286
 
 
287
                    contrlx = relative ? curx + x2 : x2;
 
288
                    contrly = relative ? cury + y2 : y2;
 
289
                    curx = relative ? curx + tox : tox;
 
290
                    cury = relative ? cury + toy : toy;
 
291
                }
 
292
                else
 
293
                    svgCurveToCubic(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1), narrowPrecisionToFloat(x2),
 
294
                                    narrowPrecisionToFloat(y2), narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative);
 
295
 
 
296
                break;
 
297
            }
 
298
            case 's':
 
299
                relative = true;
 
300
            case 'S':
 
301
            {
 
302
                if (!parseNumber(ptr, end, x2)  || !parseNumber(ptr, end, y2) ||
 
303
                    !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
 
304
                    return false;
 
305
 
 
306
                if (!(lastCommand == 'c' || lastCommand == 'C' ||
 
307
                     lastCommand == 's' || lastCommand == 'S')) {
 
308
                    contrlx = curx;
 
309
                    contrly = cury;
 
310
                }
 
311
 
 
312
                if (process) {
 
313
                    px1 = 2 * curx - contrlx;
 
314
                    py1 = 2 * cury - contrly;
 
315
                    px2 = relative ? curx + x2 : x2;
 
316
                    py2 = relative ? cury + y2 : y2;
 
317
                    px3 = relative ? curx + tox : tox;
 
318
                    py3 = relative ? cury + toy : toy;
 
319
 
 
320
                    svgCurveToCubic(narrowPrecisionToFloat(px1), narrowPrecisionToFloat(py1), narrowPrecisionToFloat(px2),
 
321
                                    narrowPrecisionToFloat(py2), narrowPrecisionToFloat(px3), narrowPrecisionToFloat(py3));
 
322
 
 
323
                    contrlx = relative ? curx + x2 : x2;
 
324
                    contrly = relative ? cury + y2 : y2;
 
325
                    curx = relative ? curx + tox : tox;
 
326
                    cury = relative ? cury + toy : toy;
 
327
                }
 
328
                else
 
329
                    svgCurveToCubicSmooth(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2), 
 
330
                                          narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative);
 
331
                break;
 
332
            }
 
333
            case 'q':
 
334
                relative = true;
 
335
            case 'Q':
 
336
            {
 
337
                if (!parseNumber(ptr, end, x1)  || !parseNumber(ptr, end, y1) ||
 
338
                    !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
 
339
                    return false;
 
340
 
 
341
                if (process) {
 
342
                    px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0);
 
343
                    py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0);
 
344
                    px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0);
 
345
                    py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0);
 
346
                    px3 = relative ? curx + tox : tox;
 
347
                    py3 = relative ? cury + toy : toy;
 
348
 
 
349
                    svgCurveToCubic(narrowPrecisionToFloat(px1), narrowPrecisionToFloat(py1), narrowPrecisionToFloat(px2),
 
350
                                    narrowPrecisionToFloat(py2), narrowPrecisionToFloat(px3), narrowPrecisionToFloat(py3));
 
351
 
 
352
                    contrlx = relative ? curx + x1 : x1;
 
353
                    contrly = relative ? cury + y1 : y1;
 
354
                    curx = relative ? curx + tox : tox;
 
355
                    cury = relative ? cury + toy : toy;
 
356
                }
 
357
                else
 
358
                    svgCurveToQuadratic(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1),
 
359
                                        narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative);
 
360
                break;
 
361
            }
 
362
            case 't':
 
363
                relative = true;
 
364
            case 'T':
 
365
            {
 
366
                if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
 
367
                    return false;
 
368
                if (!(lastCommand == 'q' || lastCommand == 'Q' ||
 
369
                     lastCommand == 't' || lastCommand == 'T')) {
 
370
                    contrlx = curx;
 
371
                    contrly = cury;
 
372
                }
 
373
 
 
374
                if (process) {
 
375
                    xc = 2 * curx - contrlx;
 
376
                    yc = 2 * cury - contrly;
 
377
 
 
378
                    px1 = relative ? (curx + 2 * xc) * (1.0 / 3.0) : (curx + 2 * xc) * (1.0 / 3.0);
 
379
                    py1 = relative ? (cury + 2 * yc) * (1.0 / 3.0) : (cury + 2 * yc) * (1.0 / 3.0);
 
380
                    px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0);
 
381
                    py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0);
 
382
                    px3 = relative ? curx + tox : tox;
 
383
                    py3 = relative ? cury + toy : toy;
 
384
 
 
385
                    svgCurveToCubic(narrowPrecisionToFloat(px1), narrowPrecisionToFloat(py1), narrowPrecisionToFloat(px2),
 
386
                                    narrowPrecisionToFloat(py2), narrowPrecisionToFloat(px3), narrowPrecisionToFloat(py3));
 
387
 
 
388
                    contrlx = xc;
 
389
                    contrly = yc;
 
390
                    curx = relative ? curx + tox : tox;
 
391
                    cury = relative ? cury + toy : toy;
 
392
                }
 
393
                else
 
394
                    svgCurveToQuadraticSmooth(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative);
 
395
                break;
 
396
            }
 
397
            case 'a':
 
398
                relative = true;
 
399
            case 'A':
 
400
            {
 
401
                bool largeArc, sweep;
 
402
                double angle, rx, ry;
 
403
                if (!parseNumber(ptr, end, rx)    || !parseNumber(ptr, end, ry) ||
 
404
                    !parseNumber(ptr, end, angle) || !parseNumber(ptr, end, tox))
 
405
                    return false;
 
406
                largeArc = tox == 1;
 
407
                if (!parseNumber(ptr, end, tox))
 
408
                    return false;
 
409
                sweep = tox == 1;
 
410
                if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
 
411
                    return false;
 
412
 
 
413
                // Spec: radii are nonnegative numbers
 
414
                rx = fabs(rx);
 
415
                ry = fabs(ry);
 
416
 
 
417
                if (process)
 
418
                    calculateArc(relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
 
419
                else
 
420
                    svgArcTo(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), narrowPrecisionToFloat(rx), narrowPrecisionToFloat(ry),
 
421
                             narrowPrecisionToFloat(angle), largeArc, sweep, !relative);
 
422
                break;
 
423
            }
 
424
            default:
 
425
                // FIXME: An error should go to the JavaScript console, or the like.
 
426
                return false;
 
427
        }
 
428
        lastCommand = command;
 
429
 
 
430
        if (ptr >= end)
 
431
            return true;
 
432
 
 
433
        // Check for remaining coordinates in the current command.
 
434
        if ((*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9')) &&
 
435
            (command != 'z' && command !='a' && command != 'A')) {
 
436
            if (command == 'M')
 
437
                command = 'L';
 
438
            else if (command == 'm')
 
439
                command = 'l';
 
440
        } else
 
441
            command = *(ptr++);
 
442
 
 
443
        if (lastCommand != 'C' && lastCommand != 'c' &&
 
444
            lastCommand != 'S' && lastCommand != 's' &&
 
445
            lastCommand != 'Q' && lastCommand != 'q' &&
 
446
            lastCommand != 'T' && lastCommand != 't') {
 
447
            contrlx = curx;
 
448
            contrly = cury;
 
449
        }
 
450
    }
 
451
 
 
452
    return false;
 
453
}
 
454
 
 
455
// This works by converting the SVG arc to "simple" beziers.
 
456
// For each bezier found a svgToCurve call is done.
 
457
// Adapted from Niko's code in kdelibs/kdecore/svgicons.
 
458
// Maybe this can serve in some shared lib? (Rob)
 
459
void SVGPathParser::calculateArc(bool relative, double& curx, double& cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag)
 
460
{
 
461
    double sin_th, cos_th;
 
462
    double a00, a01, a10, a11;
 
463
    double x0, y0, x1, y1, xc, yc;
 
464
    double d, sfactor, sfactor_sq;
 
465
    double th0, th1, th_arc;
 
466
    int i, n_segs;
 
467
 
 
468
    sin_th = sin(angle * (piDouble / 180.0));
 
469
    cos_th = cos(angle * (piDouble / 180.0));
 
470
 
 
471
    double dx;
 
472
 
 
473
    if (!relative)
 
474
        dx = (curx - x) / 2.0;
 
475
    else
 
476
        dx = -x / 2.0;
 
477
 
 
478
    double dy;
 
479
        
 
480
    if (!relative)
 
481
        dy = (cury - y) / 2.0;
 
482
    else
 
483
        dy = -y / 2.0;
 
484
        
 
485
    double _x1 =  cos_th * dx + sin_th * dy;
 
486
    double _y1 = -sin_th * dx + cos_th * dy;
 
487
    double Pr1 = r1 * r1;
 
488
    double Pr2 = r2 * r2;
 
489
    double Px = _x1 * _x1;
 
490
    double Py = _y1 * _y1;
 
491
 
 
492
    // Spec : check if radii are large enough
 
493
    double check = Px / Pr1 + Py / Pr2;
 
494
    if (check > 1) {
 
495
        r1 = r1 * sqrt(check);
 
496
        r2 = r2 * sqrt(check);
 
497
    }
 
498
 
 
499
    a00 = cos_th / r1;
 
500
    a01 = sin_th / r1;
 
501
    a10 = -sin_th / r2;
 
502
    a11 = cos_th / r2;
 
503
 
 
504
    x0 = a00 * curx + a01 * cury;
 
505
    y0 = a10 * curx + a11 * cury;
 
506
 
 
507
    if (!relative)
 
508
        x1 = a00 * x + a01 * y;
 
509
    else
 
510
        x1 = a00 * (curx + x) + a01 * (cury + y);
 
511
        
 
512
    if (!relative)
 
513
        y1 = a10 * x + a11 * y;
 
514
    else
 
515
        y1 = a10 * (curx + x) + a11 * (cury + y);
 
516
 
 
517
    /* (x0, y0) is current point in transformed coordinate space.
 
518
       (x1, y1) is new point in transformed coordinate space.
 
519
 
 
520
       The arc fits a unit-radius circle in this space.
 
521
    */
 
522
 
 
523
    d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
 
524
 
 
525
    sfactor_sq = 1.0 / d - 0.25;
 
526
 
 
527
    if (sfactor_sq < 0)
 
528
        sfactor_sq = 0;
 
529
 
 
530
    sfactor = sqrt(sfactor_sq);
 
531
 
 
532
    if (sweepFlag == largeArcFlag)
 
533
        sfactor = -sfactor;
 
534
 
 
535
    xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
 
536
    yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
 
537
 
 
538
    /* (xc, yc) is center of the circle. */
 
539
    th0 = atan2(y0 - yc, x0 - xc);
 
540
    th1 = atan2(y1 - yc, x1 - xc);
 
541
 
 
542
    th_arc = th1 - th0;
 
543
    if (th_arc < 0 && sweepFlag)
 
544
        th_arc += 2 * piDouble;
 
545
    else if (th_arc > 0 && !sweepFlag)
 
546
        th_arc -= 2 * piDouble;
 
547
 
 
548
    n_segs = (int) (int) ceil(fabs(th_arc / (piDouble * 0.5 + 0.001)));
 
549
 
 
550
    for(i = 0; i < n_segs; i++) {
 
551
        double sin_th, cos_th;
 
552
        double a00, a01, a10, a11;
 
553
        double x1, y1, x2, y2, x3, y3;
 
554
        double t;
 
555
        double th_half;
 
556
 
 
557
        double _th0 = th0 + i * th_arc / n_segs;
 
558
        double _th1 = th0 + (i + 1) * th_arc / n_segs;
 
559
 
 
560
        sin_th = sin(angle * (piDouble / 180.0));
 
561
        cos_th = cos(angle * (piDouble / 180.0));
 
562
 
 
563
        /* inverse transform compared with rsvg_path_arc */
 
564
        a00 = cos_th * r1;
 
565
        a01 = -sin_th * r2;
 
566
        a10 = sin_th * r1;
 
567
        a11 = cos_th * r2;
 
568
 
 
569
        th_half = 0.5 * (_th1 - _th0);
 
570
        t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half);
 
571
        x1 = xc + cos(_th0) - t * sin(_th0);
 
572
        y1 = yc + sin(_th0) + t * cos(_th0);
 
573
        x3 = xc + cos(_th1);
 
574
        y3 = yc + sin(_th1);
 
575
        x2 = x3 + t * sin(_th1);
 
576
        y2 = y3 - t * cos(_th1);
 
577
 
 
578
        svgCurveToCubic(narrowPrecisionToFloat(a00 * x1 + a01 * y1), narrowPrecisionToFloat(a10 * x1 + a11 * y1),
 
579
                        narrowPrecisionToFloat(a00 * x2 + a01 * y2), narrowPrecisionToFloat(a10 * x2 + a11 * y2),
 
580
                        narrowPrecisionToFloat(a00 * x3 + a01 * y3), narrowPrecisionToFloat(a10 * x3 + a11 * y3));
 
581
    }
 
582
 
 
583
    if (!relative)
 
584
        curx = x;
 
585
    else
 
586
        curx += x;
 
587
 
 
588
    if (!relative)
 
589
        cury = y;
 
590
    else
 
591
        cury += y;    
 
592
}
 
593
 
 
594
void SVGPathParser::svgLineToHorizontal(float, bool)
 
595
{
 
596
}
 
597
 
 
598
void SVGPathParser::svgLineToVertical(float, bool)
 
599
{
 
600
}
 
601
 
 
602
void SVGPathParser::svgCurveToCubicSmooth(float, float, float, float, bool)
 
603
{
 
604
}
 
605
 
 
606
void SVGPathParser::svgCurveToQuadratic(float, float, float, float, bool)
 
607
{
 
608
}
 
609
 
 
610
void SVGPathParser::svgCurveToQuadraticSmooth(float, float, bool)
 
611
{
 
612
}
 
613
 
 
614
void SVGPathParser::svgArcTo(float, float, float, float, float, bool, bool, bool)
 
615
{
 
616
 
617
 
 
618
}
 
619
 
 
620
// vim:ts=4:noet
 
621
#endif // ENABLE(SVG)