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 default: 207 { 208 break; 209 } 210 } 211 } 212 213 void SvgPatternNode::getValuesRelative(double& rfX, double& rfY, double& rfW, double& rfH, const basegfx::B2DRange& rGeoRange, SvgNode& rUser) const 214 { 215 double fTargetWidth(rGeoRange.getWidth()); 216 double fTargetHeight(rGeoRange.getHeight()); 217 218 if(fTargetWidth > 0.0 && fTargetHeight > 0.0) 219 { 220 const SvgUnits aPatternUnits(getPatternUnits() ? *getPatternUnits() : objectBoundingBox); 221 222 if(objectBoundingBox == aPatternUnits) 223 { 224 rfW = (getWidth().isSet()) ? getWidth().getNumber() : 0.0; 225 rfH = (getHeight().isSet()) ? getHeight().getNumber() : 0.0; 226 227 if(Unit_percent == getWidth().getUnit()) 228 { 229 rfW *= 0.01; 230 } 231 232 if(Unit_percent == getHeight().getUnit()) 233 { 234 rfH *= 0.01; 235 } 236 } 237 else 238 { 239 rfW = (getWidth().isSet()) ? getWidth().solve(rUser, xcoordinate) : 0.0; 240 rfH = (getHeight().isSet()) ? getHeight().solve(rUser, ycoordinate) : 0.0; 241 242 // make relative to rGeoRange 243 rfW /= fTargetWidth; 244 rfH /= fTargetHeight; 245 } 246 247 if(rfW > 0.0 && rfH > 0.0) 248 { 249 if(objectBoundingBox == aPatternUnits) 250 { 251 rfX = (getX().isSet()) ? getX().getNumber() : 0.0; 252 rfY = (getY().isSet()) ? getY().getNumber() : 0.0; 253 254 if(Unit_percent == getX().getUnit()) 255 { 256 rfX *= 0.01; 257 } 258 259 if(Unit_percent == getY().getUnit()) 260 { 261 rfY *= 0.01; 262 } 263 } 264 else 265 { 266 rfX = (getX().isSet()) ? getX().solve(rUser, xcoordinate) : 0.0; 267 rfY = (getY().isSet()) ? getY().solve(rUser, ycoordinate) : 0.0; 268 269 // make relative to rGeoRange 270 rfX = (rfX - rGeoRange.getMinX()) / fTargetWidth; 271 rfY = (rfY - rGeoRange.getMinY()) / fTargetHeight; 272 } 273 } 274 } 275 } 276 277 const drawinglayer::primitive2d::Primitive2DSequence& SvgPatternNode::getPatternPrimitives() const 278 { 279 if(!aPrimitives.hasElements()) 280 { 281 decomposeSvgNode(const_cast< SvgPatternNode* >(this)->aPrimitives, true); 282 } 283 284 if(!aPrimitives.hasElements() && maXLink.getLength()) 285 { 286 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 287 288 if(mpXLink) 289 { 290 return mpXLink->getPatternPrimitives(); 291 } 292 } 293 294 return aPrimitives; 295 } 296 297 const basegfx::B2DRange* SvgPatternNode::getCurrentViewPort() const 298 { 299 if(getViewBox()) 300 { 301 return getViewBox(); 302 } 303 else 304 { 305 return SvgNode::getCurrentViewPort(); 306 } 307 } 308 309 const basegfx::B2DRange* SvgPatternNode::getViewBox() const 310 { 311 if(mpViewBox) 312 { 313 return mpViewBox; 314 } 315 316 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 317 318 if(mpXLink) 319 { 320 return mpXLink->getViewBox(); 321 } 322 323 return 0; 324 } 325 326 const SvgAspectRatio& SvgPatternNode::getSvgAspectRatio() const 327 { 328 if(maSvgAspectRatio.isSet()) 329 { 330 return maSvgAspectRatio; 331 } 332 333 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 334 335 if(mpXLink) 336 { 337 return mpXLink->getSvgAspectRatio(); 338 } 339 340 return maSvgAspectRatio; 341 } 342 343 const SvgNumber& SvgPatternNode::getX() const 344 { 345 if(maX.isSet()) 346 { 347 return maX; 348 } 349 350 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 351 352 if(mpXLink) 353 { 354 return mpXLink->getX(); 355 } 356 357 return maX; 358 } 359 360 const SvgNumber& SvgPatternNode::getY() const 361 { 362 if(maY.isSet()) 363 { 364 return maY; 365 } 366 367 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 368 369 if(mpXLink) 370 { 371 return mpXLink->getY(); 372 } 373 374 return maY; 375 } 376 377 const SvgNumber& SvgPatternNode::getWidth() const 378 { 379 if(maWidth.isSet()) 380 { 381 return maWidth; 382 } 383 384 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 385 386 if(mpXLink) 387 { 388 return mpXLink->getWidth(); 389 } 390 391 return maWidth; 392 } 393 394 const SvgNumber& SvgPatternNode::getHeight() const 395 { 396 if(maHeight.isSet()) 397 { 398 return maHeight; 399 } 400 401 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 402 403 if(mpXLink) 404 { 405 return mpXLink->getHeight(); 406 } 407 408 return maHeight; 409 } 410 411 const SvgUnits* SvgPatternNode::getPatternUnits() const 412 { 413 if(mpPatternUnits) 414 { 415 return mpPatternUnits; 416 } 417 418 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 419 420 if(mpXLink) 421 { 422 return mpXLink->getPatternUnits(); 423 } 424 425 return 0; 426 } 427 428 const SvgUnits* SvgPatternNode::getPatternContentUnits() const 429 { 430 if(mpPatternContentUnits) 431 { 432 return mpPatternContentUnits; 433 } 434 435 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 436 437 if(mpXLink) 438 { 439 return mpXLink->getPatternContentUnits(); 440 } 441 442 return 0; 443 } 444 445 const basegfx::B2DHomMatrix* SvgPatternNode::getPatternTransform() const 446 { 447 if(mpaPatternTransform) 448 { 449 return mpaPatternTransform; 450 } 451 452 const_cast< SvgPatternNode* >(this)->tryToFindLink(); 453 454 if(mpXLink) 455 { 456 return mpXLink->getPatternTransform(); 457 } 458 459 return 0; 460 } 461 462 } // end of namespace svgreader 463 } // end of namespace svgio 464 465 ////////////////////////////////////////////////////////////////////////////// 466 // eof 467