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/svgstylenode.hxx> 26ddde725dSArmin Le Grand #include <svgio/svgreader/svgdocument.hxx> 27ddde725dSArmin Le Grand 28ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 29ddde725dSArmin Le Grand 30ddde725dSArmin Le Grand namespace svgio 31ddde725dSArmin Le Grand { 32ddde725dSArmin Le Grand namespace svgreader 33ddde725dSArmin Le Grand { SvgStyleNode(SvgDocument & rDocument,SvgNode * pParent)34ddde725dSArmin Le Grand SvgStyleNode::SvgStyleNode( 35ddde725dSArmin Le Grand SvgDocument& rDocument, 36ddde725dSArmin Le Grand SvgNode* pParent) 37ddde725dSArmin Le Grand : SvgNode(SVGTokenStyle, rDocument, pParent), 38ddde725dSArmin Le Grand maSvgStyleAttributes(), 39ddde725dSArmin Le Grand mbTextCss(false) 40ddde725dSArmin Le Grand { 41ddde725dSArmin Le Grand } 42ddde725dSArmin Le Grand ~SvgStyleNode()43ddde725dSArmin Le Grand SvgStyleNode::~SvgStyleNode() 44ddde725dSArmin Le Grand { 45ddde725dSArmin Le Grand while(!maSvgStyleAttributes.empty()) 46ddde725dSArmin Le Grand { 47ddde725dSArmin Le Grand delete *(maSvgStyleAttributes.end() - 1); 48ddde725dSArmin Le Grand maSvgStyleAttributes.pop_back(); 49ddde725dSArmin Le Grand } 50ddde725dSArmin Le Grand } 51ddde725dSArmin Le Grand 524374d266SArmin Le Grand // #125258# no parent when we are a CssStyle holder to break potential loops because 534374d266SArmin Le Grand // when using CssStyles we jump uncontrolled inside the node tree hierarchy supportsParentStyle() const544374d266SArmin Le Grand bool SvgStyleNode::supportsParentStyle() const 554374d266SArmin Le Grand { 564374d266SArmin Le Grand if(isTextCss()) 574374d266SArmin Le Grand { 584374d266SArmin Le Grand return false; 594374d266SArmin Le Grand } 604374d266SArmin Le Grand 614374d266SArmin Le Grand // call parent 624374d266SArmin Le Grand return SvgNode::supportsParentStyle(); 634374d266SArmin Le Grand } 644374d266SArmin Le Grand parseAttribute(const rtl::OUString & rTokenName,SVGToken aSVGToken,const rtl::OUString & aContent)65ddde725dSArmin Le Grand void SvgStyleNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) 66ddde725dSArmin Le Grand { 67ddde725dSArmin Le Grand // call parent 68ddde725dSArmin Le Grand SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); 69ddde725dSArmin Le Grand 70ddde725dSArmin Le Grand // parse own 71ddde725dSArmin Le Grand switch(aSVGToken) 72ddde725dSArmin Le Grand { 73ddde725dSArmin Le Grand case SVGTokenType: 74ddde725dSArmin Le Grand { 75ddde725dSArmin Le Grand if(aContent.getLength()) 76ddde725dSArmin Le Grand { 77ddde725dSArmin Le Grand static rtl::OUString aStrTextCss(rtl::OUString::createFromAscii("text/css")); 78ddde725dSArmin Le Grand 79ddde725dSArmin Le Grand if(aContent.match(aStrTextCss)) 80ddde725dSArmin Le Grand { 81ddde725dSArmin Le Grand setTextCss(true); 82ddde725dSArmin Le Grand } 83ddde725dSArmin Le Grand } 84ddde725dSArmin Le Grand break; 85ddde725dSArmin Le Grand } 86e2bf1e9dSArmin Le Grand default: 87e2bf1e9dSArmin Le Grand { 88e2bf1e9dSArmin Le Grand break; 89e2bf1e9dSArmin Le Grand } 90ddde725dSArmin Le Grand } 91ddde725dSArmin Le Grand } 92ddde725dSArmin Le Grand addCssStyleSheet(const rtl::OUString & aSelectors,const SvgStyleAttributes & rNewStyle)93eb82bfcdSArmin Le Grand void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aSelectors, const SvgStyleAttributes& rNewStyle) 94ddde725dSArmin Le Grand { 95eb82bfcdSArmin Le Grand // aSelectors: CssStyle selectors, any combination, no comma separations, no spaces at start/end 96eb82bfcdSArmin Le Grand // rNewStyle: the already preapared style to register on that name 97eb82bfcdSArmin Le Grand if(aSelectors.getLength()) 98ddde725dSArmin Le Grand { 99eb82bfcdSArmin Le Grand std::vector< rtl::OUString > aSelectorParts; 100eb82bfcdSArmin Le Grand const sal_Int32 nLen(aSelectors.getLength()); 101ddde725dSArmin Le Grand sal_Int32 nPos(0); 102eb82bfcdSArmin Le Grand rtl::OUStringBuffer aToken; 103ddde725dSArmin Le Grand 104eb82bfcdSArmin Le Grand // split into single tokens (currently only space separator) 105311ea6abSArmin Le Grand while(nPos < nLen) 106ddde725dSArmin Le Grand { 107311ea6abSArmin Le Grand const sal_Int32 nInitPos(nPos); 108eb82bfcdSArmin Le Grand copyToLimiter(aSelectors, sal_Unicode(' '), nPos, aToken, nLen); 109eb82bfcdSArmin Le Grand skip_char(aSelectors, sal_Unicode(' '), nPos, nLen); 110eb82bfcdSArmin Le Grand const rtl::OUString aSelectorPart(aToken.makeStringAndClear().trim()); 111ddde725dSArmin Le Grand 112eb82bfcdSArmin Le Grand if(aSelectorPart.getLength()) 113eb82bfcdSArmin Le Grand { 114eb82bfcdSArmin Le Grand aSelectorParts.push_back(aSelectorPart); 115eb82bfcdSArmin Le Grand } 1169d01bcdeSArmin Le Grand 117eb82bfcdSArmin Le Grand if(nInitPos == nPos) 1189d01bcdeSArmin Le Grand { 119eb82bfcdSArmin Le Grand OSL_ENSURE(false, "Could not interpret on current position (!)"); 120eb82bfcdSArmin Le Grand nPos++; 121eb82bfcdSArmin Le Grand } 122eb82bfcdSArmin Le Grand } 1239d01bcdeSArmin Le Grand 124eb82bfcdSArmin Le Grand if(aSelectorParts.size()) 125eb82bfcdSArmin Le Grand { 126eb82bfcdSArmin Le Grand rtl::OUString aConcatenatedSelector; 127eb82bfcdSArmin Le Grand 128eb82bfcdSArmin Le Grand // re-combine without spaces, create a unique name (for now) 129eb82bfcdSArmin Le Grand for(sal_uInt32 a(0); a < aSelectorParts.size(); a++) 130eb82bfcdSArmin Le Grand { 131eb82bfcdSArmin Le Grand aConcatenatedSelector += aSelectorParts[a]; 132eb82bfcdSArmin Le Grand } 1339d01bcdeSArmin Le Grand 134eb82bfcdSArmin Le Grand // CssStyles in SVG are currently not completely supported; the current idea for 135eb82bfcdSArmin Le Grand // supporting the needed minimal set is to register CssStyles associated to a string 136eb82bfcdSArmin Le Grand // which is just the space-char cleaned, concatenated Selectors. The part to 'match' 137eb82bfcdSArmin Le Grand // these is in fillCssStyleVectorUsingHierarchyAndSelectors. There, the same string is 138eb82bfcdSArmin Le Grand // built up using the priorities of local CssStyle, Id, Class and other info combined 139eb82bfcdSArmin Le Grand // with the existing hierarchy. This creates a specificity- and priority-sorted local 140eb82bfcdSArmin Le Grand // list for each node which is then chained using get/setCssStyleParent. 141eb82bfcdSArmin Le Grand // The current solution is capable of solving space-separated selectors which can be 142eb82bfcdSArmin Le Grand // mixed between Id, Class and type specifiers. 143eb82bfcdSArmin Le Grand // When CssStyles need more specific solving, the start point is here; remember the 144eb82bfcdSArmin Le Grand // needed infos not in maIdStyleTokenMapperList at the document, but select evtl. 145eb82bfcdSArmin Le Grand // more specific infos there in a class capable of handling more complex matchings. 146eb82bfcdSArmin Le Grand // Additionally fillCssStyleVector (or the mechanism above that when a linked list of 147eb82bfcdSArmin Le Grand // SvgStyleAttributes will not do it) will have to be adapted to make use of it. 148eb82bfcdSArmin Le Grand 149eb82bfcdSArmin Le Grand // register new style at document for (evtl. concatenated) stylename 150eb82bfcdSArmin Le Grand const_cast< SvgDocument& >(getDocument()).addSvgStyleAttributesToMapper(aConcatenatedSelector, rNewStyle); 151eb82bfcdSArmin Le Grand } 152eb82bfcdSArmin Le Grand } 153eb82bfcdSArmin Le Grand } 1549d01bcdeSArmin Le Grand addCssStyleSheet(const rtl::OUString & aSelectors,const rtl::OUString & aContent)155eb82bfcdSArmin Le Grand void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aSelectors, const rtl::OUString& aContent) 156eb82bfcdSArmin Le Grand { 157eb82bfcdSArmin Le Grand // aSelectors: possible comma-separated list of CssStyle definitions, no spaces at start/end 158eb82bfcdSArmin Le Grand // aContent: the svg style definitions as string 159eb82bfcdSArmin Le Grand if(aSelectors.getLength() && aContent.getLength()) 160eb82bfcdSArmin Le Grand { 161eb82bfcdSArmin Le Grand // create new style and add to local list (for ownership control) 162eb82bfcdSArmin Le Grand SvgStyleAttributes* pNewStyle = new SvgStyleAttributes(*this); 163eb82bfcdSArmin Le Grand maSvgStyleAttributes.push_back(pNewStyle); 164eb82bfcdSArmin Le Grand 165eb82bfcdSArmin Le Grand // fill with content 166*52cb04b8SArmin Le Grand pNewStyle->readCssStyle(aContent); 167eb82bfcdSArmin Le Grand 168eb82bfcdSArmin Le Grand // comma-separated split (Css abbreviation for same style for multiple selectors) 169eb82bfcdSArmin Le Grand const sal_Int32 nLen(aSelectors.getLength()); 170eb82bfcdSArmin Le Grand sal_Int32 nPos(0); 171eb82bfcdSArmin Le Grand rtl::OUStringBuffer aToken; 172eb82bfcdSArmin Le Grand 173eb82bfcdSArmin Le Grand while(nPos < nLen) 174eb82bfcdSArmin Le Grand { 175eb82bfcdSArmin Le Grand const sal_Int32 nInitPos(nPos); 176eb82bfcdSArmin Le Grand copyToLimiter(aSelectors, sal_Unicode(','), nPos, aToken, nLen); 177eb82bfcdSArmin Le Grand skip_char(aSelectors, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 178eb82bfcdSArmin Le Grand 179eb82bfcdSArmin Le Grand const rtl::OUString aSingleName(aToken.makeStringAndClear().trim()); 180eb82bfcdSArmin Le Grand 181eb82bfcdSArmin Le Grand if(aSingleName.getLength()) 182eb82bfcdSArmin Le Grand { 183eb82bfcdSArmin Le Grand addCssStyleSheet(aSingleName, *pNewStyle); 1849d01bcdeSArmin Le Grand } 1859d01bcdeSArmin Le Grand 186eb82bfcdSArmin Le Grand if(nInitPos == nPos) 187ddde725dSArmin Le Grand { 188eb82bfcdSArmin Le Grand OSL_ENSURE(false, "Could not interpret on current position (!)"); 189eb82bfcdSArmin Le Grand nPos++; 190eb82bfcdSArmin Le Grand } 191eb82bfcdSArmin Le Grand } 192eb82bfcdSArmin Le Grand } 193eb82bfcdSArmin Le Grand } 194311ea6abSArmin Le Grand addCssStyleSheet(const rtl::OUString & aSelectorsAndContent)195eb82bfcdSArmin Le Grand void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aSelectorsAndContent) 196eb82bfcdSArmin Le Grand { 197eb82bfcdSArmin Le Grand const sal_Int32 nLen(aSelectorsAndContent.getLength()); 198ddde725dSArmin Le Grand 199eb82bfcdSArmin Le Grand if(nLen) 200eb82bfcdSArmin Le Grand { 201eb82bfcdSArmin Le Grand sal_Int32 nPos(0); 202eb82bfcdSArmin Le Grand rtl::OUStringBuffer aToken; 203eb82bfcdSArmin Le Grand 204eb82bfcdSArmin Le Grand while(nPos < nLen) 205eb82bfcdSArmin Le Grand { 206eb82bfcdSArmin Le Grand // read the full selectors (may be multiple, comma-separated) 207eb82bfcdSArmin Le Grand const sal_Int32 nInitPos(nPos); 208eb82bfcdSArmin Le Grand skip_char(aSelectorsAndContent, sal_Unicode(' '), nPos, nLen); 209eb82bfcdSArmin Le Grand copyToLimiter(aSelectorsAndContent, sal_Unicode('{'), nPos, aToken, nLen); 210eb82bfcdSArmin Le Grand skip_char(aSelectorsAndContent, sal_Unicode(' '), sal_Unicode('{'), nPos, nLen); 211ddde725dSArmin Le Grand 212eb82bfcdSArmin Le Grand const rtl::OUString aSelectors(aToken.makeStringAndClear().trim()); 213eb82bfcdSArmin Le Grand rtl::OUString aContent; 2149d01bcdeSArmin Le Grand 215eb82bfcdSArmin Le Grand if(aSelectors.getLength() && nPos < nLen) 216eb82bfcdSArmin Le Grand { 217eb82bfcdSArmin Le Grand // isolate content as text, embraced by '{' and '}' 218eb82bfcdSArmin Le Grand copyToLimiter(aSelectorsAndContent, sal_Unicode('}'), nPos, aToken, nLen); 219eb82bfcdSArmin Le Grand skip_char(aSelectorsAndContent, sal_Unicode(' '), sal_Unicode('}'), nPos, nLen); 2209d01bcdeSArmin Le Grand 221eb82bfcdSArmin Le Grand aContent = aToken.makeStringAndClear().trim(); 222eb82bfcdSArmin Le Grand } 223eb82bfcdSArmin Le Grand 224eb82bfcdSArmin Le Grand if(aSelectors.getLength() && aContent.getLength()) 225eb82bfcdSArmin Le Grand { 226eb82bfcdSArmin Le Grand addCssStyleSheet(aSelectors, aContent); 227311ea6abSArmin Le Grand } 228311ea6abSArmin Le Grand 229311ea6abSArmin Le Grand if(nInitPos == nPos) 230311ea6abSArmin Le Grand { 231311ea6abSArmin Le Grand OSL_ENSURE(false, "Could not interpret on current position (!)"); 232311ea6abSArmin Le Grand nPos++; 233ddde725dSArmin Le Grand } 234ddde725dSArmin Le Grand } 235ddde725dSArmin Le Grand } 236ddde725dSArmin Le Grand } 237ddde725dSArmin Le Grand 238ddde725dSArmin Le Grand } // end of namespace svgreader 239ddde725dSArmin Le Grand } // end of namespace svgio 240ddde725dSArmin Le Grand 241ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 242ddde725dSArmin Le Grand // eof 243