From: ishmal Date: Thu, 1 May 2008 19:23:00 +0000 (+0000) Subject: Rename *Parsers to Readers X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=c8a7ccdba2ed11f4778ca11870d6332b3b5e8624;p=inkscape.git Rename *Parsers to Readers --- diff --git a/src/dom/cssparser.cpp b/src/dom/cssparser.cpp deleted file mode 100644 index 422c02e49..000000000 --- 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 -#include - -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

= 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+=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'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 (pp) - { - 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 ; ip) - { - //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 +#include + +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

= 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+=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'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 (pp) + { + 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 ; ip) + { + //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 - -#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+=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'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 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 pgetNamespaceURI(); - //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 ; igetNodeType(); - 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(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(doc->getRootElement().get()); - ElementImplPtr srcElem = dynamic_cast(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 deleted file mode 100644 index 8e53fe656..000000000 --- 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 new file mode 100644 index 000000000..7ebde97ae --- /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 + +#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+=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'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 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 pgetNamespaceURI(); + //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 ; igetNodeType(); + 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(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(doc->getRootElement().get()); + ElementImplPtr srcElem = dynamic_cast(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 new file mode 100644 index 000000000..cfc41287e --- /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 +#########################################################################*/ + + +