~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/dom/svgreader.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Phoebe DOM Implementation.
 
3
 *
 
4
 * This is a C++ approximation of the W3C DOM model, which follows
 
5
 * fairly closely the specifications in the various .idl files, copies of
 
6
 * which are provided for reference.  Most important is this one:
 
7
 *
 
8
 * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
 
9
 *
 
10
 * Authors:
 
11
 *   Bob Jamison
 
12
 *
 
13
 * Copyright (C) 2005-2008 Bob Jamison
 
14
 *
 
15
 *  This library is free software; you can redistribute it and/or
 
16
 *  modify it under the terms of the GNU Lesser General Public
 
17
 *  License as published by the Free Software Foundation; either
 
18
 *  version 2.1 of the License, or (at your option) any later version.
 
19
 *
 
20
 *  This library is distributed in the hope that it will be useful,
 
21
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
22
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
23
 *  Lesser General Public License for more details.
 
24
 *
 
25
 *  You should have received a copy of the GNU Lesser General Public
 
26
 *  License along with this library; if not, write to the Free Software
 
27
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
28
 *  
 
29
 * =======================================================================
 
30
 * NOTES
 
31
 * 
 
32
 *      
 
33
 */
 
34
 
 
35
 
 
36
#include "svgreader.h"
 
37
#include "dom/cssreader.h"
 
38
#include "dom/ucd.h"
 
39
#include "xmlreader.h"
 
40
 
 
41
#include <cstdio>
 
42
#include <stdarg.h>
 
43
 
 
44
 
 
45
namespace org
 
