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