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 "dom/cssparser.h"
33
#include "dom/charclass.h"
37
#define SVG_NAMESPACE "http://www.w3.org/2000/svg"
49
//#########################################################################
51
//#########################################################################
57
void SvgParser::error(char const *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 const *str)
96
if (get(pos++) != (XMLCh) *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 (!isWhitespace(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(SVGElementImplPtr parent,
597
ElementImplPtr sourceElem)
599
if (!parent || !sourceElem)
601
error("NULL source element");
605
DOMString namespaceURI = sourceElem->getNamespaceURI();
606
//printf("namespaceURI:%s\n", namespaceURI.c_str());
607
DOMString tagName = sourceElem->getTagName();
608
printf("tag name:%s\n", tagName.c_str());
610
ElementImplPtr newElement = NULL;
611
if (namespaceURI != SVG_NAMESPACE)
613
newElement = new SVGSVGElementImpl();
614
newElement->assign(*sourceElem);
615
parent->appendChild(newElement);
620
//####################################################
622
//####################################################
623
DOMString style = sourceElem->getAttribute("style");
624
if (style.size() > 0)
626
css::CssParser parser;
627
style.insert(0, "{");
629
//printf("CSS:%s\n", style.c_str());
630
if (!parser.parse(style))
632
error("parsing style attribute");
636
//printf("##parsed!\n");
640
DOMString transform = sourceElem->getAttribute("transform");
641
if (transform.size() > 0)
643
if (!parseTransform(transform))
645
error("parsing transform attribute");
649
//printf("##parsed!\n");
653
//####################################################
654
//## ELEMENT - SPECIFIC
655
//####################################################
656
if (tagName == "svg")
658
newElement = new SVGSVGElementImpl();
659
newElement->assign(*sourceElem);
660
parent->appendChild(newElement);
662
else if (tagName == "title")
664
newElement = new SVGTitleElementImpl();
665
newElement->assign(*sourceElem);
666
parent->appendChild(newElement);
668
else if (tagName == "desc")
670
newElement = new SVGDescElementImpl();
671
newElement->assign(*sourceElem);
672
parent->appendChild(newElement);
674
else if (tagName == "defs")
676
newElement = new SVGDefsElementImpl();
677
newElement->assign(*sourceElem);
678
parent->appendChild(newElement);
680
else if (tagName == "style")
682
newElement = new SVGStyleElementImpl();
683
newElement->assign(*sourceElem);
684
parent->appendChild(newElement);
686
else if (tagName == "g")
688
newElement = new SVGGElementImpl();
689
newElement->assign(*sourceElem);
690
parent->appendChild(newElement);
692
else if (tagName == "path")
694
newElement = new SVGPathElementImpl();
695
newElement->assign(*sourceElem);
696
parent->appendChild(newElement);
700
NodeList children = sourceElem->getChildNodes();
701
int nodeCount = children.getLength();
702
for (int i=0 ; i<nodeCount ; i++)
704
NodePtr child = children.item(i);
705
int typ = child->getNodeType();
706
if (typ == Node::TEXT_NODE)
708
NodePtr newNode = doc->createTextNode(child->getNodeValue());
709
parent->appendChild(newNode);
711
else if (typ == Node::CDATA_SECTION_NODE)
713
NodePtr newNode = doc->createCDATASection(child->getNodeValue());
714
parent->appendChild(newNode);
716
else if (newElement.get() && typ == Node::ELEMENT_NODE)
718
//ElementImplPtr childElement = dynamic_cast<ElementImpl *>(child.get());
719
//parseElement(newElement, childElement);
729
SVGDocumentPtr SvgParser::parse(const DocumentPtr src)
733
error("NULL source document");
737
DOMImplementationImpl impl;
738
doc = new SVGDocumentImpl(&impl, SVG_NAMESPACE, "svg" , NULL);
740
SVGElementImplPtr destElem = dynamic_cast<SVGElementImpl *>(doc->getRootElement().get());
741
ElementImplPtr srcElem = dynamic_cast<ElementImpl *>(src->getDocumentElement().get());
742
if (!parseElement(destElem, srcElem))
758
/*#########################################################################
760
#########################################################################*/