1ddde725dSArmin Le Grand /************************************************************** 2ddde725dSArmin Le Grand * 3ddde725dSArmin Le Grand * Licensed to the Apache Software Foundation (ASF) under one 4ddde725dSArmin Le Grand * or more contributor license agreements. See the NOTICE file 5ddde725dSArmin Le Grand * distributed with this work for additional information 6ddde725dSArmin Le Grand * regarding copyright ownership. The ASF licenses this file 7ddde725dSArmin Le Grand * to you under the Apache License, Version 2.0 (the 8ddde725dSArmin Le Grand * "License"); you may not use this file except in compliance 9ddde725dSArmin Le Grand * with the License. You may obtain a copy of the License at 10ddde725dSArmin Le Grand * 11ddde725dSArmin Le Grand * http://www.apache.org/licenses/LICENSE-2.0 12ddde725dSArmin Le Grand * 13ddde725dSArmin Le Grand * Unless required by applicable law or agreed to in writing, 14ddde725dSArmin Le Grand * software distributed under the License is distributed on an 15ddde725dSArmin Le Grand * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16ddde725dSArmin Le Grand * KIND, either express or implied. See the License for the 17ddde725dSArmin Le Grand * specific language governing permissions and limitations 18ddde725dSArmin Le Grand * under the License. 19ddde725dSArmin Le Grand * 20ddde725dSArmin Le Grand *************************************************************/ 21ddde725dSArmin Le Grand 22ddde725dSArmin Le Grand // MARKER(update_precomp.py): autogen include statement, do not remove 23ddde725dSArmin Le Grand #include "precompiled_svgio.hxx" 24ddde725dSArmin Le Grand 25ddde725dSArmin Le Grand #include <svgio/svgreader/svgdocumenthandler.hxx> 26ddde725dSArmin Le Grand #include <svgio/svgreader/svgtoken.hxx> 27ddde725dSArmin Le Grand #include <svgio/svgreader/svgsvgnode.hxx> 28ddde725dSArmin Le Grand #include <svgio/svgreader/svggnode.hxx> 29ddde725dSArmin Le Grand #include <svgio/svgreader/svgnode.hxx> 30ddde725dSArmin Le Grand #include <svgio/svgreader/svgpathnode.hxx> 31ddde725dSArmin Le Grand #include <svgio/svgreader/svgrectnode.hxx> 32ddde725dSArmin Le Grand #include <svgio/svgreader/svggradientnode.hxx> 33ddde725dSArmin Le Grand #include <svgio/svgreader/svggradientstopnode.hxx> 34ddde725dSArmin Le Grand #include <svgio/svgreader/svgsymbolnode.hxx> 35ddde725dSArmin Le Grand #include <svgio/svgreader/svgusenode.hxx> 36ddde725dSArmin Le Grand #include <svgio/svgreader/svgcirclenode.hxx> 37ddde725dSArmin Le Grand #include <svgio/svgreader/svgellipsenode.hxx> 38ddde725dSArmin Le Grand #include <svgio/svgreader/svglinenode.hxx> 39ddde725dSArmin Le Grand #include <svgio/svgreader/svgpolynode.hxx> 40ddde725dSArmin Le Grand #include <svgio/svgreader/svgsymbolnode.hxx> 41ddde725dSArmin Le Grand #include <svgio/svgreader/svgtextnode.hxx> 42ddde725dSArmin Le Grand #include <svgio/svgreader/svgcharacternode.hxx> 43ddde725dSArmin Le Grand #include <svgio/svgreader/svgtspannode.hxx> 44ddde725dSArmin Le Grand #include <svgio/svgreader/svgtrefnode.hxx> 45ddde725dSArmin Le Grand #include <svgio/svgreader/svgtextpathnode.hxx> 46ddde725dSArmin Le Grand #include <svgio/svgreader/svgstylenode.hxx> 47ddde725dSArmin Le Grand #include <svgio/svgreader/svgimagenode.hxx> 48ddde725dSArmin Le Grand #include <svgio/svgreader/svgclippathnode.hxx> 49ddde725dSArmin Le Grand #include <svgio/svgreader/svgmasknode.hxx> 50ddde725dSArmin Le Grand #include <svgio/svgreader/svgmarkernode.hxx> 51ddde725dSArmin Le Grand #include <svgio/svgreader/svgpatternnode.hxx> 52025b0597SArmin Le Grand #include <svgio/svgreader/svgtitledescnode.hxx> 53ddde725dSArmin Le Grand 54ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 55ddde725dSArmin Le Grand 56ddde725dSArmin Le Grand using namespace com::sun::star; 57ddde725dSArmin Le Grand 58ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 59ddde725dSArmin Le Grand 60ddde725dSArmin Le Grand namespace 61ddde725dSArmin Le Grand { whiteSpaceHandling(svgio::svgreader::SvgNode * pNode,svgio::svgreader::SvgCharacterNode * pLast)62ddde725dSArmin Le Grand svgio::svgreader::SvgCharacterNode* whiteSpaceHandling(svgio::svgreader::SvgNode* pNode, svgio::svgreader::SvgCharacterNode* pLast) 63ddde725dSArmin Le Grand { 64ddde725dSArmin Le Grand if(pNode) 65ddde725dSArmin Le Grand { 66ddde725dSArmin Le Grand const svgio::svgreader::SvgNodeVector& rChilds = pNode->getChildren(); 67ddde725dSArmin Le Grand const sal_uInt32 nCount(rChilds.size()); 68ddde725dSArmin Le Grand 69ddde725dSArmin Le Grand for(sal_uInt32 a(0); a < nCount; a++) 70ddde725dSArmin Le Grand { 71ddde725dSArmin Le Grand svgio::svgreader::SvgNode* pCandidate = rChilds[a]; 72ddde725dSArmin Le Grand 73ddde725dSArmin Le Grand if(pCandidate) 74ddde725dSArmin Le Grand { 75ddde725dSArmin Le Grand switch(pCandidate->getType()) 76ddde725dSArmin Le Grand { 77ddde725dSArmin Le Grand case svgio::svgreader::SVGTokenCharacter: 78ddde725dSArmin Le Grand { 79ddde725dSArmin Le Grand // clean whitespace in text span 80ddde725dSArmin Le Grand svgio::svgreader::SvgCharacterNode* pCharNode = static_cast< svgio::svgreader::SvgCharacterNode* >(pCandidate); 81ddde725dSArmin Le Grand pCharNode->whiteSpaceHandling(); 82ddde725dSArmin Le Grand 83ddde725dSArmin Le Grand // pCharNode may have lost all text. If that's the case, ignore 84ddde725dSArmin Le Grand // as invalid character node 85ddde725dSArmin Le Grand if(pCharNode->getText().getLength()) 86ddde725dSArmin Le Grand { 87ddde725dSArmin Le Grand if(pLast) 88ddde725dSArmin Le Grand { 8986d02030SArmin Le Grand bool bAddGap(true); 9086d02030SArmin Le Grand static bool bNoGapsForBaselineShift(true); 9186d02030SArmin Le Grand 9286d02030SArmin Le Grand if(bNoGapsForBaselineShift) 9386d02030SArmin Le Grand { 9486d02030SArmin Le Grand // With this option a baseline shift between two char parts ('words') 9586d02030SArmin Le Grand // will not add a space 'gap' to the end of the (non-last) word. This 9686d02030SArmin Le Grand // seems to be the standard behaviour, see last bugdoc attached #122524# 9786d02030SArmin Le Grand const svgio::svgreader::SvgStyleAttributes* pStyleLast = pLast->getSvgStyleAttributes(); 9886d02030SArmin Le Grand const svgio::svgreader::SvgStyleAttributes* pStyleCurrent = pCandidate->getSvgStyleAttributes(); 9986d02030SArmin Le Grand 10086d02030SArmin Le Grand if(pStyleLast && pStyleCurrent && pStyleLast->getBaselineShift() != pStyleCurrent->getBaselineShift()) 10186d02030SArmin Le Grand { 10286d02030SArmin Le Grand bAddGap = false; 10386d02030SArmin Le Grand } 10486d02030SArmin Le Grand } 10586d02030SArmin Le Grand 106ddde725dSArmin Le Grand // add in-between whitespace (single space) to last 107ddde725dSArmin Le Grand // known character node 10886d02030SArmin Le Grand if(bAddGap) 10986d02030SArmin Le Grand { 11086d02030SArmin Le Grand pLast->addGap(); 11186d02030SArmin Le Grand } 112ddde725dSArmin Le Grand } 113ddde725dSArmin Le Grand 114ddde725dSArmin Le Grand // remember new last corected character node 115ddde725dSArmin Le Grand pLast = pCharNode; 116ddde725dSArmin Le Grand } 117ddde725dSArmin Le Grand break; 118ddde725dSArmin Le Grand } 119ddde725dSArmin Le Grand case svgio::svgreader::SVGTokenTspan: 120ddde725dSArmin Le Grand case svgio::svgreader::SVGTokenTextPath: 121ddde725dSArmin Le Grand case svgio::svgreader::SVGTokenTref: 122ddde725dSArmin Le Grand { 123ddde725dSArmin Le Grand // recursively clean whitespaces in subhierarchy 124ddde725dSArmin Le Grand pLast = whiteSpaceHandling(pCandidate, pLast); 125ddde725dSArmin Le Grand break; 126ddde725dSArmin Le Grand } 127ddde725dSArmin Le Grand default: 128ddde725dSArmin Le Grand { 129ddde725dSArmin Le Grand OSL_ENSURE(false, "Unexpected token inside SVGTokenText (!)"); 130ddde725dSArmin Le Grand break; 131ddde725dSArmin Le Grand } 132ddde725dSArmin Le Grand } 133ddde725dSArmin Le Grand } 134ddde725dSArmin Le Grand } 135ddde725dSArmin Le Grand } 136ddde725dSArmin Le Grand 137ddde725dSArmin Le Grand return pLast; 138ddde725dSArmin Le Grand } 139ddde725dSArmin Le Grand } 140ddde725dSArmin Le Grand 141ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 142ddde725dSArmin Le Grand 143ddde725dSArmin Le Grand namespace svgio 144ddde725dSArmin Le Grand { 145ddde725dSArmin Le Grand namespace svgreader 146ddde725dSArmin Le Grand { SvgDocHdl(const rtl::OUString & aAbsolutePath)147ddde725dSArmin Le Grand SvgDocHdl::SvgDocHdl(const rtl::OUString& aAbsolutePath) 148ddde725dSArmin Le Grand : maDocument(aAbsolutePath), 1493aaca8a3SArmin Le Grand mpTarget(0), 1503aaca8a3SArmin Le Grand maCssContents() 151ddde725dSArmin Le Grand { 152ddde725dSArmin Le Grand } 153ddde725dSArmin Le Grand ~SvgDocHdl()154ddde725dSArmin Le Grand SvgDocHdl::~SvgDocHdl() 155ddde725dSArmin Le Grand { 156ddde725dSArmin Le Grand #ifdef DBG_UTIL 157ddde725dSArmin Le Grand if(mpTarget) 158ddde725dSArmin Le Grand { 159ddde725dSArmin Le Grand OSL_ENSURE(false, "SvgDocHdl destructed with active target (!)"); 160ddde725dSArmin Le Grand delete mpTarget; 161ddde725dSArmin Le Grand } 1623aaca8a3SArmin Le Grand OSL_ENSURE(!maCssContents.size(), "SvgDocHdl destructed with active css style stack entry (!)"); 163ddde725dSArmin Le Grand #endif 164ddde725dSArmin Le Grand } 165ddde725dSArmin Le Grand startDocument()166ddde725dSArmin Le Grand void SvgDocHdl::startDocument( ) throw (xml::sax::SAXException, uno::RuntimeException) 167ddde725dSArmin Le Grand { 168ddde725dSArmin Le Grand OSL_ENSURE(!mpTarget, "Already a target at document start (!)"); 1693aaca8a3SArmin Le Grand OSL_ENSURE(!maCssContents.size(), "SvgDocHdl startDocument with active css style stack entry (!)"); 170ddde725dSArmin Le Grand } 171ddde725dSArmin Le Grand endDocument()172ddde725dSArmin Le Grand void SvgDocHdl::endDocument( ) throw (xml::sax::SAXException, uno::RuntimeException) 173ddde725dSArmin Le Grand { 174ddde725dSArmin Le Grand OSL_ENSURE(!mpTarget, "Still a target at document end (!)"); 1753aaca8a3SArmin Le Grand OSL_ENSURE(!maCssContents.size(), "SvgDocHdl endDocument with active css style stack entry (!)"); 176ddde725dSArmin Le Grand } 177ddde725dSArmin Le Grand startElement(const::rtl::OUString & aName,const uno::Reference<xml::sax::XAttributeList> & xAttribs)178ddde725dSArmin Le Grand void SvgDocHdl::startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) throw (xml::sax::SAXException, uno::RuntimeException) 179ddde725dSArmin Le Grand { 180ddde725dSArmin Le Grand if(aName.getLength()) 181ddde725dSArmin Le Grand { 182ddde725dSArmin Le Grand const SVGToken aSVGToken(StrToSVGToken(aName)); 183ddde725dSArmin Le Grand 184ddde725dSArmin Le Grand switch(aSVGToken) 185ddde725dSArmin Le Grand { 186ddde725dSArmin Le Grand /// structural elements 187ddde725dSArmin Le Grand case SVGTokenSymbol: 188ddde725dSArmin Le Grand { 189ddde725dSArmin Le Grand /// new basic node for Symbol. Content gets scanned, but 190ddde725dSArmin Le Grand /// will not be decomposed (see SvgNode::decomposeSvgNode and bReferenced) 191ddde725dSArmin Le Grand mpTarget = new SvgSymbolNode(maDocument, mpTarget); 192ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 193ddde725dSArmin Le Grand break; 194ddde725dSArmin Le Grand } 195ddde725dSArmin Le Grand case SVGTokenDefs: 196ddde725dSArmin Le Grand case SVGTokenG: 197ddde725dSArmin Le Grand { 198ddde725dSArmin Le Grand /// new node for Defs/G 199ddde725dSArmin Le Grand mpTarget = new SvgGNode(aSVGToken, maDocument, mpTarget); 200ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 201ddde725dSArmin Le Grand break; 202ddde725dSArmin Le Grand } 203ddde725dSArmin Le Grand case SVGTokenSvg: 204ddde725dSArmin Le Grand { 205ddde725dSArmin Le Grand /// new node for Svg 206ddde725dSArmin Le Grand mpTarget = new SvgSvgNode(maDocument, mpTarget); 207ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 208ddde725dSArmin Le Grand break; 209ddde725dSArmin Le Grand } 210ddde725dSArmin Le Grand case SVGTokenUse: 211ddde725dSArmin Le Grand { 212ddde725dSArmin Le Grand /// new node for Use 213ddde725dSArmin Le Grand mpTarget = new SvgUseNode(maDocument, mpTarget); 214ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 215ddde725dSArmin Le Grand break; 216ddde725dSArmin Le Grand } 217ddde725dSArmin Le Grand 218ddde725dSArmin Le Grand /// shape elements 219ddde725dSArmin Le Grand case SVGTokenCircle: 220ddde725dSArmin Le Grand { 221ddde725dSArmin Le Grand /// new node for Circle 222ddde725dSArmin Le Grand mpTarget = new SvgCircleNode(maDocument, mpTarget); 223ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 224ddde725dSArmin Le Grand break; 225ddde725dSArmin Le Grand } 226ddde725dSArmin Le Grand case SVGTokenEllipse: 227ddde725dSArmin Le Grand { 228ddde725dSArmin Le Grand /// new node for Ellipse 229ddde725dSArmin Le Grand mpTarget = new SvgEllipseNode(maDocument, mpTarget); 230ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 231ddde725dSArmin Le Grand break; 232ddde725dSArmin Le Grand } 233ddde725dSArmin Le Grand case SVGTokenLine: 234ddde725dSArmin Le Grand { 235ddde725dSArmin Le Grand /// new node for Line 236ddde725dSArmin Le Grand mpTarget = new SvgLineNode(maDocument, mpTarget); 237ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 238ddde725dSArmin Le Grand break; 239ddde725dSArmin Le Grand } 240ddde725dSArmin Le Grand case SVGTokenPath: 241ddde725dSArmin Le Grand { 242ddde725dSArmin Le Grand /// new node for Path 243ddde725dSArmin Le Grand mpTarget = new SvgPathNode(maDocument, mpTarget); 244ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 245ddde725dSArmin Le Grand break; 246ddde725dSArmin Le Grand } 247ddde725dSArmin Le Grand case SVGTokenPolygon: 248ddde725dSArmin Le Grand { 249ddde725dSArmin Le Grand /// new node for Polygon 250ddde725dSArmin Le Grand mpTarget = new SvgPolyNode(maDocument, mpTarget, false); 251ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 252ddde725dSArmin Le Grand break; 253ddde725dSArmin Le Grand } 254ddde725dSArmin Le Grand case SVGTokenPolyline: 255ddde725dSArmin Le Grand { 256ddde725dSArmin Le Grand /// new node for Polyline 257ddde725dSArmin Le Grand mpTarget = new SvgPolyNode(maDocument, mpTarget, true); 258ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 259ddde725dSArmin Le Grand break; 260ddde725dSArmin Le Grand } 261ddde725dSArmin Le Grand case SVGTokenRect: 262ddde725dSArmin Le Grand { 263ddde725dSArmin Le Grand /// new node for Rect 264ddde725dSArmin Le Grand mpTarget = new SvgRectNode(maDocument, mpTarget); 265ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 266ddde725dSArmin Le Grand break; 267ddde725dSArmin Le Grand } 268ddde725dSArmin Le Grand case SVGTokenImage: 269ddde725dSArmin Le Grand { 270ddde725dSArmin Le Grand /// new node for Image 271ddde725dSArmin Le Grand mpTarget = new SvgImageNode(maDocument, mpTarget); 272ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 273ddde725dSArmin Le Grand break; 274ddde725dSArmin Le Grand } 275ddde725dSArmin Le Grand 276025b0597SArmin Le Grand /// title and description 277025b0597SArmin Le Grand case SVGTokenTitle: 278025b0597SArmin Le Grand case SVGTokenDesc: 279025b0597SArmin Le Grand { 280025b0597SArmin Le Grand /// new node for Title and/or Desc 281025b0597SArmin Le Grand mpTarget = new SvgTitleDescNode(aSVGToken, maDocument, mpTarget); 282025b0597SArmin Le Grand break; 283025b0597SArmin Le Grand } 284025b0597SArmin Le Grand 285ddde725dSArmin Le Grand /// gradients 286ddde725dSArmin Le Grand case SVGTokenLinearGradient: 287ddde725dSArmin Le Grand case SVGTokenRadialGradient: 288ddde725dSArmin Le Grand { 289ddde725dSArmin Le Grand mpTarget = new SvgGradientNode(aSVGToken, maDocument, mpTarget); 290ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 291ddde725dSArmin Le Grand break; 292ddde725dSArmin Le Grand } 293ddde725dSArmin Le Grand 294ddde725dSArmin Le Grand /// gradient stops 295ddde725dSArmin Le Grand case SVGTokenStop: 296ddde725dSArmin Le Grand { 297ddde725dSArmin Le Grand mpTarget = new SvgGradientStopNode(maDocument, mpTarget); 298ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 299ddde725dSArmin Le Grand break; 300ddde725dSArmin Le Grand } 301ddde725dSArmin Le Grand 302ddde725dSArmin Le Grand /// text 303ddde725dSArmin Le Grand case SVGTokenText: 304ddde725dSArmin Le Grand { 305ddde725dSArmin Le Grand mpTarget = new SvgTextNode(maDocument, mpTarget); 306ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 307ddde725dSArmin Le Grand break; 308ddde725dSArmin Le Grand } 309ddde725dSArmin Le Grand case SVGTokenTspan: 310ddde725dSArmin Le Grand { 311ddde725dSArmin Le Grand mpTarget = new SvgTspanNode(maDocument, mpTarget); 312ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 313ddde725dSArmin Le Grand break; 314ddde725dSArmin Le Grand } 315ddde725dSArmin Le Grand case SVGTokenTref: 316ddde725dSArmin Le Grand { 317ddde725dSArmin Le Grand mpTarget = new SvgTrefNode(maDocument, mpTarget); 318ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 319ddde725dSArmin Le Grand break; 320ddde725dSArmin Le Grand } 321ddde725dSArmin Le Grand case SVGTokenTextPath: 322ddde725dSArmin Le Grand { 323ddde725dSArmin Le Grand mpTarget = new SvgTextPathNode(maDocument, mpTarget); 324ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 325ddde725dSArmin Le Grand break; 326ddde725dSArmin Le Grand } 327ddde725dSArmin Le Grand 328ddde725dSArmin Le Grand /// styles (as stylesheets) 329ddde725dSArmin Le Grand case SVGTokenStyle: 330ddde725dSArmin Le Grand { 3313aaca8a3SArmin Le Grand SvgStyleNode* pNew = new SvgStyleNode(maDocument, mpTarget); 3323aaca8a3SArmin Le Grand mpTarget = pNew; 333*6549c64fSAndrea Pescetti const sal_uInt32 nAttributes(xAttribs->getLength()); 334*6549c64fSAndrea Pescetti 335*6549c64fSAndrea Pescetti if(0 == nAttributes) 336*6549c64fSAndrea Pescetti { 337*6549c64fSAndrea Pescetti // #125326# no attributes, thus also no type="text/css". This is allowed to be missing, 338*6549c64fSAndrea Pescetti // thus do mark this style as CssStyle. This is required to read the contained 339*6549c64fSAndrea Pescetti // text (which defines the css style) 340*6549c64fSAndrea Pescetti pNew->setTextCss(true); 341*6549c64fSAndrea Pescetti } 342*6549c64fSAndrea Pescetti else 343*6549c64fSAndrea Pescetti { 344*6549c64fSAndrea Pescetti // #125326# there are attributes, read them. This will set isTextCss to true if 345*6549c64fSAndrea Pescetti // a type="text/css" is contained as exact match, else not 346*6549c64fSAndrea Pescetti mpTarget->parseAttributes(xAttribs); 347*6549c64fSAndrea Pescetti } 3483aaca8a3SArmin Le Grand 3493aaca8a3SArmin Le Grand if(pNew->isTextCss()) 3503aaca8a3SArmin Le Grand { 351*6549c64fSAndrea Pescetti // if it is a Css style, allow reading text between the start and end tag (see 352*6549c64fSAndrea Pescetti // SvgDocHdl::characters for details) 3533aaca8a3SArmin Le Grand maCssContents.push_back(rtl::OUString()); 3543aaca8a3SArmin Le Grand } 355ddde725dSArmin Le Grand break; 356ddde725dSArmin Le Grand } 357ddde725dSArmin Le Grand 358ddde725dSArmin Le Grand /// structural elements clip-path and mask. Content gets scanned, but 359ddde725dSArmin Le Grand /// will not be decomposed (see SvgNode::decomposeSvgNode and bReferenced) 360ddde725dSArmin Le Grand case SVGTokenClipPathNode: 361ddde725dSArmin Le Grand { 362ddde725dSArmin Le Grand /// new node for ClipPath 363ddde725dSArmin Le Grand mpTarget = new SvgClipPathNode(maDocument, mpTarget); 364ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 365ddde725dSArmin Le Grand break; 366ddde725dSArmin Le Grand } 367ddde725dSArmin Le Grand case SVGTokenMask: 368ddde725dSArmin Le Grand { 369ddde725dSArmin Le Grand /// new node for Mask 370ddde725dSArmin Le Grand mpTarget = new SvgMaskNode(maDocument, mpTarget); 371ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 372ddde725dSArmin Le Grand break; 373ddde725dSArmin Le Grand } 374ddde725dSArmin Le Grand 375ddde725dSArmin Le Grand /// structural element marker 376ddde725dSArmin Le Grand case SVGTokenMarker: 377ddde725dSArmin Le Grand { 378ddde725dSArmin Le Grand /// new node for marker 379ddde725dSArmin Le Grand mpTarget = new SvgMarkerNode(maDocument, mpTarget); 380ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 381ddde725dSArmin Le Grand break; 382ddde725dSArmin Le Grand } 383ddde725dSArmin Le Grand 384ddde725dSArmin Le Grand /// structural element pattern 385ddde725dSArmin Le Grand case SVGTokenPattern: 386ddde725dSArmin Le Grand { 387ddde725dSArmin Le Grand /// new node for pattern 388ddde725dSArmin Le Grand mpTarget = new SvgPatternNode(maDocument, mpTarget); 389ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 390ddde725dSArmin Le Grand break; 391ddde725dSArmin Le Grand } 392ddde725dSArmin Le Grand 393ddde725dSArmin Le Grand default: 394ddde725dSArmin Le Grand { 395ddde725dSArmin Le Grand /// invalid token, ignore 396ddde725dSArmin Le Grand #ifdef DBG_UTIL 397ddde725dSArmin Le Grand myAssert( 398ddde725dSArmin Le Grand rtl::OUString::createFromAscii("Unknown Base SvgToken <") + 399ddde725dSArmin Le Grand aName + 400ddde725dSArmin Le Grand rtl::OUString::createFromAscii("> (!)")); 401ddde725dSArmin Le Grand #endif 402ddde725dSArmin Le Grand break; 403ddde725dSArmin Le Grand } 404ddde725dSArmin Le Grand } 405ddde725dSArmin Le Grand } 406ddde725dSArmin Le Grand } 407ddde725dSArmin Le Grand endElement(const::rtl::OUString & aName)408ddde725dSArmin Le Grand void SvgDocHdl::endElement( const ::rtl::OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException) 409ddde725dSArmin Le Grand { 410ddde725dSArmin Le Grand if(aName.getLength()) 411ddde725dSArmin Le Grand { 412ddde725dSArmin Le Grand const SVGToken aSVGToken(StrToSVGToken(aName)); 413ddde725dSArmin Le Grand SvgNode* pWhitespaceCheck(SVGTokenText == aSVGToken ? mpTarget : 0); 4143aaca8a3SArmin Le Grand SvgStyleNode* pCssStyle(SVGTokenStyle == aSVGToken ? static_cast< SvgStyleNode* >(mpTarget) : 0); 415025b0597SArmin Le Grand SvgTitleDescNode* pSvgTitleDescNode(SVGTokenTitle == aSVGToken || SVGTokenDesc == aSVGToken ? static_cast< SvgTitleDescNode* >(mpTarget) : 0); 416ddde725dSArmin Le Grand 417ddde725dSArmin Le Grand switch(aSVGToken) 418ddde725dSArmin Le Grand { 419ddde725dSArmin Le Grand /// valid tokens for which a new one was created 420ddde725dSArmin Le Grand 421ddde725dSArmin Le Grand /// structural elements 422ddde725dSArmin Le Grand case SVGTokenDefs: 423ddde725dSArmin Le Grand case SVGTokenG: 424ddde725dSArmin Le Grand case SVGTokenSvg: 425ddde725dSArmin Le Grand case SVGTokenSymbol: 426ddde725dSArmin Le Grand case SVGTokenUse: 427ddde725dSArmin Le Grand 428ddde725dSArmin Le Grand /// shape elements 429ddde725dSArmin Le Grand case SVGTokenCircle: 430ddde725dSArmin Le Grand case SVGTokenEllipse: 431ddde725dSArmin Le Grand case SVGTokenLine: 432ddde725dSArmin Le Grand case SVGTokenPath: 433ddde725dSArmin Le Grand case SVGTokenPolygon: 434ddde725dSArmin Le Grand case SVGTokenPolyline: 435ddde725dSArmin Le Grand case SVGTokenRect: 436ddde725dSArmin Le Grand case SVGTokenImage: 437ddde725dSArmin Le Grand 438025b0597SArmin Le Grand /// title and description 439025b0597SArmin Le Grand case SVGTokenTitle: 440025b0597SArmin Le Grand case SVGTokenDesc: 441025b0597SArmin Le Grand 442ddde725dSArmin Le Grand /// gradients 443ddde725dSArmin Le Grand case SVGTokenLinearGradient: 444ddde725dSArmin Le Grand case SVGTokenRadialGradient: 445ddde725dSArmin Le Grand 446ddde725dSArmin Le Grand /// gradient stops 447ddde725dSArmin Le Grand case SVGTokenStop: 448ddde725dSArmin Le Grand 449ddde725dSArmin Le Grand /// text 450ddde725dSArmin Le Grand case SVGTokenText: 451ddde725dSArmin Le Grand case SVGTokenTspan: 452ddde725dSArmin Le Grand case SVGTokenTextPath: 453ddde725dSArmin Le Grand case SVGTokenTref: 454ddde725dSArmin Le Grand 455ddde725dSArmin Le Grand /// styles (as stylesheets) 456ddde725dSArmin Le Grand case SVGTokenStyle: 457ddde725dSArmin Le Grand 458ddde725dSArmin Le Grand /// structural elements clip-path and mask 459ddde725dSArmin Le Grand case SVGTokenClipPathNode: 460ddde725dSArmin Le Grand case SVGTokenMask: 461ddde725dSArmin Le Grand 462ddde725dSArmin Le Grand /// structural element marker 463ddde725dSArmin Le Grand case SVGTokenMarker: 464ddde725dSArmin Le Grand 465ddde725dSArmin Le Grand /// structural element pattern 466ddde725dSArmin Le Grand case SVGTokenPattern: 467ddde725dSArmin Le Grand 468ddde725dSArmin Le Grand /// content handling after parsing 469ddde725dSArmin Le Grand { 470ddde725dSArmin Le Grand if(mpTarget) 471ddde725dSArmin Le Grand { 472ddde725dSArmin Le Grand if(!mpTarget->getParent()) 473ddde725dSArmin Le Grand { 474ddde725dSArmin Le Grand // last element closing, save this tree 475ddde725dSArmin Le Grand maDocument.appendNode(mpTarget); 476ddde725dSArmin Le Grand } 477ddde725dSArmin Le Grand 478ddde725dSArmin Le Grand mpTarget = const_cast< SvgNode* >(mpTarget->getParent()); 479ddde725dSArmin Le Grand } 480ddde725dSArmin Le Grand else 481ddde725dSArmin Le Grand { 482ddde725dSArmin Le Grand OSL_ENSURE(false, "Closing token, but no context (!)"); 483ddde725dSArmin Le Grand } 484ddde725dSArmin Le Grand break; 485ddde725dSArmin Le Grand } 486ddde725dSArmin Le Grand default: 487ddde725dSArmin Le Grand { 488ddde725dSArmin Le Grand /// invalid token, ignore 489ddde725dSArmin Le Grand } 490ddde725dSArmin Le Grand } 491ddde725dSArmin Le Grand 492025b0597SArmin Le Grand if(pSvgTitleDescNode && mpTarget) 493025b0597SArmin Le Grand { 494025b0597SArmin Le Grand const rtl::OUString aText(pSvgTitleDescNode->getText()); 495025b0597SArmin Le Grand 496025b0597SArmin Le Grand if(aText.getLength()) 497025b0597SArmin Le Grand { 498025b0597SArmin Le Grand if(SVGTokenTitle == aSVGToken) 499025b0597SArmin Le Grand { 500025b0597SArmin Le Grand mpTarget->parseAttribute(getStrTitle(), aSVGToken, aText); 501025b0597SArmin Le Grand } 502025b0597SArmin Le Grand else // if(SVGTokenDesc == aSVGToken) 503025b0597SArmin Le Grand { 504025b0597SArmin Le Grand mpTarget->parseAttribute(getStrDesc(), aSVGToken, aText); 505025b0597SArmin Le Grand } 506025b0597SArmin Le Grand } 507025b0597SArmin Le Grand } 508025b0597SArmin Le Grand 5093aaca8a3SArmin Le Grand if(pCssStyle && pCssStyle->isTextCss()) 5103aaca8a3SArmin Le Grand { 5113aaca8a3SArmin Le Grand // css style parsing 5123aaca8a3SArmin Le Grand if(maCssContents.size()) 5133aaca8a3SArmin Le Grand { 5143aaca8a3SArmin Le Grand // need to interpret css styles and remember them as StyleSheets 5153aaca8a3SArmin Le Grand pCssStyle->addCssStyleSheet(*(maCssContents.end() - 1)); 5163aaca8a3SArmin Le Grand maCssContents.pop_back(); 5173aaca8a3SArmin Le Grand } 5183aaca8a3SArmin Le Grand else 5193aaca8a3SArmin Le Grand { 5203aaca8a3SArmin Le Grand OSL_ENSURE(false, "Closing CssStyle, but no collector string on stack (!)"); 5213aaca8a3SArmin Le Grand } 5223aaca8a3SArmin Le Grand } 5233aaca8a3SArmin Le Grand 524ddde725dSArmin Le Grand if(pWhitespaceCheck) 525ddde725dSArmin Le Grand { 526ddde725dSArmin Le Grand // cleanup read strings 527ddde725dSArmin Le Grand whiteSpaceHandling(pWhitespaceCheck, 0); 528ddde725dSArmin Le Grand } 529ddde725dSArmin Le Grand } 530ddde725dSArmin Le Grand } 531ddde725dSArmin Le Grand characters(const::rtl::OUString & aChars)532ddde725dSArmin Le Grand void SvgDocHdl::characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException) 533ddde725dSArmin Le Grand { 534025b0597SArmin Le Grand const sal_uInt32 nLength(aChars.getLength()); 535ddde725dSArmin Le Grand 536025b0597SArmin Le Grand if(mpTarget && nLength) 537025b0597SArmin Le Grand { 538025b0597SArmin Le Grand switch(mpTarget->getType()) 539ddde725dSArmin Le Grand { 540025b0597SArmin Le Grand case SVGTokenText: 541025b0597SArmin Le Grand case SVGTokenTspan: 542025b0597SArmin Le Grand case SVGTokenTextPath: 543ddde725dSArmin Le Grand { 544025b0597SArmin Le Grand const SvgNodeVector& rChilds = mpTarget->getChildren(); 545025b0597SArmin Le Grand SvgCharacterNode* pTarget = 0; 546ddde725dSArmin Le Grand 547025b0597SArmin Le Grand if(rChilds.size()) 548025b0597SArmin Le Grand { 549025b0597SArmin Le Grand pTarget = dynamic_cast< SvgCharacterNode* >(rChilds[rChilds.size() - 1]); 550025b0597SArmin Le Grand } 551ddde725dSArmin Le Grand 552025b0597SArmin Le Grand if(pTarget) 553025b0597SArmin Le Grand { 554025b0597SArmin Le Grand // concatenate to current character span 555025b0597SArmin Le Grand pTarget->concatenate(aChars); 556ddde725dSArmin Le Grand } 557025b0597SArmin Le Grand else 558ddde725dSArmin Le Grand { 559025b0597SArmin Le Grand // add character span as simplified tspan (no arguments) 560025b0597SArmin Le Grand // as direct child of SvgTextNode/SvgTspanNode/SvgTextPathNode 561025b0597SArmin Le Grand new SvgCharacterNode(maDocument, mpTarget, aChars); 562025b0597SArmin Le Grand } 563025b0597SArmin Le Grand break; 564025b0597SArmin Le Grand } 565025b0597SArmin Le Grand case SVGTokenStyle: 566025b0597SArmin Le Grand { 567025b0597SArmin Le Grand SvgStyleNode& rSvgStyleNode = static_cast< SvgStyleNode& >(*mpTarget); 568ddde725dSArmin Le Grand 569025b0597SArmin Le Grand if(rSvgStyleNode.isTextCss()) 570025b0597SArmin Le Grand { 571025b0597SArmin Le Grand // collect characters for css style 572025b0597SArmin Le Grand if(maCssContents.size()) 573ddde725dSArmin Le Grand { 574025b0597SArmin Le Grand const ::rtl::OUString aTrimmedChars(aChars.trim()); 575ddde725dSArmin Le Grand 576025b0597SArmin Le Grand if(aTrimmedChars.getLength()) 577ddde725dSArmin Le Grand { 578025b0597SArmin Le Grand std::vector< rtl::OUString >::iterator aString(maCssContents.end() - 1); 579025b0597SArmin Le Grand (*aString) += aTrimmedChars; 580ddde725dSArmin Le Grand } 581ddde725dSArmin Le Grand } 582025b0597SArmin Le Grand else 583025b0597SArmin Le Grand { 584025b0597SArmin Le Grand OSL_ENSURE(false, "Closing CssStyle, but no collector string on stack (!)"); 585025b0597SArmin Le Grand } 586ddde725dSArmin Le Grand } 587025b0597SArmin Le Grand break; 588025b0597SArmin Le Grand } 589025b0597SArmin Le Grand case SVGTokenTitle: 590025b0597SArmin Le Grand case SVGTokenDesc: 591025b0597SArmin Le Grand { 592025b0597SArmin Le Grand SvgTitleDescNode& rSvgTitleDescNode = static_cast< SvgTitleDescNode& >(*mpTarget); 593025b0597SArmin Le Grand 594025b0597SArmin Le Grand // add text directly to SvgTitleDescNode 595025b0597SArmin Le Grand rSvgTitleDescNode.concatenate(aChars); 596025b0597SArmin Le Grand break; 597025b0597SArmin Le Grand } 598025b0597SArmin Le Grand default: 599025b0597SArmin Le Grand { 600025b0597SArmin Le Grand // characters not used by a known node 601025b0597SArmin Le Grand break; 602ddde725dSArmin Le Grand } 603ddde725dSArmin Le Grand } 604ddde725dSArmin Le Grand } 605ddde725dSArmin Le Grand } 606ddde725dSArmin Le Grand ignorableWhitespace(const::rtl::OUString &)607e2bf1e9dSArmin Le Grand void SvgDocHdl::ignorableWhitespace(const ::rtl::OUString& /*aWhitespaces*/) throw (xml::sax::SAXException, uno::RuntimeException) 608ddde725dSArmin Le Grand { 609ddde725dSArmin Le Grand } 610ddde725dSArmin Le Grand processingInstruction(const::rtl::OUString &,const::rtl::OUString &)611e2bf1e9dSArmin Le Grand void SvgDocHdl::processingInstruction(const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/) throw (xml::sax::SAXException, uno::RuntimeException) 612ddde725dSArmin Le Grand { 613ddde725dSArmin Le Grand } 614ddde725dSArmin Le Grand setDocumentLocator(const uno::Reference<xml::sax::XLocator> &)615e2bf1e9dSArmin Le Grand void SvgDocHdl::setDocumentLocator(const uno::Reference< xml::sax::XLocator >& /*xLocator*/) throw (xml::sax::SAXException, uno::RuntimeException) 616ddde725dSArmin Le Grand { 617ddde725dSArmin Le Grand } 618ddde725dSArmin Le Grand } // end of namespace svgreader 619ddde725dSArmin Le Grand } // end of namespace svgio 620ddde725dSArmin Le Grand 621ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 622ddde725dSArmin Le Grand // eof 623