summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 65386fe)
raw | patch | inline | side by side (parent: 65386fe)
author | ishmal <ishmal@users.sourceforge.net> | |
Thu, 1 May 2008 19:23:00 +0000 (19:23 +0000) | ||
committer | ishmal <ishmal@users.sourceforge.net> | |
Thu, 1 May 2008 19:23:00 +0000 (19:23 +0000) |
src/dom/cssparser.cpp | [deleted file] | patch | blob | history |
src/dom/cssparser.h | [deleted file] | patch | blob | history |
src/dom/cssreader.cpp | [new file with mode: 0644] | patch | blob |
src/dom/cssreader.h | [new file with mode: 0644] | patch | blob |
src/dom/svgparser.cpp | [deleted file] | patch | blob | history |
src/dom/svgparser.h | [deleted file] | patch | blob | history |
src/dom/svgreader.cpp | [new file with mode: 0644] | patch | blob |
src/dom/svgreader.h | [new file with mode: 0644] | patch | blob |
diff --git a/src/dom/cssparser.cpp b/src/dom/cssparser.cpp
--- a/src/dom/cssparser.cpp
+++ /dev/null
@@ -1,1670 +0,0 @@
-/**
- * Phoebe DOM Implementation.
- *
- * This is a C++ approximation of the W3C DOM model, which follows
- * fairly closely the specifications in the various .idl files, copies of
- * which are provided for reference. Most important is this one:
- *
- * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
- *
- * Authors:
- * Bob Jamison
- *
- * Copyright (C) 2005-2008 Bob Jamison
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "cssparser.h"
-#include "ucd.h"
-
-#include <stdio.h>
-#include <stdarg.h>
-
-namespace org
-{
-namespace w3c
-{
-namespace dom
-{
-namespace css
-{
-
-//#########################################################################
-//# M E S S A G E S
-//#########################################################################
-
-/**
- * Get the column and row number of the given character position
- */
-void CssParser::getColumnAndRow(int p, int &colResult, int &rowResult, int &lastNL)
-{
- int col = 1;
- int row = 1;
- int lastnl = 0;
-
- for (int i=0 ; i<p ; i++)
- {
- XMLCh ch = parsebuf[i];
- if (ch == '\n')
- {
- lastnl = i;
- row++;
- col=0;
- }
- else
- col++;
- }
-
- colResult = col;
- rowResult = row;
- lastNL = lastnl;
-}
-
-/**
- *
- */
-void CssParser::error(char const *fmt, ...)
-{
- int lineNr;
- int colNr;
- int lastNL;
- getColumnAndRow(lastPosition, colNr, lineNr, lastNL);
-
- va_list args;
- fprintf(stderr, "CssParser:error at %d, line %d, column %d:",
- lastPosition, lineNr, colNr);
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args) ;
- fprintf(stderr, "\n");
-
- /*
- int lineLen = lastPosition - lastNL;
- printf("lineLen:%d lastNL:%d\n", lineLen, lastNL);
- for (int i=lastNL+1 ; i<lastPosition ; i++)
- fprintf(stderr, "%c", parsebuf[i]);
- fprintf(stderr, "\n");
- for (int i=0 ; i<lineLen-1 ; i++)
- fprintf(stderr, " ");
- fprintf(stderr, "^\n");
- */
- for (int i=0 ; i<lastPosition ; i++)
- fprintf(stderr, "%c", parsebuf[i]);
- fprintf(stderr, "\n");
-}
-
-
-
-//#########################################################################
-//# P A R S I N G
-//#########################################################################
-
-/**
- * Get the character at the position and record the fact
- */
-XMLCh CssParser::get(int p)
-{
- if (p >= parselen)
- return 0;
- XMLCh ch = parsebuf[p];
- //printf("%c", ch);
- lastPosition = p;
- return ch;
-}
-
-
-
-/**
- * Test if the given substring exists at the given position
- * in parsebuf. Use get() in case of out-of-bounds
- */
-bool CssParser::match(int pos, const char *str)
-{
- while (*str)
- {
- if (get(pos++) != (XMLCh) *str++)
- return false;
- }
- return true;
-}
-
-/**
- *
- */
-int CssParser::skipwhite(int p)
-{
- while (p < parselen)
- {
- //# XML COMMENT
- if (match(p, "<!--"))
- {
- p+=4;
- bool done=false;
- while (p<parselen)
- {
- if (match(p, "-->"))
- {
- p+=3;
- done=true;
- break;
- }
- p++;
- }
- lastPosition = p;
- if (!done)
- {
- error("unterminated <!-- .. --> comment");
- return -1;
- }
- }
- //# C comment
- else if (match(p, "/*"))
- {
- p+=2;
- bool done=false;
- while (p<parselen)
- {
- if (match(p, "*/"))
- {
- p+=2;
- done=true;
- break;
- }
- p++;
- }
- lastPosition = p;
- if (!done)
- {
- error("unterminated /* .. */ comment");
- return -1;
- }
- }
- else if (!uni_is_space(get(p)))
- break;
- else
- p++;
- }
- lastPosition = p;
- return p;
-}
-
-/**
- * get a word from the buffer
- */
-int CssParser::getWord(int p, DOMString &result)
-{
- XMLCh ch = get(p);
- if (!uni_is_letter(ch))
- return p;
- DOMString str;
- str.push_back(ch);
- p++;
-
- while (p < parselen)
- {
- ch = get(p);
- if (uni_is_letter_or_digit(ch) || ch=='-' || ch=='_')
- {
- str.push_back(ch);
- p++;
- }
- else if (ch == '\\')
- {
- p+=2;
- }
- else
- break;
- }
- result = str;
- return p;
-}
-
-
-/**
- * get a word from the buffer
- */
-int CssParser::getNumber(int p0, double &result)
-{
- int p=p0;
- DOMString str;
- while (p < parselen)
- {
- XMLCh ch = get(p);
- if (ch<'0' || ch>'9')
- break;
- str.push_back(ch);
- p++;
- }
- if (get(p) == '.' && get(p+1)>='0' && get(p+1)<='9')
- {
- p++;
- str.push_back('.');
- while (p < parselen)
- {
- XMLCh ch = get(p);
- if (ch<'0' || ch>'9')
- break;
- str.push_back(ch);
- p++;
- }
- }
- if (p>p0)
- {
- char *start = (char *)str.c_str();
- char *end = NULL;
- double val = strtod(start, &end);
- if (end > start)
- {
- result = val;
- return p;
- }
- }
-
- //not a number
- return p0;
-}
-
-
-
-/**
- * Assume that we are starting on a quote. Ends on the char
- * after the final '"'
- */
-int CssParser::getQuoted(int p0, DOMString &result)
-{
-
- int p = p0;
-
- XMLCh quoteChar = get(p);
- if (quoteChar != '"' && quoteChar != '\'')
- return p0;
-
- p++;
-
- DOMString buf;
-
- bool done = false;
- while (p<parselen )
- {
- XMLCh ch = get(p);
- if (ch == quoteChar)
- {
- done = true;
- p++;
- break;
- }
- else
- {
- buf.push_back(ch);
- }
- p++;
- }
-
- if (!done)
- {
- error("unterminated quoted string");
- return -1;
- }
-
- result.append(buf);
-
- return p;
-}
-
-/**
- * Not in api. replaces URI return by lexer
- */
-int CssParser::getUri(int p0, DOMString &str)
-{
- int p = p0;
- if (!match(p, "url("))
- return p0;
- p+=4;
- p = skipwhite(p);
- DOMString buf;
- XMLCh ch;
- while (p < parselen)
- {
- ch = get(p);
- if (isspace(ch) || ch==')')
- break;
- buf.push_back(ch);
- p++;
- }
- p = skipwhite(p);
- ch = get(p);
- if (ch != ')')
- {
- error("no closing ')' on url spec");
- return -1;
- }
- p++;
- str = buf;
- return p;
-}
-
-/**
- * Skip to the end of the block
- */
-int CssParser::skipBlock(int p0)
-{
- int p = p0;
- while (p < parselen)
- {
- XMLCh ch = get(p);
- if (ch == '}')
- {
- p++;
- break;
- }
- else
- {
- p++;
- }
- }
- return p;
-}
-
-//#########################################################################
-//# P R O D U C T I O N S
-//#########################################################################
-
-/**
- * stylesheet
- * : [ CHARSET_SYM S* STRING S* ';' ]?
- * [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*
- * [ [ ruleset | media | page ] [S|CDO|CDC]* ]*
- * ;
- */
-int CssParser::getStyleSheet(int p0)
-{
- int p = p0;
- int p2 = p;
- XMLCh ch;
-
- //# CHARSET 0 or 1
- if (match(p, "@charset"))
- {
- p+=8;
- p = skipwhite(p);
- DOMString str;
- p2 = getQuoted(p, str);
- if (p2<=p)
- {
- error("quoted string required after @charset");
- return -1;
- }
- p = skipwhite(p2);
- ch = get(p);
- if (ch !=';')
- {
- error("';' required after @charset declaration");
- return -1;
- }
- p++;
- p = skipwhite(p);
- }
-
- //# IMPORT 0 to many
- while (true)
- {
- p2 = getImport(p);
- if (p2<0)
- {
- return -1;
- }
- if (p2<=p)
- break;
- p = p2;
- }
-
- //# RULESET | MEDIA | PAGE 0 to many
- while (true)
- {
- //Ruleset
- p2 = getRuleSet(p);
- if (p2<0)
- {
- return -1;
- }
- if (p2>p)
- {
- p = p2;
- continue;
- }
-
- //Media
- p2 = getMedia(p);
- if (p2<0)
- {
- return -1;
- }
- if (p2>p)
- {
- p = p2;
- continue;
- }
-
- //Page
- p2 = getPage(p);
- if (p2<0)
- {
- return -1;
- }
- if (p2>p)
- {
- p = p2;
- continue;
- }
-
- //none of the above
- break;
- }
-
- return p;
-}
-
-/**
- * import
- * : IMPORT_SYM S*
- * [STRING|URI] S* [ medium [ COMMA S* medium]* ]? ';' S*
- * ;
- */
-int CssParser::getImport(int p0)
-{
- int p = p0;
- if (!match(p, "@import"))
- return p0;
- p+=7;
- p = skipwhite(p);
-
- //# STRING | URI
- DOMString str;
- int p2 = getQuoted(p, str);
- if (p2<0)
- {
- return -1;
- }
- if (p2<=p)
- {
- p2 = getUri(p, str);
- if (p2<0)
- {
- return -1;
- }
- if (p2<=p)
- {
- error("quoted string or URI required after @import");
- return -1;
- }
- }
- p = p2;
- p2 = getMedium(p);
- if (p2<0)
- return -1;
-
- p = p2;
- p = skipwhite(p);
- XMLCh ch = get(p);
- if (ch != ';')
- {
- error("@import must be terminated with ';'");
- return -1;
- }
- p++;
- return p;
-}
-
-/**
- * media
- * : MEDIA_SYM S* medium [ COMMA S* medium ]* LBRACE S* ruleset* '}' S*
- * ;
- */
-int CssParser::getMedia(int p0)
-{
- int p = p0;
- XMLCh ch;
- if (!match(p, "@media"))
- return p0;
- p+=6;
- p = skipwhite(p);
-
- //# MEDIUM LIST
- int p2 = getMedium(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("@media must be followed by medium");
- return -1;
- }
- p = p2;
- while (true)
- {
- ch = get(p);
- if (ch != ',')
- break;
- p2 = getMedium(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("',' in medium list must be followed by medium");
- return -1;
- }
- p = p2;
- }
-
- p = skipwhite(p);
- ch = get(p);
- if (ch!='{')
- {
- error("@media requires '{' for ruleset");
- return -1;
- }
- p++;
- p2 = getRuleSet(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("@media requires ruleset after '{'");
- return -1;
- }
- p = p2;
- ch = get(p);
- if (ch != '}')
- {
- error("@media requires '}' after ruleset");
- return -1;
- }
- p++;
- return p0;
-}
-
-/**
- * medium
- * : IDENT S*
- * ;
- */
-int CssParser::getMedium(int p0)
-{
- int p = p0;
- p = skipwhite(p);
-
- DOMString ident;
- int p2 = getWord(p, ident);
- if (p2<0)
- return -1;
- if (p2<=p)
- return p0;
- p = p2;
-
- return p;
-}
-
-/**
- * page
- * : PAGE_SYM S* pseudo_page? S*
- * LBRACE S* declaration [ ';' S* declaration ]* '}' S*
- * ;
- */
-int CssParser::getPage(int p0)
-{
- int p = p0;
-
- //# @PAGE
- p = skipwhite(p);
- if (!match(p, "@page"))
- return p0;
- p+= 5;
-
- //#PSEUDO PAGE 0 or 1
- p = skipwhite(p);
- int p2 = getPseudoPage(p);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- p = p2;
- }
-
- //# {
- p=skipwhite(p);
- XMLCh ch = get(p);
- if (p != '{')
- {
- error("@page requires '{' before declarations");
- }
- p++;
-
- //# DECLARATION LIST
- p = skipwhite(p);
- CSSStyleDeclaration declarationList;
- p2 = getDeclaration(p, declarationList);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("@page requires declaration(s) after '{'");
- return -1;
- }
- while (true)
- {
- p = skipwhite(p2);
- ch = get(p);
- if (ch != ';')
- break;
- p++;
- p = skipwhite(p);
- p2 = getDeclaration(p, declarationList);
- if (p2<0)
- return -1;
- if (p2<= p)
- {
- error("@page requires declaration after ';'");
- return -1;
- }
- }
-
- //# }
- p=skipwhite(p);
- ch = get(p);
- if (p != '}')
- {
- error("@page requires '}' after declarations");
- }
- p++;
-
- return p;
-}
-
-/**
- * pseudo_page
- * : ':' IDENT
- * ;
- */
-int CssParser::getPseudoPage(int p0)
-{
- int p = p0;
- if (!match(p, ":"))
- return p0;
- p++;
- DOMString str;
- int p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("pseudo-page requires identifier after ':'");
- return -1;
- }
- p = p2;
- return p;
-}
-
-/**
- * ruleset
- * : selector [ COMMA S* selector ]*
- * LBRACE S* declaration [ ';' S* declaration ]* '}' S*
- * ;
- */
-int CssParser::getRuleSet(int p0)
-{
- int p = p0;
- XMLCh ch;
-
- //## SELECTOR
- p = skipwhite(p);
- int p2 = getSelector(p);
- if (p2<0)
- return -1;
- if (p2<=p) //no selector
- {
- if (get(p) != '{')//check for selector-less rule
- return p0;//not me
- }
- p = p2;
- while (true)
- {
- p = skipwhite(p);
- ch = get(p);
- if (ch != ',')
- break;
- p++;
- p = skipwhite(p);
- int p2 = getSelector(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("selector required after ',' in list");
- return -1;
- }
- p = p2;
- }
-
- //## {
- ch = get(p);
- if (ch != '{')
- {
- error("'{' required before declarations of ruleset");
- return -1;
- }
- p++;
-
- //## DECLARATIONS ( 0 to many )
- CSSStyleDeclaration declarationList;
-
- p = skipwhite(p);
- p2 = getDeclaration(p, declarationList);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- p = p2;
- while (true)
- {
- p = skipwhite(p);
- ch = get(p);
- if (ch != ';')
- break;
- p++;
- p = skipwhite(p);
- p2 = getDeclaration(p, declarationList);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- //apparently this is ok
- //error("declaration required after ';' in ruleset");
- //return -1;
- break;
- }
- p = p2;
- }
- }
- //## }
- ch = get(p);
- if (ch != '}')
- {
- error("ruleset requires closing '}'");
- return -1;
- }
- p++;
- p = skipwhite(p);
-
- return p;
-}
-
-/**
- * selector
- * : simple_selector [ combinator simple_selector ]*
- * ;
- */
-int CssParser::getSelector(int p0)
-{
- int p = p0;
-
- //## SIMPLE SELECTOR
- p = skipwhite(p);
- int p2 = getSimpleSelector(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- return p0; //not me
- p = p2;
-
- //## COMBINATORS + MORE SELECTORS
- while (true)
- {
- XMLCh ch = get(p);
- bool wasSpace = isspace(ch);
- p = skipwhite(p);
- ch = get(p);
- //# Combinators
- //easier to do here than have a getCombinator()
- int visibleCombinator = false;
- if (ch == '+')
- {
- visibleCombinator = true;
- p++;
- }
- else if (ch == '>')
- {
- visibleCombinator = true;
- p++;
- }
- else if (wasSpace)
- {
- }
- else
- {
- break;
- }
- p = skipwhite(p);
- p2 = getSimpleSelector(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- if (visibleCombinator)
- {
- error("need simple selector after combinator");
- return -1;
- }
- else
- {
- break;
- }
- }
- p = p2;
- }
- return p;
-}
-
-/**
- * simple_selector
- * : element_name [ HASH | class | attrib | pseudo ]*
- * | [ HASH | class | attrib | pseudo ]+
- * ;
- */
-int CssParser::getSimpleSelector(int p0)
-{
- int p = p0;
- int p2;
-
- DOMString str;
-
- p = skipwhite(p);
-
- int selectorItems = 0;
-
- XMLCh ch = get(p);
-
- //######################
- //# Note: do NOT skipwhite between items. Only within the
- //# pseudo function and attrib below
- //######################
-
- //#Element name 0 or 1
- if (uni_is_letter(ch))
- {
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("null element name");
- return -1;
- }
- selectorItems++;
- p = p2;
- }
- else if (ch == '*')
- {
- str = "*";
- p++;
- selectorItems++;
- }
-
-
-
- //## HASH, CLASS, ATTRIB, PSEUDO (0 to many with elem name, 1 to many without)
- while (true)
- {
- XMLCh ch = get(p);
-
- //# HASH
- if (ch == '#')
- {
- p++;
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("no name for hash");
- return -1;
- }
- p = p2;
- selectorItems++;
- }
-
- //# CLASS
- else if (ch == '.')
- {
- p++;
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("no name for class");
- return -1;
- }
- p = p2;
- selectorItems++;
- }
-
- //# ATTRIB
- else if (ch == '[')
- {
- p++;
- p = skipwhite(p);
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("no name for class");
- return -1;
- }
- p = skipwhite(p2);
- bool getRHS=false;
- if (match(p, "="))
- {
- p++;
- getRHS=true;
- }
- else if (match(p, "~="))
- {
- p+=2;
- getRHS=true;
- }
- else if (match(p, "|="))
- {
- p+=2;
- getRHS=true;
- }
- if (getRHS)
- {
- p = skipwhite(p);
- ch = get(p);
- if (uni_is_letter(ch))
- {
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("null ident on rhs of attrib");
- return -1;
- }
- p = p2;
- }
- else if (ch == '\'' || ch =='"')
- {
- p2 = getQuoted(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("null literal string on rhs of attrib");
- return -1;
- }
- p = p2;
- }
- }//getRHS
- p = skipwhite(p);
- ch = get(p);
- if (ch != ']')
- {
- error("attrib needs closing ']'");
- //return -1;
- p = skipBlock(p);
- return p;
- }
- p++;
- selectorItems++;
- }
-
- //# PSEUDO
- else if (ch == ':')
- {
- p++;
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("no name for pseudo");
- return -1;
- }
- p = p2;
- selectorItems++;
- ch = get(p);
- if (ch == '(')
- {
- p++;
- p = skipwhite(p);
- ch = get(p);
- if (uni_is_letter(ch))
- {
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("null function parameter in pseudo");
- return -1;
- }
- p = skipwhite(p2);
- ch = get(p);
- }
- if (ch != ')')
- {
- error("function in pseudo needs ')'");
- return -1;
- }
- p++;
- }// ch==( -function-
- }//pseudo
-
- //# none of the above
- else
- {
- break;
- }
-
- }//while
-
-
- if (selectorItems > 0)
- return p;
- return p0;
-}
-
-/**
- * declaration
- * : property ':' S* expr prio?
- * | {empty}
- * ;
- */
-int CssParser::getDeclaration(int p0, CSSStyleDeclaration &declarationList)
-{
- int p = p0;
-
- //## PROPERTY
- p = skipwhite(p);
- XMLCh ch = get(p);
- if (!uni_is_letter(ch))
- return p0; //not me
- DOMString propName;
- int p2 = getWord(p, propName);
- if (p2<0)
- return -1;
-
- //## ':'
- p = skipwhite(p2);
- ch = get(p);
- if (ch != ':')
- {
- error("declaration requires ':' between name and value");
- return -1;
- }
- p++;
-
- //## EXPR
- p = skipwhite(p);
- p2 = getExpr(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("declaration requires value after ':'");
- return -1;
- }
- DOMString propVal;
- for (int i=p ; i<p2 ; i++) //get our substring
- propVal.push_back(get(i));
- printf("propVal:%s\n", propVal.c_str());
- p = p2;
-
- //## PRIO (optional)
- p = skipwhite(p);
- DOMString prio;
- p2 = getPrio(p, prio);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- //do something
- p = p2;
- }
-
- return p;
-}
-
-/**
- * prio
- * : IMPORTANT_SYM S*
- * ;
- */
-int CssParser::getPrio(int p0, DOMString &val)
-{
- int p = p0;
-
- //## '!"
- p = skipwhite(p);
- XMLCh ch = get(p);
- if (ch != '!')
- return p0;
- p++;
-
- //## "important"
- p = skipwhite(p);
- if (!match(p, "important"))
- {
- error("priority symbol is 'important'");
- return -1;
- }
- p += 9;
- val = "important";
- return p;
-}
-
-/**
- * expr
- * : term [ operator term ]*
- * ;
- */
-int CssParser::getExpr(int p0)
-{
- int p = p0;
-
- //## TERM
- p = skipwhite(p);
- int p2 = getTerm(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- return p0; //not me
- p = p2;
- while (p < parselen)
- {
- p = skipwhite(p);
- //#Operator. do this instead of getOperator()
- XMLCh ch = get(p);
- int visibleTerm = false;
- if (ch == '/')
- {
- visibleTerm = true;
- p++;
- }
- else if (ch == ',')
- {
- visibleTerm = true;
- p++;
- }
- else
- {
- //just space. this is allowable between terms,
- // so we still need to check for another term
- }
- p = skipwhite(p);
- p2 = getTerm(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- if (visibleTerm)
- {
- error("expression requires term after operator");
- return -1;
- }
- else
- {
- break;
- }
- }
- p = p2;
- }
-
- return p;
-}
-
-/**
- * term
- * : unary_operator?
- * [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |
- * TIME S* | FREQ S* | function ]
- * | STRING S* | IDENT S* | URI S* | hexcolor
- * ;
- */
-int CssParser::getTerm(int p0)
-{
- int p = p0;
- p = skipwhite(p);
- int unitType = CSSPrimitiveValue::CSS_UNKNOWN;
- //# Unary operator
- XMLCh ch = get(p);
- bool hasUnary = false;
- if (ch == '-')
- {
- p++;
- hasUnary = true;
- }
- else if (ch == '+')
- {
- p++;
- hasUnary = true;
- }
- //# NUMERIC
- double numVal;
- int p2 = getNumber(p, numVal);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- p = p2;
- if (match(p, "%"))
- {
- unitType = CSSPrimitiveValue::CSS_PERCENTAGE;
- p++;
- }
- else if (match(p, "em"))
- {
- unitType = CSSPrimitiveValue::CSS_EMS;
- p+=2;
- }
- else if (match(p, "ex"))
- {
- unitType = CSSPrimitiveValue::CSS_EXS;
- p+=2;
- }
- else if (match(p, "px"))
- {
- unitType = CSSPrimitiveValue::CSS_PX;
- p+=2;
- }
- else if (match(p, "cm"))
- {
- unitType = CSSPrimitiveValue::CSS_CM;
- p+=2;
- }
- else if (match(p, "mm"))
- {
- unitType = CSSPrimitiveValue::CSS_MM;
- p+=2;
- }
- else if (match(p, "in"))
- {
- unitType = CSSPrimitiveValue::CSS_IN;
- p+=2;
- }
- else if (match(p, "pt"))
- {
- unitType = CSSPrimitiveValue::CSS_PT;
- p+=2;
- }
- else if (match(p, "pc"))
- {
- unitType = CSSPrimitiveValue::CSS_PC;
- p+=2;
- }
- else if (match(p, "deg"))
- {
- unitType = CSSPrimitiveValue::CSS_DEG;
- p+=3;
- }
- else if (match(p, "rad"))
- {
- unitType = CSSPrimitiveValue::CSS_RAD;
- p+=3;
- }
- else if (match(p, "grad"))
- {
- unitType = CSSPrimitiveValue::CSS_GRAD;
- p+=4;
- }
- else if (match(p, "ms"))
- {
- unitType = CSSPrimitiveValue::CSS_MS;
- p+=2;
- }
- else if (match(p, "s"))
- {
- unitType = CSSPrimitiveValue::CSS_S;
- p+=1;
- }
- else if (match(p, "Hz"))
- {
- unitType = CSSPrimitiveValue::CSS_HZ;
- p+=2;
- }
- else if (match(p, "kHz"))
- {
- unitType = CSSPrimitiveValue::CSS_KHZ;
- p+=2;
- }
- else if (uni_is_letter(get(p)))//some other string
- {
- DOMString suffix;
- p2 = getWord(p, suffix);
- if (p2<0)
- return -1;
- unitType = CSSPrimitiveValue::CSS_DIMENSION;
- p = p2;
- }
- else //plain number
- {
- unitType = CSSPrimitiveValue::CSS_NUMBER;
- }
- return p;
- }
-
- DOMString str;
-
- //## URI --do before function, as syntax is similar
- p2 = getUri(p, str);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- if (hasUnary)
- {
- error("+ or - not allowed on URI");
- return -1;
- }
- p = p2;
- unitType = CSSPrimitiveValue::CSS_URI;
- return p;
- }
-
- //## FUNCTION
- p2 = getFunction(p);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- p = p2;
- return p;
- }
-
- //## STRING
- ch = get(p);
- if (ch == '"' || ch == '\'')
- {
- p2 = getQuoted(p, str);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- if (hasUnary)
- {
- error("+ or - not allowed on a string");
- return -1;
- }
- p = p2;
- unitType = CSSPrimitiveValue::CSS_STRING;
- return p;
- }
- }
-
- //## IDENT
- ch = get(p);
- if (uni_is_letter(ch))
- {
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- if (hasUnary)
- {
- error("+ or - not allowed on an identifier");
- return -1;
- }
- p = p2;
- unitType = CSSPrimitiveValue::CSS_IDENT;
- return p;
- }
- }
-
-
- //## HEXCOLOR
- p2 = getHexColor(p);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- if (hasUnary)
- {
- error("+ or - not allowed on hex color");
- return -1;
- }
- p = p2;
- unitType = CSSPrimitiveValue::CSS_RGBCOLOR;
- return p;
- }
-
-
- return p0;
-}
-
-/**
- * function
- * : FUNCTION S* expr ')' S*
- * ;
- */
-int CssParser::getFunction(int p0)
-{
- int p = p0;
-
- //## IDENT + ( (both)
- DOMString name;
- p = skipwhite(p);
- int p2 = getWord(p, name);
- if (p2<0)
- return -1;
- if (p2<=p)
- return p0; //not me
- if (name == "uri" || name=="url")
- return p0; //not me
- p = skipwhite(p2);
- XMLCh ch = get(p);
- if (ch != '(')
- return p0; //still not me
- p++;
-
- //## EXPR
- p = skipwhite(p);
- p2 = getExpr(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("function requires expression");
- return -1;
- }
- p = p2;
-
- //## ')'
- p = skipwhite(p);
- ch = get(p);
- if (ch != ')')
- {
- error("function requires closing ')'");
- return -1;
- }
- p++;
- p = skipwhite(p);
-
- return p;
-}
-
-/**
- * There is a constraint on the color that it must
- * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
- * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
- * hexcolor
- * : HASH S*
- * ;
- */
-int CssParser::getHexColor(int p0)
-{
- int p = p0;
-
- //## '#'
- p = skipwhite(p);
- if (!match(p, "#"))
- return p0;
- p++;
-
- //## HEX
- DOMString hex;
- long hexVal = 0;
- while (p < parselen)
- {
- XMLCh b = get(p);
- if (b>='0' && b<='9')
- {
- hexVal = (hexVal << 4) + (b - '0');
- hex.push_back(b);
- p++;
- }
- else if (b>='a' && b<='f')
- {
- hexVal = (hexVal << 4) + (b - 'a' + 10);
- hex.push_back(b);
- p++;
- }
- else if (b>='A' && b<='F')
- {
- hexVal = (hexVal << 4) + (b - 'A' + 10);
- hex.push_back(b);
- p++;
- }
- else
- {
- break;
- }
- }
-
- if (hex.size() != 3 && hex.size() != 6)
- {
- error("exactly 3 or 6 hex digits are required after '#'");
- return -1;
- }
-
- return p;
-}
-
-
-
-/**
- *
- */
-bool CssParser::parse(const DOMString &str)
-{
- /*
- int len = str.size();
- for (int i=0 ; i<len ; i++)
- {
- XMLCh ch = str[i];
- if (ch == '\\' && i<(len-1)) //escape!
- {
- i++;
- }
- else
- parsebuf.push_back(ch);
- }
- */
- parsebuf = str;
-
- parselen = parsebuf.size();
- //printf("==============================\n%s\n========================\n", str.c_str());
-
- lastPosition = 0;
-
- int p = getStyleSheet(0);
- if (p < parselen)
- {
- error("Not everything parsed");
- return false;
- }
-
- return true;
-}
-
-
-/**
- *
- */
-bool CssParser::parseFile(const DOMString &fileName)
-{
- DOMString tmp = fileName;
- char *fname = (char *)tmp.c_str();
- FILE *f = fopen(fname, "r");
- if (!f)
- {
- printf("Could not open %s for reading\n", fname);
- return false;
- }
-
- DOMString str;
- while (!feof(f))
- {
- int ch = fgetc(f);
- if (ch<0)
- break;
- str.push_back((XMLCh)ch);
- }
- fclose(f);
-
- bool ret = parse(str);
-
- return ret;
-}
-
-
-
-
-
-
-
-} // namespace css
-} // namespace dom
-} // namespace w3c
-} // namespace org
-
-
-#ifdef TEST
-
-int main(int argc, char **argv)
-{
- org::w3c::dom::css::CssParser parser;
- char *fileName;
- fileName = "001.css";
- //fileName = "acid.css";
- //fileName = "base.css";
- //fileName = "inkscape.css";
- //fileName = "meyerweb.css";
- if (!parser.parseFile(fileName))
- {
- printf("Test failed\n");
- return 1;
- }
- return 0;
-}
-
-#endif /* TEST */
-
-//#########################################################################
-//# E N D O F F I L E
-//#########################################################################
-
diff --git a/src/dom/cssparser.h b/src/dom/cssparser.h
--- a/src/dom/cssparser.h
+++ /dev/null
@@ -1,290 +0,0 @@
-#ifndef __CSSPARSER_H__
-#define __CSSPARSER_H__
-/**
- * Phoebe DOM Implementation.
- *
- * This is a C++ approximation of the W3C DOM model, which follows
- * fairly closely the specifications in the various .idl files, copies of
- * which are provided for reference. Most important is this one:
- *
- * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
- *
- * Authors:
- * Bob Jamison
- *
- * Copyright (C) 2005-2008 Bob Jamison
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-
-#include "dom.h"
-
-#include "css.h"
-
-namespace org
-{
-namespace w3c
-{
-namespace dom
-{
-namespace css
-{
-
-class CssParser
-{
-
-public:
-
- /**
- *
- */
- CssParser()
- {}
-
- /**
- *
- */
- virtual ~CssParser()
- {}
-
- /**
- *
- */
- virtual bool parse(const DOMString &str);
-
- /**
- *
- */
- virtual bool parseFile(const DOMString &str);
-
-
-private:
-
- DOMString parsebuf;
- long parselen;
- CSSStyleSheet stylesheet;
-
-
- /**
- *
- */
- void error(char const *fmt, ...)
- #ifdef G_GNUC_PRINTF
- G_GNUC_PRINTF(2, 3)
- #endif
- ;
-
- /**
- * Get the character at the given location in the buffer.
- * Return 0 if out-of-bounds
- */
- XMLCh get(int index);
-
-
- /**
- * Test if the given substring exists at the given position
- * in parsebuf. Use get() in case of out-of-bounds
- */
- bool match(int pos, const char *str);
-
- /**
- * Skip over whitespace
- * Return new position
- */
- int skipwhite(int index);
-
- /**
- * Get the word at the current position. Return the new
- * position if successful, the current position if no word,
- * -1 if error.
- */
- int getWord(int index, DOMString &str);
-
-
- /**
- * Get a number at the current position
- * Return the new position if a proper number, else the original pos
- */
- int getNumber(int index, double &result);
-
- /**
- * Assume that we are starting on a quote. Ends on the char
- * after the final '"'
- */
- int getQuoted(int p0, DOMString &result);
-
-/**
- * Not in api. replaces URI return by lexer
- */
-int getUri(int p0, DOMString &str);
-
-
-/**
- * Skip to the next rule
- */
-int skipBlock(int p0);
-
-//#########################################################################
-//# P R O D U C T I O N S
-//#########################################################################
-
-/**
- * stylesheet
- * : [ CHARSET_SYM S* STRING S* ';' ]?
- * [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*
- * [ [ ruleset | media | page ] [S|CDO|CDC]* ]*
- * ;
- */
-int getStyleSheet(int p0);
-
-/**
- * import
- * : IMPORT_SYM S*
- * [STRING|URI] S* [ medium [ COMMA S* medium]* ]? ';' S*
- * ;
- */
-int getImport(int p0);
-
-/**
- * media
- * : MEDIA_SYM S* medium [ COMMA S* medium ]* LBRACE S* ruleset* '}' S*
- * ;
- */
-int getMedia(int p0);
-
-/**
- * medium
- * : IDENT S*
- * ;
- */
-int getMedium(int p0);
-
-/**
- * page
- * : PAGE_SYM S* pseudo_page? S*
- * LBRACE S* declaration [ ';' S* declaration ]* '}' S*
- * ;
- */
-int getPage(int p0);
-
-/**
- * pseudo_page
- * : ':' IDENT
- * ;
- */
-int getPseudoPage(int p0);
-
-/**
- * ruleset
- * : selector [ COMMA S* selector ]*
- * LBRACE S* declaration [ ';' S* declaration ]* '}' S*
- * ;
- */
-int getRuleSet(int p0);
-
-/**
- * selector
- * : simple_selector [ combinator simple_selector ]*
- * ;
- */
-int getSelector(int p0);
-
-/**
- * simple_selector
- * : element_name [ HASH | class | attrib | pseudo ]*
- * | [ HASH | class | attrib | pseudo ]+
- * ;
- */
-int getSimpleSelector(int p0);
-
-/**
- * declaration
- * : property ':' S* expr prio?
- * | {empty}
- * ;
- */
-int getDeclaration(int p0, CSSStyleDeclaration &declarationList);
-
-/**
- * prio
- * : IMPORTANT_SYM S*
- * ;
- */
-int getPrio(int p0, DOMString &val);
-
-/**
- * expr
- * : term [ operator term ]*
- * ;
- */
-int getExpr(int p0);
-
-/**
- * term
- * : unary_operator?
- * [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |
- * TIME S* | FREQ S* | function ]
- * | STRING S* | IDENT S* | URI S* | hexcolor
- * ;
- */
-int getTerm(int p0);
-
-/**
- * function
- * : FUNCTION S* expr ')' S*
- * ;
- */
-int getFunction(int p0);
-
-/**
- * There is a constraint on the color that it must
- * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
- * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
- *
- * hexcolor
- * : HASH S*
- * ;
- */
-int getHexColor(int p0);
-
-
-int lastPosition;
-
-/**
- * Get the column and row number of the given character position.
- * Also gets the last-occuring newline before the position
- */
-void getColumnAndRow(int p, int &col, int &row, int &lastNL);
-
-};
-
-
-} // namespace css
-} // namespace dom
-} // namespace w3c
-} // namespace org
-
-
-
-
-
-
-
-#endif /* __CSSPARSER_H__ */
-//#########################################################################
-//# E N D O F F I L E
-//#########################################################################
-
diff --git a/src/dom/cssreader.cpp b/src/dom/cssreader.cpp
--- /dev/null
+++ b/src/dom/cssreader.cpp
@@ -0,0 +1,1670 @@
+/**
+ * Phoebe DOM Implementation.
+ *
+ * This is a C++ approximation of the W3C DOM model, which follows
+ * fairly closely the specifications in the various .idl files, copies of
+ * which are provided for reference. Most important is this one:
+ *
+ * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
+ *
+ * Authors:
+ * Bob Jamison
+ *
+ * Copyright (C) 2005-2008 Bob Jamison
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "cssreader.h"
+#include "ucd.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+namespace org
+{
+namespace w3c
+{
+namespace dom
+{
+namespace css
+{
+
+//#########################################################################
+//# M E S S A G E S
+//#########################################################################
+
+/**
+ * Get the column and row number of the given character position
+ */
+void CssParser::getColumnAndRow(int p, int &colResult, int &rowResult, int &lastNL)
+{
+ int col = 1;
+ int row = 1;
+ int lastnl = 0;
+
+ for (int i=0 ; i<p ; i++)
+ {
+ XMLCh ch = parsebuf[i];
+ if (ch == '\n')
+ {
+ lastnl = i;
+ row++;
+ col=0;
+ }
+ else
+ col++;
+ }
+
+ colResult = col;
+ rowResult = row;
+ lastNL = lastnl;
+}
+
+/**
+ *
+ */
+void CssParser::error(char const *fmt, ...)
+{
+ int lineNr;
+ int colNr;
+ int lastNL;
+ getColumnAndRow(lastPosition, colNr, lineNr, lastNL);
+
+ va_list args;
+ fprintf(stderr, "CssParser:error at %d, line %d, column %d:",
+ lastPosition, lineNr, colNr);
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args) ;
+ fprintf(stderr, "\n");
+
+ /*
+ int lineLen = lastPosition - lastNL;
+ printf("lineLen:%d lastNL:%d\n", lineLen, lastNL);
+ for (int i=lastNL+1 ; i<lastPosition ; i++)
+ fprintf(stderr, "%c", parsebuf[i]);
+ fprintf(stderr, "\n");
+ for (int i=0 ; i<lineLen-1 ; i++)
+ fprintf(stderr, " ");
+ fprintf(stderr, "^\n");
+ */
+ for (int i=0 ; i<lastPosition ; i++)
+ fprintf(stderr, "%c", parsebuf[i]);
+ fprintf(stderr, "\n");
+}
+
+
+
+//#########################################################################
+//# P A R S I N G
+//#########################################################################
+
+/**
+ * Get the character at the position and record the fact
+ */
+XMLCh CssParser::get(int p)
+{
+ if (p >= parselen)
+ return 0;
+ XMLCh ch = parsebuf[p];
+ //printf("%c", ch);
+ lastPosition = p;
+ return ch;
+}
+
+
+
+/**
+ * Test if the given substring exists at the given position
+ * in parsebuf. Use get() in case of out-of-bounds
+ */
+bool CssParser::match(int pos, const char *str)
+{
+ while (*str)
+ {
+ if (get(pos++) != (XMLCh) *str++)
+ return false;
+ }
+ return true;
+}
+
+/**
+ *
+ */
+int CssParser::skipwhite(int p)
+{
+ while (p < parselen)
+ {
+ //# XML COMMENT
+ if (match(p, "<!--"))
+ {
+ p+=4;
+ bool done=false;
+ while (p<parselen)
+ {
+ if (match(p, "-->"))
+ {
+ p+=3;
+ done=true;
+ break;
+ }
+ p++;
+ }
+ lastPosition = p;
+ if (!done)
+ {
+ error("unterminated <!-- .. --> comment");
+ return -1;
+ }
+ }
+ //# C comment
+ else if (match(p, "/*"))
+ {
+ p+=2;
+ bool done=false;
+ while (p<parselen)
+ {
+ if (match(p, "*/"))
+ {
+ p+=2;
+ done=true;
+ break;
+ }
+ p++;
+ }
+ lastPosition = p;
+ if (!done)
+ {
+ error("unterminated /* .. */ comment");
+ return -1;
+ }
+ }
+ else if (!uni_is_space(get(p)))
+ break;
+ else
+ p++;
+ }
+ lastPosition = p;
+ return p;
+}
+
+/**
+ * get a word from the buffer
+ */
+int CssParser::getWord(int p, DOMString &result)
+{
+ XMLCh ch = get(p);
+ if (!uni_is_letter(ch))
+ return p;
+ DOMString str;
+ str.push_back(ch);
+ p++;
+
+ while (p < parselen)
+ {
+ ch = get(p);
+ if (uni_is_letter_or_digit(ch) || ch=='-' || ch=='_')
+ {
+ str.push_back(ch);
+ p++;
+ }
+ else if (ch == '\\')
+ {
+ p+=2;
+ }
+ else
+ break;
+ }
+ result = str;
+ return p;
+}
+
+
+/**
+ * get a word from the buffer
+ */
+int CssParser::getNumber(int p0, double &result)
+{
+ int p=p0;
+ DOMString str;
+ while (p < parselen)
+ {
+ XMLCh ch = get(p);
+ if (ch<'0' || ch>'9')
+ break;
+ str.push_back(ch);
+ p++;
+ }
+ if (get(p) == '.' && get(p+1)>='0' && get(p+1)<='9')
+ {
+ p++;
+ str.push_back('.');
+ while (p < parselen)
+ {
+ XMLCh ch = get(p);
+ if (ch<'0' || ch>'9')
+ break;
+ str.push_back(ch);
+ p++;
+ }
+ }
+ if (p>p0)
+ {
+ char *start = (char *)str.c_str();
+ char *end = NULL;
+ double val = strtod(start, &end);
+ if (end > start)
+ {
+ result = val;
+ return p;
+ }
+ }
+
+ //not a number
+ return p0;
+}
+
+
+
+/**
+ * Assume that we are starting on a quote. Ends on the char
+ * after the final '"'
+ */
+int CssParser::getQuoted(int p0, DOMString &result)
+{
+
+ int p = p0;
+
+ XMLCh quoteChar = get(p);
+ if (quoteChar != '"' && quoteChar != '\'')
+ return p0;
+
+ p++;
+
+ DOMString buf;
+
+ bool done = false;
+ while (p<parselen )
+ {
+ XMLCh ch = get(p);
+ if (ch == quoteChar)
+ {
+ done = true;
+ p++;
+ break;
+ }
+ else
+ {
+ buf.push_back(ch);
+ }
+ p++;
+ }
+
+ if (!done)
+ {
+ error("unterminated quoted string");
+ return -1;
+ }
+
+ result.append(buf);
+
+ return p;
+}
+
+/**
+ * Not in api. replaces URI return by lexer
+ */
+int CssParser::getUri(int p0, DOMString &str)
+{
+ int p = p0;
+ if (!match(p, "url("))
+ return p0;
+ p+=4;
+ p = skipwhite(p);
+ DOMString buf;
+ XMLCh ch;
+ while (p < parselen)
+ {
+ ch = get(p);
+ if (isspace(ch) || ch==')')
+ break;
+ buf.push_back(ch);
+ p++;
+ }
+ p = skipwhite(p);
+ ch = get(p);
+ if (ch != ')')
+ {
+ error("no closing ')' on url spec");
+ return -1;
+ }
+ p++;
+ str = buf;
+ return p;
+}
+
+/**
+ * Skip to the end of the block
+ */
+int CssParser::skipBlock(int p0)
+{
+ int p = p0;
+ while (p < parselen)
+ {
+ XMLCh ch = get(p);
+ if (ch == '}')
+ {
+ p++;
+ break;
+ }
+ else
+ {
+ p++;
+ }
+ }
+ return p;
+}
+
+//#########################################################################
+//# P R O D U C T I O N S
+//#########################################################################
+
+/**
+ * stylesheet
+ * : [ CHARSET_SYM S* STRING S* ';' ]?
+ * [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*
+ * [ [ ruleset | media | page ] [S|CDO|CDC]* ]*
+ * ;
+ */
+int CssParser::getStyleSheet(int p0)
+{
+ int p = p0;
+ int p2 = p;
+ XMLCh ch;
+
+ //# CHARSET 0 or 1
+ if (match(p, "@charset"))
+ {
+ p+=8;
+ p = skipwhite(p);
+ DOMString str;
+ p2 = getQuoted(p, str);
+ if (p2<=p)
+ {
+ error("quoted string required after @charset");
+ return -1;
+ }
+ p = skipwhite(p2);
+ ch = get(p);
+ if (ch !=';')
+ {
+ error("';' required after @charset declaration");
+ return -1;
+ }
+ p++;
+ p = skipwhite(p);
+ }
+
+ //# IMPORT 0 to many
+ while (true)
+ {
+ p2 = getImport(p);
+ if (p2<0)
+ {
+ return -1;
+ }
+ if (p2<=p)
+ break;
+ p = p2;
+ }
+
+ //# RULESET | MEDIA | PAGE 0 to many
+ while (true)
+ {
+ //Ruleset
+ p2 = getRuleSet(p);
+ if (p2<0)
+ {
+ return -1;
+ }
+ if (p2>p)
+ {
+ p = p2;
+ continue;
+ }
+
+ //Media
+ p2 = getMedia(p);
+ if (p2<0)
+ {
+ return -1;
+ }
+ if (p2>p)
+ {
+ p = p2;
+ continue;
+ }
+
+ //Page
+ p2 = getPage(p);
+ if (p2<0)
+ {
+ return -1;
+ }
+ if (p2>p)
+ {
+ p = p2;
+ continue;
+ }
+
+ //none of the above
+ break;
+ }
+
+ return p;
+}
+
+/**
+ * import
+ * : IMPORT_SYM S*
+ * [STRING|URI] S* [ medium [ COMMA S* medium]* ]? ';' S*
+ * ;
+ */
+int CssParser::getImport(int p0)
+{
+ int p = p0;
+ if (!match(p, "@import"))
+ return p0;
+ p+=7;
+ p = skipwhite(p);
+
+ //# STRING | URI
+ DOMString str;
+ int p2 = getQuoted(p, str);
+ if (p2<0)
+ {
+ return -1;
+ }
+ if (p2<=p)
+ {
+ p2 = getUri(p, str);
+ if (p2<0)
+ {
+ return -1;
+ }
+ if (p2<=p)
+ {
+ error("quoted string or URI required after @import");
+ return -1;
+ }
+ }
+ p = p2;
+ p2 = getMedium(p);
+ if (p2<0)
+ return -1;
+
+ p = p2;
+ p = skipwhite(p);
+ XMLCh ch = get(p);
+ if (ch != ';')
+ {
+ error("@import must be terminated with ';'");
+ return -1;
+ }
+ p++;
+ return p;
+}
+
+/**
+ * media
+ * : MEDIA_SYM S* medium [ COMMA S* medium ]* LBRACE S* ruleset* '}' S*
+ * ;
+ */
+int CssParser::getMedia(int p0)
+{
+ int p = p0;
+ XMLCh ch;
+ if (!match(p, "@media"))
+ return p0;
+ p+=6;
+ p = skipwhite(p);
+
+ //# MEDIUM LIST
+ int p2 = getMedium(p);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("@media must be followed by medium");
+ return -1;
+ }
+ p = p2;
+ while (true)
+ {
+ ch = get(p);
+ if (ch != ',')
+ break;
+ p2 = getMedium(p);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("',' in medium list must be followed by medium");
+ return -1;
+ }
+ p = p2;
+ }
+
+ p = skipwhite(p);
+ ch = get(p);
+ if (ch!='{')
+ {
+ error("@media requires '{' for ruleset");
+ return -1;
+ }
+ p++;
+ p2 = getRuleSet(p);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("@media requires ruleset after '{'");
+ return -1;
+ }
+ p = p2;
+ ch = get(p);
+ if (ch != '}')
+ {
+ error("@media requires '}' after ruleset");
+ return -1;
+ }
+ p++;
+ return p0;
+}
+
+/**
+ * medium
+ * : IDENT S*
+ * ;
+ */
+int CssParser::getMedium(int p0)
+{
+ int p = p0;
+ p = skipwhite(p);
+
+ DOMString ident;
+ int p2 = getWord(p, ident);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ return p0;
+ p = p2;
+
+ return p;
+}
+
+/**
+ * page
+ * : PAGE_SYM S* pseudo_page? S*
+ * LBRACE S* declaration [ ';' S* declaration ]* '}' S*
+ * ;
+ */
+int CssParser::getPage(int p0)
+{
+ int p = p0;
+
+ //# @PAGE
+ p = skipwhite(p);
+ if (!match(p, "@page"))
+ return p0;
+ p+= 5;
+
+ //#PSEUDO PAGE 0 or 1
+ p = skipwhite(p);
+ int p2 = getPseudoPage(p);
+ if (p2<0)
+ return -1;
+ if (p2>p)
+ {
+ p = p2;
+ }
+
+ //# {
+ p=skipwhite(p);
+ XMLCh ch = get(p);
+ if (p != '{')
+ {
+ error("@page requires '{' before declarations");
+ }
+ p++;
+
+ //# DECLARATION LIST
+ p = skipwhite(p);
+ CSSStyleDeclaration declarationList;
+ p2 = getDeclaration(p, declarationList);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("@page requires declaration(s) after '{'");
+ return -1;
+ }
+ while (true)
+ {
+ p = skipwhite(p2);
+ ch = get(p);
+ if (ch != ';')
+ break;
+ p++;
+ p = skipwhite(p);
+ p2 = getDeclaration(p, declarationList);
+ if (p2<0)
+ return -1;
+ if (p2<= p)
+ {
+ error("@page requires declaration after ';'");
+ return -1;
+ }
+ }
+
+ //# }
+ p=skipwhite(p);
+ ch = get(p);
+ if (p != '}')
+ {
+ error("@page requires '}' after declarations");
+ }
+ p++;
+
+ return p;
+}
+
+/**
+ * pseudo_page
+ * : ':' IDENT
+ * ;
+ */
+int CssParser::getPseudoPage(int p0)
+{
+ int p = p0;
+ if (!match(p, ":"))
+ return p0;
+ p++;
+ DOMString str;
+ int p2 = getWord(p, str);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("pseudo-page requires identifier after ':'");
+ return -1;
+ }
+ p = p2;
+ return p;
+}
+
+/**
+ * ruleset
+ * : selector [ COMMA S* selector ]*
+ * LBRACE S* declaration [ ';' S* declaration ]* '}' S*
+ * ;
+ */
+int CssParser::getRuleSet(int p0)
+{
+ int p = p0;
+ XMLCh ch;
+
+ //## SELECTOR
+ p = skipwhite(p);
+ int p2 = getSelector(p);
+ if (p2<0)
+ return -1;
+ if (p2<=p) //no selector
+ {
+ if (get(p) != '{')//check for selector-less rule
+ return p0;//not me
+ }
+ p = p2;
+ while (true)
+ {
+ p = skipwhite(p);
+ ch = get(p);
+ if (ch != ',')
+ break;
+ p++;
+ p = skipwhite(p);
+ int p2 = getSelector(p);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("selector required after ',' in list");
+ return -1;
+ }
+ p = p2;
+ }
+
+ //## {
+ ch = get(p);
+ if (ch != '{')
+ {
+ error("'{' required before declarations of ruleset");
+ return -1;
+ }
+ p++;
+
+ //## DECLARATIONS ( 0 to many )
+ CSSStyleDeclaration declarationList;
+
+ p = skipwhite(p);
+ p2 = getDeclaration(p, declarationList);
+ if (p2<0)
+ return -1;
+ if (p2>p)
+ {
+ p = p2;
+ while (true)
+ {
+ p = skipwhite(p);
+ ch = get(p);
+ if (ch != ';')
+ break;
+ p++;
+ p = skipwhite(p);
+ p2 = getDeclaration(p, declarationList);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ //apparently this is ok
+ //error("declaration required after ';' in ruleset");
+ //return -1;
+ break;
+ }
+ p = p2;
+ }
+ }
+ //## }
+ ch = get(p);
+ if (ch != '}')
+ {
+ error("ruleset requires closing '}'");
+ return -1;
+ }
+ p++;
+ p = skipwhite(p);
+
+ return p;
+}
+
+/**
+ * selector
+ * : simple_selector [ combinator simple_selector ]*
+ * ;
+ */
+int CssParser::getSelector(int p0)
+{
+ int p = p0;
+
+ //## SIMPLE SELECTOR
+ p = skipwhite(p);
+ int p2 = getSimpleSelector(p);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ return p0; //not me
+ p = p2;
+
+ //## COMBINATORS + MORE SELECTORS
+ while (true)
+ {
+ XMLCh ch = get(p);
+ bool wasSpace = isspace(ch);
+ p = skipwhite(p);
+ ch = get(p);
+ //# Combinators
+ //easier to do here than have a getCombinator()
+ int visibleCombinator = false;
+ if (ch == '+')
+ {
+ visibleCombinator = true;
+ p++;
+ }
+ else if (ch == '>')
+ {
+ visibleCombinator = true;
+ p++;
+ }
+ else if (wasSpace)
+ {
+ }
+ else
+ {
+ break;
+ }
+ p = skipwhite(p);
+ p2 = getSimpleSelector(p);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ if (visibleCombinator)
+ {
+ error("need simple selector after combinator");
+ return -1;
+ }
+ else
+ {
+ break;
+ }
+ }
+ p = p2;
+ }
+ return p;
+}
+
+/**
+ * simple_selector
+ * : element_name [ HASH | class | attrib | pseudo ]*
+ * | [ HASH | class | attrib | pseudo ]+
+ * ;
+ */
+int CssParser::getSimpleSelector(int p0)
+{
+ int p = p0;
+ int p2;
+
+ DOMString str;
+
+ p = skipwhite(p);
+
+ int selectorItems = 0;
+
+ XMLCh ch = get(p);
+
+ //######################
+ //# Note: do NOT skipwhite between items. Only within the
+ //# pseudo function and attrib below
+ //######################
+
+ //#Element name 0 or 1
+ if (uni_is_letter(ch))
+ {
+ p2 = getWord(p, str);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("null element name");
+ return -1;
+ }
+ selectorItems++;
+ p = p2;
+ }
+ else if (ch == '*')
+ {
+ str = "*";
+ p++;
+ selectorItems++;
+ }
+
+
+
+ //## HASH, CLASS, ATTRIB, PSEUDO (0 to many with elem name, 1 to many without)
+ while (true)
+ {
+ XMLCh ch = get(p);
+
+ //# HASH
+ if (ch == '#')
+ {
+ p++;
+ p2 = getWord(p, str);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("no name for hash");
+ return -1;
+ }
+ p = p2;
+ selectorItems++;
+ }
+
+ //# CLASS
+ else if (ch == '.')
+ {
+ p++;
+ p2 = getWord(p, str);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("no name for class");
+ return -1;
+ }
+ p = p2;
+ selectorItems++;
+ }
+
+ //# ATTRIB
+ else if (ch == '[')
+ {
+ p++;
+ p = skipwhite(p);
+ p2 = getWord(p, str);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("no name for class");
+ return -1;
+ }
+ p = skipwhite(p2);
+ bool getRHS=false;
+ if (match(p, "="))
+ {
+ p++;
+ getRHS=true;
+ }
+ else if (match(p, "~="))
+ {
+ p+=2;
+ getRHS=true;
+ }
+ else if (match(p, "|="))
+ {
+ p+=2;
+ getRHS=true;
+ }
+ if (getRHS)
+ {
+ p = skipwhite(p);
+ ch = get(p);
+ if (uni_is_letter(ch))
+ {
+ p2 = getWord(p, str);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("null ident on rhs of attrib");
+ return -1;
+ }
+ p = p2;
+ }
+ else if (ch == '\'' || ch =='"')
+ {
+ p2 = getQuoted(p, str);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("null literal string on rhs of attrib");
+ return -1;
+ }
+ p = p2;
+ }
+ }//getRHS
+ p = skipwhite(p);
+ ch = get(p);
+ if (ch != ']')
+ {
+ error("attrib needs closing ']'");
+ //return -1;
+ p = skipBlock(p);
+ return p;
+ }
+ p++;
+ selectorItems++;
+ }
+
+ //# PSEUDO
+ else if (ch == ':')
+ {
+ p++;
+ p2 = getWord(p, str);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("no name for pseudo");
+ return -1;
+ }
+ p = p2;
+ selectorItems++;
+ ch = get(p);
+ if (ch == '(')
+ {
+ p++;
+ p = skipwhite(p);
+ ch = get(p);
+ if (uni_is_letter(ch))
+ {
+ p2 = getWord(p, str);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("null function parameter in pseudo");
+ return -1;
+ }
+ p = skipwhite(p2);
+ ch = get(p);
+ }
+ if (ch != ')')
+ {
+ error("function in pseudo needs ')'");
+ return -1;
+ }
+ p++;
+ }// ch==( -function-
+ }//pseudo
+
+ //# none of the above
+ else
+ {
+ break;
+ }
+
+ }//while
+
+
+ if (selectorItems > 0)
+ return p;
+ return p0;
+}
+
+/**
+ * declaration
+ * : property ':' S* expr prio?
+ * | {empty}
+ * ;
+ */
+int CssParser::getDeclaration(int p0, CSSStyleDeclaration &declarationList)
+{
+ int p = p0;
+
+ //## PROPERTY
+ p = skipwhite(p);
+ XMLCh ch = get(p);
+ if (!uni_is_letter(ch))
+ return p0; //not me
+ DOMString propName;
+ int p2 = getWord(p, propName);
+ if (p2<0)
+ return -1;
+
+ //## ':'
+ p = skipwhite(p2);
+ ch = get(p);
+ if (ch != ':')
+ {
+ error("declaration requires ':' between name and value");
+ return -1;
+ }
+ p++;
+
+ //## EXPR
+ p = skipwhite(p);
+ p2 = getExpr(p);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("declaration requires value after ':'");
+ return -1;
+ }
+ DOMString propVal;
+ for (int i=p ; i<p2 ; i++) //get our substring
+ propVal.push_back(get(i));
+ printf("propVal:%s\n", propVal.c_str());
+ p = p2;
+
+ //## PRIO (optional)
+ p = skipwhite(p);
+ DOMString prio;
+ p2 = getPrio(p, prio);
+ if (p2<0)
+ return -1;
+ if (p2>p)
+ {
+ //do something
+ p = p2;
+ }
+
+ return p;
+}
+
+/**
+ * prio
+ * : IMPORTANT_SYM S*
+ * ;
+ */
+int CssParser::getPrio(int p0, DOMString &val)
+{
+ int p = p0;
+
+ //## '!"
+ p = skipwhite(p);
+ XMLCh ch = get(p);
+ if (ch != '!')
+ return p0;
+ p++;
+
+ //## "important"
+ p = skipwhite(p);
+ if (!match(p, "important"))
+ {
+ error("priority symbol is 'important'");
+ return -1;
+ }
+ p += 9;
+ val = "important";
+ return p;
+}
+
+/**
+ * expr
+ * : term [ operator term ]*
+ * ;
+ */
+int CssParser::getExpr(int p0)
+{
+ int p = p0;
+
+ //## TERM
+ p = skipwhite(p);
+ int p2 = getTerm(p);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ return p0; //not me
+ p = p2;
+ while (p < parselen)
+ {
+ p = skipwhite(p);
+ //#Operator. do this instead of getOperator()
+ XMLCh ch = get(p);
+ int visibleTerm = false;
+ if (ch == '/')
+ {
+ visibleTerm = true;
+ p++;
+ }
+ else if (ch == ',')
+ {
+ visibleTerm = true;
+ p++;
+ }
+ else
+ {
+ //just space. this is allowable between terms,
+ // so we still need to check for another term
+ }
+ p = skipwhite(p);
+ p2 = getTerm(p);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ if (visibleTerm)
+ {
+ error("expression requires term after operator");
+ return -1;
+ }
+ else
+ {
+ break;
+ }
+ }
+ p = p2;
+ }
+
+ return p;
+}
+
+/**
+ * term
+ * : unary_operator?
+ * [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |
+ * TIME S* | FREQ S* | function ]
+ * | STRING S* | IDENT S* | URI S* | hexcolor
+ * ;
+ */
+int CssParser::getTerm(int p0)
+{
+ int p = p0;
+ p = skipwhite(p);
+ int unitType = CSSPrimitiveValue::CSS_UNKNOWN;
+ //# Unary operator
+ XMLCh ch = get(p);
+ bool hasUnary = false;
+ if (ch == '-')
+ {
+ p++;
+ hasUnary = true;
+ }
+ else if (ch == '+')
+ {
+ p++;
+ hasUnary = true;
+ }
+ //# NUMERIC
+ double numVal;
+ int p2 = getNumber(p, numVal);
+ if (p2<0)
+ return -1;
+ if (p2>p)
+ {
+ p = p2;
+ if (match(p, "%"))
+ {
+ unitType = CSSPrimitiveValue::CSS_PERCENTAGE;
+ p++;
+ }
+ else if (match(p, "em"))
+ {
+ unitType = CSSPrimitiveValue::CSS_EMS;
+ p+=2;
+ }
+ else if (match(p, "ex"))
+ {
+ unitType = CSSPrimitiveValue::CSS_EXS;
+ p+=2;
+ }
+ else if (match(p, "px"))
+ {
+ unitType = CSSPrimitiveValue::CSS_PX;
+ p+=2;
+ }
+ else if (match(p, "cm"))
+ {
+ unitType = CSSPrimitiveValue::CSS_CM;
+ p+=2;
+ }
+ else if (match(p, "mm"))
+ {
+ unitType = CSSPrimitiveValue::CSS_MM;
+ p+=2;
+ }
+ else if (match(p, "in"))
+ {
+ unitType = CSSPrimitiveValue::CSS_IN;
+ p+=2;
+ }
+ else if (match(p, "pt"))
+ {
+ unitType = CSSPrimitiveValue::CSS_PT;
+ p+=2;
+ }
+ else if (match(p, "pc"))
+ {
+ unitType = CSSPrimitiveValue::CSS_PC;
+ p+=2;
+ }
+ else if (match(p, "deg"))
+ {
+ unitType = CSSPrimitiveValue::CSS_DEG;
+ p+=3;
+ }
+ else if (match(p, "rad"))
+ {
+ unitType = CSSPrimitiveValue::CSS_RAD;
+ p+=3;
+ }
+ else if (match(p, "grad"))
+ {
+ unitType = CSSPrimitiveValue::CSS_GRAD;
+ p+=4;
+ }
+ else if (match(p, "ms"))
+ {
+ unitType = CSSPrimitiveValue::CSS_MS;
+ p+=2;
+ }
+ else if (match(p, "s"))
+ {
+ unitType = CSSPrimitiveValue::CSS_S;
+ p+=1;
+ }
+ else if (match(p, "Hz"))
+ {
+ unitType = CSSPrimitiveValue::CSS_HZ;
+ p+=2;
+ }
+ else if (match(p, "kHz"))
+ {
+ unitType = CSSPrimitiveValue::CSS_KHZ;
+ p+=2;
+ }
+ else if (uni_is_letter(get(p)))//some other string
+ {
+ DOMString suffix;
+ p2 = getWord(p, suffix);
+ if (p2<0)
+ return -1;
+ unitType = CSSPrimitiveValue::CSS_DIMENSION;
+ p = p2;
+ }
+ else //plain number
+ {
+ unitType = CSSPrimitiveValue::CSS_NUMBER;
+ }
+ return p;
+ }
+
+ DOMString str;
+
+ //## URI --do before function, as syntax is similar
+ p2 = getUri(p, str);
+ if (p2<0)
+ return -1;
+ if (p2>p)
+ {
+ if (hasUnary)
+ {
+ error("+ or - not allowed on URI");
+ return -1;
+ }
+ p = p2;
+ unitType = CSSPrimitiveValue::CSS_URI;
+ return p;
+ }
+
+ //## FUNCTION
+ p2 = getFunction(p);
+ if (p2<0)
+ return -1;
+ if (p2>p)
+ {
+ p = p2;
+ return p;
+ }
+
+ //## STRING
+ ch = get(p);
+ if (ch == '"' || ch == '\'')
+ {
+ p2 = getQuoted(p, str);
+ if (p2<0)
+ return -1;
+ if (p2>p)
+ {
+ if (hasUnary)
+ {
+ error("+ or - not allowed on a string");
+ return -1;
+ }
+ p = p2;
+ unitType = CSSPrimitiveValue::CSS_STRING;
+ return p;
+ }
+ }
+
+ //## IDENT
+ ch = get(p);
+ if (uni_is_letter(ch))
+ {
+ p2 = getWord(p, str);
+ if (p2<0)
+ return -1;
+ if (p2>p)
+ {
+ if (hasUnary)
+ {
+ error("+ or - not allowed on an identifier");
+ return -1;
+ }
+ p = p2;
+ unitType = CSSPrimitiveValue::CSS_IDENT;
+ return p;
+ }
+ }
+
+
+ //## HEXCOLOR
+ p2 = getHexColor(p);
+ if (p2<0)
+ return -1;
+ if (p2>p)
+ {
+ if (hasUnary)
+ {
+ error("+ or - not allowed on hex color");
+ return -1;
+ }
+ p = p2;
+ unitType = CSSPrimitiveValue::CSS_RGBCOLOR;
+ return p;
+ }
+
+
+ return p0;
+}
+
+/**
+ * function
+ * : FUNCTION S* expr ')' S*
+ * ;
+ */
+int CssParser::getFunction(int p0)
+{
+ int p = p0;
+
+ //## IDENT + ( (both)
+ DOMString name;
+ p = skipwhite(p);
+ int p2 = getWord(p, name);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ return p0; //not me
+ if (name == "uri" || name=="url")
+ return p0; //not me
+ p = skipwhite(p2);
+ XMLCh ch = get(p);
+ if (ch != '(')
+ return p0; //still not me
+ p++;
+
+ //## EXPR
+ p = skipwhite(p);
+ p2 = getExpr(p);
+ if (p2<0)
+ return -1;
+ if (p2<=p)
+ {
+ error("function requires expression");
+ return -1;
+ }
+ p = p2;
+
+ //## ')'
+ p = skipwhite(p);
+ ch = get(p);
+ if (ch != ')')
+ {
+ error("function requires closing ')'");
+ return -1;
+ }
+ p++;
+ p = skipwhite(p);
+
+ return p;
+}
+
+/**
+ * There is a constraint on the color that it must
+ * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
+ * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
+ * hexcolor
+ * : HASH S*
+ * ;
+ */
+int CssParser::getHexColor(int p0)
+{
+ int p = p0;
+
+ //## '#'
+ p = skipwhite(p);
+ if (!match(p, "#"))
+ return p0;
+ p++;
+
+ //## HEX
+ DOMString hex;
+ long hexVal = 0;
+ while (p < parselen)
+ {
+ XMLCh b = get(p);
+ if (b>='0' && b<='9')
+ {
+ hexVal = (hexVal << 4) + (b - '0');
+ hex.push_back(b);
+ p++;
+ }
+ else if (b>='a' && b<='f')
+ {
+ hexVal = (hexVal << 4) + (b - 'a' + 10);
+ hex.push_back(b);
+ p++;
+ }
+ else if (b>='A' && b<='F')
+ {
+ hexVal = (hexVal << 4) + (b - 'A' + 10);
+ hex.push_back(b);
+ p++;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (hex.size() != 3 && hex.size() != 6)
+ {
+ error("exactly 3 or 6 hex digits are required after '#'");
+ return -1;
+ }
+
+ return p;
+}
+
+
+
+/**
+ *
+ */
+bool CssParser::parse(const DOMString &str)
+{
+ /*
+ int len = str.size();
+ for (int i=0 ; i<len ; i++)
+ {
+ XMLCh ch = str[i];
+ if (ch == '\\' && i<(len-1)) //escape!
+ {
+ i++;
+ }
+ else
+ parsebuf.push_back(ch);
+ }
+ */
+ parsebuf = str;
+
+ parselen = parsebuf.size();
+ //printf("==============================\n%s\n========================\n", str.c_str());
+
+ lastPosition = 0;
+
+ int p = getStyleSheet(0);
+ if (p < parselen)
+ {
+ error("Not everything parsed");
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ *
+ */
+bool CssParser::parseFile(const DOMString &fileName)
+{
+ DOMString tmp = fileName;
+ char *fname = (char *)tmp.c_str();
+ FILE *f = fopen(fname, "r");
+ if (!f)
+ {
+ printf("Could not open %s for reading\n", fname);
+ return false;
+ }
+
+ DOMString str;
+ while (!feof(f))
+ {
+ int ch = fgetc(f);
+ if (ch<0)
+ break;
+ str.push_back((XMLCh)ch);
+ }
+ fclose(f);
+
+ bool ret = parse(str);
+
+ return ret;
+}
+
+
+
+
+
+
+
+} // namespace css
+} // namespace dom
+} // namespace w3c
+} // namespace org
+
+
+#ifdef TEST
+
+int main(int argc, char **argv)
+{
+ org::w3c::dom::css::CssParser parser;
+ char *fileName;
+ fileName = "001.css";
+ //fileName = "acid.css";
+ //fileName = "base.css";
+ //fileName = "inkscape.css";
+ //fileName = "meyerweb.css";
+ if (!parser.parseFile(fileName))
+ {
+ printf("Test failed\n");
+ return 1;
+ }
+ return 0;
+}
+
+#endif /* TEST */
+
+//#########################################################################
+//# E N D O F F I L E
+//#########################################################################
+
diff --git a/src/dom/cssreader.h b/src/dom/cssreader.h
--- /dev/null
+++ b/src/dom/cssreader.h
@@ -0,0 +1,290 @@
+#ifndef __CSSREADER_H__
+#define __CSSREADER_H__
+/**
+ * Phoebe DOM Implementation.
+ *
+ * This is a C++ approximation of the W3C DOM model, which follows
+ * fairly closely the specifications in the various .idl files, copies of
+ * which are provided for reference. Most important is this one:
+ *
+ * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
+ *
+ * Authors:
+ * Bob Jamison
+ *
+ * Copyright (C) 2005-2008 Bob Jamison
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include "dom.h"
+
+#include "css.h"
+
+namespace org
+{
+namespace w3c
+{
+namespace dom
+{
+namespace css
+{
+
+class CssParser
+{
+
+public:
+
+ /**
+ *
+ */
+ CssParser()
+ {}
+
+ /**
+ *
+ */
+ virtual ~CssParser()
+ {}
+
+ /**
+ *
+ */
+ virtual bool parse(const DOMString &str);
+
+ /**
+ *
+ */
+ virtual bool parseFile(const DOMString &str);
+
+
+private:
+
+ DOMString parsebuf;
+ long parselen;
+ CSSStyleSheet stylesheet;
+
+
+ /**
+ *
+ */
+ void error(char const *fmt, ...)
+ #ifdef G_GNUC_PRINTF
+ G_GNUC_PRINTF(2, 3)
+ #endif
+ ;
+
+ /**
+ * Get the character at the given location in the buffer.
+ * Return 0 if out-of-bounds
+ */
+ XMLCh get(int index);
+
+
+ /**
+ * Test if the given substring exists at the given position
+ * in parsebuf. Use get() in case of out-of-bounds
+ */
+ bool match(int pos, const char *str);
+
+ /**
+ * Skip over whitespace
+ * Return new position
+ */
+ int skipwhite(int index);
+
+ /**
+ * Get the word at the current position. Return the new
+ * position if successful, the current position if no word,
+ * -1 if error.
+ */
+ int getWord(int index, DOMString &str);
+
+
+ /**
+ * Get a number at the current position
+ * Return the new position if a proper number, else the original pos
+ */
+ int getNumber(int index, double &result);
+
+ /**
+ * Assume that we are starting on a quote. Ends on the char
+ * after the final '"'
+ */
+ int getQuoted(int p0, DOMString &result);
+
+/**
+ * Not in api. replaces URI return by lexer
+ */
+int getUri(int p0, DOMString &str);
+
+
+/**
+ * Skip to the next rule
+ */
+int skipBlock(int p0);
+
+//#########################################################################
+//# P R O D U C T I O N S
+//#########################################################################
+
+/**
+ * stylesheet
+ * : [ CHARSET_SYM S* STRING S* ';' ]?
+ * [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*
+ * [ [ ruleset | media | page ] [S|CDO|CDC]* ]*
+ * ;
+ */
+int getStyleSheet(int p0);
+
+/**
+ * import
+ * : IMPORT_SYM S*
+ * [STRING|URI] S* [ medium [ COMMA S* medium]* ]? ';' S*
+ * ;
+ */
+int getImport(int p0);
+
+/**
+ * media
+ * : MEDIA_SYM S* medium [ COMMA S* medium ]* LBRACE S* ruleset* '}' S*
+ * ;
+ */
+int getMedia(int p0);
+
+/**
+ * medium
+ * : IDENT S*
+ * ;
+ */
+int getMedium(int p0);
+
+/**
+ * page
+ * : PAGE_SYM S* pseudo_page? S*
+ * LBRACE S* declaration [ ';' S* declaration ]* '}' S*
+ * ;
+ */
+int getPage(int p0);
+
+/**
+ * pseudo_page
+ * : ':' IDENT
+ * ;
+ */
+int getPseudoPage(int p0);
+
+/**
+ * ruleset
+ * : selector [ COMMA S* selector ]*
+ * LBRACE S* declaration [ ';' S* declaration ]* '}' S*
+ * ;
+ */
+int getRuleSet(int p0);
+
+/**
+ * selector
+ * : simple_selector [ combinator simple_selector ]*
+ * ;
+ */
+int getSelector(int p0);
+
+/**
+ * simple_selector
+ * : element_name [ HASH | class | attrib | pseudo ]*
+ * | [ HASH | class | attrib | pseudo ]+
+ * ;
+ */
+int getSimpleSelector(int p0);
+
+/**
+ * declaration
+ * : property ':' S* expr prio?
+ * | {empty}
+ * ;
+ */
+int getDeclaration(int p0, CSSStyleDeclaration &declarationList);
+
+/**
+ * prio
+ * : IMPORTANT_SYM S*
+ * ;
+ */
+int getPrio(int p0, DOMString &val);
+
+/**
+ * expr
+ * : term [ operator term ]*
+ * ;
+ */
+int getExpr(int p0);
+
+/**
+ * term
+ * : unary_operator?
+ * [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |
+ * TIME S* | FREQ S* | function ]
+ * | STRING S* | IDENT S* | URI S* | hexcolor
+ * ;
+ */
+int getTerm(int p0);
+
+/**
+ * function
+ * : FUNCTION S* expr ')' S*
+ * ;
+ */
+int getFunction(int p0);
+
+/**
+ * There is a constraint on the color that it must
+ * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
+ * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
+ *
+ * hexcolor
+ * : HASH S*
+ * ;
+ */
+int getHexColor(int p0);
+
+
+int lastPosition;
+
+/**
+ * Get the column and row number of the given character position.
+ * Also gets the last-occuring newline before the position
+ */
+void getColumnAndRow(int p, int &col, int &row, int &lastNL);
+
+};
+
+
+} // namespace css
+} // namespace dom
+} // namespace w3c
+} // namespace org
+
+
+
+
+
+
+
+#endif /* __CSSREADER_H__ */
+//#########################################################################
+//# E N D O F F I L E
+//#########################################################################
+
diff --git a/src/dom/svgparser.cpp b/src/dom/svgparser.cpp
--- a/src/dom/svgparser.cpp
+++ /dev/null
@@ -1,805 +0,0 @@
-/**
- * Phoebe DOM Implementation.
- *
- * This is a C++ approximation of the W3C DOM model, which follows
- * fairly closely the specifications in the various .idl files, copies of
- * which are provided for reference. Most important is this one:
- *
- * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
- *
- * Authors:
- * Bob Jamison
- *
- * Copyright (C) 2005-2008 Bob Jamison
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * =======================================================================
- * NOTES
- *
- *
- */
-
-
-#include "svgparser.h"
-#include "dom/cssparser.h"
-#include "dom/ucd.h"
-#include "xmlreader.h"
-
-#include <stdarg.h>
-
-#define SVG_NAMESPACE "http://www.w3.org/2000/svg"
-
-namespace org
-{
-namespace w3c
-{
-namespace dom
-{
-namespace svg
-{
-
-
-//#########################################################################
-//# M E S S A G E S
-//#########################################################################
-
-
-/**
- *
- */
-void SvgReader::error(char const *fmt, ...)
-{
- va_list args;
- fprintf(stderr, "SvgReader:error:");
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args) ;
- fprintf(stderr, "\n");
-}
-
-
-
-//#########################################################################
-//# P A R S I N G
-//#########################################################################
-
-/**
- * Get the character at the position and record the fact
- */
-XMLCh SvgReader::get(int p)
-{
- if (p >= parselen)
- return 0;
- XMLCh ch = parsebuf[p];
- //printf("%c", ch);
- lastPosition = p;
- return ch;
-}
-
-
-
-/**
- * Test if the given substring exists at the given position
- * in parsebuf. Use get() in case of out-of-bounds
- */
-bool SvgReader::match(int pos, char const *str)
-{
- while (*str)
- {
- if (get(pos++) != (XMLCh) *str++)
- return false;
- }
- return true;
-}
-
-/**
- *
- */
-int SvgReader::skipwhite(int p)
-{
- while (p < parselen)
- {
- //# XML COMMENT
- if (match(p, "<!--"))
- {
- p+=4;
- bool done=false;
- while (p<parselen)
- {
- if (match(p, "-->"))
- {
- p+=3;
- done=true;
- break;
- }
- p++;
- }
- lastPosition = p;
- if (!done)
- {
- error("unterminated <!-- .. --> comment");
- return -1;
- }
- }
- //# C comment
- else if (match(p, "/*"))
- {
- p+=2;
- bool done=false;
- while (p<parselen)
- {
- if (match(p, "*/"))
- {
- p+=2;
- done=true;
- break;
- }
- p++;
- }
- lastPosition = p;
- if (!done)
- {
- error("unterminated /* .. */ comment");
- return -1;
- }
- }
- else if (!uni_is_space(get(p)))
- break;
- else
- p++;
- }
- lastPosition = p;
- return p;
-}
-
-/**
- * get a word from the buffer
- */
-int SvgReader::getWord(int p, DOMString &result)
-{
- XMLCh ch = get(p);
- if (!uni_is_letter(ch))
- return p;
- DOMString str;
- str.push_back(ch);
- p++;
-
- while (p < parselen)
- {
- ch = get(p);
- if (uni_is_letter_or_digit(ch) || ch=='-' || ch=='_')
- {
- str.push_back(ch);
- p++;
- }
- else if (ch == '\\')
- {
- p+=2;
- }
- else
- break;
- }
- result = str;
- return p;
-}
-
-
-# if 0
-/**
- * get a word from the buffer
- */
-int SvgReader::getNumber(int p0, double &result)
-{
- int p=p0;
-
- DOMString str;
-
- //allow sign
- if (get(p) == '-')
- {
- p++;
- }
-
- while (p < parselen)
- {
- XMLCh ch = get(p);
- if (ch<'0' || ch>'9')
- break;
- str.push_back(ch);
- p++;
- }
- if (get(p) == '.' && get(p+1)>='0' && get(p+1)<='9')
- {
- p++;
- str.push_back('.');
- while (p < parselen)
- {
- XMLCh ch = get(p);
- if (ch<'0' || ch>'9')
- break;
- str.push_back(ch);
- p++;
- }
- }
- if (p>p0)
- {
- char *start = (char *)str.c_str();
- char *end = NULL;
- double val = strtod(start, &end);
- if (end > start)
- {
- result = val;
- return p;
- }
- }
-
- //not a number
- return p0;
-}
-#endif
-
-
-/**
- * get a word from the buffer
- */
-int SvgReader::getNumber(int p0, double &result)
-{
- int p=p0;
-
- char buf[64];
-
- int i;
- for (i=0 ; i<63 && p<parselen ; i++)
- {
- buf[i] = (char) get(p++);
- }
- buf[i] = '\0';
-
- char *start = buf;
- char *end = NULL;
- double val = strtod(start, &end);
- if (end > start)
- {
- result = val;
- int count = (int)(end - start);
- p = p0 + count;
- return p;
- }
-
- //not a number
- return p0;
-}
-
-
-bool SvgReader::parseTransform(const DOMString &str)
-{
- parsebuf = str;
- parselen = str.size();
-
- //printf("transform:%s\n", str.c_str());
-
- SVGTransformList transformList;
-
- int p = 0;
-
- while (p < parselen)
- {
- p = skipwhite(p);
- DOMString name;
- int p2 = getWord(p, name);
- if (p2<0)
- return false;
- if (p2<=p)
- {
- error("transform: need transform name");
- //return false;
- break;
- }
- p = p2;
- //printf("transform name:%s\n", name.c_str());
-
- //######### MATRIX
- if (name == "matrix")
- {
- p = skipwhite(p);
- if (get(p++) != '(')
- {
- error("matrix transform needs opening '('");
- return false;
- }
- int nrVals = 0;
- double vals[6];
- bool seenBrace = false;
- while (p < parselen && nrVals < 6)
- {
- p = skipwhite(p);
- double val = 0.0;
- p2 = getNumber(p, val);
- if (p2<0)
- return false;
- if (p2<=p)
- {
- error("matrix() expected number");
- return false;
- }
- vals[nrVals++] = val;
- p = skipwhite(p2);
- XMLCh ch = get(p);
- if (ch == ',')
- {
- p++;
- p = skipwhite(p);
- ch = get(p);
- }
- if (ch == ')')
- {
- seenBrace = true;
- p++;
- break;
- }
- }
- if (!seenBrace)
- {
- error("matrix() needs closing brace");
- return false;
- }
- if (nrVals != 6)
- {
- error("matrix() requires exactly 6 arguments");
- return false;
- }
- //We got our arguments
- //printf("translate: %f %f %f %f %f %f\n",
- // vals[0], vals[1], vals[2], vals[3], vals[4], vals[5]);
- SVGMatrix matrix(vals[0], vals[1], vals[2],
- vals[3], vals[4], vals[5]);
- SVGTransform transform;
- transform.setMatrix(matrix);
- transformList.appendItem(transform);
- }
-
- //######### TRANSLATE
- else if (name == "translate")
- {
- p = skipwhite(p);
- if (get(p++) != '(')
- {
- error("matrix transform needs opening '('");
- return false;
- }
- p = skipwhite(p);
- double x = 0.0;
- p2 = getNumber(p, x);
- if (p2<0)
- return false;
- if (p2<=p)
- {
- error("translate() expected 'x' value");
- return false;
- }
- p = skipwhite(p2);
- if (get(p) == ',')
- {
- p++;
- p = skipwhite(p);
- }
- double y = 0.0;
- p2 = getNumber(p, y);
- if (p2<0)
- return false;
- if (p2<=p) //no y specified. use default
- y = 0.0;
- p = skipwhite(p2);
- if (get(p++) != ')')
- {
- error("translate() needs closing ')'");
- return false;
- }
- //printf("translate: %f %f\n", x, y);
- SVGTransform transform;
- transform.setTranslate(x, y);
- transformList.appendItem(transform);
- }
-
- //######### SCALE
- else if (name == "scale")
- {
- p = skipwhite(p);
- if (get(p++) != '(')
- {
- error("scale transform needs opening '('");
- return false;
- }
- p = skipwhite(p);
- double x = 0.0;
- p2 = getNumber(p, x);
- if (p2<0)
- return false;
- if (p2<=p)
- {
- error("scale() expected 'x' value");
- return false;
- }
- p = skipwhite(p2);
- if (get(p) == ',')
- {
- p++;
- p = skipwhite(p);
- }
- double y = 0.0;
- p2 = getNumber(p, y);
- if (p2<0)
- return false;
- if (p2<=p) //no y specified. use default
- y = x; // y is same as x. uniform scaling
- p = skipwhite(p2);
- if (get(p++) != ')')
- {
- error("scale() needs closing ')'");
- return false;
- }
- //printf("scale: %f %f\n", x, y);
- SVGTransform transform;
- transform.setScale(x, y);
- transformList.appendItem(transform);
- }
-
- //######### ROTATE
- else if (name == "rotate")
- {
- p = skipwhite(p);
- if (get(p++) != '(')
- {
- error("rotate transform needs opening '('");
- return false;
- }
- p = skipwhite(p);
- double angle = 0.0;
- p2 = getNumber(p, angle);
- if (p2<0)
- return false;
- if (p2<=p)
- {
- error("rotate() expected 'angle' value");
- return false;
- }
- p = skipwhite(p2);
- if (get(p) == ',')
- {
- p++;
- p = skipwhite(p);
- }
- double cx = 0.0;
- double cy = 0.0;
- p2 = getNumber(p, cx);
- if (p2>p)
- {
- p = skipwhite(p2);
- if (get(p) == ',')
- {
- p++;
- p = skipwhite(p);
- }
- p2 = getNumber(p, cy);
- if (p2<0)
- return false;
- if (p2<=p)
- {
- error("rotate() arguments should be either rotate(angle) or rotate(angle, cx, cy)");
- return false;
- }
- p = skipwhite(p2);
- }
- if (get(p++) != ')')
- {
- error("rotate() needs closing ')'");
- return false;
- }
- //printf("rotate: %f %f %f\n", angle, cx, cy);
- SVGTransform transform;
- transform.setRotate(angle, cx, cy);
- transformList.appendItem(transform);
- }
-
- //######### SKEWX
- else if (name == "skewX")
- {
- p = skipwhite(p);
- if (get(p++) != '(')
- {
- error("skewX transform needs opening '('");
- return false;
- }
- p = skipwhite(p);
- double x = 0.0;
- p2 = getNumber(p, x);
- if (p2<0)
- return false;
- if (p2<=p)
- {
- error("skewX() expected 'x' value");
- return false;
- }
- p = skipwhite(p2);
- if (get(p++) != ')')
- {
- error("skewX() needs closing ')'");
- return false;
- }
- //printf("skewX: %f\n", x);
- SVGTransform transform;
- transform.setSkewX(x);
- transformList.appendItem(transform);
- }
-
- //######### SKEWY
- else if (name == "skewY")
- {
- p = skipwhite(p);
- if (get(p++) != '(')
- {
- error("skewY transform needs opening '('");
- return false;
- }
- p = skipwhite(p);
- double y = 0.0;
- p2 = getNumber(p, y);
- if (p2<0)
- return false;
- if (p2<=p)
- {
- error("skewY() expected 'y' value");
- return false;
- }
- p = skipwhite(p2);
- if (get(p++) != ')')
- {
- error("skewY() needs closing ')'");
- return false;
- }
- //printf("skewY: %f\n", y);
- SVGTransform transform;
- transform.setSkewY(y);
- transformList.appendItem(transform);
- }
-
- //### NONE OF THE ABOVE
- else
- {
- error("unknown transform type:'%s'", name.c_str());
- }
-
- p = skipwhite(p);
- XMLCh ch = get(p);
- if (ch == ',')
- {
- p++;
- p = skipwhite(p);
- }
-
- }//WHILE p<parselen
-
- return true;
-}
-
-
-/**
- *
- */
-bool SvgReader::parseElement(SVGElementImplPtr parent,
- ElementImplPtr sourceElem)
-{
- if (!parent || !sourceElem)
- {
- error("NULL source element");
- return false;
- }
-
- DOMString namespaceURI = sourceElem->getNamespaceURI();
- //printf("namespaceURI:%s\n", namespaceURI.c_str());
- DOMString tagName = sourceElem->getTagName();
- printf("tag name:%s\n", tagName.c_str());
-
- ElementImplPtr newElement = NULL;
- if (namespaceURI != SVG_NAMESPACE)
- {
- newElement = new SVGSVGElementImpl();
- newElement->assign(*sourceElem);
- parent->appendChild(newElement);
- }
- else //## SVG!!
- {
-
- //####################################################
- //## ATTRIBUTES
- //####################################################
- DOMString style = sourceElem->getAttribute("style");
- if (style.size() > 0)
- {
- css::CssParser parser;
- style.insert(0, "{");
- style.append("}");
- //printf("CSS:%s\n", style.c_str());
- if (!parser.parse(style))
- {
- error("parsing style attribute");
- }
- else
- {
- //printf("##parsed!\n");
- }
- }
-
- DOMString transform = sourceElem->getAttribute("transform");
- if (transform.size() > 0)
- {
- if (!parseTransform(transform))
- {
- error("parsing transform attribute");
- }
- else
- {
- //printf("##parsed!\n");
- }
- }
-
- //####################################################
- //## ELEMENT - SPECIFIC
- //####################################################
- if (tagName == "svg")
- {
- newElement = new SVGSVGElementImpl();
- newElement->assign(*sourceElem);
- parent->appendChild(newElement);
- }
- else if (tagName == "title")
- {
- newElement = new SVGTitleElementImpl();
- newElement->assign(*sourceElem);
- parent->appendChild(newElement);
- }
- else if (tagName == "desc")
- {
- newElement = new SVGDescElementImpl();
- newElement->assign(*sourceElem);
- parent->appendChild(newElement);
- }
- else if (tagName == "defs")
- {
- newElement = new SVGDefsElementImpl();
- newElement->assign(*sourceElem);
- parent->appendChild(newElement);
- }
- else if (tagName == "style")
- {
- newElement = new SVGStyleElementImpl();
- newElement->assign(*sourceElem);
- parent->appendChild(newElement);
- }
- else if (tagName == "g")
- {
- newElement = new SVGGElementImpl();
- newElement->assign(*sourceElem);
- parent->appendChild(newElement);
- }
- else if (tagName == "path")
- {
- newElement = new SVGPathElementImpl();
- newElement->assign(*sourceElem);
- parent->appendChild(newElement);
- }
- }
-
- NodeList children = sourceElem->getChildNodes();
- int nodeCount = children.getLength();
- for (int i=0 ; i<nodeCount ; i++)
- {
- NodePtr child = children.item(i);
- int typ = child->getNodeType();
- if (typ == Node::TEXT_NODE)
- {
- NodePtr newNode = doc->createTextNode(child->getNodeValue());
- parent->appendChild(newNode);
- }
- else if (typ == Node::CDATA_SECTION_NODE)
- {
- NodePtr newNode = doc->createCDATASection(child->getNodeValue());
- parent->appendChild(newNode);
- }
- else if (newElement.get() && typ == Node::ELEMENT_NODE)
- {
- //ElementImplPtr childElement = dynamic_cast<ElementImpl *>(child.get());
- //parseElement(newElement, childElement);
- }
- }
- return true;
-}
-
-
-/**
- *
- */
-SVGDocumentPtr SvgReader::parse(const DocumentPtr src)
-{
- if (!src)
- {
- error("NULL source document");
- return NULL;
- }
-
- DOMImplementationImpl impl;
- doc = new SVGDocumentImpl(&impl, SVG_NAMESPACE, "svg" , NULL);
-
- SVGElementImplPtr destElem = dynamic_cast<SVGElementImpl *>(doc->getRootElement().get());
- ElementImplPtr srcElem = dynamic_cast<ElementImpl *>(src->getDocumentElement().get());
- if (!parseElement(destElem, srcElem))
- {
- return NULL;
- }
-
- return doc;
-}
-
-
-
-/**
- *
- */
-SVGDocumentPtr SvgReader::parse(const DOMString &buf)
-{
- /* remember, smartptrs are null-testable*/
- SVGDocumentPtr svgdoc;
- XmlReader parser;
- DocumentPtr doc = parser.parse(buf);
- if (!doc)
- {
- return svgdoc;
- }
- svgdoc = parse(doc);
- return svgdoc;
-}
-
-
-
-/**
- *
- */
-SVGDocumentPtr SvgReader::parseFile(const DOMString &fileName)
-{
- /* remember, smartptrs are null-testable*/
- SVGDocumentPtr svgdoc;
- XmlReader parser;
- DocumentPtr doc = parser.parseFile(fileName);
- if (!doc)
- {
- return svgdoc;
- }
- svgdoc = parse(doc);
- return svgdoc;
-}
-
-
-
-
-} //namespace svg
-} //namespace dom
-} //namespace w3c
-} //namespace org
-
-/*#########################################################################
-## E N D O F F I L E
-#########################################################################*/
-
diff --git a/src/dom/svgparser.h b/src/dom/svgparser.h
--- a/src/dom/svgparser.h
+++ /dev/null
@@ -1,179 +0,0 @@
-#ifndef __SVGPARSER_H__
-#define __SVGPARSER_H__
-
-/**
- * Phoebe DOM Implementation.
- *
- * This is a C++ approximation of the W3C DOM model, which follows
- * fairly closely the specifications in the various .idl files, copies of
- * which are provided for reference. Most important is this one:
- *
- * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
- *
- * Authors:
- * Bob Jamison
- *
- * Copyright (C) 2005-2008 Bob Jamison
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * =======================================================================
- * NOTES
- *
- * This parser takes an XML document, as a file, string, or DOM Document,
- * and attempts to parse it as an SVG-DOM SVGDocument.
- *
- * Look in svg.h and svgtypes.h for the classes which are the target of this
- * parser.
- *
- * They loosely follow the specification:
- * http://www.w3.org/TR/SVG11/svgdom.html
- *
- */
-
-
-#include "svgimpl.h"
-
-namespace org
-{
-namespace w3c
-{
-namespace dom
-{
-namespace svg
-{
-
-
-class SvgReader
-{
-public:
-
- /**
- *
- */
- SvgReader()
- {
- }
-
- /**
- *
- */
- SvgReader(const SvgReader &/*other*/)
- {
- }
-
- /**
- *
- */
- virtual ~SvgReader()
- {
- }
-
- /**
- *
- */
- SVGDocumentPtr parse(const DocumentPtr /*sourceDoc*/);
-
- /**
- *
- */
- SVGDocumentPtr parse(const DOMString &/*buffer*/);
-
- /**
- *
- */
- SVGDocumentPtr parseFile(const DOMString &/*fileName*/);
-
-
-
-
-private:
-
- /**
- * Get the next character in the parse buf, 0 if out
- * of range
- */
- XMLCh get(int p);
-
- /**
- * Test if the given substring exists at the given position
- * in parsebuf. Use get() in case of out-of-bounds
- */
- bool match(int pos, char const *str);
-
- /**
- *
- */
- int skipwhite(int p);
-
- /**
- * get a word from the buffer
- */
- int getWord(int p, DOMString &result);
-
- /**
- * get a word from the buffer
- */
- int getNumber(int p0, double &result);
-
-
- /**
- *
- */
- bool parseTransform(const DOMString &str);
-
-
- /**
- *
- */
- bool parseElement(SVGElementImplPtr destElem,
- ElementImplPtr sourceElem);
-
-
- /**
- *
- */
- void error(char const *format, ...)
- #ifdef G_GNUC_PRINTF
- G_GNUC_PRINTF(2, 3)
- #endif
- ;
-
-
-
- DOMString parsebuf;
- int parselen;
- int lastPosition;
-
- SVGDocumentImplPtr doc;
-
-};
-
-
-
-
-
-} //namespace svg
-} //namespace dom
-} //namespace w3c
-} //namespace org
-
-#endif /* __SVGPARSER_H__ */
-/*#########################################################################
-## E N D O F F I L E
-#########################################################################*/
-
-
-
diff --git a/src/dom/svgreader.cpp b/src/dom/svgreader.cpp
--- /dev/null
+++ b/src/dom/svgreader.cpp
@@ -0,0 +1,805 @@
+/**
+ * Phoebe DOM Implementation.
+ *
+ * This is a C++ approximation of the W3C DOM model, which follows
+ * fairly closely the specifications in the various .idl files, copies of
+ * which are provided for reference. Most important is this one:
+ *
+ * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
+ *
+ * Authors:
+ * Bob Jamison
+ *
+ * Copyright (C) 2005-2008 Bob Jamison
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * =======================================================================
+ * NOTES
+ *
+ *
+ */
+
+
+#include "svgreader.h"
+#include "dom/cssreader.h"
+#include "dom/ucd.h"
+#include "xmlreader.h"
+
+#include <stdarg.h>
+
+#define SVG_NAMESPACE "http://www.w3.org/2000/svg"
+
+namespace org
+{
+namespace w3c
+{
+namespace dom
+{
+namespace svg
+{
+
+
+//#########################################################################
+//# M E S S A G E S
+//#########################################################################
+
+
+/**
+ *
+ */
+void SvgReader::error(char const *fmt, ...)
+{
+ va_list args;
+ fprintf(stderr, "SvgReader:error:");
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args) ;
+ fprintf(stderr, "\n");
+}
+
+
+
+//#########################################################################
+//# P A R S I N G
+//#########################################################################
+
+/**
+ * Get the character at the position and record the fact
+ */
+XMLCh SvgReader::get(int p)
+{
+ if (p >= parselen)
+ return 0;
+ XMLCh ch = parsebuf[p];
+ //printf("%c", ch);
+ lastPosition = p;
+ return ch;
+}
+
+
+
+/**
+ * Test if the given substring exists at the given position
+ * in parsebuf. Use get() in case of out-of-bounds
+ */
+bool SvgReader::match(int pos, char const *str)
+{
+ while (*str)
+ {
+ if (get(pos++) != (XMLCh) *str++)
+ return false;
+ }
+ return true;
+}
+
+/**
+ *
+ */
+int SvgReader::skipwhite(int p)
+{
+ while (p < parselen)
+ {
+ //# XML COMMENT
+ if (match(p, "<!--"))
+ {
+ p+=4;
+ bool done=false;
+ while (p<parselen)
+ {
+ if (match(p, "-->"))
+ {
+ p+=3;
+ done=true;
+ break;
+ }
+ p++;
+ }
+ lastPosition = p;
+ if (!done)
+ {
+ error("unterminated <!-- .. --> comment");
+ return -1;
+ }
+ }
+ //# C comment
+ else if (match(p, "/*"))
+ {
+ p+=2;
+ bool done=false;
+ while (p<parselen)
+ {
+ if (match(p, "*/"))
+ {
+ p+=2;
+ done=true;
+ break;
+ }
+ p++;
+ }
+ lastPosition = p;
+ if (!done)
+ {
+ error("unterminated /* .. */ comment");
+ return -1;
+ }
+ }
+ else if (!uni_is_space(get(p)))
+ break;
+ else
+ p++;
+ }
+ lastPosition = p;
+ return p;
+}
+
+/**
+ * get a word from the buffer
+ */
+int SvgReader::getWord(int p, DOMString &result)
+{
+ XMLCh ch = get(p);
+ if (!uni_is_letter(ch))
+ return p;
+ DOMString str;
+ str.push_back(ch);
+ p++;
+
+ while (p < parselen)
+ {
+ ch = get(p);
+ if (uni_is_letter_or_digit(ch) || ch=='-' || ch=='_')
+ {
+ str.push_back(ch);
+ p++;
+ }
+ else if (ch == '\\')
+ {
+ p+=2;
+ }
+ else
+ break;
+ }
+ result = str;
+ return p;
+}
+
+
+# if 0
+/**
+ * get a word from the buffer
+ */
+int SvgReader::getNumber(int p0, double &result)
+{
+ int p=p0;
+
+ DOMString str;
+
+ //allow sign
+ if (get(p) == '-')
+ {
+ p++;
+ }
+
+ while (p < parselen)
+ {
+ XMLCh ch = get(p);
+ if (ch<'0' || ch>'9')
+ break;
+ str.push_back(ch);
+ p++;
+ }
+ if (get(p) == '.' && get(p+1)>='0' && get(p+1)<='9')
+ {
+ p++;
+ str.push_back('.');
+ while (p < parselen)
+ {
+ XMLCh ch = get(p);
+ if (ch<'0' || ch>'9')
+ break;
+ str.push_back(ch);
+ p++;
+ }
+ }
+ if (p>p0)
+ {
+ char *start = (char *)str.c_str();
+ char *end = NULL;
+ double val = strtod(start, &end);
+ if (end > start)
+ {
+ result = val;
+ return p;
+ }
+ }
+
+ //not a number
+ return p0;
+}
+#endif
+
+
+/**
+ * get a word from the buffer
+ */
+int SvgReader::getNumber(int p0, double &result)
+{
+ int p=p0;
+
+ char buf[64];
+
+ int i;
+ for (i=0 ; i<63 && p<parselen ; i++)
+ {
+ buf[i] = (char) get(p++);
+ }
+ buf[i] = '\0';
+
+ char *start = buf;
+ char *end = NULL;
+ double val = strtod(start, &end);
+ if (end > start)
+ {
+ result = val;
+ int count = (int)(end - start);
+ p = p0 + count;
+ return p;
+ }
+
+ //not a number
+ return p0;
+}
+
+
+bool SvgReader::parseTransform(const DOMString &str)
+{
+ parsebuf = str;
+ parselen = str.size();
+
+ //printf("transform:%s\n", str.c_str());
+
+ SVGTransformList transformList;
+
+ int p = 0;
+
+ while (p < parselen)
+ {
+ p = skipwhite(p);
+ DOMString name;
+ int p2 = getWord(p, name);
+ if (p2<0)
+ return false;
+ if (p2<=p)
+ {
+ error("transform: need transform name");
+ //return false;
+ break;
+ }
+ p = p2;
+ //printf("transform name:%s\n", name.c_str());
+
+ //######### MATRIX
+ if (name == "matrix")
+ {
+ p = skipwhite(p);
+ if (get(p++) != '(')
+ {
+ error("matrix transform needs opening '('");
+ return false;
+ }
+ int nrVals = 0;
+ double vals[6];
+ bool seenBrace = false;
+ while (p < parselen && nrVals < 6)
+ {
+ p = skipwhite(p);
+ double val = 0.0;
+ p2 = getNumber(p, val);
+ if (p2<0)
+ return false;
+ if (p2<=p)
+ {
+ error("matrix() expected number");
+ return false;
+ }
+ vals[nrVals++] = val;
+ p = skipwhite(p2);
+ XMLCh ch = get(p);
+ if (ch == ',')
+ {
+ p++;
+ p = skipwhite(p);
+ ch = get(p);
+ }
+ if (ch == ')')
+ {
+ seenBrace = true;
+ p++;
+ break;
+ }
+ }
+ if (!seenBrace)
+ {
+ error("matrix() needs closing brace");
+ return false;
+ }
+ if (nrVals != 6)
+ {
+ error("matrix() requires exactly 6 arguments");
+ return false;
+ }
+ //We got our arguments
+ //printf("translate: %f %f %f %f %f %f\n",
+ // vals[0], vals[1], vals[2], vals[3], vals[4], vals[5]);
+ SVGMatrix matrix(vals[0], vals[1], vals[2],
+ vals[3], vals[4], vals[5]);
+ SVGTransform transform;
+ transform.setMatrix(matrix);
+ transformList.appendItem(transform);
+ }
+
+ //######### TRANSLATE
+ else if (name == "translate")
+ {
+ p = skipwhite(p);
+ if (get(p++) != '(')
+ {
+ error("matrix transform needs opening '('");
+ return false;
+ }
+ p = skipwhite(p);
+ double x = 0.0;
+ p2 = getNumber(p, x);
+ if (p2<0)
+ return false;
+ if (p2<=p)
+ {
+ error("translate() expected 'x' value");
+ return false;
+ }
+ p = skipwhite(p2);
+ if (get(p) == ',')
+ {
+ p++;
+ p = skipwhite(p);
+ }
+ double y = 0.0;
+ p2 = getNumber(p, y);
+ if (p2<0)
+ return false;
+ if (p2<=p) //no y specified. use default
+ y = 0.0;
+ p = skipwhite(p2);
+ if (get(p++) != ')')
+ {
+ error("translate() needs closing ')'");
+ return false;
+ }
+ //printf("translate: %f %f\n", x, y);
+ SVGTransform transform;
+ transform.setTranslate(x, y);
+ transformList.appendItem(transform);
+ }
+
+ //######### SCALE
+ else if (name == "scale")
+ {
+ p = skipwhite(p);
+ if (get(p++) != '(')
+ {
+ error("scale transform needs opening '('");
+ return false;
+ }
+ p = skipwhite(p);
+ double x = 0.0;
+ p2 = getNumber(p, x);
+ if (p2<0)
+ return false;
+ if (p2<=p)
+ {
+ error("scale() expected 'x' value");
+ return false;
+ }
+ p = skipwhite(p2);
+ if (get(p) == ',')
+ {
+ p++;
+ p = skipwhite(p);
+ }
+ double y = 0.0;
+ p2 = getNumber(p, y);
+ if (p2<0)
+ return false;
+ if (p2<=p) //no y specified. use default
+ y = x; // y is same as x. uniform scaling
+ p = skipwhite(p2);
+ if (get(p++) != ')')
+ {
+ error("scale() needs closing ')'");
+ return false;
+ }
+ //printf("scale: %f %f\n", x, y);
+ SVGTransform transform;
+ transform.setScale(x, y);
+ transformList.appendItem(transform);
+ }
+
+ //######### ROTATE
+ else if (name == "rotate")
+ {
+ p = skipwhite(p);
+ if (get(p++) != '(')
+ {
+ error("rotate transform needs opening '('");
+ return false;
+ }
+ p = skipwhite(p);
+ double angle = 0.0;
+ p2 = getNumber(p, angle);
+ if (p2<0)
+ return false;
+ if (p2<=p)
+ {
+ error("rotate() expected 'angle' value");
+ return false;
+ }
+ p = skipwhite(p2);
+ if (get(p) == ',')
+ {
+ p++;
+ p = skipwhite(p);
+ }
+ double cx = 0.0;
+ double cy = 0.0;
+ p2 = getNumber(p, cx);
+ if (p2>p)
+ {
+ p = skipwhite(p2);
+ if (get(p) == ',')
+ {
+ p++;
+ p = skipwhite(p);
+ }
+ p2 = getNumber(p, cy);
+ if (p2<0)
+ return false;
+ if (p2<=p)
+ {
+ error("rotate() arguments should be either rotate(angle) or rotate(angle, cx, cy)");
+ return false;
+ }
+ p = skipwhite(p2);
+ }
+ if (get(p++) != ')')
+ {
+ error("rotate() needs closing ')'");
+ return false;
+ }
+ //printf("rotate: %f %f %f\n", angle, cx, cy);
+ SVGTransform transform;
+ transform.setRotate(angle, cx, cy);
+ transformList.appendItem(transform);
+ }
+
+ //######### SKEWX
+ else if (name == "skewX")
+ {
+ p = skipwhite(p);
+ if (get(p++) != '(')
+ {
+ error("skewX transform needs opening '('");
+ return false;
+ }
+ p = skipwhite(p);
+ double x = 0.0;
+ p2 = getNumber(p, x);
+ if (p2<0)
+ return false;
+ if (p2<=p)
+ {
+ error("skewX() expected 'x' value");
+ return false;
+ }
+ p = skipwhite(p2);
+ if (get(p++) != ')')
+ {
+ error("skewX() needs closing ')'");
+ return false;
+ }
+ //printf("skewX: %f\n", x);
+ SVGTransform transform;
+ transform.setSkewX(x);
+ transformList.appendItem(transform);
+ }
+
+ //######### SKEWY
+ else if (name == "skewY")
+ {
+ p = skipwhite(p);
+ if (get(p++) != '(')
+ {
+ error("skewY transform needs opening '('");
+ return false;
+ }
+ p = skipwhite(p);
+ double y = 0.0;
+ p2 = getNumber(p, y);
+ if (p2<0)
+ return false;
+ if (p2<=p)
+ {
+ error("skewY() expected 'y' value");
+ return false;
+ }
+ p = skipwhite(p2);
+ if (get(p++) != ')')
+ {
+ error("skewY() needs closing ')'");
+ return false;
+ }
+ //printf("skewY: %f\n", y);
+ SVGTransform transform;
+ transform.setSkewY(y);
+ transformList.appendItem(transform);
+ }
+
+ //### NONE OF THE ABOVE
+ else
+ {
+ error("unknown transform type:'%s'", name.c_str());
+ }
+
+ p = skipwhite(p);
+ XMLCh ch = get(p);
+ if (ch == ',')
+ {
+ p++;
+ p = skipwhite(p);
+ }
+
+ }//WHILE p<parselen
+
+ return true;
+}
+
+
+/**
+ *
+ */
+bool SvgReader::parseElement(SVGElementImplPtr parent,
+ ElementImplPtr sourceElem)
+{
+ if (!parent || !sourceElem)
+ {
+ error("NULL source element");
+ return false;
+ }
+
+ DOMString namespaceURI = sourceElem->getNamespaceURI();
+ //printf("namespaceURI:%s\n", namespaceURI.c_str());
+ DOMString tagName = sourceElem->getTagName();
+ printf("tag name:%s\n", tagName.c_str());
+
+ ElementImplPtr newElement = NULL;
+ if (namespaceURI != SVG_NAMESPACE)
+ {
+ newElement = new SVGSVGElementImpl();
+ newElement->assign(*sourceElem);
+ parent->appendChild(newElement);
+ }
+ else //## SVG!!
+ {
+
+ //####################################################
+ //## ATTRIBUTES
+ //####################################################
+ DOMString style = sourceElem->getAttribute("style");
+ if (style.size() > 0)
+ {
+ css::CssParser parser;
+ style.insert(0, "{");
+ style.append("}");
+ //printf("CSS:%s\n", style.c_str());
+ if (!parser.parse(style))
+ {
+ error("parsing style attribute");
+ }
+ else
+ {
+ //printf("##parsed!\n");
+ }
+ }
+
+ DOMString transform = sourceElem->getAttribute("transform");
+ if (transform.size() > 0)
+ {
+ if (!parseTransform(transform))
+ {
+ error("parsing transform attribute");
+ }
+ else
+ {
+ //printf("##parsed!\n");
+ }
+ }
+
+ //####################################################
+ //## ELEMENT - SPECIFIC
+ //####################################################
+ if (tagName == "svg")
+ {
+ newElement = new SVGSVGElementImpl();
+ newElement->assign(*sourceElem);
+ parent->appendChild(newElement);
+ }
+ else if (tagName == "title")
+ {
+ newElement = new SVGTitleElementImpl();
+ newElement->assign(*sourceElem);
+ parent->appendChild(newElement);
+ }
+ else if (tagName == "desc")
+ {
+ newElement = new SVGDescElementImpl();
+ newElement->assign(*sourceElem);
+ parent->appendChild(newElement);
+ }
+ else if (tagName == "defs")
+ {
+ newElement = new SVGDefsElementImpl();
+ newElement->assign(*sourceElem);
+ parent->appendChild(newElement);
+ }
+ else if (tagName == "style")
+ {
+ newElement = new SVGStyleElementImpl();
+ newElement->assign(*sourceElem);
+ parent->appendChild(newElement);
+ }
+ else if (tagName == "g")
+ {
+ newElement = new SVGGElementImpl();
+ newElement->assign(*sourceElem);
+ parent->appendChild(newElement);
+ }
+ else if (tagName == "path")
+ {
+ newElement = new SVGPathElementImpl();
+ newElement->assign(*sourceElem);
+ parent->appendChild(newElement);
+ }
+ }
+
+ NodeList children = sourceElem->getChildNodes();
+ int nodeCount = children.getLength();
+ for (int i=0 ; i<nodeCount ; i++)
+ {
+ NodePtr child = children.item(i);
+ int typ = child->getNodeType();
+ if (typ == Node::TEXT_NODE)
+ {
+ NodePtr newNode = doc->createTextNode(child->getNodeValue());
+ parent->appendChild(newNode);
+ }
+ else if (typ == Node::CDATA_SECTION_NODE)
+ {
+ NodePtr newNode = doc->createCDATASection(child->getNodeValue());
+ parent->appendChild(newNode);
+ }
+ else if (newElement.get() && typ == Node::ELEMENT_NODE)
+ {
+ //ElementImplPtr childElement = dynamic_cast<ElementImpl *>(child.get());
+ //parseElement(newElement, childElement);
+ }
+ }
+ return true;
+}
+
+
+/**
+ *
+ */
+SVGDocumentPtr SvgReader::parse(const DocumentPtr src)
+{
+ if (!src)
+ {
+ error("NULL source document");
+ return NULL;
+ }
+
+ DOMImplementationImpl impl;
+ doc = new SVGDocumentImpl(&impl, SVG_NAMESPACE, "svg" , NULL);
+
+ SVGElementImplPtr destElem = dynamic_cast<SVGElementImpl *>(doc->getRootElement().get());
+ ElementImplPtr srcElem = dynamic_cast<ElementImpl *>(src->getDocumentElement().get());
+ if (!parseElement(destElem, srcElem))
+ {
+ return NULL;
+ }
+
+ return doc;
+}
+
+
+
+/**
+ *
+ */
+SVGDocumentPtr SvgReader::parse(const DOMString &buf)
+{
+ /* remember, smartptrs are null-testable*/
+ SVGDocumentPtr svgdoc;
+ XmlReader parser;
+ DocumentPtr doc = parser.parse(buf);
+ if (!doc)
+ {
+ return svgdoc;
+ }
+ svgdoc = parse(doc);
+ return svgdoc;
+}
+
+
+
+/**
+ *
+ */
+SVGDocumentPtr SvgReader::parseFile(const DOMString &fileName)
+{
+ /* remember, smartptrs are null-testable*/
+ SVGDocumentPtr svgdoc;
+ XmlReader parser;
+ DocumentPtr doc = parser.parseFile(fileName);
+ if (!doc)
+ {
+ return svgdoc;
+ }
+ svgdoc = parse(doc);
+ return svgdoc;
+}
+
+
+
+
+} //namespace svg
+} //namespace dom
+} //namespace w3c
+} //namespace org
+
+/*#########################################################################
+## E N D O F F I L E
+#########################################################################*/
+
diff --git a/src/dom/svgreader.h b/src/dom/svgreader.h
--- /dev/null
+++ b/src/dom/svgreader.h
@@ -0,0 +1,179 @@
+#ifndef __SVGREADER_H__
+#define __SVGREADER_H__
+
+/**
+ * Phoebe DOM Implementation.
+ *
+ * This is a C++ approximation of the W3C DOM model, which follows
+ * fairly closely the specifications in the various .idl files, copies of
+ * which are provided for reference. Most important is this one:
+ *
+ * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
+ *
+ * Authors:
+ * Bob Jamison
+ *
+ * Copyright (C) 2005-2008 Bob Jamison
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * =======================================================================
+ * NOTES
+ *
+ * This parser takes an XML document, as a file, string, or DOM Document,
+ * and attempts to parse it as an SVG-DOM SVGDocument.
+ *
+ * Look in svg.h and svgtypes.h for the classes which are the target of this
+ * parser.
+ *
+ * They loosely follow the specification:
+ * http://www.w3.org/TR/SVG11/svgdom.html
+ *
+ */
+
+
+#include "svgimpl.h"
+
+namespace org
+{
+namespace w3c
+{
+namespace dom
+{
+namespace svg
+{
+
+
+class SvgReader
+{
+public:
+
+ /**
+ *
+ */
+ SvgReader()
+ {
+ }
+
+ /**
+ *
+ */
+ SvgReader(const SvgReader &/*other*/)
+ {
+ }
+
+ /**
+ *
+ */
+ virtual ~SvgReader()
+ {
+ }
+
+ /**
+ *
+ */
+ SVGDocumentPtr parse(const DocumentPtr /*sourceDoc*/);
+
+ /**
+ *
+ */
+ SVGDocumentPtr parse(const DOMString &/*buffer*/);
+
+ /**
+ *
+ */
+ SVGDocumentPtr parseFile(const DOMString &/*fileName*/);
+
+
+
+
+private:
+
+ /**
+ * Get the next character in the parse buf, 0 if out
+ * of range
+ */
+ XMLCh get(int p);
+
+ /**
+ * Test if the given substring exists at the given position
+ * in parsebuf. Use get() in case of out-of-bounds
+ */
+ bool match(int pos, char const *str);
+
+ /**
+ *
+ */
+ int skipwhite(int p);
+
+ /**
+ * get a word from the buffer
+ */
+ int getWord(int p, DOMString &result);
+
+ /**
+ * get a word from the buffer
+ */
+ int getNumber(int p0, double &result);
+
+
+ /**
+ *
+ */
+ bool parseTransform(const DOMString &str);
+
+
+ /**
+ *
+ */
+ bool parseElement(SVGElementImplPtr destElem,
+ ElementImplPtr sourceElem);
+
+
+ /**
+ *
+ */
+ void error(char const *format, ...)
+ #ifdef G_GNUC_PRINTF
+ G_GNUC_PRINTF(2, 3)
+ #endif
+ ;
+
+
+
+ DOMString parsebuf;
+ int parselen;
+ int lastPosition;
+
+ SVGDocumentImplPtr doc;
+
+};
+
+
+
+
+
+} //namespace svg
+} //namespace dom
+} //namespace w3c
+} //namespace org
+
+#endif /* __SVGREADER_H__ */
+/*#########################################################################
+## E N D O F F I L E
+#########################################################################*/
+
+
+