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/svggradientnode.hxx> 26 #include <svgio/svgreader/svgdocument.hxx> 27 #include <svgio/svgreader/svggradientstopnode.hxx> 28 29 ////////////////////////////////////////////////////////////////////////////// 30 31 namespace svgio 32 { 33 namespace svgreader 34 { tryToFindLink()35 void SvgGradientNode::tryToFindLink() 36 { 37 if(!mpXLink && maXLink.getLength()) 38 { 39 mpXLink = dynamic_cast< const SvgGradientNode* >(getDocument().findSvgNodeById(maXLink)); 40 } 41 } 42 SvgGradientNode(SVGToken aType,SvgDocument & rDocument,SvgNode * pParent)43 SvgGradientNode::SvgGradientNode( 44 SVGToken aType, 45 SvgDocument& rDocument, 46 SvgNode* pParent) 47 : SvgNode(aType, rDocument, pParent), 48 maSvgStyleAttributes(*this), 49 maX1(), 50 maY1(), 51 maX2(), 52 maY2(), 53 maCx(), 54 maCy(), 55 maR(), 56 maFx(), 57 maFy(), 58 maGradientUnits(objectBoundingBox), 59 maSpreadMethod(drawinglayer::primitive2d::Spread_pad), 60 mpaGradientTransform(0), 61 maXLink(), 62 mpXLink(0) 63 { 64 OSL_ENSURE(aType == SVGTokenLinearGradient || aType == SVGTokenRadialGradient, "SvgGradientNode should ony be used for Linear and Radial gradient (!)"); 65 } 66 ~SvgGradientNode()67 SvgGradientNode::~SvgGradientNode() 68 { 69 if(mpaGradientTransform) delete mpaGradientTransform; 70 // do NOT delete mpXLink, it's only referenced, not owned 71 } 72 getSvgStyleAttributes() const73 const SvgStyleAttributes* SvgGradientNode::getSvgStyleAttributes() const 74 { 75 return &maSvgStyleAttributes; 76 } 77 parseAttribute(const rtl::OUString & rTokenName,SVGToken aSVGToken,const rtl::OUString & aContent)78 void SvgGradientNode::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 SVGTokenX1: 95 { 96 SvgNumber aNum; 97 98 if(readSingleNumber(aContent, aNum)) 99 { 100 setX1(aNum); 101 } 102 break; 103 } 104 case SVGTokenY1: 105 { 106 SvgNumber aNum; 107 108 if(readSingleNumber(aContent, aNum)) 109 { 110 setY1(aNum); 111 } 112 break; 113 } 114 case SVGTokenX2: 115 { 116 SvgNumber aNum; 117 118 if(readSingleNumber(aContent, aNum)) 119 { 120 setX2(aNum); 121 } 122 break; 123 } 124 case SVGTokenY2: 125 { 126 SvgNumber aNum; 127 128 if(readSingleNumber(aContent, aNum)) 129 { 130 setY2(aNum); 131 } 132 break; 133 } 134 case SVGTokenCx: 135 { 136 SvgNumber aNum; 137 138 if(readSingleNumber(aContent, aNum)) 139 { 140 setCx(aNum); 141 } 142 break; 143 } 144 case SVGTokenCy: 145 { 146 SvgNumber aNum; 147 148 if(readSingleNumber(aContent, aNum)) 149 { 150 setCy(aNum); 151 } 152 break; 153 } 154 case SVGTokenFx: 155 { 156 SvgNumber aNum; 157 158 if(readSingleNumber(aContent, aNum)) 159 { 160 setFx(aNum); 161 } 162 break; 163 } 164 case SVGTokenFy: 165 { 166 SvgNumber aNum; 167 168 if(readSingleNumber(aContent, aNum)) 169 { 170 setFy(aNum); 171 } 172 break; 173 } 174 case SVGTokenR: 175 { 176 SvgNumber aNum; 177 178 if(readSingleNumber(aContent, aNum)) 179 { 180 if(aNum.isPositive()) 181 { 182 setR(aNum); 183 } 184 } 185 break; 186 } 187 case SVGTokenGradientUnits: 188 { 189 if(aContent.getLength()) 190 { 191 if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0)) 192 { 193 setGradientUnits(userSpaceOnUse); 194 } 195 else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0)) 196 { 197 setGradientUnits(objectBoundingBox); 198 } 199 } 200 break; 201 } 202 case SVGTokenSpreadMethod: 203 { 204 if(aContent.getLength()) 205 { 206 static rtl::OUString aStrPad(rtl::OUString::createFromAscii("pad")); 207 static rtl::OUString aStrReflect(rtl::OUString::createFromAscii("reflect")); 208 static rtl::OUString aStrRepeat(rtl::OUString::createFromAscii("repeat")); 209 210 if(aContent.match(aStrPad, 0)) 211 { 212 setSpreadMethod(drawinglayer::primitive2d::Spread_pad); 213 } 214 else if(aContent.match(aStrReflect, 0)) 215 { 216 setSpreadMethod(drawinglayer::primitive2d::Spread_reflect); 217 } 218 else if(aContent.match(aStrRepeat, 0)) 219 { 220 setSpreadMethod(drawinglayer::primitive2d::Spread_repeat); 221 } 222 } 223 break; 224 } 225 case SVGTokenGradientTransform: 226 { 227 const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); 228 229 if(!aMatrix.isIdentity()) 230 { 231 setGradientTransform(&aMatrix); 232 } 233 break; 234 } 235 case SVGTokenXlinkHref: 236 { 237 const sal_Int32 nLen(aContent.getLength()); 238 239 if(nLen && sal_Unicode('#') == aContent[0]) 240 { 241 maXLink = aContent.copy(1); 242 tryToFindLink(); 243 } 244 break; 245 } 246 default: 247 { 248 break; 249 } 250 } 251 } 252 collectGradientEntries(drawinglayer::primitive2d::SvgGradientEntryVector & aVector) const253 void SvgGradientNode::collectGradientEntries(drawinglayer::primitive2d::SvgGradientEntryVector& aVector) const 254 { 255 if(getChildren().empty()) 256 { 257 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 258 259 if(mpXLink) 260 { 261 mpXLink->collectGradientEntries(aVector); 262 } 263 } 264 else 265 { 266 const sal_uInt32 nCount(getChildren().size()); 267 268 for(sal_uInt32 a(0); a < nCount; a++) 269 { 270 const SvgGradientStopNode* pCandidate = dynamic_cast< const SvgGradientStopNode* >(getChildren()[a]); 271 272 if(pCandidate) 273 { 274 const SvgStyleAttributes* pStyle = pCandidate->getSvgStyleAttributes(); 275 276 if(pStyle) 277 { 278 const SvgNumber aOffset(pCandidate->getOffset()); 279 double fOffset(0.0); 280 281 if(Unit_percent == aOffset.getUnit()) 282 { 283 // percent is not relative to distances in ColorStop context, solve locally 284 fOffset = aOffset.getNumber() * 0.01; 285 } 286 else 287 { 288 fOffset = aOffset.solve(*this); 289 } 290 291 if(fOffset < 0.0) 292 { 293 OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)"); 294 fOffset = 0.0; 295 } 296 else if(fOffset > 1.0) 297 { 298 OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)"); 299 fOffset = 1.0; 300 } 301 302 aVector.push_back( 303 drawinglayer::primitive2d::SvgGradientEntry( 304 fOffset, 305 pStyle->getStopColor(), 306 pStyle->getStopOpacity().solve(*this))); 307 } 308 else 309 { 310 OSL_ENSURE(false, "OOps, SvgGradientStopNode without Style (!)"); 311 } 312 } 313 } 314 } 315 } 316 getX1() const317 const SvgNumber SvgGradientNode::getX1() const 318 { 319 if(maX1.isSet()) 320 { 321 return maX1; 322 } 323 324 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 325 326 if(mpXLink) 327 { 328 return mpXLink->getX1(); 329 } 330 331 // default is 0% 332 return SvgNumber(0.0, Unit_percent); 333 } 334 getY1() const335 const SvgNumber SvgGradientNode::getY1() const 336 { 337 if(maY1.isSet()) 338 { 339 return maY1; 340 } 341 342 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 343 344 if(mpXLink) 345 { 346 return mpXLink->getY1(); 347 } 348 349 // default is 0% 350 return SvgNumber(0.0, Unit_percent); 351 } 352 getX2() const353 const SvgNumber SvgGradientNode::getX2() const 354 { 355 if(maX2.isSet()) 356 { 357 return maX2; 358 } 359 360 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 361 362 if(mpXLink) 363 { 364 return mpXLink->getX2(); 365 } 366 367 // default is 100% 368 return SvgNumber(100.0, Unit_percent); 369 } 370 getY2() const371 const SvgNumber SvgGradientNode::getY2() const 372 { 373 if(maY2.isSet()) 374 { 375 return maY2; 376 } 377 378 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 379 380 if(mpXLink) 381 { 382 return mpXLink->getY2(); 383 } 384 385 // default is 0% 386 return SvgNumber(0.0, Unit_percent); 387 } 388 getCx() const389 const SvgNumber SvgGradientNode::getCx() const 390 { 391 if(maCx.isSet()) 392 { 393 return maCx; 394 } 395 396 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 397 398 if(mpXLink) 399 { 400 return mpXLink->getCx(); 401 } 402 403 // default is 50% 404 return SvgNumber(50.0, Unit_percent); 405 } 406 getCy() const407 const SvgNumber SvgGradientNode::getCy() const 408 { 409 if(maCy.isSet()) 410 { 411 return maCy; 412 } 413 414 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 415 416 if(mpXLink) 417 { 418 return mpXLink->getCy(); 419 } 420 421 // default is 50% 422 return SvgNumber(50.0, Unit_percent); 423 } 424 getR() const425 const SvgNumber SvgGradientNode::getR() const 426 { 427 if(maR.isSet()) 428 { 429 return maR; 430 } 431 432 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 433 434 if(mpXLink) 435 { 436 return mpXLink->getR(); 437 } 438 439 // default is 50% 440 return SvgNumber(50.0, Unit_percent); 441 } 442 getFx() const443 const SvgNumber* SvgGradientNode::getFx() const 444 { 445 if(maFx.isSet()) 446 { 447 return &maFx; 448 } 449 450 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 451 452 if(mpXLink) 453 { 454 return mpXLink->getFx(); 455 } 456 457 return 0; 458 } 459 getFy() const460 const SvgNumber* SvgGradientNode::getFy() const 461 { 462 if(maFy.isSet()) 463 { 464 return &maFy; 465 } 466 467 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 468 469 if(mpXLink) 470 { 471 return mpXLink->getFy(); 472 } 473 474 return 0; 475 } 476 getGradientTransform() const477 const basegfx::B2DHomMatrix* SvgGradientNode::getGradientTransform() const 478 { 479 if(mpaGradientTransform) 480 { 481 return mpaGradientTransform; 482 } 483 484 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 485 486 if(mpXLink) 487 { 488 return mpXLink->getGradientTransform(); 489 } 490 491 return 0; 492 } 493 setGradientTransform(const basegfx::B2DHomMatrix * pMatrix)494 void SvgGradientNode::setGradientTransform(const basegfx::B2DHomMatrix* pMatrix) 495 { 496 if(mpaGradientTransform) 497 { 498 delete mpaGradientTransform; 499 mpaGradientTransform = 0; 500 } 501 502 if(pMatrix) 503 { 504 mpaGradientTransform = new basegfx::B2DHomMatrix(*pMatrix); 505 } 506 } 507 508 } // end of namespace svgreader 509 } // end of namespace svgio 510 511 ////////////////////////////////////////////////////////////////////////////// 512 // eof 513