1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_svgio.hxx" 24 25 #include <svgio/svgreader/svgstylenode.hxx> 26 #include <svgio/svgreader/svgdocument.hxx> 27 28 ////////////////////////////////////////////////////////////////////////////// 29 30 namespace svgio 31 { 32 namespace svgreader 33 { SvgStyleNode(SvgDocument & rDocument,SvgNode * pParent)34 SvgStyleNode::SvgStyleNode( 35 SvgDocument& rDocument, 36 SvgNode* pParent) 37 : SvgNode(SVGTokenStyle, rDocument, pParent), 38 maSvgStyleAttributes(), 39 mbTextCss(false) 40 { 41 } 42 ~SvgStyleNode()43 SvgStyleNode::~SvgStyleNode() 44 { 45 while(!maSvgStyleAttributes.empty()) 46 { 47 delete *(maSvgStyleAttributes.end() - 1); 48 maSvgStyleAttributes.pop_back(); 49 } 50 } 51 52 // #125258# no parent when we are a CssStyle holder to break potential loops because 53 // when using CssStyles we jump uncontrolled inside the node tree hierarchy supportsParentStyle() const54 bool SvgStyleNode::supportsParentStyle() const 55 { 56 if(isTextCss()) 57 { 58 return false; 59 } 60 61 // call parent 62 return SvgNode::supportsParentStyle(); 63 } 64 parseAttribute(const rtl::OUString & rTokenName,SVGToken aSVGToken,const rtl::OUString & aContent)65 void SvgStyleNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) 66 { 67 // call parent 68 SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); 69 70 // parse own 71 switch(aSVGToken) 72 { 73 case SVGTokenType: 74 { 75 if(aContent.getLength()) 76 { 77 static rtl::OUString aStrTextCss(rtl::OUString::createFromAscii("text/css")); 78 79 if(aContent.match(aStrTextCss)) 80 { 81 setTextCss(true); 82 } 83 } 84 break; 85 } 86 default: 87 { 88 break; 89 } 90 } 91 } 92 addCssStyleSheet(const rtl::OUString & aSelectors,const SvgStyleAttributes & rNewStyle)93 void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aSelectors, const SvgStyleAttributes& rNewStyle) 94 { 95 // aSelectors: CssStyle selectors, any combination, no comma separations, no spaces at start/end 96 // rNewStyle: the already preapared style to register on that name 97 if(aSelectors.getLength()) 98 { 99 std::vector< rtl::OUString > aSelectorParts; 100 const sal_Int32 nLen(aSelectors.getLength()); 101 sal_Int32 nPos(0); 102 rtl::OUStringBuffer aToken; 103 104 // split into single tokens (currently only space separator) 105 while(nPos < nLen) 106 { 107 const sal_Int32 nInitPos(nPos); 108 copyToLimiter(aSelectors, sal_Unicode(' '), nPos, aToken, nLen); 109 skip_char(aSelectors, sal_Unicode(' '), nPos, nLen); 110 const rtl::OUString aSelectorPart(aToken.makeStringAndClear().trim()); 111 112 if(aSelectorPart.getLength()) 113 { 114 aSelectorParts.push_back(aSelectorPart); 115 } 116 117 if(nInitPos == nPos) 118 { 119 OSL_ENSURE(false, "Could not interpret on current position (!)"); 120 nPos++; 121 } 122 } 123 124 if(aSelectorParts.size()) 125 { 126 rtl::OUString aConcatenatedSelector; 127 128 // re-combine without spaces, create a unique name (for now) 129 for(sal_uInt32 a(0); a < aSelectorParts.size(); a++) 130 { 131 aConcatenatedSelector += aSelectorParts[a]; 132 } 133 134 // CssStyles in SVG are currently not completely supported; the current idea for 135 // supporting the needed minimal set is to register CssStyles associated to a string 136 // which is just the space-char cleaned, concatenated Selectors. The part to 'match' 137 // these is in fillCssStyleVectorUsingHierarchyAndSelectors. There, the same string is 138 // built up using the priorities of local CssStyle, Id, Class and other info combined 139 // with the existing hierarchy. This creates a specificity- and priority-sorted local 140 // list for each node which is then chained using get/setCssStyleParent. 141 // The current solution is capable of solving space-separated selectors which can be 142 // mixed between Id, Class and type specifiers. 143 // When CssStyles need more specific solving, the start point is here; remember the 144 // needed infos not in maIdStyleTokenMapperList at the document, but select evtl. 145 // more specific infos there in a class capable of handling more complex matchings. 146 // Additionally fillCssStyleVector (or the mechanism above that when a linked list of 147 // SvgStyleAttributes will not do it) will have to be adapted to make use of it. 148 149 // register new style at document for (evtl. concatenated) stylename 150 const_cast< SvgDocument& >(getDocument()).addSvgStyleAttributesToMapper(aConcatenatedSelector, rNewStyle); 151 } 152 } 153 } 154 addCssStyleSheet(const rtl::OUString & aSelectors,const rtl::OUString & aContent)155 void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aSelectors, const rtl::OUString& aContent) 156 { 157 // aSelectors: possible comma-separated list of CssStyle definitions, no spaces at start/end 158 // aContent: the svg style definitions as string 159 if(aSelectors.getLength() && aContent.getLength()) 160 { 161 // create new style and add to local list (for ownership control) 162 SvgStyleAttributes* pNewStyle = new SvgStyleAttributes(*this); 163 maSvgStyleAttributes.push_back(pNewStyle); 164 165 // fill with content 166 pNewStyle->readCssStyle(aContent); 167 168 // comma-separated split (Css abbreviation for same style for multiple selectors) 169 const sal_Int32 nLen(aSelectors.getLength()); 170 sal_Int32 nPos(0); 171 rtl::OUStringBuffer aToken; 172 173 while(nPos < nLen) 174 { 175 const sal_Int32 nInitPos(nPos); 176 copyToLimiter(aSelectors, sal_Unicode(','), nPos, aToken, nLen); 177 skip_char(aSelectors, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 178 179 const rtl::OUString aSingleName(aToken.makeStringAndClear().trim()); 180 181 if(aSingleName.getLength()) 182 { 183 addCssStyleSheet(aSingleName, *pNewStyle); 184 } 185 186 if(nInitPos == nPos) 187 { 188 OSL_ENSURE(false, "Could not interpret on current position (!)"); 189 nPos++; 190 } 191 } 192 } 193 } 194 addCssStyleSheet(const rtl::OUString & aSelectorsAndContent)195 void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aSelectorsAndContent) 196 { 197 const sal_Int32 nLen(aSelectorsAndContent.getLength()); 198 199 if(nLen) 200 { 201 sal_Int32 nPos(0); 202 rtl::OUStringBuffer aToken; 203 204 while(nPos < nLen) 205 { 206 // read the full selectors (may be multiple, comma-separated) 207 const sal_Int32 nInitPos(nPos); 208 skip_char(aSelectorsAndContent, sal_Unicode(' '), nPos, nLen); 209 copyToLimiter(aSelectorsAndContent, sal_Unicode('{'), nPos, aToken, nLen); 210 skip_char(aSelectorsAndContent, sal_Unicode(' '), sal_Unicode('{'), nPos, nLen); 211 212 const rtl::OUString aSelectors(aToken.makeStringAndClear().trim()); 213 rtl::OUString aContent; 214 215 if(aSelectors.getLength() && nPos < nLen) 216 { 217 // isolate content as text, embraced by '{' and '}' 218 copyToLimiter(aSelectorsAndContent, sal_Unicode('}'), nPos, aToken, nLen); 219 skip_char(aSelectorsAndContent, sal_Unicode(' '), sal_Unicode('}'), nPos, nLen); 220 221 aContent = aToken.makeStringAndClear().trim(); 222 } 223 224 if(aSelectors.getLength() && aContent.getLength()) 225 { 226 addCssStyleSheet(aSelectors, aContent); 227 } 228 229 if(nInitPos == nPos) 230 { 231 OSL_ENSURE(false, "Could not interpret on current position (!)"); 232 nPos++; 233 } 234 } 235 } 236 } 237 238 } // end of namespace svgreader 239 } // end of namespace svgio 240 241 ////////////////////////////////////////////////////////////////////////////// 242 // eof 243