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/svgnode.hxx> 26ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolypolygontools.hxx> 27ddde725dSArmin Le Grand #include <svgio/svgreader/svgdocument.hxx> 28ddde725dSArmin Le Grand #include <svgio/svgreader/svgnode.hxx> 29ddde725dSArmin Le Grand #include <svgio/svgreader/svgstyleattributes.hxx> 30025b0597SArmin Le Grand #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx> 31172c67b2SArmin Le Grand #include <tools/urlobj.hxx> 32ddde725dSArmin Le Grand 33ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 34ddde725dSArmin Le Grand 35ddde725dSArmin Le Grand namespace svgio 36ddde725dSArmin Le Grand { 37ddde725dSArmin Le Grand namespace svgreader 38ddde725dSArmin Le Grand { 394374d266SArmin Le Grand /// #125258# 404374d266SArmin Le Grand bool SvgNode::supportsParentStyle() const 414374d266SArmin Le Grand { 424374d266SArmin Le Grand return true; 434374d266SArmin Le Grand } 444374d266SArmin Le Grand 45ddde725dSArmin Le Grand const SvgStyleAttributes* SvgNode::getSvgStyleAttributes() const 46ddde725dSArmin Le Grand { 47ddde725dSArmin Le Grand return 0; 48ddde725dSArmin Le Grand } 49ddde725dSArmin Le Grand 50eb82bfcdSArmin Le Grand void SvgNode::fillCssStyleVectorUsingHierarchyAndSelectors( 51eb82bfcdSArmin Le Grand const rtl::OUString& rClassStr, 52eb82bfcdSArmin Le Grand const SvgNode& rCurrent, 53eb82bfcdSArmin Le Grand rtl::OUString aConcatenated) 5450b37974SArmin Le Grand { 559d01bcdeSArmin Le Grand const SvgDocument& rDocument = getDocument(); 569d01bcdeSArmin Le Grand 57eb82bfcdSArmin Le Grand if(rDocument.hasGlobalCssStyleAttributes()) 589d01bcdeSArmin Le Grand { 59eb82bfcdSArmin Le Grand const SvgNode* pParent = rCurrent.getParent(); 60eb82bfcdSArmin Le Grand 61eb82bfcdSArmin Le Grand // check for ID (highest priority) 62eb82bfcdSArmin Le Grand if(rCurrent.getId()) 6350b37974SArmin Le Grand { 64eb82bfcdSArmin Le Grand const rtl::OUString& rId = *rCurrent.getId(); 65eb82bfcdSArmin Le Grand 66eb82bfcdSArmin Le Grand if(rId.getLength()) 67eb82bfcdSArmin Le Grand { 68eb82bfcdSArmin Le Grand const rtl::OUString aNewConcatenated( 69eb82bfcdSArmin Le Grand rtl::OUString::createFromAscii("#") + 70eb82bfcdSArmin Le Grand rId + 71eb82bfcdSArmin Le Grand aConcatenated); 72eb82bfcdSArmin Le Grand 73eb82bfcdSArmin Le Grand if(pParent) 74eb82bfcdSArmin Le Grand { 75eb82bfcdSArmin Le Grand // check for combined selectors at parent firstso that higher specificity will be in front 76eb82bfcdSArmin Le Grand fillCssStyleVectorUsingHierarchyAndSelectors(rClassStr, *pParent, aNewConcatenated); 77eb82bfcdSArmin Le Grand } 78eb82bfcdSArmin Le Grand 79eb82bfcdSArmin Le Grand const SvgStyleAttributes* pNew = rDocument.findGlobalCssStyleAttributes(aNewConcatenated); 809d01bcdeSArmin Le Grand 81eb82bfcdSArmin Le Grand if(pNew) 829d01bcdeSArmin Le Grand { 83eb82bfcdSArmin Le Grand // add CssStyle if found 84eb82bfcdSArmin Le Grand maCssStyleVector.push_back(pNew); 859d01bcdeSArmin Le Grand } 869d01bcdeSArmin Le Grand } 879d01bcdeSArmin Le Grand } 889d01bcdeSArmin Le Grand 89eb82bfcdSArmin Le Grand // check for 'class' references (a list of entries is allowed) 90eb82bfcdSArmin Le Grand if(rCurrent.getClass()) 919d01bcdeSArmin Le Grand { 92eb82bfcdSArmin Le Grand const rtl::OUString& rClassList = *rCurrent.getClass(); 93eb82bfcdSArmin Le Grand const sal_Int32 nLen(rClassList.getLength()); 949d01bcdeSArmin Le Grand 95eb82bfcdSArmin Le Grand if(nLen) 960906e779SArmin Le Grand { 97eb82bfcdSArmin Le Grand std::vector< rtl::OUString > aParts; 98eb82bfcdSArmin Le Grand sal_Int32 nPos(0); 99eb82bfcdSArmin Le Grand rtl::OUStringBuffer aToken; 1009d56236fSArmin Le Grand 101eb82bfcdSArmin Le Grand while(nPos < nLen) 1029d01bcdeSArmin Le Grand { 103eb82bfcdSArmin Le Grand const sal_Int32 nInitPos(nPos); 104eb82bfcdSArmin Le Grand copyToLimiter(rClassList, sal_Unicode(' '), nPos, aToken, nLen); 105eb82bfcdSArmin Le Grand skip_char(rClassList, sal_Unicode(' '), nPos, nLen); 106eb82bfcdSArmin Le Grand const rtl::OUString aPart(aToken.makeStringAndClear().trim()); 107eb82bfcdSArmin Le Grand 108eb82bfcdSArmin Le Grand if(aPart.getLength()) 109eb82bfcdSArmin Le Grand { 110eb82bfcdSArmin Le Grand aParts.push_back(aPart); 111eb82bfcdSArmin Le Grand } 112eb82bfcdSArmin Le Grand 113eb82bfcdSArmin Le Grand if(nInitPos == nPos) 114eb82bfcdSArmin Le Grand { 115eb82bfcdSArmin Le Grand OSL_ENSURE(false, "Could not interpret on current position (!)"); 116eb82bfcdSArmin Le Grand nPos++; 117eb82bfcdSArmin Le Grand } 1180906e779SArmin Le Grand } 1199d56236fSArmin Le Grand 120eb82bfcdSArmin Le Grand for(sal_uInt32 a(0); a < aParts.size(); a++) 1210906e779SArmin Le Grand { 122eb82bfcdSArmin Le Grand const rtl::OUString aNewConcatenated( 123eb82bfcdSArmin Le Grand rtl::OUString::createFromAscii(".") + 124eb82bfcdSArmin Le Grand aParts[a] + 125eb82bfcdSArmin Le Grand aConcatenated); 126eb82bfcdSArmin Le Grand 127eb82bfcdSArmin Le Grand if(pParent) 128eb82bfcdSArmin Le Grand { 129eb82bfcdSArmin Le Grand // check for combined selectors at parent firstso that higher specificity will be in front 130eb82bfcdSArmin Le Grand fillCssStyleVectorUsingHierarchyAndSelectors(rClassStr, *pParent, aNewConcatenated); 131eb82bfcdSArmin Le Grand } 132eb82bfcdSArmin Le Grand 133eb82bfcdSArmin Le Grand const SvgStyleAttributes* pNew = rDocument.findGlobalCssStyleAttributes(aNewConcatenated); 134eb82bfcdSArmin Le Grand 135eb82bfcdSArmin Le Grand if(pNew) 136eb82bfcdSArmin Le Grand { 137eb82bfcdSArmin Le Grand // add CssStyle if found 138eb82bfcdSArmin Le Grand maCssStyleVector.push_back(pNew); 139eb82bfcdSArmin Le Grand } 1400906e779SArmin Le Grand } 14150b37974SArmin Le Grand } 14250b37974SArmin Le Grand } 1439d01bcdeSArmin Le Grand 1449d01bcdeSArmin Le Grand // check for class-dependent references to CssStyles 1459d01bcdeSArmin Le Grand if(rClassStr.getLength()) 1469d01bcdeSArmin Le Grand { 147eb82bfcdSArmin Le Grand rtl::OUString aNewConcatenated(aConcatenated); 1489d01bcdeSArmin Le Grand 149eb82bfcdSArmin Le Grand if(!rCurrent.getId() && !rCurrent.getClass() && 0 == aConcatenated.indexOf(rClassStr)) 1509d01bcdeSArmin Le Grand { 151eb82bfcdSArmin Le Grand // no new CssStyle Selector and already starts with rClassStr, do not concatenate; 152eb82bfcdSArmin Le Grand // we pass an 'empty' node (in the sense of CssStyle Selector) 153eb82bfcdSArmin Le Grand } 154eb82bfcdSArmin Le Grand else 155eb82bfcdSArmin Le Grand { 156eb82bfcdSArmin Le Grand aNewConcatenated = rClassStr + aConcatenated; 157eb82bfcdSArmin Le Grand } 158eb82bfcdSArmin Le Grand 159eb82bfcdSArmin Le Grand if(pParent) 160eb82bfcdSArmin Le Grand { 161eb82bfcdSArmin Le Grand // check for combined selectors at parent firstso that higher specificity will be in front 162eb82bfcdSArmin Le Grand fillCssStyleVectorUsingHierarchyAndSelectors(rClassStr, *pParent, aNewConcatenated); 1639d01bcdeSArmin Le Grand } 164eb82bfcdSArmin Le Grand 165eb82bfcdSArmin Le Grand const SvgStyleAttributes* pNew = rDocument.findGlobalCssStyleAttributes(aNewConcatenated); 166eb82bfcdSArmin Le Grand 167eb82bfcdSArmin Le Grand if(pNew) 168eb82bfcdSArmin Le Grand { 169eb82bfcdSArmin Le Grand // add CssStyle if found 170eb82bfcdSArmin Le Grand maCssStyleVector.push_back(pNew); 171eb82bfcdSArmin Le Grand } 1729d01bcdeSArmin Le Grand } 1739d01bcdeSArmin Le Grand } 1749d01bcdeSArmin Le Grand } 1759d01bcdeSArmin Le Grand 176eb82bfcdSArmin Le Grand void SvgNode::fillCssStyleVector(const rtl::OUString& rClassStr) 177eb82bfcdSArmin Le Grand { 178eb82bfcdSArmin Le Grand OSL_ENSURE(!mbCssStyleVectorBuilt, "OOps, fillCssStyleVector called double ?!?"); 179eb82bfcdSArmin Le Grand mbCssStyleVectorBuilt = true; 180eb82bfcdSArmin Le Grand 181eb82bfcdSArmin Le Grand // #125293# If we have CssStyles we need to buuild a linked list of SvgStyleAttributes 182eb82bfcdSArmin Le Grand // which represent this for the current object. There are various methods to 183eb82bfcdSArmin Le Grand // specify CssStyles which need to be taken into account in a given order: 184eb82bfcdSArmin Le Grand // - local CssStyle (independent from global CssStyles at SvgDocument) 185eb82bfcdSArmin Le Grand // - 'id' CssStyle 186eb82bfcdSArmin Le Grand // - 'class' CssStyle(s) 187eb82bfcdSArmin Le Grand // - type-dependent elements (e..g. 'rect' for all rect elements) 188eb82bfcdSArmin Le Grand // - local attributes (rOriginal) 189eb82bfcdSArmin Le Grand // - inherited attributes (up the hierarchy) 190eb82bfcdSArmin Le Grand // The first four will be collected in maCssStyleVector for the current element 191eb82bfcdSArmin Le Grand // (once, this will not change) and be linked in the needed order using the 192eb82bfcdSArmin Le Grand // get/setCssStyleParent at the SvgStyleAttributes which will be used preferred in 193eb82bfcdSArmin Le Grand // member evaluation over the existing parent hierarchy 194eb82bfcdSArmin Le Grand 195eb82bfcdSArmin Le Grand // check for local CssStyle with highest priority 196eb82bfcdSArmin Le Grand if(mpLocalCssStyle) 197eb82bfcdSArmin Le Grand { 198eb82bfcdSArmin Le Grand // if we have one, use as first entry 199eb82bfcdSArmin Le Grand maCssStyleVector.push_back(mpLocalCssStyle); 200eb82bfcdSArmin Le Grand } 201eb82bfcdSArmin Le Grand 202eb82bfcdSArmin Le Grand // check the hierarchy for concatenated patterns of Selectors 203eb82bfcdSArmin Le Grand fillCssStyleVectorUsingHierarchyAndSelectors(rClassStr, *this, rtl::OUString()); 204*e9ec990dSArmin Le Grand 205*e9ec990dSArmin Le Grand // #125329# find Css selector '*', add as last element if found 206*e9ec990dSArmin Le Grand const SvgStyleAttributes* pNew = getDocument().findGlobalCssStyleAttributes(rtl::OUString::createFromAscii("*")); 207*e9ec990dSArmin Le Grand 208*e9ec990dSArmin Le Grand if(pNew) 209*e9ec990dSArmin Le Grand { 210*e9ec990dSArmin Le Grand // add CssStyle for selector '*' if found 211*e9ec990dSArmin Le Grand maCssStyleVector.push_back(pNew); 212*e9ec990dSArmin Le Grand } 213eb82bfcdSArmin Le Grand } 214eb82bfcdSArmin Le Grand 2159d01bcdeSArmin Le Grand const SvgStyleAttributes* SvgNode::checkForCssStyle(const rtl::OUString& rClassStr, const SvgStyleAttributes& rOriginal) const 2169d01bcdeSArmin Le Grand { 2179d01bcdeSArmin Le Grand if(!mbCssStyleVectorBuilt) 2189d01bcdeSArmin Le Grand { 2199d01bcdeSArmin Le Grand // build needed CssStyleVector for local node 2209d01bcdeSArmin Le Grand const_cast< SvgNode* >(this)->fillCssStyleVector(rClassStr); 22150b37974SArmin Le Grand } 22250b37974SArmin Le Grand 2239d56236fSArmin Le Grand if(maCssStyleVector.empty()) 2249d56236fSArmin Le Grand { 2259d01bcdeSArmin Le Grand // return given original if no CssStlyes found 2269d56236fSArmin Le Grand return &rOriginal; 2279d56236fSArmin Le Grand } 2289d56236fSArmin Le Grand else 22950b37974SArmin Le Grand { 2309d56236fSArmin Le Grand // #125293# rOriginal will be the last element in the linked list; use no CssStyleParent 2319d56236fSArmin Le Grand // there (reset it) to ensure that the parent hierarchy will be used when it's base 2329d56236fSArmin Le Grand // is referenced. This new chaning inserts the CssStyles before the original style, 2339d56236fSArmin Le Grand // this makes the whole process much safer since the original style when used will 2349d56236fSArmin Le Grand // be not different to the situation without CssStyles; thus loops which may be caused 2359d56236fSArmin Le Grand // by trying to use the parent hierarchy of the owner of the style will be avoided 2369d56236fSArmin Le Grand // already in this mechanism. It's still good to keep the supportsParentStyle 2379d56236fSArmin Le Grand // from #125258# in place, though. 2389d56236fSArmin Le Grand // This chain building using pointers will be done every time when checkForCssStyle 2399d56236fSArmin Le Grand // is used (not the search, only the chaining). This is needed since the CssStyles 2409d56236fSArmin Le Grand // themselves will be potentially used multiple times. It is not expensive since it's 2419d56236fSArmin Le Grand // only changing some pointers. 2429d56236fSArmin Le Grand // The alternative would be to create the style hierarchy for every element (or even 2439d56236fSArmin Le Grand // for the element containing the hierarchy) in a vector of pointers and to use that. 2449d56236fSArmin Le Grand // Resetting the CssStyleParent on rOriginal is probably not needeed 2459d56236fSArmin Le Grand // but simply safer to do. 2469d56236fSArmin Le Grand const_cast< SvgStyleAttributes& >(rOriginal).setCssStyleParent(0); 2479d56236fSArmin Le Grand 2489d56236fSArmin Le Grand // loop over the existing CssStyles and link them. There is a first one, take 2499d56236fSArmin Le Grand // as current 2509d56236fSArmin Le Grand SvgStyleAttributes* pCurrent = const_cast< SvgStyleAttributes* >(maCssStyleVector[0]); 2519d56236fSArmin Le Grand 2529d56236fSArmin Le Grand for(sal_uInt32 a(1); a < maCssStyleVector.size(); a++) 25350b37974SArmin Le Grand { 2547b027e49SArmin Le Grand SvgStyleAttributes* pNext = const_cast< SvgStyleAttributes* >(maCssStyleVector[a]); 25550b37974SArmin Le Grand 2567b027e49SArmin Le Grand pCurrent->setCssStyleParent(pNext); 2577b027e49SArmin Le Grand pCurrent = pNext; 25850b37974SArmin Le Grand } 2597b027e49SArmin Le Grand 2609d56236fSArmin Le Grand // pCurrent is the last used CssStyle, let it point to the original style 2619d56236fSArmin Le Grand pCurrent->setCssStyleParent(&rOriginal); 2629d56236fSArmin Le Grand 2639d56236fSArmin Le Grand // return 1st CssStyle as style chain start element (only for the 2649d56236fSArmin Le Grand // local element, still no hierarchy used here) 2659d56236fSArmin Le Grand return maCssStyleVector[0]; 2669d56236fSArmin Le Grand } 26750b37974SArmin Le Grand } 26850b37974SArmin Le Grand 269ddde725dSArmin Le Grand SvgNode::SvgNode( 270ddde725dSArmin Le Grand SVGToken aType, 271ddde725dSArmin Le Grand SvgDocument& rDocument, 272ddde725dSArmin Le Grand SvgNode* pParent) 273ddde725dSArmin Le Grand : maType(aType), 274ddde725dSArmin Le Grand mrDocument(rDocument), 275ddde725dSArmin Le Grand mpParent(pParent), 276ddde725dSArmin Le Grand mpAlternativeParent(0), 277ddde725dSArmin Le Grand maChildren(), 278ddde725dSArmin Le Grand mpId(0), 279ddde725dSArmin Le Grand mpClass(0), 28050b37974SArmin Le Grand maXmlSpace(XmlSpace_notset), 281a275c134SArmin Le Grand maDisplay(Display_inline), 2829d01bcdeSArmin Le Grand maCssStyleVector(), 2839d01bcdeSArmin Le Grand mpLocalCssStyle(0), 2849d01bcdeSArmin Le Grand mbCssStyleVectorBuilt(false) 285ddde725dSArmin Le Grand { 286ddde725dSArmin Le Grand OSL_ENSURE(SVGTokenUnknown != maType, "SvgNode with unknown type created (!)"); 287ddde725dSArmin Le Grand 288ddde725dSArmin Le Grand if(pParent) 289ddde725dSArmin Le Grand { 290ddde725dSArmin Le Grand pParent->maChildren.push_back(this); 291ddde725dSArmin Le Grand } 292ddde725dSArmin Le Grand else 293ddde725dSArmin Le Grand { 294ddde725dSArmin Le Grand #ifdef DBG_UTIL 295ddde725dSArmin Le Grand if(SVGTokenSvg != getType()) 296ddde725dSArmin Le Grand { 297ddde725dSArmin Le Grand OSL_ENSURE(false, "No parent for this node (!)"); 298ddde725dSArmin Le Grand } 299ddde725dSArmin Le Grand #endif 300ddde725dSArmin Le Grand } 301ddde725dSArmin Le Grand } 302ddde725dSArmin Le Grand 303ddde725dSArmin Le Grand SvgNode::~SvgNode() 304ddde725dSArmin Le Grand { 305ddde725dSArmin Le Grand while(maChildren.size()) 306ddde725dSArmin Le Grand { 307ddde725dSArmin Le Grand delete maChildren[maChildren.size() - 1]; 308ddde725dSArmin Le Grand maChildren.pop_back(); 309ddde725dSArmin Le Grand } 310ddde725dSArmin Le Grand 3119d01bcdeSArmin Le Grand if(mpId) 3129d01bcdeSArmin Le Grand { 3139d01bcdeSArmin Le Grand delete mpId; 3149d01bcdeSArmin Le Grand } 3159d01bcdeSArmin Le Grand 3169d01bcdeSArmin Le Grand if(mpClass) 3179d01bcdeSArmin Le Grand { 3189d01bcdeSArmin Le Grand delete mpClass; 3199d01bcdeSArmin Le Grand } 3209d01bcdeSArmin Le Grand 3219d01bcdeSArmin Le Grand if(mpLocalCssStyle) 3229d01bcdeSArmin Le Grand { 3239d01bcdeSArmin Le Grand delete mpLocalCssStyle; 3249d01bcdeSArmin Le Grand } 3259d01bcdeSArmin Le Grand } 3269d01bcdeSArmin Le Grand 3279d01bcdeSArmin Le Grand void SvgNode::readLocalCssStyle(const rtl::OUString& aContent) 3289d01bcdeSArmin Le Grand { 3299d01bcdeSArmin Le Grand if(!mpLocalCssStyle) 3309d01bcdeSArmin Le Grand { 3319d01bcdeSArmin Le Grand // create LocalCssStyle if needed but not yet added 3329d01bcdeSArmin Le Grand mpLocalCssStyle = new SvgStyleAttributes(*this); 3339d01bcdeSArmin Le Grand } 3349d01bcdeSArmin Le Grand else 3359d01bcdeSArmin Le Grand { 3369d01bcdeSArmin Le Grand // 2nd fill would be an error 3379d01bcdeSArmin Le Grand OSL_ENSURE(false, "Svg node has two local CssStyles, this may lead to problems (!)"); 3389d01bcdeSArmin Le Grand } 3399d01bcdeSArmin Le Grand 3409d01bcdeSArmin Le Grand if(mpLocalCssStyle) 3419d01bcdeSArmin Le Grand { 3429d01bcdeSArmin Le Grand // parse and set values to it 34352cb04b8SArmin Le Grand mpLocalCssStyle->readCssStyle(aContent); 3449d01bcdeSArmin Le Grand } 3459d01bcdeSArmin Le Grand else 3469d01bcdeSArmin Le Grand { 3479d01bcdeSArmin Le Grand OSL_ENSURE(false, "Could not get/create a local CssStyle for a node (!)"); 3489d01bcdeSArmin Le Grand } 349ddde725dSArmin Le Grand } 350ddde725dSArmin Le Grand 351ddde725dSArmin Le Grand void SvgNode::parseAttributes(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs) 352ddde725dSArmin Le Grand { 3539d01bcdeSArmin Le Grand // no longer need to pre-sort moving 'style' entries to the back so that 3549d01bcdeSArmin Le Grand // values get overwritten - that was the previous, not complete solution for 3559d01bcdeSArmin Le Grand // handling the priorities between svg and Css properties 356ddde725dSArmin Le Grand const sal_uInt32 nAttributes(xAttribs->getLength()); 357175cd092SArmin Le Grand 358ddde725dSArmin Le Grand for(sal_uInt32 a(0); a < nAttributes; a++) 359ddde725dSArmin Le Grand { 360ddde725dSArmin Le Grand const ::rtl::OUString aTokenName(xAttribs->getNameByIndex(a)); 36152cb04b8SArmin Le Grand const SVGToken aSVGToken(StrToSVGToken(aTokenName, false)); 362175cd092SArmin Le Grand 3639d01bcdeSArmin Le Grand parseAttribute(aTokenName, aSVGToken, xAttribs->getValueByIndex(a)); 364ddde725dSArmin Le Grand } 365ddde725dSArmin Le Grand } 366ddde725dSArmin Le Grand 36701e92ad6SArmin Le Grand Display getDisplayFromContent(const rtl::OUString& aContent) 36801e92ad6SArmin Le Grand { 36901e92ad6SArmin Le Grand if(aContent.getLength()) 37001e92ad6SArmin Le Grand { 371e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrInline(rtl::OUString::createFromAscii("inline")); 372e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrBlock(rtl::OUString::createFromAscii("block")); 373e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrList_item(rtl::OUString::createFromAscii("list-item")); 374e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrRun_in(rtl::OUString::createFromAscii("run-in")); 375e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrCompact(rtl::OUString::createFromAscii("compact")); 376e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrMarker(rtl::OUString::createFromAscii("marker")); 377e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrTable(rtl::OUString::createFromAscii("table")); 378e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrInline_table(rtl::OUString::createFromAscii("inline-table")); 379e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrTable_row_group(rtl::OUString::createFromAscii("table-row-group")); 380e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrTable_header_group(rtl::OUString::createFromAscii("table-header-group")); 381e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrTable_footer_group(rtl::OUString::createFromAscii("table-footer-group")); 382e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrTable_row(rtl::OUString::createFromAscii("table-row")); 383e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrTable_column_group(rtl::OUString::createFromAscii("table-column-group")); 384e92bb418SOliver-Rainer Wittmann static rtl::OUString aStrTable_column(rtl::OUString::createFromAscii("table-column")); 38501e92ad6SArmin Le Grand static rtl::OUString aStrTable_cell(rtl::OUString::createFromAscii("table-cell")); 38601e92ad6SArmin Le Grand static rtl::OUString aStrTable_caption(rtl::OUString::createFromAscii("table-caption")); 38701e92ad6SArmin Le Grand static rtl::OUString aStrNone(rtl::OUString::createFromAscii("none")); 38801e92ad6SArmin Le Grand static rtl::OUString aStrInherit(rtl::OUString::createFromAscii("inherit")); 38901e92ad6SArmin Le Grand 39001e92ad6SArmin Le Grand if(aContent.match(aStrInline)) 39101e92ad6SArmin Le Grand { 39201e92ad6SArmin Le Grand return Display_inline; 39301e92ad6SArmin Le Grand } 39401e92ad6SArmin Le Grand else if(aContent.match(aStrNone)) 39501e92ad6SArmin Le Grand { 39601e92ad6SArmin Le Grand return Display_none; 39701e92ad6SArmin Le Grand } 39801e92ad6SArmin Le Grand else if(aContent.match(aStrInherit)) 39901e92ad6SArmin Le Grand { 40001e92ad6SArmin Le Grand return Display_inherit; 40101e92ad6SArmin Le Grand } 402e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrBlock)) 40301e92ad6SArmin Le Grand { 40401e92ad6SArmin Le Grand return Display_block; 40501e92ad6SArmin Le Grand } 406e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrList_item)) 40701e92ad6SArmin Le Grand { 40801e92ad6SArmin Le Grand return Display_list_item; 40901e92ad6SArmin Le Grand } 410e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrRun_in)) 41101e92ad6SArmin Le Grand { 41201e92ad6SArmin Le Grand return Display_run_in; 41301e92ad6SArmin Le Grand } 414e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrCompact)) 41501e92ad6SArmin Le Grand { 41601e92ad6SArmin Le Grand return Display_compact; 41701e92ad6SArmin Le Grand } 418e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrMarker)) 41901e92ad6SArmin Le Grand { 42001e92ad6SArmin Le Grand return Display_marker; 42101e92ad6SArmin Le Grand } 422e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrTable)) 42301e92ad6SArmin Le Grand { 42401e92ad6SArmin Le Grand return Display_table; 42501e92ad6SArmin Le Grand } 426e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrInline_table)) 42701e92ad6SArmin Le Grand { 42801e92ad6SArmin Le Grand return Display_inline_table; 42901e92ad6SArmin Le Grand } 430e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrTable_row_group)) 43101e92ad6SArmin Le Grand { 43201e92ad6SArmin Le Grand return Display_table_row_group; 43301e92ad6SArmin Le Grand } 434e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrTable_header_group)) 43501e92ad6SArmin Le Grand { 43601e92ad6SArmin Le Grand return Display_table_header_group; 43701e92ad6SArmin Le Grand } 438e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrTable_footer_group)) 43901e92ad6SArmin Le Grand { 44001e92ad6SArmin Le Grand return Display_table_footer_group; 44101e92ad6SArmin Le Grand } 442e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrTable_row)) 44301e92ad6SArmin Le Grand { 44401e92ad6SArmin Le Grand return Display_table_row; 44501e92ad6SArmin Le Grand } 446e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrTable_column_group)) 44701e92ad6SArmin Le Grand { 44801e92ad6SArmin Le Grand return Display_table_column_group; 44901e92ad6SArmin Le Grand } 450e92bb418SOliver-Rainer Wittmann else if(aContent.match(aStrTable_column)) 45101e92ad6SArmin Le Grand { 45201e92ad6SArmin Le Grand return Display_table_column; 45301e92ad6SArmin Le Grand } 45401e92ad6SArmin Le Grand else if(aContent.match(aStrTable_cell)) 45501e92ad6SArmin Le Grand { 45601e92ad6SArmin Le Grand return Display_table_cell; 45701e92ad6SArmin Le Grand } 45801e92ad6SArmin Le Grand else if(aContent.match(aStrTable_caption)) 45901e92ad6SArmin Le Grand { 46001e92ad6SArmin Le Grand return Display_table_caption; 46101e92ad6SArmin Le Grand } 46201e92ad6SArmin Le Grand } 46301e92ad6SArmin Le Grand 46401e92ad6SArmin Le Grand // return the default 46501e92ad6SArmin Le Grand return Display_inline; 46601e92ad6SArmin Le Grand } 46701e92ad6SArmin Le Grand 468e2bf1e9dSArmin Le Grand void SvgNode::parseAttribute(const rtl::OUString& /*rTokenName*/, SVGToken aSVGToken, const rtl::OUString& aContent) 469ddde725dSArmin Le Grand { 470ddde725dSArmin Le Grand switch(aSVGToken) 471ddde725dSArmin Le Grand { 472ddde725dSArmin Le Grand case SVGTokenId: 473ddde725dSArmin Le Grand { 474ddde725dSArmin Le Grand if(aContent.getLength()) 475ddde725dSArmin Le Grand { 476ddde725dSArmin Le Grand setId(&aContent); 477ddde725dSArmin Le Grand } 478ddde725dSArmin Le Grand break; 479ddde725dSArmin Le Grand } 480ddde725dSArmin Le Grand case SVGTokenClass: 481ddde725dSArmin Le Grand { 482ddde725dSArmin Le Grand if(aContent.getLength()) 483ddde725dSArmin Le Grand { 484ddde725dSArmin Le Grand setClass(&aContent); 485ddde725dSArmin Le Grand } 486ddde725dSArmin Le Grand break; 487ddde725dSArmin Le Grand } 488ddde725dSArmin Le Grand case SVGTokenXmlSpace: 489ddde725dSArmin Le Grand { 490ddde725dSArmin Le Grand if(aContent.getLength()) 491ddde725dSArmin Le Grand { 492ddde725dSArmin Le Grand static rtl::OUString aStrDefault(rtl::OUString::createFromAscii("default")); 493ddde725dSArmin Le Grand static rtl::OUString aStrPreserve(rtl::OUString::createFromAscii("preserve")); 494ddde725dSArmin Le Grand 495ddde725dSArmin Le Grand if(aContent.match(aStrDefault)) 496ddde725dSArmin Le Grand { 497ddde725dSArmin Le Grand setXmlSpace(XmlSpace_default); 498ddde725dSArmin Le Grand } 499ddde725dSArmin Le Grand else if(aContent.match(aStrPreserve)) 500ddde725dSArmin Le Grand { 501ddde725dSArmin Le Grand setXmlSpace(XmlSpace_preserve); 502ddde725dSArmin Le Grand } 503ddde725dSArmin Le Grand } 504ddde725dSArmin Le Grand break; 505ddde725dSArmin Le Grand } 506a275c134SArmin Le Grand case SVGTokenDisplay: 507a275c134SArmin Le Grand { 508a275c134SArmin Le Grand if(aContent.getLength()) 509a275c134SArmin Le Grand { 51001e92ad6SArmin Le Grand setDisplay(getDisplayFromContent(aContent)); 511a275c134SArmin Le Grand } 512a275c134SArmin Le Grand break; 513a275c134SArmin Le Grand } 514e2bf1e9dSArmin Le Grand default: 515e2bf1e9dSArmin Le Grand { 516e2bf1e9dSArmin Le Grand break; 517e2bf1e9dSArmin Le Grand } 518ddde725dSArmin Le Grand } 519ddde725dSArmin Le Grand } 520ddde725dSArmin Le Grand 521ddde725dSArmin Le Grand void SvgNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const 522ddde725dSArmin Le Grand { 523a275c134SArmin Le Grand if(Display_none == getDisplay()) 524a275c134SArmin Le Grand { 525a275c134SArmin Le Grand return; 526a275c134SArmin Le Grand } 527a275c134SArmin Le Grand 528ddde725dSArmin Le Grand if(!bReferenced) 529ddde725dSArmin Le Grand { 530ddde725dSArmin Le Grand if(SVGTokenDefs == getType() || 531ddde725dSArmin Le Grand SVGTokenSymbol == getType() || 532ddde725dSArmin Le Grand SVGTokenClipPathNode == getType() || 533ddde725dSArmin Le Grand SVGTokenMask == getType() || 534ddde725dSArmin Le Grand SVGTokenMarker == getType() || 535ddde725dSArmin Le Grand SVGTokenPattern == getType()) 536ddde725dSArmin Le Grand { 537ddde725dSArmin Le Grand // do not decompose defs or symbol nodes (these hold only style-like 538ddde725dSArmin Le Grand // objects which may be used by referencing them) except when doing 539ddde725dSArmin Le Grand // so controlled referenced 540ddde725dSArmin Le Grand 541ddde725dSArmin Le Grand // also do not decompose ClipPaths and Masks. These should be embedded 542ddde725dSArmin Le Grand // in a defs node (which gets not decomposed by itself), but you never 543ddde725dSArmin Le Grand // know 544ddde725dSArmin Le Grand 545ddde725dSArmin Le Grand // also not directly used are Markers and Patterns, only indirecty used 546ddde725dSArmin Le Grand // by reference 547a275c134SArmin Le Grand 548a275c134SArmin Le Grand // #121656# also do not decompose nodes which have display="none" set 549a275c134SArmin Le Grand // as property 550ddde725dSArmin Le Grand return; 551ddde725dSArmin Le Grand } 552ddde725dSArmin Le Grand } 553ddde725dSArmin Le Grand 554ddde725dSArmin Le Grand const SvgNodeVector& rChildren = getChildren(); 555ddde725dSArmin Le Grand 556ddde725dSArmin Le Grand if(!rChildren.empty()) 557ddde725dSArmin Le Grand { 558ddde725dSArmin Le Grand const sal_uInt32 nCount(rChildren.size()); 559ddde725dSArmin Le Grand 560ddde725dSArmin Le Grand for(sal_uInt32 a(0); a < nCount; a++) 561ddde725dSArmin Le Grand { 562ddde725dSArmin Le Grand SvgNode* pCandidate = rChildren[a]; 563ddde725dSArmin Le Grand 564a275c134SArmin Le Grand if(pCandidate && Display_none != pCandidate->getDisplay()) 565ddde725dSArmin Le Grand { 566ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence aNewTarget; 567ddde725dSArmin Le Grand 568ddde725dSArmin Le Grand pCandidate->decomposeSvgNode(aNewTarget, bReferenced); 569ddde725dSArmin Le Grand 570ddde725dSArmin Le Grand if(aNewTarget.hasElements()) 571ddde725dSArmin Le Grand { 572ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewTarget); 573ddde725dSArmin Le Grand } 574ddde725dSArmin Le Grand } 575ddde725dSArmin Le Grand else 576ddde725dSArmin Le Grand { 577ddde725dSArmin Le Grand OSL_ENSURE(false, "Null-Pointer in child node list (!)"); 578ddde725dSArmin Le Grand } 579ddde725dSArmin Le Grand } 580025b0597SArmin Le Grand 581025b0597SArmin Le Grand if(rTarget.hasElements()) 582025b0597SArmin Le Grand { 583025b0597SArmin Le Grand const SvgStyleAttributes* pStyles = getSvgStyleAttributes(); 584025b0597SArmin Le Grand 585025b0597SArmin Le Grand if(pStyles) 586025b0597SArmin Le Grand { 587025b0597SArmin Le Grand // check if we have Title or Desc 588025b0597SArmin Le Grand const rtl::OUString& rTitle = pStyles->getTitle(); 589025b0597SArmin Le Grand const rtl::OUString& rDesc = pStyles->getDesc(); 590025b0597SArmin Le Grand 591025b0597SArmin Le Grand if(rTitle.getLength() || rDesc.getLength()) 592025b0597SArmin Le Grand { 593025b0597SArmin Le Grand // default object name is empty 594025b0597SArmin Le Grand rtl::OUString aObjectName; 595025b0597SArmin Le Grand 596025b0597SArmin Le Grand // use path as object name when outmost element 597025b0597SArmin Le Grand if(SVGTokenSvg == getType()) 598025b0597SArmin Le Grand { 599025b0597SArmin Le Grand aObjectName = getDocument().getAbsolutePath(); 600172c67b2SArmin Le Grand 601172c67b2SArmin Le Grand if(aObjectName.getLength()) 602172c67b2SArmin Le Grand { 603172c67b2SArmin Le Grand INetURLObject aURL(aObjectName); 604172c67b2SArmin Le Grand 605172c67b2SArmin Le Grand aObjectName = aURL.getName( 606172c67b2SArmin Le Grand INetURLObject::LAST_SEGMENT, 607172c67b2SArmin Le Grand true, 608172c67b2SArmin Le Grand INetURLObject::DECODE_WITH_CHARSET); 609172c67b2SArmin Le Grand } 610025b0597SArmin Le Grand } 611025b0597SArmin Le Grand 612025b0597SArmin Le Grand // pack in ObjectInfoPrimitive2D group 613025b0597SArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xRef( 614025b0597SArmin Le Grand new drawinglayer::primitive2d::ObjectInfoPrimitive2D( 615025b0597SArmin Le Grand rTarget, 616025b0597SArmin Le Grand aObjectName, 617025b0597SArmin Le Grand rTitle, 618025b0597SArmin Le Grand rDesc)); 619025b0597SArmin Le Grand 620025b0597SArmin Le Grand rTarget = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); 621025b0597SArmin Le Grand } 622025b0597SArmin Le Grand } 623025b0597SArmin Le Grand } 624ddde725dSArmin Le Grand } 625ddde725dSArmin Le Grand } 626ddde725dSArmin Le Grand 627e92bb418SOliver-Rainer Wittmann const basegfx::B2DRange SvgNode::getCurrentViewPort() const 628ddde725dSArmin Le Grand { 629ddde725dSArmin Le Grand if(getParent()) 630ddde725dSArmin Le Grand { 631ddde725dSArmin Le Grand return getParent()->getCurrentViewPort(); 632ddde725dSArmin Le Grand } 633ddde725dSArmin Le Grand else 634ddde725dSArmin Le Grand { 635e92bb418SOliver-Rainer Wittmann return basegfx::B2DRange(); // return empty B2DRange 636ddde725dSArmin Le Grand } 637ddde725dSArmin Le Grand } 638ddde725dSArmin Le Grand 639ddde725dSArmin Le Grand double SvgNode::getCurrentFontSize() const 640ddde725dSArmin Le Grand { 641ddde725dSArmin Le Grand if(getSvgStyleAttributes()) 642ddde725dSArmin Le Grand { 643ddde725dSArmin Le Grand return getSvgStyleAttributes()->getFontSize().solve(*this, xcoordinate); 644ddde725dSArmin Le Grand } 645ddde725dSArmin Le Grand else if(getParent()) 646ddde725dSArmin Le Grand { 647ddde725dSArmin Le Grand return getParent()->getCurrentFontSize(); 648ddde725dSArmin Le Grand } 649ddde725dSArmin Le Grand else 650ddde725dSArmin Le Grand { 651ddde725dSArmin Le Grand return 0.0; 652ddde725dSArmin Le Grand } 653ddde725dSArmin Le Grand } 654ddde725dSArmin Le Grand 655ddde725dSArmin Le Grand double SvgNode::getCurrentXHeight() const 656ddde725dSArmin Le Grand { 657ddde725dSArmin Le Grand if(getSvgStyleAttributes()) 658ddde725dSArmin Le Grand { 659ddde725dSArmin Le Grand // for XHeight, use FontSize currently 660ddde725dSArmin Le Grand return getSvgStyleAttributes()->getFontSize().solve(*this, ycoordinate); 661ddde725dSArmin Le Grand } 662ddde725dSArmin Le Grand else if(getParent()) 663ddde725dSArmin Le Grand { 664ddde725dSArmin Le Grand return getParent()->getCurrentXHeight(); 665ddde725dSArmin Le Grand } 666ddde725dSArmin Le Grand else 667ddde725dSArmin Le Grand { 668ddde725dSArmin Le Grand return 0.0; 669ddde725dSArmin Le Grand } 670ddde725dSArmin Le Grand } 671ddde725dSArmin Le Grand 672ddde725dSArmin Le Grand void SvgNode::setId(const rtl::OUString* pfId) 673ddde725dSArmin Le Grand { 674ddde725dSArmin Le Grand if(mpId) 675ddde725dSArmin Le Grand { 676ddde725dSArmin Le Grand mrDocument.removeSvgNodeFromMapper(*mpId); 677ddde725dSArmin Le Grand delete mpId; 678ddde725dSArmin Le Grand mpId = 0; 679ddde725dSArmin Le Grand } 680ddde725dSArmin Le Grand 681ddde725dSArmin Le Grand if(pfId) 682ddde725dSArmin Le Grand { 683ddde725dSArmin Le Grand mpId = new rtl::OUString(*pfId); 684ddde725dSArmin Le Grand mrDocument.addSvgNodeToMapper(*mpId, *this); 685ddde725dSArmin Le Grand } 686ddde725dSArmin Le Grand } 687ddde725dSArmin Le Grand 688ddde725dSArmin Le Grand void SvgNode::setClass(const rtl::OUString* pfClass) 689ddde725dSArmin Le Grand { 690ddde725dSArmin Le Grand if(mpClass) 691ddde725dSArmin Le Grand { 692ddde725dSArmin Le Grand mrDocument.removeSvgNodeFromMapper(*mpClass); 693ddde725dSArmin Le Grand delete mpClass; 694ddde725dSArmin Le Grand mpClass = 0; 695ddde725dSArmin Le Grand } 696ddde725dSArmin Le Grand 697ddde725dSArmin Le Grand if(pfClass) 698ddde725dSArmin Le Grand { 699ddde725dSArmin Le Grand mpClass = new rtl::OUString(*pfClass); 700ddde725dSArmin Le Grand mrDocument.addSvgNodeToMapper(*mpClass, *this); 701ddde725dSArmin Le Grand } 702ddde725dSArmin Le Grand } 703ddde725dSArmin Le Grand 704ddde725dSArmin Le Grand XmlSpace SvgNode::getXmlSpace() const 705ddde725dSArmin Le Grand { 706ddde725dSArmin Le Grand if(maXmlSpace != XmlSpace_notset) 707ddde725dSArmin Le Grand { 708ddde725dSArmin Le Grand return maXmlSpace; 709ddde725dSArmin Le Grand } 710ddde725dSArmin Le Grand 711ddde725dSArmin Le Grand if(getParent()) 712ddde725dSArmin Le Grand { 713ddde725dSArmin Le Grand return getParent()->getXmlSpace(); 714ddde725dSArmin Le Grand } 715ddde725dSArmin Le Grand 716ddde725dSArmin Le Grand // default is XmlSpace_default 717ddde725dSArmin Le Grand return XmlSpace_default; 718ddde725dSArmin Le Grand } 719ddde725dSArmin Le Grand 720ddde725dSArmin Le Grand } // end of namespace svgreader 721ddde725dSArmin Le Grand } // end of namespace svgio 722ddde725dSArmin Le Grand 723ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 724ddde725dSArmin Le Grand // eof 725