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/svgnode.hxx> 26 #include <basegfx/polygon/b2dpolypolygontools.hxx> 27 #include <svgio/svgreader/svgdocument.hxx> 28 #include <svgio/svgreader/svgnode.hxx> 29 #include <svgio/svgreader/svgstyleattributes.hxx> 30 #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx> 31 32 ////////////////////////////////////////////////////////////////////////////// 33 34 namespace svgio 35 { 36 namespace svgreader 37 { 38 const SvgStyleAttributes* SvgNode::getSvgStyleAttributes() const 39 { 40 return 0; 41 } 42 43 SvgNode::SvgNode( 44 SVGToken aType, 45 SvgDocument& rDocument, 46 SvgNode* pParent) 47 : maType(aType), 48 mrDocument(rDocument), 49 mpParent(pParent), 50 mpAlternativeParent(0), 51 maChildren(), 52 mpId(0), 53 mpClass(0), 54 maXmlSpace(XmlSpace_notset) 55 { 56 OSL_ENSURE(SVGTokenUnknown != maType, "SvgNode with unknown type created (!)"); 57 58 if(pParent) 59 { 60 pParent->maChildren.push_back(this); 61 } 62 else 63 { 64 #ifdef DBG_UTIL 65 if(SVGTokenSvg != getType()) 66 { 67 OSL_ENSURE(false, "No parent for this node (!)"); 68 } 69 #endif 70 } 71 } 72 73 SvgNode::~SvgNode() 74 { 75 while(maChildren.size()) 76 { 77 delete maChildren[maChildren.size() - 1]; 78 maChildren.pop_back(); 79 } 80 81 if(mpId) delete mpId; 82 if(mpClass) delete mpClass; 83 } 84 85 void SvgNode::parseAttributes(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs) 86 { 87 const sal_uInt32 nAttributes(xAttribs->getLength()); 88 89 for(sal_uInt32 a(0); a < nAttributes; a++) 90 { 91 const ::rtl::OUString aTokenName(xAttribs->getNameByIndex(a)); 92 93 parseAttribute(aTokenName, StrToSVGToken(aTokenName), xAttribs->getValueByIndex(a)); 94 } 95 } 96 97 void SvgNode::parseAttribute(const rtl::OUString& /*rTokenName*/, SVGToken aSVGToken, const rtl::OUString& aContent) 98 { 99 switch(aSVGToken) 100 { 101 case SVGTokenId: 102 { 103 if(aContent.getLength()) 104 { 105 setId(&aContent); 106 } 107 break; 108 } 109 case SVGTokenClass: 110 { 111 if(aContent.getLength()) 112 { 113 setClass(&aContent); 114 } 115 break; 116 } 117 case SVGTokenXmlSpace: 118 { 119 if(aContent.getLength()) 120 { 121 static rtl::OUString aStrDefault(rtl::OUString::createFromAscii("default")); 122 static rtl::OUString aStrPreserve(rtl::OUString::createFromAscii("preserve")); 123 124 if(aContent.match(aStrDefault)) 125 { 126 setXmlSpace(XmlSpace_default); 127 } 128 else if(aContent.match(aStrPreserve)) 129 { 130 setXmlSpace(XmlSpace_preserve); 131 } 132 } 133 break; 134 } 135 default: 136 { 137 break; 138 } 139 } 140 } 141 142 void SvgNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const 143 { 144 if(!bReferenced) 145 { 146 if(SVGTokenDefs == getType() || 147 SVGTokenSymbol == getType() || 148 SVGTokenClipPathNode == getType() || 149 SVGTokenMask == getType() || 150 SVGTokenMarker == getType() || 151 SVGTokenPattern == getType()) 152 { 153 // do not decompose defs or symbol nodes (these hold only style-like 154 // objects which may be used by referencing them) except when doing 155 // so controlled referenced 156 157 // also do not decompose ClipPaths and Masks. These should be embedded 158 // in a defs node (which gets not decomposed by itself), but you never 159 // know 160 161 // also not directly used are Markers and Patterns, only indirecty used 162 // by reference 163 return; 164 } 165 } 166 167 const SvgNodeVector& rChildren = getChildren(); 168 169 if(!rChildren.empty()) 170 { 171 const sal_uInt32 nCount(rChildren.size()); 172 173 for(sal_uInt32 a(0); a < nCount; a++) 174 { 175 SvgNode* pCandidate = rChildren[a]; 176 177 if(pCandidate) 178 { 179 drawinglayer::primitive2d::Primitive2DSequence aNewTarget; 180 181 pCandidate->decomposeSvgNode(aNewTarget, bReferenced); 182 183 if(aNewTarget.hasElements()) 184 { 185 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewTarget); 186 } 187 } 188 else 189 { 190 OSL_ENSURE(false, "Null-Pointer in child node list (!)"); 191 } 192 } 193 194 if(rTarget.hasElements()) 195 { 196 const SvgStyleAttributes* pStyles = getSvgStyleAttributes(); 197 198 if(pStyles) 199 { 200 // check if we have Title or Desc 201 const rtl::OUString& rTitle = pStyles->getTitle(); 202 const rtl::OUString& rDesc = pStyles->getDesc(); 203 204 if(rTitle.getLength() || rDesc.getLength()) 205 { 206 // default object name is empty 207 rtl::OUString aObjectName; 208 209 // use path as object name when outmost element 210 if(SVGTokenSvg == getType()) 211 { 212 aObjectName = getDocument().getAbsolutePath(); 213 } 214 215 // pack in ObjectInfoPrimitive2D group 216 const drawinglayer::primitive2d::Primitive2DReference xRef( 217 new drawinglayer::primitive2d::ObjectInfoPrimitive2D( 218 rTarget, 219 aObjectName, 220 rTitle, 221 rDesc)); 222 223 rTarget = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); 224 } 225 } 226 } 227 } 228 } 229 230 const basegfx::B2DRange* SvgNode::getCurrentViewPort() const 231 { 232 if(getParent()) 233 { 234 return getParent()->getCurrentViewPort(); 235 } 236 else 237 { 238 return 0; 239 } 240 } 241 242 double SvgNode::getCurrentFontSize() const 243 { 244 if(getSvgStyleAttributes()) 245 { 246 return getSvgStyleAttributes()->getFontSize().solve(*this, xcoordinate); 247 } 248 else if(getParent()) 249 { 250 return getParent()->getCurrentFontSize(); 251 } 252 else 253 { 254 return 0.0; 255 } 256 } 257 258 double SvgNode::getCurrentXHeight() const 259 { 260 if(getSvgStyleAttributes()) 261 { 262 // for XHeight, use FontSize currently 263 return getSvgStyleAttributes()->getFontSize().solve(*this, ycoordinate); 264 } 265 else if(getParent()) 266 { 267 return getParent()->getCurrentXHeight(); 268 } 269 else 270 { 271 return 0.0; 272 } 273 } 274 275 void SvgNode::setId(const rtl::OUString* pfId) 276 { 277 if(mpId) 278 { 279 mrDocument.removeSvgNodeFromMapper(*mpId); 280 delete mpId; 281 mpId = 0; 282 } 283 284 if(pfId) 285 { 286 mpId = new rtl::OUString(*pfId); 287 mrDocument.addSvgNodeToMapper(*mpId, *this); 288 } 289 } 290 291 void SvgNode::setClass(const rtl::OUString* pfClass) 292 { 293 if(mpClass) 294 { 295 mrDocument.removeSvgNodeFromMapper(*mpClass); 296 delete mpClass; 297 mpClass = 0; 298 } 299 300 if(pfClass) 301 { 302 mpClass = new rtl::OUString(*pfClass); 303 mrDocument.addSvgNodeToMapper(*mpClass, *this); 304 } 305 } 306 307 XmlSpace SvgNode::getXmlSpace() const 308 { 309 if(maXmlSpace != XmlSpace_notset) 310 { 311 return maXmlSpace; 312 } 313 314 if(getParent()) 315 { 316 return getParent()->getXmlSpace(); 317 } 318 319 // default is XmlSpace_default 320 return XmlSpace_default; 321 } 322 323 } // end of namespace svgreader 324 } // end of namespace svgio 325 326 ////////////////////////////////////////////////////////////////////////////// 327 // eof 328