1*b1cdbd2cSJim Jagielski /************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove 23*b1cdbd2cSJim Jagielski #include "precompiled_svgio.hxx" 24*b1cdbd2cSJim Jagielski 25*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgdocumenthandler.hxx> 26*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgtoken.hxx> 27*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgsvgnode.hxx> 28*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svggnode.hxx> 29*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgnode.hxx> 30*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgpathnode.hxx> 31*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgrectnode.hxx> 32*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svggradientnode.hxx> 33*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svggradientstopnode.hxx> 34*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgsymbolnode.hxx> 35*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgusenode.hxx> 36*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgcirclenode.hxx> 37*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgellipsenode.hxx> 38*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svglinenode.hxx> 39*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgpolynode.hxx> 40*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgsymbolnode.hxx> 41*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgtextnode.hxx> 42*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgcharacternode.hxx> 43*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgtspannode.hxx> 44*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgtrefnode.hxx> 45*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgtextpathnode.hxx> 46*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgstylenode.hxx> 47*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgimagenode.hxx> 48*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgclippathnode.hxx> 49*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgmasknode.hxx> 50*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgmarkernode.hxx> 51*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgpatternnode.hxx> 52*b1cdbd2cSJim Jagielski #include <svgio/svgreader/svgtitledescnode.hxx> 53*b1cdbd2cSJim Jagielski 54*b1cdbd2cSJim Jagielski ////////////////////////////////////////////////////////////////////////////// 55*b1cdbd2cSJim Jagielski 56*b1cdbd2cSJim Jagielski using namespace com::sun::star; 57*b1cdbd2cSJim Jagielski 58*b1cdbd2cSJim Jagielski ////////////////////////////////////////////////////////////////////////////// 59*b1cdbd2cSJim Jagielski 60*b1cdbd2cSJim Jagielski namespace 61*b1cdbd2cSJim Jagielski { whiteSpaceHandling(svgio::svgreader::SvgNode * pNode,svgio::svgreader::SvgCharacterNode * pLast)62*b1cdbd2cSJim Jagielski svgio::svgreader::SvgCharacterNode* whiteSpaceHandling(svgio::svgreader::SvgNode* pNode, svgio::svgreader::SvgCharacterNode* pLast) 63*b1cdbd2cSJim Jagielski { 64*b1cdbd2cSJim Jagielski if(pNode) 65*b1cdbd2cSJim Jagielski { 66*b1cdbd2cSJim Jagielski const svgio::svgreader::SvgNodeVector& rChilds = pNode->getChildren(); 67*b1cdbd2cSJim Jagielski const sal_uInt32 nCount(rChilds.size()); 68*b1cdbd2cSJim Jagielski 69*b1cdbd2cSJim Jagielski for(sal_uInt32 a(0); a < nCount; a++) 70*b1cdbd2cSJim Jagielski { 71*b1cdbd2cSJim Jagielski svgio::svgreader::SvgNode* pCandidate = rChilds[a]; 72*b1cdbd2cSJim Jagielski 73*b1cdbd2cSJim Jagielski if(pCandidate) 74*b1cdbd2cSJim Jagielski { 75*b1cdbd2cSJim Jagielski switch(pCandidate->getType()) 76*b1cdbd2cSJim Jagielski { 77*b1cdbd2cSJim Jagielski case svgio::svgreader::SVGTokenCharacter: 78*b1cdbd2cSJim Jagielski { 79*b1cdbd2cSJim Jagielski // clean whitespace in text span 80*b1cdbd2cSJim Jagielski svgio::svgreader::SvgCharacterNode* pCharNode = static_cast< svgio::svgreader::SvgCharacterNode* >(pCandidate); 81*b1cdbd2cSJim Jagielski pCharNode->whiteSpaceHandling(); 82*b1cdbd2cSJim Jagielski 83*b1cdbd2cSJim Jagielski // pCharNode may have lost all text. If that's the case, ignore 84*b1cdbd2cSJim Jagielski // as invalid character node 85*b1cdbd2cSJim Jagielski if(pCharNode->getText().getLength()) 86*b1cdbd2cSJim Jagielski { 87*b1cdbd2cSJim Jagielski if(pLast) 88*b1cdbd2cSJim Jagielski { 89*b1cdbd2cSJim Jagielski bool bAddGap(true); 90*b1cdbd2cSJim Jagielski static bool bNoGapsForBaselineShift(true); 91*b1cdbd2cSJim Jagielski 92*b1cdbd2cSJim Jagielski if(bNoGapsForBaselineShift) 93*b1cdbd2cSJim Jagielski { 94*b1cdbd2cSJim Jagielski // With this option a baseline shift between two char parts ('words') 95*b1cdbd2cSJim Jagielski // will not add a space 'gap' to the end of the (non-last) word. This 96*b1cdbd2cSJim Jagielski // seems to be the standard behaviour, see last bugdoc attached #122524# 97*b1cdbd2cSJim Jagielski const svgio::svgreader::SvgStyleAttributes* pStyleLast = pLast->getSvgStyleAttributes(); 98*b1cdbd2cSJim Jagielski const svgio::svgreader::SvgStyleAttributes* pStyleCurrent = pCandidate->getSvgStyleAttributes(); 99*b1cdbd2cSJim Jagielski 100*b1cdbd2cSJim Jagielski if(pStyleLast && pStyleCurrent && pStyleLast->getBaselineShift() != pStyleCurrent->getBaselineShift()) 101*b1cdbd2cSJim Jagielski { 102*b1cdbd2cSJim Jagielski bAddGap = false; 103*b1cdbd2cSJim Jagielski } 104*b1cdbd2cSJim Jagielski } 105*b1cdbd2cSJim Jagielski 106*b1cdbd2cSJim Jagielski // add in-between whitespace (single space) to last 107*b1cdbd2cSJim Jagielski // known character node 108*b1cdbd2cSJim Jagielski if(bAddGap) 109*b1cdbd2cSJim Jagielski { 110*b1cdbd2cSJim Jagielski pLast->addGap(); 111*b1cdbd2cSJim Jagielski } 112*b1cdbd2cSJim Jagielski } 113*b1cdbd2cSJim Jagielski 114*b1cdbd2cSJim Jagielski // remember new last corected character node 115*b1cdbd2cSJim Jagielski pLast = pCharNode; 116*b1cdbd2cSJim Jagielski } 117*b1cdbd2cSJim Jagielski break; 118*b1cdbd2cSJim Jagielski } 119*b1cdbd2cSJim Jagielski case svgio::svgreader::SVGTokenTspan: 120*b1cdbd2cSJim Jagielski case svgio::svgreader::SVGTokenTextPath: 121*b1cdbd2cSJim Jagielski case svgio::svgreader::SVGTokenTref: 122*b1cdbd2cSJim Jagielski { 123*b1cdbd2cSJim Jagielski // recursively clean whitespaces in subhierarchy 124*b1cdbd2cSJim Jagielski pLast = whiteSpaceHandling(pCandidate, pLast); 125*b1cdbd2cSJim Jagielski break; 126*b1cdbd2cSJim Jagielski } 127*b1cdbd2cSJim Jagielski default: 128*b1cdbd2cSJim Jagielski { 129*b1cdbd2cSJim Jagielski OSL_ENSURE(false, "Unexpected token inside SVGTokenText (!)"); 130*b1cdbd2cSJim Jagielski break; 131*b1cdbd2cSJim Jagielski } 132*b1cdbd2cSJim Jagielski } 133*b1cdbd2cSJim Jagielski } 134*b1cdbd2cSJim Jagielski } 135*b1cdbd2cSJim Jagielski } 136*b1cdbd2cSJim Jagielski 137*b1cdbd2cSJim Jagielski return pLast; 138*b1cdbd2cSJim Jagielski } 139*b1cdbd2cSJim Jagielski } 140*b1cdbd2cSJim Jagielski 141*b1cdbd2cSJim Jagielski ////////////////////////////////////////////////////////////////////////////// 142*b1cdbd2cSJim Jagielski 143*b1cdbd2cSJim Jagielski namespace svgio 144*b1cdbd2cSJim Jagielski { 145*b1cdbd2cSJim Jagielski namespace svgreader 146*b1cdbd2cSJim Jagielski { SvgDocHdl(const rtl::OUString & aAbsolutePath)147*b1cdbd2cSJim Jagielski SvgDocHdl::SvgDocHdl(const rtl::OUString& aAbsolutePath) 148*b1cdbd2cSJim Jagielski : maDocument(aAbsolutePath), 149*b1cdbd2cSJim Jagielski mpTarget(0), 150*b1cdbd2cSJim Jagielski maCssContents() 151*b1cdbd2cSJim Jagielski { 152*b1cdbd2cSJim Jagielski } 153*b1cdbd2cSJim Jagielski ~SvgDocHdl()154*b1cdbd2cSJim Jagielski SvgDocHdl::~SvgDocHdl() 155*b1cdbd2cSJim Jagielski { 156*b1cdbd2cSJim Jagielski #ifdef DBG_UTIL 157*b1cdbd2cSJim Jagielski if(mpTarget) 158*b1cdbd2cSJim Jagielski { 159*b1cdbd2cSJim Jagielski OSL_ENSURE(false, "SvgDocHdl destructed with active target (!)"); 160*b1cdbd2cSJim Jagielski delete mpTarget; 161*b1cdbd2cSJim Jagielski } 162*b1cdbd2cSJim Jagielski OSL_ENSURE(!maCssContents.size(), "SvgDocHdl destructed with active css style stack entry (!)"); 163*b1cdbd2cSJim Jagielski #endif 164*b1cdbd2cSJim Jagielski } 165*b1cdbd2cSJim Jagielski startDocument()166*b1cdbd2cSJim Jagielski void SvgDocHdl::startDocument( ) throw (xml::sax::SAXException, uno::RuntimeException) 167*b1cdbd2cSJim Jagielski { 168*b1cdbd2cSJim Jagielski OSL_ENSURE(!mpTarget, "Already a target at document start (!)"); 169*b1cdbd2cSJim Jagielski OSL_ENSURE(!maCssContents.size(), "SvgDocHdl startDocument with active css style stack entry (!)"); 170*b1cdbd2cSJim Jagielski } 171*b1cdbd2cSJim Jagielski endDocument()172*b1cdbd2cSJim Jagielski void SvgDocHdl::endDocument( ) throw (xml::sax::SAXException, uno::RuntimeException) 173*b1cdbd2cSJim Jagielski { 174*b1cdbd2cSJim Jagielski OSL_ENSURE(!mpTarget, "Still a target at document end (!)"); 175*b1cdbd2cSJim Jagielski OSL_ENSURE(!maCssContents.size(), "SvgDocHdl endDocument with active css style stack entry (!)"); 176*b1cdbd2cSJim Jagielski } 177*b1cdbd2cSJim Jagielski startElement(const::rtl::OUString & aName,const uno::Reference<xml::sax::XAttributeList> & xAttribs)178*b1cdbd2cSJim Jagielski void SvgDocHdl::startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) throw (xml::sax::SAXException, uno::RuntimeException) 179*b1cdbd2cSJim Jagielski { 180*b1cdbd2cSJim Jagielski if(aName.getLength()) 181*b1cdbd2cSJim Jagielski { 182*b1cdbd2cSJim Jagielski const SVGToken aSVGToken(StrToSVGToken(aName)); 183*b1cdbd2cSJim Jagielski 184*b1cdbd2cSJim Jagielski switch(aSVGToken) 185*b1cdbd2cSJim Jagielski { 186*b1cdbd2cSJim Jagielski /// structural elements 187*b1cdbd2cSJim Jagielski case SVGTokenSymbol: 188*b1cdbd2cSJim Jagielski { 189*b1cdbd2cSJim Jagielski /// new basic node for Symbol. Content gets scanned, but 190*b1cdbd2cSJim Jagielski /// will not be decomposed (see SvgNode::decomposeSvgNode and bReferenced) 191*b1cdbd2cSJim Jagielski mpTarget = new SvgSymbolNode(maDocument, mpTarget); 192*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 193*b1cdbd2cSJim Jagielski break; 194*b1cdbd2cSJim Jagielski } 195*b1cdbd2cSJim Jagielski case SVGTokenDefs: 196*b1cdbd2cSJim Jagielski case SVGTokenG: 197*b1cdbd2cSJim Jagielski { 198*b1cdbd2cSJim Jagielski /// new node for Defs/G 199*b1cdbd2cSJim Jagielski mpTarget = new SvgGNode(aSVGToken, maDocument, mpTarget); 200*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 201*b1cdbd2cSJim Jagielski break; 202*b1cdbd2cSJim Jagielski } 203*b1cdbd2cSJim Jagielski case SVGTokenSvg: 204*b1cdbd2cSJim Jagielski { 205*b1cdbd2cSJim Jagielski /// new node for Svg 206*b1cdbd2cSJim Jagielski mpTarget = new SvgSvgNode(maDocument, mpTarget); 207*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 208*b1cdbd2cSJim Jagielski break; 209*b1cdbd2cSJim Jagielski } 210*b1cdbd2cSJim Jagielski case SVGTokenUse: 211*b1cdbd2cSJim Jagielski { 212*b1cdbd2cSJim Jagielski /// new node for Use 213*b1cdbd2cSJim Jagielski mpTarget = new SvgUseNode(maDocument, mpTarget); 214*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 215*b1cdbd2cSJim Jagielski break; 216*b1cdbd2cSJim Jagielski } 217*b1cdbd2cSJim Jagielski 218*b1cdbd2cSJim Jagielski /// shape elements 219*b1cdbd2cSJim Jagielski case SVGTokenCircle: 220*b1cdbd2cSJim Jagielski { 221*b1cdbd2cSJim Jagielski /// new node for Circle 222*b1cdbd2cSJim Jagielski mpTarget = new SvgCircleNode(maDocument, mpTarget); 223*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 224*b1cdbd2cSJim Jagielski break; 225*b1cdbd2cSJim Jagielski } 226*b1cdbd2cSJim Jagielski case SVGTokenEllipse: 227*b1cdbd2cSJim Jagielski { 228*b1cdbd2cSJim Jagielski /// new node for Ellipse 229*b1cdbd2cSJim Jagielski mpTarget = new SvgEllipseNode(maDocument, mpTarget); 230*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 231*b1cdbd2cSJim Jagielski break; 232*b1cdbd2cSJim Jagielski } 233*b1cdbd2cSJim Jagielski case SVGTokenLine: 234*b1cdbd2cSJim Jagielski { 235*b1cdbd2cSJim Jagielski /// new node for Line 236*b1cdbd2cSJim Jagielski mpTarget = new SvgLineNode(maDocument, mpTarget); 237*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 238*b1cdbd2cSJim Jagielski break; 239*b1cdbd2cSJim Jagielski } 240*b1cdbd2cSJim Jagielski case SVGTokenPath: 241*b1cdbd2cSJim Jagielski { 242*b1cdbd2cSJim Jagielski /// new node for Path 243*b1cdbd2cSJim Jagielski mpTarget = new SvgPathNode(maDocument, mpTarget); 244*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 245*b1cdbd2cSJim Jagielski break; 246*b1cdbd2cSJim Jagielski } 247*b1cdbd2cSJim Jagielski case SVGTokenPolygon: 248*b1cdbd2cSJim Jagielski { 249*b1cdbd2cSJim Jagielski /// new node for Polygon 250*b1cdbd2cSJim Jagielski mpTarget = new SvgPolyNode(maDocument, mpTarget, false); 251*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 252*b1cdbd2cSJim Jagielski break; 253*b1cdbd2cSJim Jagielski } 254*b1cdbd2cSJim Jagielski case SVGTokenPolyline: 255*b1cdbd2cSJim Jagielski { 256*b1cdbd2cSJim Jagielski /// new node for Polyline 257*b1cdbd2cSJim Jagielski mpTarget = new SvgPolyNode(maDocument, mpTarget, true); 258*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 259*b1cdbd2cSJim Jagielski break; 260*b1cdbd2cSJim Jagielski } 261*b1cdbd2cSJim Jagielski case SVGTokenRect: 262*b1cdbd2cSJim Jagielski { 263*b1cdbd2cSJim Jagielski /// new node for Rect 264*b1cdbd2cSJim Jagielski mpTarget = new SvgRectNode(maDocument, mpTarget); 265*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 266*b1cdbd2cSJim Jagielski break; 267*b1cdbd2cSJim Jagielski } 268*b1cdbd2cSJim Jagielski case SVGTokenImage: 269*b1cdbd2cSJim Jagielski { 270*b1cdbd2cSJim Jagielski /// new node for Image 271*b1cdbd2cSJim Jagielski mpTarget = new SvgImageNode(maDocument, mpTarget); 272*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 273*b1cdbd2cSJim Jagielski break; 274*b1cdbd2cSJim Jagielski } 275*b1cdbd2cSJim Jagielski 276*b1cdbd2cSJim Jagielski /// title and description 277*b1cdbd2cSJim Jagielski case SVGTokenTitle: 278*b1cdbd2cSJim Jagielski case SVGTokenDesc: 279*b1cdbd2cSJim Jagielski { 280*b1cdbd2cSJim Jagielski /// new node for Title and/or Desc 281*b1cdbd2cSJim Jagielski mpTarget = new SvgTitleDescNode(aSVGToken, maDocument, mpTarget); 282*b1cdbd2cSJim Jagielski break; 283*b1cdbd2cSJim Jagielski } 284*b1cdbd2cSJim Jagielski 285*b1cdbd2cSJim Jagielski /// gradients 286*b1cdbd2cSJim Jagielski case SVGTokenLinearGradient: 287*b1cdbd2cSJim Jagielski case SVGTokenRadialGradient: 288*b1cdbd2cSJim Jagielski { 289*b1cdbd2cSJim Jagielski mpTarget = new SvgGradientNode(aSVGToken, maDocument, mpTarget); 290*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 291*b1cdbd2cSJim Jagielski break; 292*b1cdbd2cSJim Jagielski } 293*b1cdbd2cSJim Jagielski 294*b1cdbd2cSJim Jagielski /// gradient stops 295*b1cdbd2cSJim Jagielski case SVGTokenStop: 296*b1cdbd2cSJim Jagielski { 297*b1cdbd2cSJim Jagielski mpTarget = new SvgGradientStopNode(maDocument, mpTarget); 298*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 299*b1cdbd2cSJim Jagielski break; 300*b1cdbd2cSJim Jagielski } 301*b1cdbd2cSJim Jagielski 302*b1cdbd2cSJim Jagielski /// text 303*b1cdbd2cSJim Jagielski case SVGTokenText: 304*b1cdbd2cSJim Jagielski { 305*b1cdbd2cSJim Jagielski mpTarget = new SvgTextNode(maDocument, mpTarget); 306*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 307*b1cdbd2cSJim Jagielski break; 308*b1cdbd2cSJim Jagielski } 309*b1cdbd2cSJim Jagielski case SVGTokenTspan: 310*b1cdbd2cSJim Jagielski { 311*b1cdbd2cSJim Jagielski mpTarget = new SvgTspanNode(maDocument, mpTarget); 312*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 313*b1cdbd2cSJim Jagielski break; 314*b1cdbd2cSJim Jagielski } 315*b1cdbd2cSJim Jagielski case SVGTokenTref: 316*b1cdbd2cSJim Jagielski { 317*b1cdbd2cSJim Jagielski mpTarget = new SvgTrefNode(maDocument, mpTarget); 318*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 319*b1cdbd2cSJim Jagielski break; 320*b1cdbd2cSJim Jagielski } 321*b1cdbd2cSJim Jagielski case SVGTokenTextPath: 322*b1cdbd2cSJim Jagielski { 323*b1cdbd2cSJim Jagielski mpTarget = new SvgTextPathNode(maDocument, mpTarget); 324*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 325*b1cdbd2cSJim Jagielski break; 326*b1cdbd2cSJim Jagielski } 327*b1cdbd2cSJim Jagielski 328*b1cdbd2cSJim Jagielski /// styles (as stylesheets) 329*b1cdbd2cSJim Jagielski case SVGTokenStyle: 330*b1cdbd2cSJim Jagielski { 331*b1cdbd2cSJim Jagielski SvgStyleNode* pNew = new SvgStyleNode(maDocument, mpTarget); 332*b1cdbd2cSJim Jagielski mpTarget = pNew; 333*b1cdbd2cSJim Jagielski const sal_uInt32 nAttributes(xAttribs->getLength()); 334*b1cdbd2cSJim Jagielski 335*b1cdbd2cSJim Jagielski if(0 == nAttributes) 336*b1cdbd2cSJim Jagielski { 337*b1cdbd2cSJim Jagielski // #125326# no attributes, thus also no type="text/css". This is allowed to be missing, 338*b1cdbd2cSJim Jagielski // thus do mark this style as CssStyle. This is required to read the contained 339*b1cdbd2cSJim Jagielski // text (which defines the css style) 340*b1cdbd2cSJim Jagielski pNew->setTextCss(true); 341*b1cdbd2cSJim Jagielski } 342*b1cdbd2cSJim Jagielski else 343*b1cdbd2cSJim Jagielski { 344*b1cdbd2cSJim Jagielski // #125326# there are attributes, read them. This will set isTextCss to true if 345*b1cdbd2cSJim Jagielski // a type="text/css" is contained as exact match, else not 346*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 347*b1cdbd2cSJim Jagielski } 348*b1cdbd2cSJim Jagielski 349*b1cdbd2cSJim Jagielski if(pNew->isTextCss()) 350*b1cdbd2cSJim Jagielski { 351*b1cdbd2cSJim Jagielski // if it is a Css style, allow reading text between the start and end tag (see 352*b1cdbd2cSJim Jagielski // SvgDocHdl::characters for details) 353*b1cdbd2cSJim Jagielski maCssContents.push_back(rtl::OUString()); 354*b1cdbd2cSJim Jagielski } 355*b1cdbd2cSJim Jagielski break; 356*b1cdbd2cSJim Jagielski } 357*b1cdbd2cSJim Jagielski 358*b1cdbd2cSJim Jagielski /// structural elements clip-path and mask. Content gets scanned, but 359*b1cdbd2cSJim Jagielski /// will not be decomposed (see SvgNode::decomposeSvgNode and bReferenced) 360*b1cdbd2cSJim Jagielski case SVGTokenClipPathNode: 361*b1cdbd2cSJim Jagielski { 362*b1cdbd2cSJim Jagielski /// new node for ClipPath 363*b1cdbd2cSJim Jagielski mpTarget = new SvgClipPathNode(maDocument, mpTarget); 364*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 365*b1cdbd2cSJim Jagielski break; 366*b1cdbd2cSJim Jagielski } 367*b1cdbd2cSJim Jagielski case SVGTokenMask: 368*b1cdbd2cSJim Jagielski { 369*b1cdbd2cSJim Jagielski /// new node for Mask 370*b1cdbd2cSJim Jagielski mpTarget = new SvgMaskNode(maDocument, mpTarget); 371*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 372*b1cdbd2cSJim Jagielski break; 373*b1cdbd2cSJim Jagielski } 374*b1cdbd2cSJim Jagielski 375*b1cdbd2cSJim Jagielski /// structural element marker 376*b1cdbd2cSJim Jagielski case SVGTokenMarker: 377*b1cdbd2cSJim Jagielski { 378*b1cdbd2cSJim Jagielski /// new node for marker 379*b1cdbd2cSJim Jagielski mpTarget = new SvgMarkerNode(maDocument, mpTarget); 380*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 381*b1cdbd2cSJim Jagielski break; 382*b1cdbd2cSJim Jagielski } 383*b1cdbd2cSJim Jagielski 384*b1cdbd2cSJim Jagielski /// structural element pattern 385*b1cdbd2cSJim Jagielski case SVGTokenPattern: 386*b1cdbd2cSJim Jagielski { 387*b1cdbd2cSJim Jagielski /// new node for pattern 388*b1cdbd2cSJim Jagielski mpTarget = new SvgPatternNode(maDocument, mpTarget); 389*b1cdbd2cSJim Jagielski mpTarget->parseAttributes(xAttribs); 390*b1cdbd2cSJim Jagielski break; 391*b1cdbd2cSJim Jagielski } 392*b1cdbd2cSJim Jagielski 393*b1cdbd2cSJim Jagielski default: 394*b1cdbd2cSJim Jagielski { 395*b1cdbd2cSJim Jagielski /// invalid token, ignore 396*b1cdbd2cSJim Jagielski #ifdef DBG_UTIL 397*b1cdbd2cSJim Jagielski myAssert( 398*b1cdbd2cSJim Jagielski rtl::OUString::createFromAscii("Unknown Base SvgToken <") + 399*b1cdbd2cSJim Jagielski aName + 400*b1cdbd2cSJim Jagielski rtl::OUString::createFromAscii("> (!)")); 401*b1cdbd2cSJim Jagielski #endif 402*b1cdbd2cSJim Jagielski break; 403*b1cdbd2cSJim Jagielski } 404*b1cdbd2cSJim Jagielski } 405*b1cdbd2cSJim Jagielski } 406*b1cdbd2cSJim Jagielski } 407*b1cdbd2cSJim Jagielski endElement(const::rtl::OUString & aName)408*b1cdbd2cSJim Jagielski void SvgDocHdl::endElement( const ::rtl::OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException) 409*b1cdbd2cSJim Jagielski { 410*b1cdbd2cSJim Jagielski if(aName.getLength()) 411*b1cdbd2cSJim Jagielski { 412*b1cdbd2cSJim Jagielski const SVGToken aSVGToken(StrToSVGToken(aName)); 413*b1cdbd2cSJim Jagielski SvgNode* pWhitespaceCheck(SVGTokenText == aSVGToken ? mpTarget : 0); 414*b1cdbd2cSJim Jagielski SvgStyleNode* pCssStyle(SVGTokenStyle == aSVGToken ? static_cast< SvgStyleNode* >(mpTarget) : 0); 415*b1cdbd2cSJim Jagielski SvgTitleDescNode* pSvgTitleDescNode(SVGTokenTitle == aSVGToken || SVGTokenDesc == aSVGToken ? static_cast< SvgTitleDescNode* >(mpTarget) : 0); 416*b1cdbd2cSJim Jagielski 417*b1cdbd2cSJim Jagielski switch(aSVGToken) 418*b1cdbd2cSJim Jagielski { 419*b1cdbd2cSJim Jagielski /// valid tokens for which a new one was created 420*b1cdbd2cSJim Jagielski 421*b1cdbd2cSJim Jagielski /// structural elements 422*b1cdbd2cSJim Jagielski case SVGTokenDefs: 423*b1cdbd2cSJim Jagielski case SVGTokenG: 424*b1cdbd2cSJim Jagielski case SVGTokenSvg: 425*b1cdbd2cSJim Jagielski case SVGTokenSymbol: 426*b1cdbd2cSJim Jagielski case SVGTokenUse: 427*b1cdbd2cSJim Jagielski 428*b1cdbd2cSJim Jagielski /// shape elements 429*b1cdbd2cSJim Jagielski case SVGTokenCircle: 430*b1cdbd2cSJim Jagielski case SVGTokenEllipse: 431*b1cdbd2cSJim Jagielski case SVGTokenLine: 432*b1cdbd2cSJim Jagielski case SVGTokenPath: 433*b1cdbd2cSJim Jagielski case SVGTokenPolygon: 434*b1cdbd2cSJim Jagielski case SVGTokenPolyline: 435*b1cdbd2cSJim Jagielski case SVGTokenRect: 436*b1cdbd2cSJim Jagielski case SVGTokenImage: 437*b1cdbd2cSJim Jagielski 438*b1cdbd2cSJim Jagielski /// title and description 439*b1cdbd2cSJim Jagielski case SVGTokenTitle: 440*b1cdbd2cSJim Jagielski case SVGTokenDesc: 441*b1cdbd2cSJim Jagielski 442*b1cdbd2cSJim Jagielski /// gradients 443*b1cdbd2cSJim Jagielski case SVGTokenLinearGradient: 444*b1cdbd2cSJim Jagielski case SVGTokenRadialGradient: 445*b1cdbd2cSJim Jagielski 446*b1cdbd2cSJim Jagielski /// gradient stops 447*b1cdbd2cSJim Jagielski case SVGTokenStop: 448*b1cdbd2cSJim Jagielski 449*b1cdbd2cSJim Jagielski /// text 450*b1cdbd2cSJim Jagielski case SVGTokenText: 451*b1cdbd2cSJim Jagielski case SVGTokenTspan: 452*b1cdbd2cSJim Jagielski case SVGTokenTextPath: 453*b1cdbd2cSJim Jagielski case SVGTokenTref: 454*b1cdbd2cSJim Jagielski 455*b1cdbd2cSJim Jagielski /// styles (as stylesheets) 456*b1cdbd2cSJim Jagielski case SVGTokenStyle: 457*b1cdbd2cSJim Jagielski 458*b1cdbd2cSJim Jagielski /// structural elements clip-path and mask 459*b1cdbd2cSJim Jagielski case SVGTokenClipPathNode: 460*b1cdbd2cSJim Jagielski case SVGTokenMask: 461*b1cdbd2cSJim Jagielski 462*b1cdbd2cSJim Jagielski /// structural element marker 463*b1cdbd2cSJim Jagielski case SVGTokenMarker: 464*b1cdbd2cSJim Jagielski 465*b1cdbd2cSJim Jagielski /// structural element pattern 466*b1cdbd2cSJim Jagielski case SVGTokenPattern: 467*b1cdbd2cSJim Jagielski 468*b1cdbd2cSJim Jagielski /// content handling after parsing 469*b1cdbd2cSJim Jagielski { 470*b1cdbd2cSJim Jagielski if(mpTarget) 471*b1cdbd2cSJim Jagielski { 472*b1cdbd2cSJim Jagielski if(!mpTarget->getParent()) 473*b1cdbd2cSJim Jagielski { 474*b1cdbd2cSJim Jagielski // last element closing, save this tree 475*b1cdbd2cSJim Jagielski maDocument.appendNode(mpTarget); 476*b1cdbd2cSJim Jagielski } 477*b1cdbd2cSJim Jagielski 478*b1cdbd2cSJim Jagielski mpTarget = const_cast< SvgNode* >(mpTarget->getParent()); 479*b1cdbd2cSJim Jagielski } 480*b1cdbd2cSJim Jagielski else 481*b1cdbd2cSJim Jagielski { 482*b1cdbd2cSJim Jagielski OSL_ENSURE(false, "Closing token, but no context (!)"); 483*b1cdbd2cSJim Jagielski } 484*b1cdbd2cSJim Jagielski break; 485*b1cdbd2cSJim Jagielski } 486*b1cdbd2cSJim Jagielski default: 487*b1cdbd2cSJim Jagielski { 488*b1cdbd2cSJim Jagielski /// invalid token, ignore 489*b1cdbd2cSJim Jagielski } 490*b1cdbd2cSJim Jagielski } 491*b1cdbd2cSJim Jagielski 492*b1cdbd2cSJim Jagielski if(pSvgTitleDescNode && mpTarget) 493*b1cdbd2cSJim Jagielski { 494*b1cdbd2cSJim Jagielski const rtl::OUString aText(pSvgTitleDescNode->getText()); 495*b1cdbd2cSJim Jagielski 496*b1cdbd2cSJim Jagielski if(aText.getLength()) 497*b1cdbd2cSJim Jagielski { 498*b1cdbd2cSJim Jagielski if(SVGTokenTitle == aSVGToken) 499*b1cdbd2cSJim Jagielski { 500*b1cdbd2cSJim Jagielski mpTarget->parseAttribute(getStrTitle(), aSVGToken, aText); 501*b1cdbd2cSJim Jagielski } 502*b1cdbd2cSJim Jagielski else // if(SVGTokenDesc == aSVGToken) 503*b1cdbd2cSJim Jagielski { 504*b1cdbd2cSJim Jagielski mpTarget->parseAttribute(getStrDesc(), aSVGToken, aText); 505*b1cdbd2cSJim Jagielski } 506*b1cdbd2cSJim Jagielski } 507*b1cdbd2cSJim Jagielski } 508*b1cdbd2cSJim Jagielski 509*b1cdbd2cSJim Jagielski if(pCssStyle && pCssStyle->isTextCss()) 510*b1cdbd2cSJim Jagielski { 511*b1cdbd2cSJim Jagielski // css style parsing 512*b1cdbd2cSJim Jagielski if(maCssContents.size()) 513*b1cdbd2cSJim Jagielski { 514*b1cdbd2cSJim Jagielski // need to interpret css styles and remember them as StyleSheets 515*b1cdbd2cSJim Jagielski pCssStyle->addCssStyleSheet(*(maCssContents.end() - 1)); 516*b1cdbd2cSJim Jagielski maCssContents.pop_back(); 517*b1cdbd2cSJim Jagielski } 518*b1cdbd2cSJim Jagielski else 519*b1cdbd2cSJim Jagielski { 520*b1cdbd2cSJim Jagielski OSL_ENSURE(false, "Closing CssStyle, but no collector string on stack (!)"); 521*b1cdbd2cSJim Jagielski } 522*b1cdbd2cSJim Jagielski } 523*b1cdbd2cSJim Jagielski 524*b1cdbd2cSJim Jagielski if(pWhitespaceCheck) 525*b1cdbd2cSJim Jagielski { 526*b1cdbd2cSJim Jagielski // cleanup read strings 527*b1cdbd2cSJim Jagielski whiteSpaceHandling(pWhitespaceCheck, 0); 528*b1cdbd2cSJim Jagielski } 529*b1cdbd2cSJim Jagielski } 530*b1cdbd2cSJim Jagielski } 531*b1cdbd2cSJim Jagielski characters(const::rtl::OUString & aChars)532*b1cdbd2cSJim Jagielski void SvgDocHdl::characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException) 533*b1cdbd2cSJim Jagielski { 534*b1cdbd2cSJim Jagielski const sal_uInt32 nLength(aChars.getLength()); 535*b1cdbd2cSJim Jagielski 536*b1cdbd2cSJim Jagielski if(mpTarget && nLength) 537*b1cdbd2cSJim Jagielski { 538*b1cdbd2cSJim Jagielski switch(mpTarget->getType()) 539*b1cdbd2cSJim Jagielski { 540*b1cdbd2cSJim Jagielski case SVGTokenText: 541*b1cdbd2cSJim Jagielski case SVGTokenTspan: 542*b1cdbd2cSJim Jagielski case SVGTokenTextPath: 543*b1cdbd2cSJim Jagielski { 544*b1cdbd2cSJim Jagielski const SvgNodeVector& rChilds = mpTarget->getChildren(); 545*b1cdbd2cSJim Jagielski SvgCharacterNode* pTarget = 0; 546*b1cdbd2cSJim Jagielski 547*b1cdbd2cSJim Jagielski if(rChilds.size()) 548*b1cdbd2cSJim Jagielski { 549*b1cdbd2cSJim Jagielski pTarget = dynamic_cast< SvgCharacterNode* >(rChilds[rChilds.size() - 1]); 550*b1cdbd2cSJim Jagielski } 551*b1cdbd2cSJim Jagielski 552*b1cdbd2cSJim Jagielski if(pTarget) 553*b1cdbd2cSJim Jagielski { 554*b1cdbd2cSJim Jagielski // concatenate to current character span 555*b1cdbd2cSJim Jagielski pTarget->concatenate(aChars); 556*b1cdbd2cSJim Jagielski } 557*b1cdbd2cSJim Jagielski else 558*b1cdbd2cSJim Jagielski { 559*b1cdbd2cSJim Jagielski // add character span as simplified tspan (no arguments) 560*b1cdbd2cSJim Jagielski // as direct child of SvgTextNode/SvgTspanNode/SvgTextPathNode 561*b1cdbd2cSJim Jagielski new SvgCharacterNode(maDocument, mpTarget, aChars); 562*b1cdbd2cSJim Jagielski } 563*b1cdbd2cSJim Jagielski break; 564*b1cdbd2cSJim Jagielski } 565*b1cdbd2cSJim Jagielski case SVGTokenStyle: 566*b1cdbd2cSJim Jagielski { 567*b1cdbd2cSJim Jagielski SvgStyleNode& rSvgStyleNode = static_cast< SvgStyleNode& >(*mpTarget); 568*b1cdbd2cSJim Jagielski 569*b1cdbd2cSJim Jagielski if(rSvgStyleNode.isTextCss()) 570*b1cdbd2cSJim Jagielski { 571*b1cdbd2cSJim Jagielski // collect characters for css style 572*b1cdbd2cSJim Jagielski if(maCssContents.size()) 573*b1cdbd2cSJim Jagielski { 574*b1cdbd2cSJim Jagielski const ::rtl::OUString aTrimmedChars(aChars.trim()); 575*b1cdbd2cSJim Jagielski 576*b1cdbd2cSJim Jagielski if(aTrimmedChars.getLength()) 577*b1cdbd2cSJim Jagielski { 578*b1cdbd2cSJim Jagielski std::vector< rtl::OUString >::iterator aString(maCssContents.end() - 1); 579*b1cdbd2cSJim Jagielski (*aString) += aTrimmedChars; 580*b1cdbd2cSJim Jagielski } 581*b1cdbd2cSJim Jagielski } 582*b1cdbd2cSJim Jagielski else 583*b1cdbd2cSJim Jagielski { 584*b1cdbd2cSJim Jagielski OSL_ENSURE(false, "Closing CssStyle, but no collector string on stack (!)"); 585*b1cdbd2cSJim Jagielski } 586*b1cdbd2cSJim Jagielski } 587*b1cdbd2cSJim Jagielski break; 588*b1cdbd2cSJim Jagielski } 589*b1cdbd2cSJim Jagielski case SVGTokenTitle: 590*b1cdbd2cSJim Jagielski case SVGTokenDesc: 591*b1cdbd2cSJim Jagielski { 592*b1cdbd2cSJim Jagielski SvgTitleDescNode& rSvgTitleDescNode = static_cast< SvgTitleDescNode& >(*mpTarget); 593*b1cdbd2cSJim Jagielski 594*b1cdbd2cSJim Jagielski // add text directly to SvgTitleDescNode 595*b1cdbd2cSJim Jagielski rSvgTitleDescNode.concatenate(aChars); 596*b1cdbd2cSJim Jagielski break; 597*b1cdbd2cSJim Jagielski } 598*b1cdbd2cSJim Jagielski default: 599*b1cdbd2cSJim Jagielski { 600*b1cdbd2cSJim Jagielski // characters not used by a known node 601*b1cdbd2cSJim Jagielski break; 602*b1cdbd2cSJim Jagielski } 603*b1cdbd2cSJim Jagielski } 604*b1cdbd2cSJim Jagielski } 605*b1cdbd2cSJim Jagielski } 606*b1cdbd2cSJim Jagielski ignorableWhitespace(const::rtl::OUString &)607*b1cdbd2cSJim Jagielski void SvgDocHdl::ignorableWhitespace(const ::rtl::OUString& /*aWhitespaces*/) throw (xml::sax::SAXException, uno::RuntimeException) 608*b1cdbd2cSJim Jagielski { 609*b1cdbd2cSJim Jagielski } 610*b1cdbd2cSJim Jagielski processingInstruction(const::rtl::OUString &,const::rtl::OUString &)611*b1cdbd2cSJim Jagielski void SvgDocHdl::processingInstruction(const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/) throw (xml::sax::SAXException, uno::RuntimeException) 612*b1cdbd2cSJim Jagielski { 613*b1cdbd2cSJim Jagielski } 614*b1cdbd2cSJim Jagielski setDocumentLocator(const uno::Reference<xml::sax::XLocator> &)615*b1cdbd2cSJim Jagielski void SvgDocHdl::setDocumentLocator(const uno::Reference< xml::sax::XLocator >& /*xLocator*/) throw (xml::sax::SAXException, uno::RuntimeException) 616*b1cdbd2cSJim Jagielski { 617*b1cdbd2cSJim Jagielski } 618*b1cdbd2cSJim Jagielski } // end of namespace svgreader 619*b1cdbd2cSJim Jagielski } // end of namespace svgio 620*b1cdbd2cSJim Jagielski 621*b1cdbd2cSJim Jagielski ////////////////////////////////////////////////////////////////////////////// 622*b1cdbd2cSJim Jagielski // eof 623