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