46
{
 
47
namespace w3c
 
48
{
 
49
namespace dom
 
50
{
 
51
namespace svg
 
52
{
 
53
 
 
54
 
 
55
//#########################################################################
 
56
//# M E S S A G E S
 
57
//#########################################################################
 
58
 
 
59
 
 
60
/**
 
61
 *
 
62
 */
 
63
void SVGReader::error(char const *fmt, ...)
 
64
{
 
65
    va_list args;
 
66
    fprintf(stderr, "SVGReader:error: ");
 
67
    va_start(args, fmt);
 
68
    vfprintf(stderr, fmt, args);
 
69
    va_end(args) ;
 
70
    fprintf(stderr, "\n");
 
71
}
 
72
 
 
73
 
 
74
/**
 
75
 *
 
76
 */
 
77
void SVGReader::trace(char const *fmt, ...)
 
78
{
 
79
    va_list args;
 
80
    fprintf(stdout, "SVGReader: ");
 
81
    va_start(args, fmt);
 
82
    vfprintf(stdout, fmt, args);
 
83
    va_end(args) ;
 
84
    fprintf(stdout, "\n");
 
85
}
 
86
 
 
87
 
 
88
 
 
89
//#########################################################################
 
90
//# P A R S I N G
 
91
//#########################################################################
 
92
 
 
93
 
 
94
 
 
95
/**
 
96
 *  Get the character at the position and record the fact
 
97
 */
 
98
XMLCh SVGReader::get(int p)
 
99
{
 
100
    if (p >= parselen)
 
101
        return 0;
 
102
    XMLCh ch = parsebuf[p];
 
103
    //printf("%c", ch);
 
104
    lastPosition = p;
 
105
    return ch;
 
106
}
 
107
 
 
108
 
 
109
 
 
110
/**
 
111
 *  Test if the given substring exists at the given position
 
112
 *  in parsebuf.  Use get() in case of out-of-bounds
 
113
 */
 
114
bool SVGReader::match(int pos, char const *str)
 
115
{
 
116
    while (*str)
 
117
       {
 
118
       if (get(pos++) != (XMLCh) *str++)
 
119
           return false;
 
120
       }
 
121
   return true;
 
122
}
 
123
 
 
124
/**
 
125
 *
 
126
 */
 
127
int SVGReader::skipwhite(int p)
 
128
{
 
129
  while (p < parselen)
 
130
    {
 
131
    //# XML COMMENT
 
132
    if (match(p, "<!--"))
 
133
        {
 
134
        p+=4;
 
135
        bool done=false;
 
136
        while (p<parselen)
 
137
            {
 
138
            if (match(p, "-->"))
 
139
                {
 
140
                p+=3;
 
141
                done=true;
 
142
                break;
 
143
                }
 
144
            p++;
 
145
            }
 
146
        lastPosition = p;
 
147
        if (!done)
 
148
            {
 
149
            error("unterminated <!-- .. --> comment");
 
150
            return -1;
 
151
            }
 
152
        }
 
153
    //# C comment
 
154
    else if (match(p, "/*"))
 
155
        {
 
156
        p+=2;
 
157
        bool done=false;
 
158
        while (p<parselen)
 
159
            {
 
160
            if (match(p, "*/"))
 
161
                {
 
162
                p+=2;
 
163
                done=true;
 
164
                break;
 
165
                }
 
166
            p++;
 
167
            }
 
168
        lastPosition = p;
 
169
        if (!done)
 
170
            {
 
171
            error("unterminated /* .. */ comment");
 
172
            return -1;
 
173
            }
 
174
        }
 
175
    else if (!uni_is_space(get(p)))
 
176
        break;
 
177
    else
 
178
        p++;
 
179
    }
 
180
  lastPosition = p;
 
181
  return p;
 
182
}
 
183
 
 
184
/**
 
185
 * get a word from the buffer
 
186
 */
 
187
int SVGReader::getWord(int p, DOMString &result)
 
188
{
 
189
    XMLCh ch = get(p);
 
190
    if (!uni_is_letter(ch))
 
191
        return p;
 
192
    DOMString str;
 
193
    str.push_back(ch);
 
194
    p++;
 
195
 
 
196
    while (p < parselen)
 
197
        {
 
198
        ch = get(p);
 
199
        if (uni_is_letter_or_digit(ch) || ch=='-' || ch=='_')
 
200
            {
 
201
            str.push_back(ch);
 
202
            p++;
 
203
            }
 
204
        else if (ch == '\\')
 
205
            {
 
206
            p+=2;
 
207
            }
 
208
        else
 
209
            break;
 
210
        }
 
211
    result = str;
 
212
    return p;
 
213
}
 
214
 
 
215
 
 
216
# if 0
 
217
/**
 
218
 * get a word from the buffer
 
219
 */
 
220
int SVGReader::getNumber(int p0, double &result)
 
221
{
 
222
    int p=p0;
 
223
 
 
224
    DOMString str;
 
225
 
 
226
    //allow sign
 
227
    if (get(p) == '-')
 
228
        {
 
229
        p++;
 
230
        }
 
231
 
 
232
    while (p < parselen)
 
233
        {
 
234
        XMLCh ch = get(p);
 
235
        if (ch<'0' || ch>'9')
 
236
            break;
 
237
        str.push_back(ch);
 
238
        p++;
 
239
        }
 
240
    if (get(p) == '.' && get(p+1)>='0' && get(p+1)<='9')
 
241
        {
 
242
        p++;
 
243
        str.push_back('.');
 
244
        while (p < parselen)
 
245
            {
 
246
            XMLCh ch = get(p);
 
247
            if (ch<'0' || ch>'9')
 
248
                break;
 
249
            str.push_back(ch);
 
250
            p++;
 
251
            }
 
252
        }
 
253
    if (p>p0)
 
254
        {
 
255
        char *start = (char *)str.c_str();
 
256
        char *end   = NULL;
 
257
        double val = strtod(start, &end);
 
258
        if (end > start)
 
259
            {
 
260
            result = val;
 
261
            return p;
 
262
            }
 
263
        }
 
264
 
 
265
    //not a number
 
266
    return p0;
 
267
}
 
268
#endif
 
269
 
 
270
 
 
271
/**
 
272
 * get a word from the buffer
 
273
 */
 
274
int SVGReader::getNumber(int p0, double &result)
 
275
{
 
276
    int p=p0;
 
277
 
 
278
    char buf[64];
 
279
 
 
280
    int i;
 
281
    for (i=0 ; i<63 && p<parselen ; i++)
 
282
        {
 
283
        buf[i] = (char) get(p++);
 
284
        }
 
285
    buf[i] = '\0';
 
286
 
 
287
    char *start = buf;
 
288
    char *end   = NULL;
 
289
    double val = strtod(start, &end);
 
290
    if (end > start)
 
291
        {
 
292
        result = val;
 
293
        int count = (int)(end - start);
 
294
        p = p0 + count;
 
295
        return p;
 
296
        }
 
297
 
 
298
    //not a number
 
299
    return p0;
 
300
}
 
301
 
 
302
 
 
303
bool SVGReader::parseTransform(const DOMString &str)
 
304
{
 
305
    parsebuf = str;
 
306
    parselen = str.size();
 
307
 
 
308
    //printf("transform:%s\n", str.c_str());
 
309
 
 
310
    SVGTransformList transformList;
 
311
 
 
312
    int p = 0;
 
313
 
 
314
    while (p < parselen)
 
315
        {
 
316
        p = skipwhite(p);
 
317
        DOMString name;
 
318
        int p2 = getWord(p, name);
 
319
        if (p2<0)
 
320
            return false;
 
321
        if (p2<=p)
 
322
            {
 
323
            error("transform: need transform name");
 
324
            //return false;
 
325
            break;
 
326
            }
 
327
        p = p2;
 
328
        //printf("transform name:%s\n", name.c_str());
 
329
 
 
330
        //######### MATRIX
 
331
        if (name == "matrix")
 
332
            {
 
333
            p = skipwhite(p);
 
334
            if (get(p++) != '(')
 
335
                {
 
336
                error("matrix transform needs opening '('");
 
337
                return false;
 
338
                }
 
339
            int nrVals = 0;
 
340
            double vals[6];
 
341
            bool seenBrace = false;
 
342
            while (p < parselen && nrVals < 6)
 
343
                {
 
344
                p = skipwhite(p);
 
345
                double val = 0.0;
 
346
                p2 = getNumber(p, val);
 
347
                if (p2<0)
 
348
                    return false;
 
349
                if (p2<=p)
 
350
                    {
 
351
                    error("matrix() expected number");
 
352
                    return false;
 
353
                    }
 
354
                vals[nrVals++] = val;
 
355
                p = skipwhite(p2);
 
356
                XMLCh ch = get(p);
 
357
                if (ch == ',')
 
358
                    {
 
359
                    p++;
 
360
                    p = skipwhite(p);
 
361
                    ch = get(p);
 
362
                    }
 
363
                if (ch == ')')
 
364
                    {
 
365
                    seenBrace = true;
 
366
                    p++;
 
367
                    break;
 
368
                    }
 
369
                }
 
370
            if (!seenBrace)
 
371
                {
 
372
                error("matrix() needs closing brace");
 
373
                return false;
 
374
                }
 
375
            if (nrVals != 6)
 
376
                {
 
377
                error("matrix() requires exactly 6 arguments");
 
378
                return false;
 
379
                }
 
380
            //We got our arguments
 
381
            //printf("translate: %f %f %f %f %f %f\n",
 
382
            //      vals[0], vals[1], vals[2], vals[3], vals[4], vals[5]);
 
383
            SVGMatrix matrix(vals[0], vals[1], vals[2],
 
384
                             vals[3], vals[4], vals[5]);
 
385
            SVGTransform transform;
 
386
            transform.setMatrix(matrix);
 
387
            transformList.appendItem(transform);
 
388
            }
 
389
 
 
390
        //######### TRANSLATE
 
391
        else if (name == "translate")
 
392
            {
 
393
            p = skipwhite(p);
 
394
            if (get(p++) != '(')
 
395
                {
 
396
                error("matrix transform needs opening '('");
 
397
                return false;
 
398
                }
 
399
            p = skipwhite(p);
 
400
            double x = 0.0;
 
401
            p2 = getNumber(p, x);
 
402
            if (p2<0)
 
403
                return false;
 
404
            if (p2<=p)
 
405
                {
 
406
                error("translate() expected 'x' value");
 
407
                return false;
 
408
                }
 
409
            p = skipwhite(p2);
 
410
            if (get(p) == ',')
 
411
                {
 
412
                p++;
 
413
                p = skipwhite(p);
 
414
                }
 
415
            double y = 0.0;
 
416
            p2 = getNumber(p, y);
 
417
            if (p2<0)
 
418
                return false;
 
419
            if (p2<=p) //no y specified. use default
 
420
                y = 0.0;
 
421
            p = skipwhite(p2);
 
422
            if (get(p++) != ')')
 
423
                {
 
424
                error("translate() needs closing ')'");
 
425
                return false;
 
426
                }
 
427
            //printf("translate: %f %f\n", x, y);
 
428
            SVGTransform transform;
 
429
            transform.setTranslate(x, y);
 
430
            transformList.appendItem(transform);
 
431
            }
 
432
 
 
433
        //######### SCALE
 
434
        else if (name == "scale")
 
435
            {
 
436
            p = skipwhite(p);
 
437
            if (get(p++) != '(')
 
438
                {
 
439
                error("scale transform needs opening '('");
 
440
                return false;
 
441
                }
 
442
            p = skipwhite(p);
 
443
            double x = 0.0;
 
444
            p2 = getNumber(p, x);
 
445
            if (p2<0)
 
446
                return false;
 
447
            if (p2<=p)
 
448
                {
 
449
                error("scale() expected 'x' value");
 
450
                return false;
 
451
                }
 
452
            p = skipwhite(p2);
 
453
            if (get(p) == ',')
 
454
                {
 
455
                p++;
 
456
                p = skipwhite(p);
 
457
                }
 
458
            double y = 0.0;
 
459
            p2 = getNumber(p, y);
 
460
            if (p2<0)
 
461
                return false;
 
462
            if (p2<=p) //no y specified. use default
 
463
                y = x; // y is same as x.  uniform scaling
 
464
            p = skipwhite(p2);
 
465
            if (get(p++) != ')')
 
466
                {
 
467
                error("scale() needs closing ')'");
 
468
                return false;
 
469
                }
 
470
            //printf("scale: %f %f\n", x, y);
 
471
            SVGTransform transform;
 
472
            transform.setScale(x, y);
 
473
            transformList.appendItem(transform);
 
474
            }
 
475
 
 
476
        //######### ROTATE
 
477
        else if (name == "rotate")
 
478
            {
 
479
            p = skipwhite(p);
 
480
            if (get(p++) != '(')
 
481
                {
 
482
                error("rotate transform needs opening '('");
 
483
                return false;
 
484
                }
 
485
            p = skipwhite(p);
 
486
            double angle = 0.0;
 
487
            p2 = getNumber(p, angle);
 
488
            if (p2<0)
 
489
                return false;
 
490
            if (p2<=p)
 
491
                {
 
492
                error("rotate() expected 'angle' value");
 
493
                return false;
 
494
                }
 
495
            p = skipwhite(p2);
 
496
            if (get(p) == ',')
 
497
                {
 
498
                p++;
 
499
                p = skipwhite(p);
 
500
                }
 
501
            double cx = 0.0;
 
502
            double cy = 0.0;
 
503
            p2 = getNumber(p, cx);
 
504
            if (p2>p)
 
505
                {
 
506
                p = skipwhite(p2);
 
507
                if (get(p) == ',')
 
508
                    {
 
509
                    p++;
 
510
                    p = skipwhite(p);
 
511
                    }
 
512
                p2 = getNumber(p, cy);
 
513
                if (p2<0)
 
514
                    return false;
 
515
                if (p2<=p)
 
516
                    {
 
517
                    error("rotate() arguments should be either rotate(angle) or rotate(angle, cx, cy)");
 
518
                    return false;
 
519
                    }
 
520
                p = skipwhite(p2);
 
521
                }
 
522
            if (get(p++) != ')')
 
523
                {
 
524
                error("rotate() needs closing ')'");
 
525
                return false;
 
526
                }
 
527
            //printf("rotate: %f %f %f\n", angle, cx, cy);
 
528
            SVGTransform transform;
 
529
            transform.setRotate(angle, cx, cy);
 
530
            transformList.appendItem(transform);
 
531
            }
 
532
 
 
533
        //######### SKEWX
 
534
        else if (name == "skewX")
 
535
            {
 
536
            p = skipwhite(p);
 
537
            if (get(p++) != '(')
 
538
                {
 
539
                error("skewX transform needs opening '('");
 
540
                return false;
 
541
                }
 
542
            p = skipwhite(p);
 
543
            double x = 0.0;
 
544
            p2 = getNumber(p, x);
 
545
            if (p2<0)
 
546
                return false;
 
547
            if (p2<=p)
 
548
                {
 
549
                error("skewX() expected 'x' value");
 
550
                return false;
 
551
                }
 
552
            p = skipwhite(p2);
 
553
            if (get(p++) != ')')
 
554
                {
 
555
                error("skewX() needs closing ')'");
 
556
                return false;
 
557
                }
 
558
            //printf("skewX: %f\n", x);
 
559
            SVGTransform transform;
 
560
            transform.setSkewX(x);
 
561
            transformList.appendItem(transform);
 
562
            }
 
563
 
 
564
        //######### SKEWY
 
565
        else if (name == "skewY")
 
566
            {
 
567
            p = skipwhite(p);
 
568
            if (get(p++) != '(')
 
569
                {
 
570
                error("skewY transform needs opening '('");
 
571
                return false;
 
572
                }
 
573
            p = skipwhite(p);
 
574
            double y = 0.0;
 
575
            p2 = getNumber(p, y);
 
576
            if (p2<0)
 
577
                return false;
 
578
            if (p2<=p)
 
579
                {
 
580
                error("skewY() expected 'y' value");
 
581
                return false;
 
582
                }
 
583
            p = skipwhite(p2);
 
584
            if (get(p++) != ')')
 
585
                {
 
586
                error("skewY() needs closing ')'");
 
587
                return false;
 
588
                }
 
589
            //printf("skewY: %f\n", y);
 
590
            SVGTransform transform;
 
591
            transform.setSkewY(y);
 
592
            transformList.appendItem(transform);
 
593
            }
 
594
 
 
595
        //### NONE OF THE ABOVE
 
596
        else
 
597
            {
 
598
            error("unknown transform type:'%s'", name.c_str());
 
599
            }
 
600
 
 
601
        p = skipwhite(p);
 
602
        XMLCh ch = get(p);
 
603
        if (ch == ',')
 
604
            {
 
605
            p++;
 
606
            p = skipwhite(p);
 
607
            }
 
608
 
 
609
        }//WHILE p<parselen
 
610
 
 
611
    return true;
 
612
}
 
613
 
 
614
 
 
615
/**
 
616
 *
 
617
 */
 
618
bool SVGReader::parseElement(SVGElementImplPtr parent,
 
619
                             ElementImplPtr sourceElem)
 
620
{
 
621
    if (!parent)
 
622
        {
 
623
        error("NULL dest element");
 
624
        return false;
 
625
        }
 
626
    if (!sourceElem)
 
627
        {
 
628
        error("NULL source element");
 
629
        return false;
 
630
        }
 
631
 
 
632
    DOMString namespaceURI = sourceElem->getNamespaceURI();
 
633
    //printf("namespaceURI:%s\n", namespaceURI.c_str());
 
634
    DOMString tagName      = sourceElem->getTagName();
 
635
    printf("tag name:%s\n", tagName.c_str());
 
636
    ElementPtr newElement = doc->createElementNS(namespaceURI, tagName);
 
637
    if (!newElement)
 
638
        {
 
639
                return false;
 
640
                }
 
641
        NamedNodeMap &attrs = sourceElem->getAttributes();
 
642
        for (unsigned int i=0 ; i<attrs.getLength() ; i++)
 
643
            {
 
644
            NodePtr n = attrs.item(i);
 
645
            newElement->setAttribute(n->getNodeName(), n->getNodeValue());//should be exception here
 
646
                }
 
647
        parent->appendChild(newElement);
 
648
 
 
649
 
 
650
    NodeList children = sourceElem->getChildNodes();
 
651
    int nodeCount = children.getLength();
 
652
    for (int i=0 ; i<nodeCount ; i++)
 
653
        {
 
654
        NodePtr child = children.item(i);
 
655
        int typ = child->getNodeType();
 
656
        if (typ == Node::TEXT_NODE)
 
657
            {
 
658
            NodePtr newNode = doc->createTextNode(child->getNodeValue());
 
659
            parent->appendChild(newNode);
 
660
            }
 
661
        else if (typ == Node::CDATA_SECTION_NODE)
 
662
            {
 
663
            NodePtr newNode = doc->createCDATASection(child->getNodeValue());
 
664
            parent->appendChild(newNode);
 
665
            }
 
666
        else if (newElement.get() && typ == Node::ELEMENT_NODE)
 
667
            {
 
668
            //ElementImplPtr childElement = dynamic_cast<ElementImpl *>(child.get());
 
669
            //parseElement(newElement, childElement);
 
670
            }
 
671
        }
 
672
    return true;
 
673
}
 
674
 
 
675
 
 
676
/**
 
677
 *
 
678
 */
 
679
SVGDocumentPtr SVGReader::parse(const DocumentPtr src)
 
680
{
 
681
    if (!src)
 
682
        {
 
683
        error("NULL source document");
 
684
        return NULL;
 
685
        }
 
686
 
 
687
    DOMImplementationImpl impl;
 
688
    doc = new SVGDocumentImpl(&impl, SVG_NAMESPACE, "svg" , NULL);
 
689
 
 
690
    SVGElementImplPtr destElem = dynamic_pointer_cast<SVGElementImpl, SVGElement>(doc->getRootElement());
 
691
    ElementImplPtr    srcElem  = dynamic_pointer_cast<ElementImpl, Element>(src->getDocumentElement());
 
692
    if (!parseElement(destElem, srcElem))
 
693
        {
 
694
        return NULL;
 
695
        }
 
696
 
 
697
    return doc;
 
698
}
 
699
 
 
700
 
 
701
 
 
702
/**
 
703
 *
 
704
 */
 
705
SVGDocumentPtr SVGReader::parse(const DOMString &buf)
 
706
{
 
707
    /* remember, smartptrs are null-testable*/
 
708
    SVGDocumentPtr svgdoc;
 
709
    XmlReader parser;
 
710
    DocumentPtr doc = parser.parse(buf);
 
711
    if (!doc)
 
712
        {
 
713
        return svgdoc;
 
714
        }
 
715
    svgdoc = parse(doc);
 
716
    return svgdoc;
 
717
}
 
718
 
 
719
 
 
720
 
 
721
/**
 
722
 *
 
723
 */
 
724
SVGDocumentPtr SVGReader::parseFile(const DOMString &fileName)
 
725
{
 
726
    /* remember, smartptrs are null-testable*/
 
727
    SVGDocumentPtr svgdoc;
 
728
    XmlReader parser;
 
729
    DocumentPtr doc = parser.parseFile(fileName);
 
730
    if (!doc)
 
731
        {
 
732
        error("Could not load xml doc");
 
733
        return svgdoc;
 
734
        }
 
735
    svgdoc = parse(doc);
 
736
    return svgdoc;
 
737
}
 
738
 
 
739
 
 
740
 
 
741
 
 
742
}  //namespace svg
 
743
}  //namespace dom
 
744
}  //namespace w3c
 
745
}  //namespace org
 
746
 
 
747
/*#########################################################################
 
748
## E N D    O F    F I L E
 
749
#########################################################################*/
 
750