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