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 { 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 { 89*86d02030SArmin Le Grand bool bAddGap(true); 90*86d02030SArmin Le Grand static bool bNoGapsForBaselineShift(true); 91*86d02030SArmin Le Grand 92*86d02030SArmin Le Grand if(bNoGapsForBaselineShift) 93*86d02030SArmin Le Grand { 94*86d02030SArmin Le Grand // With this option a baseline shift between two char parts ('words') 95*86d02030SArmin Le Grand // will not add a space 'gap' to the end of the (non-last) word. This 96*86d02030SArmin Le Grand // seems to be the standard behaviour, see last bugdoc attached #122524# 97*86d02030SArmin Le Grand const svgio::svgreader::SvgStyleAttributes* pStyleLast = pLast->getSvgStyleAttributes(); 98*86d02030SArmin Le Grand const svgio::svgreader::SvgStyleAttributes* pStyleCurrent = pCandidate->getSvgStyleAttributes(); 99*86d02030SArmin Le Grand 100*86d02030SArmin Le Grand if(pStyleLast && pStyleCurrent && pStyleLast->getBaselineShift() != pStyleCurrent->getBaselineShift()) 101*86d02030SArmin Le Grand { 102*86d02030SArmin Le Grand bAddGap = false; 103*86d02030SArmin Le Grand } 104*86d02030SArmin Le Grand } 105*86d02030SArmin Le Grand 106ddde725dSArmin Le Grand // add in-between whitespace (single space) to last 107ddde725dSArmin Le Grand // known character node 108*86d02030SArmin Le Grand if(bAddGap) 109*86d02030SArmin Le Grand { 110*86d02030SArmin Le Grand pLast->addGap(); 111*86d02030SArmin 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 { 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 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 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 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 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; 333ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 3343aaca8a3SArmin Le Grand 3353aaca8a3SArmin Le Grand if(pNew->isTextCss()) 3363aaca8a3SArmin Le Grand { 3373aaca8a3SArmin Le Grand maCssContents.push_back(rtl::OUString()); 3383aaca8a3SArmin Le Grand } 339ddde725dSArmin Le Grand break; 340ddde725dSArmin Le Grand } 341ddde725dSArmin Le Grand 342ddde725dSArmin Le Grand /// structural elements clip-path and mask. Content gets scanned, but 343ddde725dSArmin Le Grand /// will not be decomposed (see SvgNode::decomposeSvgNode and bReferenced) 344ddde725dSArmin Le Grand case SVGTokenClipPathNode: 345ddde725dSArmin Le Grand { 346ddde725dSArmin Le Grand /// new node for ClipPath 347ddde725dSArmin Le Grand mpTarget = new SvgClipPathNode(maDocument, mpTarget); 348ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 349ddde725dSArmin Le Grand break; 350ddde725dSArmin Le Grand } 351ddde725dSArmin Le Grand case SVGTokenMask: 352ddde725dSArmin Le Grand { 353ddde725dSArmin Le Grand /// new node for Mask 354ddde725dSArmin Le Grand mpTarget = new SvgMaskNode(maDocument, mpTarget); 355ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 356ddde725dSArmin Le Grand break; 357ddde725dSArmin Le Grand } 358ddde725dSArmin Le Grand 359ddde725dSArmin Le Grand /// structural element marker 360ddde725dSArmin Le Grand case SVGTokenMarker: 361ddde725dSArmin Le Grand { 362ddde725dSArmin Le Grand /// new node for marker 363ddde725dSArmin Le Grand mpTarget = new SvgMarkerNode(maDocument, mpTarget); 364ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 365ddde725dSArmin Le Grand break; 366ddde725dSArmin Le Grand } 367ddde725dSArmin Le Grand 368ddde725dSArmin Le Grand /// structural element pattern 369ddde725dSArmin Le Grand case SVGTokenPattern: 370ddde725dSArmin Le Grand { 371ddde725dSArmin Le Grand /// new node for pattern 372ddde725dSArmin Le Grand mpTarget = new SvgPatternNode(maDocument, mpTarget); 373ddde725dSArmin Le Grand mpTarget->parseAttributes(xAttribs); 374ddde725dSArmin Le Grand break; 375ddde725dSArmin Le Grand } 376ddde725dSArmin Le Grand 377ddde725dSArmin Le Grand default: 378ddde725dSArmin Le Grand { 379ddde725dSArmin Le Grand /// invalid token, ignore 380ddde725dSArmin Le Grand #ifdef DBG_UTIL 381ddde725dSArmin Le Grand myAssert( 382ddde725dSArmin Le Grand rtl::OUString::createFromAscii("Unknown Base SvgToken <") + 383ddde725dSArmin Le Grand aName + 384ddde725dSArmin Le Grand rtl::OUString::createFromAscii("> (!)")); 385ddde725dSArmin Le Grand #endif 386ddde725dSArmin Le Grand break; 387ddde725dSArmin Le Grand } 388ddde725dSArmin Le Grand } 389ddde725dSArmin Le Grand } 390ddde725dSArmin Le Grand } 391ddde725dSArmin Le Grand 392ddde725dSArmin Le Grand void SvgDocHdl::endElement( const ::rtl::OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException) 393ddde725dSArmin Le Grand { 394ddde725dSArmin Le Grand if(aName.getLength()) 395ddde725dSArmin Le Grand { 396ddde725dSArmin Le Grand const SVGToken aSVGToken(StrToSVGToken(aName)); 397ddde725dSArmin Le Grand SvgNode* pWhitespaceCheck(SVGTokenText == aSVGToken ? mpTarget : 0); 3983aaca8a3SArmin Le Grand SvgStyleNode* pCssStyle(SVGTokenStyle == aSVGToken ? static_cast< SvgStyleNode* >(mpTarget) : 0); 399025b0597SArmin Le Grand SvgTitleDescNode* pSvgTitleDescNode(SVGTokenTitle == aSVGToken || SVGTokenDesc == aSVGToken ? static_cast< SvgTitleDescNode* >(mpTarget) : 0); 400ddde725dSArmin Le Grand 401ddde725dSArmin Le Grand switch(aSVGToken) 402ddde725dSArmin Le Grand { 403ddde725dSArmin Le Grand /// valid tokens for which a new one was created 404ddde725dSArmin Le Grand 405ddde725dSArmin Le Grand /// structural elements 406ddde725dSArmin Le Grand case SVGTokenDefs: 407ddde725dSArmin Le Grand case SVGTokenG: 408ddde725dSArmin Le Grand case SVGTokenSvg: 409ddde725dSArmin Le Grand case SVGTokenSymbol: 410ddde725dSArmin Le Grand case SVGTokenUse: 411ddde725dSArmin Le Grand 412ddde725dSArmin Le Grand /// shape elements 413ddde725dSArmin Le Grand case SVGTokenCircle: 414ddde725dSArmin Le Grand case SVGTokenEllipse: 415ddde725dSArmin Le Grand case SVGTokenLine: 416ddde725dSArmin Le Grand case SVGTokenPath: 417ddde725dSArmin Le Grand case SVGTokenPolygon: 418ddde725dSArmin Le Grand case SVGTokenPolyline: 419ddde725dSArmin Le Grand case SVGTokenRect: 420ddde725dSArmin Le Grand case SVGTokenImage: 421ddde725dSArmin Le Grand 422025b0597SArmin Le Grand /// title and description 423025b0597SArmin Le Grand case SVGTokenTitle: 424025b0597SArmin Le Grand case SVGTokenDesc: 425025b0597SArmin Le Grand 426ddde725dSArmin Le Grand /// gradients 427ddde725dSArmin Le Grand case SVGTokenLinearGradient: 428ddde725dSArmin Le Grand case SVGTokenRadialGradient: 429ddde725dSArmin Le Grand 430ddde725dSArmin Le Grand /// gradient stops 431ddde725dSArmin Le Grand case SVGTokenStop: 432ddde725dSArmin Le Grand 433ddde725dSArmin Le Grand /// text 434ddde725dSArmin Le Grand case SVGTokenText: 435ddde725dSArmin Le Grand case SVGTokenTspan: 436ddde725dSArmin Le Grand case SVGTokenTextPath: 437ddde725dSArmin Le Grand case SVGTokenTref: 438ddde725dSArmin Le Grand 439ddde725dSArmin Le Grand /// styles (as stylesheets) 440ddde725dSArmin Le Grand case SVGTokenStyle: 441ddde725dSArmin Le Grand 442ddde725dSArmin Le Grand /// structural elements clip-path and mask 443ddde725dSArmin Le Grand case SVGTokenClipPathNode: 444ddde725dSArmin Le Grand case SVGTokenMask: 445ddde725dSArmin Le Grand 446ddde725dSArmin Le Grand /// structural element marker 447ddde725dSArmin Le Grand case SVGTokenMarker: 448ddde725dSArmin Le Grand 449ddde725dSArmin Le Grand /// structural element pattern 450ddde725dSArmin Le Grand case SVGTokenPattern: 451ddde725dSArmin Le Grand 452ddde725dSArmin Le Grand /// content handling after parsing 453ddde725dSArmin Le Grand { 454ddde725dSArmin Le Grand if(mpTarget) 455ddde725dSArmin Le Grand { 456ddde725dSArmin Le Grand if(!mpTarget->getParent()) 457ddde725dSArmin Le Grand { 458ddde725dSArmin Le Grand // last element closing, save this tree 459ddde725dSArmin Le Grand maDocument.appendNode(mpTarget); 460ddde725dSArmin Le Grand } 461ddde725dSArmin Le Grand 462ddde725dSArmin Le Grand mpTarget = const_cast< SvgNode* >(mpTarget->getParent()); 463ddde725dSArmin Le Grand } 464ddde725dSArmin Le Grand else 465ddde725dSArmin Le Grand { 466ddde725dSArmin Le Grand OSL_ENSURE(false, "Closing token, but no context (!)"); 467ddde725dSArmin Le Grand } 468ddde725dSArmin Le Grand break; 469ddde725dSArmin Le Grand } 470ddde725dSArmin Le Grand default: 471ddde725dSArmin Le Grand { 472ddde725dSArmin Le Grand /// invalid token, ignore 473ddde725dSArmin Le Grand } 474ddde725dSArmin Le Grand } 475ddde725dSArmin Le Grand 476025b0597SArmin Le Grand if(pSvgTitleDescNode && mpTarget) 477025b0597SArmin Le Grand { 478025b0597SArmin Le Grand const rtl::OUString aText(pSvgTitleDescNode->getText()); 479025b0597SArmin Le Grand 480025b0597SArmin Le Grand if(aText.getLength()) 481025b0597SArmin Le Grand { 482025b0597SArmin Le Grand if(SVGTokenTitle == aSVGToken) 483025b0597SArmin Le Grand { 484025b0597SArmin Le Grand mpTarget->parseAttribute(getStrTitle(), aSVGToken, aText); 485025b0597SArmin Le Grand } 486025b0597SArmin Le Grand else // if(SVGTokenDesc == aSVGToken) 487025b0597SArmin Le Grand { 488025b0597SArmin Le Grand mpTarget->parseAttribute(getStrDesc(), aSVGToken, aText); 489025b0597SArmin Le Grand } 490025b0597SArmin Le Grand } 491025b0597SArmin Le Grand } 492025b0597SArmin Le Grand 4933aaca8a3SArmin Le Grand if(pCssStyle && pCssStyle->isTextCss()) 4943aaca8a3SArmin Le Grand { 4953aaca8a3SArmin Le Grand // css style parsing 4963aaca8a3SArmin Le Grand if(maCssContents.size()) 4973aaca8a3SArmin Le Grand { 4983aaca8a3SArmin Le Grand // need to interpret css styles and remember them as StyleSheets 4993aaca8a3SArmin Le Grand pCssStyle->addCssStyleSheet(*(maCssContents.end() - 1)); 5003aaca8a3SArmin Le Grand maCssContents.pop_back(); 5013aaca8a3SArmin Le Grand } 5023aaca8a3SArmin Le Grand else 5033aaca8a3SArmin Le Grand { 5043aaca8a3SArmin Le Grand OSL_ENSURE(false, "Closing CssStyle, but no collector string on stack (!)"); 5053aaca8a3SArmin Le Grand } 5063aaca8a3SArmin Le Grand } 5073aaca8a3SArmin Le Grand 508ddde725dSArmin Le Grand if(pWhitespaceCheck) 509ddde725dSArmin Le Grand { 510ddde725dSArmin Le Grand // cleanup read strings 511ddde725dSArmin Le Grand whiteSpaceHandling(pWhitespaceCheck, 0); 512ddde725dSArmin Le Grand } 513ddde725dSArmin Le Grand } 514ddde725dSArmin Le Grand } 515ddde725dSArmin Le Grand 516ddde725dSArmin Le Grand void SvgDocHdl::characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException) 517ddde725dSArmin Le Grand { 518025b0597SArmin Le Grand const sal_uInt32 nLength(aChars.getLength()); 519ddde725dSArmin Le Grand 520025b0597SArmin Le Grand if(mpTarget && nLength) 521025b0597SArmin Le Grand { 522025b0597SArmin Le Grand switch(mpTarget->getType()) 523ddde725dSArmin Le Grand { 524025b0597SArmin Le Grand case SVGTokenText: 525025b0597SArmin Le Grand case SVGTokenTspan: 526025b0597SArmin Le Grand case SVGTokenTextPath: 527ddde725dSArmin Le Grand { 528025b0597SArmin Le Grand const SvgNodeVector& rChilds = mpTarget->getChildren(); 529025b0597SArmin Le Grand SvgCharacterNode* pTarget = 0; 530ddde725dSArmin Le Grand 531025b0597SArmin Le Grand if(rChilds.size()) 532025b0597SArmin Le Grand { 533025b0597SArmin Le Grand pTarget = dynamic_cast< SvgCharacterNode* >(rChilds[rChilds.size() - 1]); 534025b0597SArmin Le Grand } 535ddde725dSArmin Le Grand 536025b0597SArmin Le Grand if(pTarget) 537025b0597SArmin Le Grand { 538025b0597SArmin Le Grand // concatenate to current character span 539025b0597SArmin Le Grand pTarget->concatenate(aChars); 540ddde725dSArmin Le Grand } 541025b0597SArmin Le Grand else 542ddde725dSArmin Le Grand { 543025b0597SArmin Le Grand // add character span as simplified tspan (no arguments) 544025b0597SArmin Le Grand // as direct child of SvgTextNode/SvgTspanNode/SvgTextPathNode 545025b0597SArmin Le Grand new SvgCharacterNode(maDocument, mpTarget, aChars); 546025b0597SArmin Le Grand } 547025b0597SArmin Le Grand break; 548025b0597SArmin Le Grand } 549025b0597SArmin Le Grand case SVGTokenStyle: 550025b0597SArmin Le Grand { 551025b0597SArmin Le Grand SvgStyleNode& rSvgStyleNode = static_cast< SvgStyleNode& >(*mpTarget); 552ddde725dSArmin Le Grand 553025b0597SArmin Le Grand if(rSvgStyleNode.isTextCss()) 554025b0597SArmin Le Grand { 555025b0597SArmin Le Grand // collect characters for css style 556025b0597SArmin Le Grand if(maCssContents.size()) 557ddde725dSArmin Le Grand { 558025b0597SArmin Le Grand const ::rtl::OUString aTrimmedChars(aChars.trim()); 559ddde725dSArmin Le Grand 560025b0597SArmin Le Grand if(aTrimmedChars.getLength()) 561ddde725dSArmin Le Grand { 562025b0597SArmin Le Grand std::vector< rtl::OUString >::iterator aString(maCssContents.end() - 1); 563025b0597SArmin Le Grand (*aString) += aTrimmedChars; 564ddde725dSArmin Le Grand } 565ddde725dSArmin Le Grand } 566025b0597SArmin Le Grand else 567025b0597SArmin Le Grand { 568025b0597SArmin Le Grand OSL_ENSURE(false, "Closing CssStyle, but no collector string on stack (!)"); 569025b0597SArmin Le Grand } 570ddde725dSArmin Le Grand } 571025b0597SArmin Le Grand break; 572025b0597SArmin Le Grand } 573025b0597SArmin Le Grand case SVGTokenTitle: 574025b0597SArmin Le Grand case SVGTokenDesc: 575025b0597SArmin Le Grand { 576025b0597SArmin Le Grand SvgTitleDescNode& rSvgTitleDescNode = static_cast< SvgTitleDescNode& >(*mpTarget); 577025b0597SArmin Le Grand 578025b0597SArmin Le Grand // add text directly to SvgTitleDescNode 579025b0597SArmin Le Grand rSvgTitleDescNode.concatenate(aChars); 580025b0597SArmin Le Grand break; 581025b0597SArmin Le Grand } 582025b0597SArmin Le Grand default: 583025b0597SArmin Le Grand { 584025b0597SArmin Le Grand // characters not used by a known node 585025b0597SArmin Le Grand break; 586ddde725dSArmin Le Grand } 587ddde725dSArmin Le Grand } 588ddde725dSArmin Le Grand } 589ddde725dSArmin Le Grand } 590ddde725dSArmin Le Grand 591e2bf1e9dSArmin Le Grand void SvgDocHdl::ignorableWhitespace(const ::rtl::OUString& /*aWhitespaces*/) throw (xml::sax::SAXException, uno::RuntimeException) 592ddde725dSArmin Le Grand { 593ddde725dSArmin Le Grand } 594ddde725dSArmin Le Grand 595e2bf1e9dSArmin Le Grand void SvgDocHdl::processingInstruction(const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/) throw (xml::sax::SAXException, uno::RuntimeException) 596ddde725dSArmin Le Grand { 597ddde725dSArmin Le Grand } 598ddde725dSArmin Le Grand 599e2bf1e9dSArmin Le Grand void SvgDocHdl::setDocumentLocator(const uno::Reference< xml::sax::XLocator >& /*xLocator*/) throw (xml::sax::SAXException, uno::RuntimeException) 600ddde725dSArmin Le Grand { 601ddde725dSArmin Le Grand } 602ddde725dSArmin Le Grand } // end of namespace svgreader 603ddde725dSArmin Le Grand } // end of namespace svgio 604ddde725dSArmin Le Grand 605ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 606ddde725dSArmin Le Grand // eof 607