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 { 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 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 544374d266SArmin 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 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 93*eb82bfcdSArmin Le Grand void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aSelectors, const SvgStyleAttributes& rNewStyle) 94ddde725dSArmin Le Grand { 95*eb82bfcdSArmin Le Grand // aSelectors: CssStyle selectors, any combination, no comma separations, no spaces at start/end 96*eb82bfcdSArmin Le Grand // rNewStyle: the already preapared style to register on that name 97*eb82bfcdSArmin Le Grand if(aSelectors.getLength()) 98ddde725dSArmin Le Grand { 99*eb82bfcdSArmin Le Grand std::vector< rtl::OUString > aSelectorParts; 100*eb82bfcdSArmin Le Grand const sal_Int32 nLen(aSelectors.getLength()); 101ddde725dSArmin Le Grand sal_Int32 nPos(0); 102*eb82bfcdSArmin Le Grand rtl::OUStringBuffer aToken; 103ddde725dSArmin Le Grand 104*eb82bfcdSArmin 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); 108*eb82bfcdSArmin Le Grand copyToLimiter(aSelectors, sal_Unicode(' '), nPos, aToken, nLen); 109*eb82bfcdSArmin Le Grand skip_char(aSelectors, sal_Unicode(' '), nPos, nLen); 110*eb82bfcdSArmin Le Grand const rtl::OUString aSelectorPart(aToken.makeStringAndClear().trim()); 111ddde725dSArmin Le Grand 112*eb82bfcdSArmin Le Grand if(aSelectorPart.getLength()) 113*eb82bfcdSArmin Le Grand { 114*eb82bfcdSArmin Le Grand aSelectorParts.push_back(aSelectorPart); 115*eb82bfcdSArmin Le Grand } 1169d01bcdeSArmin Le Grand 117*eb82bfcdSArmin Le Grand if(nInitPos == nPos) 1189d01bcdeSArmin Le Grand { 119*eb82bfcdSArmin Le Grand OSL_ENSURE(false, "Could not interpret on current position (!)"); 120*eb82bfcdSArmin Le Grand nPos++; 121*eb82bfcdSArmin Le Grand } 122*eb82bfcdSArmin Le Grand } 1239d01bcdeSArmin Le Grand 124*eb82bfcdSArmin Le Grand if(aSelectorParts.size()) 125*eb82bfcdSArmin Le Grand { 126*eb82bfcdSArmin Le Grand rtl::OUString aConcatenatedSelector; 127*eb82bfcdSArmin Le Grand 128*eb82bfcdSArmin Le Grand // re-combine without spaces, create a unique name (for now) 129*eb82bfcdSArmin Le Grand for(sal_uInt32 a(0); a < aSelectorParts.size(); a++) 130*eb82bfcdSArmin Le Grand { 131*eb82bfcdSArmin Le Grand aConcatenatedSelector += aSelectorParts[a]; 132*eb82bfcdSArmin Le Grand } 1339d01bcdeSArmin Le Grand 134*eb82bfcdSArmin Le Grand // CssStyles in SVG are currently not completely supported; the current idea for 135*eb82bfcdSArmin Le Grand // supporting the needed minimal set is to register CssStyles associated to a string 136*eb82bfcdSArmin Le Grand // which is just the space-char cleaned, concatenated Selectors. The part to 'match' 137*eb82bfcdSArmin Le Grand // these is in fillCssStyleVectorUsingHierarchyAndSelectors. There, the same string is 138*eb82bfcdSArmin Le Grand // built up using the priorities of local CssStyle, Id, Class and other info combined 139*eb82bfcdSArmin Le Grand // with the existing hierarchy. This creates a specificity- and priority-sorted local 140*eb82bfcdSArmin Le Grand // list for each node which is then chained using get/setCssStyleParent. 141*eb82bfcdSArmin Le Grand // The current solution is capable of solving space-separated selectors which can be 142*eb82bfcdSArmin Le Grand // mixed between Id, Class and type specifiers. 143*eb82bfcdSArmin Le Grand // When CssStyles need more specific solving, the start point is here; remember the 144*eb82bfcdSArmin Le Grand // needed infos not in maIdStyleTokenMapperList at the document, but select evtl. 145*eb82bfcdSArmin Le Grand // more specific infos there in a class capable of handling more complex matchings. 146*eb82bfcdSArmin Le Grand // Additionally fillCssStyleVector (or the mechanism above that when a linked list of 147*eb82bfcdSArmin Le Grand // SvgStyleAttributes will not do it) will have to be adapted to make use of it. 148*eb82bfcdSArmin Le Grand 149*eb82bfcdSArmin Le Grand // register new style at document for (evtl. concatenated) stylename 150*eb82bfcdSArmin Le Grand const_cast< SvgDocument& >(getDocument()).addSvgStyleAttributesToMapper(aConcatenatedSelector, rNewStyle); 151*eb82bfcdSArmin Le Grand } 152*eb82bfcdSArmin Le Grand } 153*eb82bfcdSArmin Le Grand } 1549d01bcdeSArmin Le Grand 155*eb82bfcdSArmin Le Grand void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aSelectors, const rtl::OUString& aContent) 156*eb82bfcdSArmin Le Grand { 157*eb82bfcdSArmin Le Grand // aSelectors: possible comma-separated list of CssStyle definitions, no spaces at start/end 158*eb82bfcdSArmin Le Grand // aContent: the svg style definitions as string 159*eb82bfcdSArmin Le Grand if(aSelectors.getLength() && aContent.getLength()) 160*eb82bfcdSArmin Le Grand { 161*eb82bfcdSArmin Le Grand // create new style and add to local list (for ownership control) 162*eb82bfcdSArmin Le Grand SvgStyleAttributes* pNewStyle = new SvgStyleAttributes(*this); 163*eb82bfcdSArmin Le Grand maSvgStyleAttributes.push_back(pNewStyle); 164*eb82bfcdSArmin Le Grand 165*eb82bfcdSArmin Le Grand // fill with content 166*eb82bfcdSArmin Le Grand pNewStyle->readStyle(aContent); 167*eb82bfcdSArmin Le Grand 168*eb82bfcdSArmin Le Grand // comma-separated split (Css abbreviation for same style for multiple selectors) 169*eb82bfcdSArmin Le Grand const sal_Int32 nLen(aSelectors.getLength()); 170*eb82bfcdSArmin Le Grand sal_Int32 nPos(0); 171*eb82bfcdSArmin Le Grand rtl::OUStringBuffer aToken; 172*eb82bfcdSArmin Le Grand 173*eb82bfcdSArmin Le Grand while(nPos < nLen) 174*eb82bfcdSArmin Le Grand { 175*eb82bfcdSArmin Le Grand const sal_Int32 nInitPos(nPos); 176*eb82bfcdSArmin Le Grand copyToLimiter(aSelectors, sal_Unicode(','), nPos, aToken, nLen); 177*eb82bfcdSArmin Le Grand skip_char(aSelectors, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 178*eb82bfcdSArmin Le Grand 179*eb82bfcdSArmin Le Grand const rtl::OUString aSingleName(aToken.makeStringAndClear().trim()); 180*eb82bfcdSArmin Le Grand 181*eb82bfcdSArmin Le Grand if(aSingleName.getLength()) 182*eb82bfcdSArmin Le Grand { 183*eb82bfcdSArmin Le Grand addCssStyleSheet(aSingleName, *pNewStyle); 1849d01bcdeSArmin Le Grand } 1859d01bcdeSArmin Le Grand 186*eb82bfcdSArmin Le Grand if(nInitPos == nPos) 187ddde725dSArmin Le Grand { 188*eb82bfcdSArmin Le Grand OSL_ENSURE(false, "Could not interpret on current position (!)"); 189*eb82bfcdSArmin Le Grand nPos++; 190*eb82bfcdSArmin Le Grand } 191*eb82bfcdSArmin Le Grand } 192*eb82bfcdSArmin Le Grand } 193*eb82bfcdSArmin Le Grand } 194311ea6abSArmin Le Grand 195*eb82bfcdSArmin Le Grand void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aSelectorsAndContent) 196*eb82bfcdSArmin Le Grand { 197*eb82bfcdSArmin Le Grand const sal_Int32 nLen(aSelectorsAndContent.getLength()); 198ddde725dSArmin Le Grand 199*eb82bfcdSArmin Le Grand if(nLen) 200*eb82bfcdSArmin Le Grand { 201*eb82bfcdSArmin Le Grand sal_Int32 nPos(0); 202*eb82bfcdSArmin Le Grand rtl::OUStringBuffer aToken; 203*eb82bfcdSArmin Le Grand 204*eb82bfcdSArmin Le Grand while(nPos < nLen) 205*eb82bfcdSArmin Le Grand { 206*eb82bfcdSArmin Le Grand // read the full selectors (may be multiple, comma-separated) 207*eb82bfcdSArmin Le Grand const sal_Int32 nInitPos(nPos); 208*eb82bfcdSArmin Le Grand skip_char(aSelectorsAndContent, sal_Unicode(' '), nPos, nLen); 209*eb82bfcdSArmin Le Grand copyToLimiter(aSelectorsAndContent, sal_Unicode('{'), nPos, aToken, nLen); 210*eb82bfcdSArmin Le Grand skip_char(aSelectorsAndContent, sal_Unicode(' '), sal_Unicode('{'), nPos, nLen); 211ddde725dSArmin Le Grand 212*eb82bfcdSArmin Le Grand const rtl::OUString aSelectors(aToken.makeStringAndClear().trim()); 213*eb82bfcdSArmin Le Grand rtl::OUString aContent; 2149d01bcdeSArmin Le Grand 215*eb82bfcdSArmin Le Grand if(aSelectors.getLength() && nPos < nLen) 216*eb82bfcdSArmin Le Grand { 217*eb82bfcdSArmin Le Grand // isolate content as text, embraced by '{' and '}' 218*eb82bfcdSArmin Le Grand copyToLimiter(aSelectorsAndContent, sal_Unicode('}'), nPos, aToken, nLen); 219*eb82bfcdSArmin Le Grand skip_char(aSelectorsAndContent, sal_Unicode(' '), sal_Unicode('}'), nPos, nLen); 2209d01bcdeSArmin Le Grand 221*eb82bfcdSArmin Le Grand aContent = aToken.makeStringAndClear().trim(); 222*eb82bfcdSArmin Le Grand } 223*eb82bfcdSArmin Le Grand 224*eb82bfcdSArmin Le Grand if(aSelectors.getLength() && aContent.getLength()) 225*eb82bfcdSArmin Le Grand { 226*eb82bfcdSArmin 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