2
* Phoebe DOM Implementation.
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:
8
* http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
13
* Copyright (C) 2005 Bob Jamison
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.
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.
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
31
#include "svgparser.h"
32
#include "cssparser.h"
33
#include "charclass.h"
37
#define SVG_NAMESPACE "http://www.w3.org/2000/svg"
49
//#########################################################################
51
//#########################################################################
57
void SvgParser::error(char *fmt, ...)
60
fprintf(stderr, "SvgParser:error:");
62
vfprintf(stderr, fmt, args);
64
fprintf(stderr, "\n");
69
//#########################################################################
71
//#########################################################################
74
* Get the character at the position and record the fact
76
XMLCh SvgParser::get(int p)
80
XMLCh ch = parsebuf[p];
89
* Test if the given substring exists at the given position
90
* in parsebuf. Use get() in case of out-of-bounds
92
bool SvgParser::match(int pos, char *str)
96
if (get(pos++) != *str++)
105
int SvgParser::skipwhite(int p)
110
if (match(p, "<!--"))
127
error("unterminated <!-- .. --> comment");
132
else if (match(p, "/*"))
149
error("unterminated /* .. */ comment");
153
else if (!isspace(get(p)))
163
* get a word from the buffer
165
int SvgParser::getWord(int p, DOMString &result)
177
if (isLetterOrDigit(ch) || ch=='-' || ch=='_')
196
* get a word from the buffer
198
int SvgParser::getNumber(int p0, double &result)
213
if (ch<'0' || ch>'9')
218
if (get(p) == '.' && get(p+1)>='0' && get(p+1)<='9')
225
if (ch<'0' || ch>'9')
233
char *start = (char *)str.c_str();
235
double val = strtod(start, &end);
250
* get a word from the buffer
252
int SvgParser::getNumber(int p0, double &result)
259
for (i=0 ; i<63 && p<parselen ; i++)
261
buf[i] = (char) get(p++);
267
double val = strtod(start, &end);
271
int count = (int)(end - start);
281
bool SvgParser::parseTransform(const DOMString &str)
284
parselen = str.size();
286
//printf("transform:%s\n", str.c_str());
288
SVGTransformList transformList;
296
int p2 = getWord(p, name);
301
error("transform: need transform name");
306
//printf("transform name:%s\n", name.c_str());
309
if (name == "matrix")
314
error("matrix transform needs opening '('");
319
bool seenBrace = false;
320
while (p < parselen && nrVals < 6)
324
p2 = getNumber(p, val);
329
error("matrix() expected number");
332
vals[nrVals++] = val;
350
error("matrix() needs closing brace");
355
error("matrix() requires exactly 6 arguments");
358
//We got our arguments
359
//printf("translate: %f %f %f %f %f %f\n",
360
// vals[0], vals[1], vals[2], vals[3], vals[4], vals[5]);
361
SVGMatrix matrix(vals[0], vals[1], vals[2],
362
vals[3], vals[4], vals[5]);
363
SVGTransform transform;
364
transform.setMatrix(matrix);
365
transformList.appendItem(transform);
368
//######### TRANSLATE
369
else if (name == "translate")
374
error("matrix transform needs opening '('");
379
p2 = getNumber(p, x);
384
error("translate() expected 'x' value");
394
p2 = getNumber(p, y);
397
if (p2<=p) //no y specified. use default
402
error("translate() needs closing ')'");
405
//printf("translate: %f %f\n", x, y);
406
SVGTransform transform;
407
transform.setTranslate(x, y);
408
transformList.appendItem(transform);
412
else if (name == "scale")
417
error("scale transform needs opening '('");
422
p2 = getNumber(p, x);
427
error("scale() expected 'x' value");
437
p2 = getNumber(p, y);
440
if (p2<=p) //no y specified. use default
441
y = x; // y is same as x. uniform scaling
445
error("scale() needs closing ')'");
448
//printf("scale: %f %f\n", x, y);
449
SVGTransform transform;
450
transform.setScale(x, y);
451
transformList.appendItem(transform);
455
else if (name == "rotate")
460
error("rotate transform needs opening '('");
465
p2 = getNumber(p, angle);
470
error("rotate() expected 'angle' value");
481
p2 = getNumber(p, cx);
490
p2 = getNumber(p, cy);
495
error("rotate() arguments should be either rotate(angle) or rotate(angle, cx, cy)");
502
error("rotate() needs closing ')'");
505
//printf("rotate: %f %f %f\n", angle, cx, cy);
506
SVGTransform transform;
507
transform.setRotate(angle, cx, cy);
508
transformList.appendItem(transform);
512
else if (name == "skewX")
517
error("skewX transform needs opening '('");
522
p2 = getNumber(p, x);
527
error("skewX() expected 'x' value");
533
error("skewX() needs closing ')'");
536
//printf("skewX: %f\n", x);
537
SVGTransform transform;
538
transform.setSkewX(x);
539
transformList.appendItem(transform);
543
else if (name == "skewY")
548
error("skewY transform needs opening '('");
553
p2 = getNumber(p, y);
558
error("skewY() expected 'y' value");
564
error("skewY() needs closing ')'");
567
//printf("skewY: %f\n", y);
568
SVGTransform transform;
569
transform.setSkewY(y);
570
transformList.appendItem(transform);
573
//### NONE OF THE ABOVE
576
error("unknown transform type:'%s'", name.c_str());
596
bool SvgParser::parseElement(ElementImpl *parent, ElementImpl *sourceElem)
598
if (!parent || !sourceElem)
600
error("NULL source element");
604
DOMString namespaceURI = sourceElem->getNamespaceURI();
605
//printf("namespaceURI:%s\n", namespaceURI.c_str());
606
DOMString tagName = sourceElem->getTagName();
607
printf("tag name:%s\n", tagName.c_str());
609
ElementImpl *newElement = NULL;
610
if (namespaceURI != SVG_NAMESPACE)
612
newElement = new SVGSVGElementImpl();
613
newElement->assign(*sourceElem);
614
parent->appendChild(newElement);
619
//####################################################
621
//####################################################
622
DOMString style = sourceElem->getAttribute("style");
623
if (style.size() > 0)
625
css::CssParser parser;
626
style.insert(0, "{");
628
//printf("CSS:%s\n", style.c_str());
629
if (!parser.parse(style))
631
error("parsing style attribute");
635
//printf("##parsed!\n");
639
DOMString transform = sourceElem->getAttribute("transform");
640
if (transform.size() > 0)
642
if (!parseTransform(transform))
644
error("parsing transform attribute");
648
//printf("##parsed!\n");
652
//####################################################
653
//## ELEMENT - SPECIFIC
654
//####################################################
655
if (tagName == "svg")
657
newElement = new SVGSVGElementImpl();
658
newElement->assign(*sourceElem);
659
parent->appendChild(newElement);
661
else if (tagName == "title")
663
newElement = new SVGTitleElementImpl();
664
newElement->assign(*sourceElem);
665
parent->appendChild(newElement);
667
else if (tagName == "desc")
669
newElement = new SVGDescElementImpl();
670
newElement->assign(*sourceElem);
671
parent->appendChild(newElement);
673
else if (tagName == "defs")
675
newElement = new SVGDefsElementImpl();
676
newElement->assign(*sourceElem);
677
parent->appendChild(newElement);
679
else if (tagName == "style")
681
newElement = new SVGStyleElementImpl();
682
newElement->assign(*sourceElem);
683
parent->appendChild(newElement);
685
else if (tagName == "g")
687
newElement = new SVGGElementImpl();
688
newElement->assign(*sourceElem);
689
parent->appendChild(newElement);
691
else if (tagName == "path")
693
newElement = new SVGPathElementImpl();
694
newElement->assign(*sourceElem);
695
parent->appendChild(newElement);
699
NodeList children = sourceElem->getChildNodes();
700
int nodeCount = children.getLength();
701
for (int i=0 ; i<nodeCount ; i++)
703
Node *child = children.item(i);
704
int typ = child->getNodeType();
705
if (typ == Node::TEXT_NODE)
707
Node *newNode = doc->createTextNode(child->getNodeValue());
708
parent->appendChild(newNode);
710
else if (typ == Node::CDATA_SECTION_NODE)
712
Node *newNode = doc->createCDATASection(child->getNodeValue());
713
parent->appendChild(newNode);
715
else if (newElement && typ == Node::ELEMENT_NODE)
717
ElementImpl *childElement = dynamic_cast<ElementImpl *>(child);
718
parseElement(newElement, childElement);
728
Document *SvgParser::parse(const Document *sourceDoc)
732
error("NULL source document");
736
Document *src = (Document *)sourceDoc;
737
DOMImplementationImpl impl;
738
doc = new SVGDocumentImpl(&impl, SVG_NAMESPACE, "svg" , NULL);
740
ElementImpl *destElem = dynamic_cast<ElementImpl *>(doc->getDocumentElement());
741
ElementImpl *srcElem = dynamic_cast<ElementImpl *>(src->getDocumentElement());
742
if (!parseElement(destElem, srcElem))
759
/*#########################################################################
761
#########################################################################*/