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/svgpatternnode.hxx> 26 #include <svgio/svgreader/svgdocument.hxx> 27 28 ////////////////////////////////////////////////////////////////////////////// 29 30 namespace svgio 31 { 32 namespace svgreader 33 { 34 void SvgPatternNode::tryToFindLink() 35 { 36 if(!mpXLink && maXLink.getLength()) 37 { 38 mpXLink = dynamic_cast< const SvgPatternNode* >(getDocument().findSvgNodeById(maXLink)); 39 } 40 } 41 42 SvgPatternNode::SvgPatternNode( 43 SvgDocument& rDocument, 44 SvgNode* pParent) 45 : SvgNode(SVGTokenPattern, rDocument, pParent), 46 aPrimitives(), 47 maSvgStyleAttributes(*this), 48 mpViewBox(0), 49 maSvgAspectRatio(), 50 maX(), 51 maY(), 52 maWidth(), 53 maHeight(), 54 mpPatternUnits(0), 55 mpPatternContentUnits(0), 56 mpaPatternTransform(0), 57 maXLink(), 58 mpXLink(0) 59 { 60 } 61 62 SvgPatternNode::~SvgPatternNode() 63 { 64 if(mpViewBox) delete mpViewBox; 65 if(mpaPatternTransform) delete mpaPatternTransform; 66 if(mpPatternUnits) delete mpPatternUnits; 67 if(mpPatternContentUnits) delete mpPatternContentUnits; 68 } 69 70 const SvgStyleAttributes* SvgPatternNode::getSvgStyleAttributes() const 71 { 72 static rtl::OUString aClassStr(rtl::OUString::createFromAscii("pattern")); 73 maSvgStyleAttributes.checkForCssStyle(aClassStr); 74 75 return &maSvgStyleAttributes; 76 } 77 78 void SvgPatternNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) 79 { 80 // call parent 81 SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); 82 83 // read style attributes 84 maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); 85 86 // parse own 87 switch(aSVGToken) 88 { 89 case SVGTokenStyle: 90 { 91 maSvgStyleAttributes.readStyle(aContent); 92 break; 93 } 94 case SVGTokenViewBox: 95 { 96 const basegfx::B2DRange aRange(readViewBox(aContent, *this)); 97 98 if(!aRange.isEmpty()) 99 { 100 setViewBox(&aRange); 101 } 102 break; 103 } 104 case SVGTokenPreserveAspectRatio: 105 { 106 setSvgAspectRatio(readSvgAspectRatio(aContent)); 107 break; 108 } 109 case SVGTokenX: 110 { 111 SvgNumber aNum; 112 113 if(readSingleNumber(aContent, aNum)) 114 { 115 setX(aNum); 116 } 117 break; 118 } 119 case SVGTokenY: 120 { 121 SvgNumber aNum; 122 123 if(readSingleNumber(aContent, aNum)) 124 { 125 setY(aNum); 126 } 127 break; 128 } 129 case SVGTokenWidth: 130 { 131 SvgNumber aNum; 132 133 if(readSingleNumber(aContent, aNum)) 134 { 135 if(aNum.isPositive()) 136 { 137 setWidth(aNum); 138 } 139 } 140 break; 141 } 142 case SVGTokenHeight: 143 { 144 SvgNumber aNum; 145 146 if(readSingleNumber(aContent, aNum)) 147 { 148 if(aNum.isPositive()) 149 { 150 setHeight(aNum); 151 } 152 } 153 break; 154 } 155 case SVGTokenPatternUnits: 156 { 157 if(aContent.getLength()) 158 { 159 if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0)) 160 { 161 setPatternUnits(userSpaceOnUse); 162 } 163 else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0)) 164 { 165 setPatternUnits(objectBoundingBox); 166 } 167 } 168 break; 169 } 170 case SVGTokenPatternContentUnits: 171 { 172 if(aContent.getLength()) 173 { 174 if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0)) 175 { 176 setPatternContentUnits(userSpaceOnUse); 177 } 178 else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0)) 179 { 180 setPatternContentUnits(objectBoundingBox); 181 } 182 } 183 break; 184 } 185 case SVGTokenPatternTransform: 186 { 187 const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); 188 189 if(!aMatrix.isIdentity()) 190 { 191 setPatternTransform(&aMatrix); 192 } 193 break; 194 } 195 case SVGTokenXlinkHref: 196 { 197 const sal_Int32 nLen(aContent.getLength()); 198 199 if(nLen && sal_Unicode('#') == aContent[0]) 200 { 201 maXLink = aContent.copy(1); 202 tryToFindLink(); 203 } 204 break; 205 } 206 } 207 } 208 209 void SvgPatternNode::getValuesRelative(double& rfX, double& rfY, double& rfW, double& rfH, const basegfx::B2DRange& rGeoRange, SvgNode& rUser) const 210 { 211 double fTargetWidth(rGeoRange.getWidth()); 212 double fTargetHeight(rGeoRange.getHeight()); 213 214 if(fTargetWidth > 0.0 && fTargetHeight > 0.0) 215 { 216 const SvgUnits aPatternUnits(getPatternUnits() ? *getPatternUnits() : objectBoundingBox); 217 218 if(objectBoundingBox == aPatternUnits) 219 { 220 rfW = (getWidth().isSet()) ? getWidth().getNumber() : 0.0; 221 rfH = (getHeight().isSet()) ? getHeight().getNumber() : 0.0; 222 223 if(Unit_percent == getWidth().getUnit()) 224 { 225 rfW *= 0.01; 226 } 227 228 if(Unit_percent == getHeight().getUnit()) 229 { 230 rfH *= 0.01; 231 } 232 } 233 else 234 { 235 rfW = (getWidth().isSet()) ? getWidth().solve(rUser, xcoordinate) : 0.0; 236 rfH = (getHeight().isSet()) ? getHeight().solve(rUser, ycoordinate) : 0.0; 237 238 // make relative to rGeoRange 239 rfW /= fTargetWidth; 240 rfH /= fTargetHeight; 241 } 242 243 if(rfW > 0.0 && rfH > 0.0) 244 { 245 if(objectBoundingBox == aPatternUnits) 246 { 247 rfX = (getX().isSet()) ? getX().getNumber() : 0.0; 248 rfY = (getY().isSet()) ? getY().getNumber() : 0.0; 249 250 if(Unit_percent == getX().getUnit()) 251 { 252 rfX *= 0.01; 253 } 254 255 if(Unit_percent == getY().getUnit()) 256 { 257 rfY *= 0.01; 258 } 259 } 260 else 261 { 262 rfX = (getX().isSet()) ? getX().solve(rUser, xcoordinate) : 0.0; 263 rfY = (getY().isSet()) ? getY().solve(rUser, ycoordinate) : 0.0; 264 265 // make relative to rGeoRange 266 rfX = (rfX - rGeoRange.getMinX()) / fTargetWidth; 267 rfY = (rfY - rGeoRange.getMinY()) / fTargetHeight; 268 } 269 } 270 } 271 } 272 273 const drawinglayer::primitive2d::Primitive2DSequence& SvgPatternNode::getPatternPrimitives() const 274 { 275 if(!aPrimitives.hasElements()) 276 { 277 decomposeSvgNode(const_cast< SvgPatternNode* >(this)->aPrimitives, true); 278 } 279 280 if(!aPrimitives.hasElements() && maXLink.getLength()) 281 { 282 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 283 284 if(mpXLink) 285 { 286 return mpXLink->getPatternPrimitives(); 287 } 288 } 289 290 return aPrimitives; 291 } 292 293 const basegfx::B2DRange* SvgPatternNode::getCurrentViewPort() const 294 { 295 if(getViewBox()) 296 { 297 return getViewBox(); 298 } 299 else 300 { 301 return SvgNode::getCurrentViewPort(); 302 } 303 } 304 305 const basegfx::B2DRange* SvgPatternNode::getViewBox() const 306 { 307 if(mpViewBox) 308 { 309 return mpViewBox; 310 } 311 312 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 313 314 if(mpXLink) 315 { 316 return mpXLink->getViewBox(); 317 } 318 319 return 0; 320 } 321 322 const SvgAspectRatio& SvgPatternNode::getSvgAspectRatio() const 323 { 324 if(maSvgAspectRatio.isSet()) 325 { 326 return maSvgAspectRatio; 327 } 328 329 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 330 331 if(mpXLink) 332 { 333 return mpXLink->getSvgAspectRatio(); 334 } 335 336 return maSvgAspectRatio; 337 } 338 339 const SvgNumber& SvgPatternNode::getX() const 340 { 341 if(maX.isSet()) 342 { 343 return maX; 344 } 345 346 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 347 348 if(mpXLink) 349 { 350 return mpXLink->getX(); 351 } 352 353 return maX; 354 } 355 356 const SvgNumber& SvgPatternNode::getY() const 357 { 358 if(maY.isSet()) 359 { 360 return maY; 361 } 362 363 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 364 365 if(mpXLink) 366 { 367 return mpXLink->getY(); 368 } 369 370 return maY; 371 } 372 373 const SvgNumber& SvgPatternNode::getWidth() const 374 { 375 if(maWidth.isSet()) 376 { 377 return maWidth; 378 } 379 380 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 381 382 if(mpXLink) 383 { 384 return mpXLink->getWidth(); 385 } 386 387 return maWidth; 388 } 389 390 const SvgNumber& SvgPatternNode::getHeight() const 391 { 392 if(maHeight.isSet()) 393 { 394 return maHeight; 395 } 396 397 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 398 399 if(mpXLink) 400 { 401 return mpXLink->getHeight(); 402 } 403 404 return maHeight; 405 } 406 407 const SvgUnits* SvgPatternNode::getPatternUnits() const 408 { 409 if(mpPatternUnits) 410 { 411 return mpPatternUnits; 412 } 413 414 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 415 416 if(mpXLink) 417 { 418 return mpXLink->getPatternUnits(); 419 } 420 421 return 0; 422 } 423 424 const SvgUnits* SvgPatternNode::getPatternContentUnits() const 425 { 426 if(mpPatternContentUnits) 427 { 428 return mpPatternContentUnits; 429 } 430 431 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 432 433 if(mpXLink) 434 { 435 return mpXLink->getPatternContentUnits(); 436 } 437 438 return 0; 439 } 440 441 const basegfx::B2DHomMatrix* SvgPatternNode::getPatternTransform() const 442 { 443 if(mpaPatternTransform) 444 { 445 return mpaPatternTransform; 446 } 447 448 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 449 450 if(mpXLink) 451 { 452 return mpXLink->getPatternTransform(); 453 } 454 455 return 0; 456 } 457 458 } // end of namespace svgreader 459 } // end of namespace svgio 460 461 ////////////////////////////////////////////////////////////////////////////// 462 // eof 463