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 } 246 } 247 248 void SvgGradientNode::collectGradientEntries(drawinglayer::primitive2d::SvgGradientEntryVector& aVector) const 249 { 250 if(getChildren().empty()) 251 { 252 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 253 254 if(mpXLink) 255 { 256 mpXLink->collectGradientEntries(aVector); 257 } 258 } 259 else 260 { 261 const sal_uInt32 nCount(getChildren().size()); 262 263 for(sal_uInt32 a(0); a < nCount; a++) 264 { 265 const SvgGradientStopNode* pCandidate = dynamic_cast< const SvgGradientStopNode* >(getChildren()[a]); 266 267 if(pCandidate) 268 { 269 const SvgStyleAttributes* pStyle = pCandidate->getSvgStyleAttributes(); 270 271 if(pStyle) 272 { 273 const SvgNumber aOffset(pCandidate->getOffset()); 274 double fOffset(0.0); 275 276 if(Unit_percent == aOffset.getUnit()) 277 { 278 // percent is not relative to distances in ColorStop context, solve locally 279 fOffset = aOffset.getNumber() * 0.01; 280 } 281 else 282 { 283 fOffset = aOffset.solve(*this); 284 } 285 286 if(fOffset < 0.0) 287 { 288 OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)"); 289 fOffset = 0.0; 290 } 291 else if(fOffset > 1.0) 292 { 293 OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)"); 294 fOffset = 1.0; 295 } 296 297 aVector.push_back( 298 drawinglayer::primitive2d::SvgGradientEntry( 299 fOffset, 300 pStyle->getStopColor(), 301 pStyle->getStopOpacity().solve(*this))); 302 } 303 else 304 { 305 OSL_ENSURE(false, "OOps, SvgGradientStopNode without Style (!)"); 306 } 307 } 308 } 309 } 310 } 311 312 const SvgNumber SvgGradientNode::getX1() const 313 { 314 if(maX1.isSet()) 315 { 316 return maX1; 317 } 318 319 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 320 321 if(mpXLink) 322 { 323 return mpXLink->getX1(); 324 } 325 326 // default is 0% 327 return SvgNumber(0.0, Unit_percent); 328 } 329 330 const SvgNumber SvgGradientNode::getY1() const 331 { 332 if(maY1.isSet()) 333 { 334 return maY1; 335 } 336 337 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 338 339 if(mpXLink) 340 { 341 return mpXLink->getY1(); 342 } 343 344 // default is 0% 345 return SvgNumber(0.0, Unit_percent); 346 } 347 348 const SvgNumber SvgGradientNode::getX2() const 349 { 350 if(maX2.isSet()) 351 { 352 return maX2; 353 } 354 355 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 356 357 if(mpXLink) 358 { 359 return mpXLink->getX2(); 360 } 361 362 // default is 100% 363 return SvgNumber(100.0, Unit_percent); 364 } 365 366 const SvgNumber SvgGradientNode::getY2() const 367 { 368 if(maY2.isSet()) 369 { 370 return maY2; 371 } 372 373 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 374 375 if(mpXLink) 376 { 377 return mpXLink->getY2(); 378 } 379 380 // default is 0% 381 return SvgNumber(0.0, Unit_percent); 382 } 383 384 const SvgNumber SvgGradientNode::getCx() const 385 { 386 if(maCx.isSet()) 387 { 388 return maCx; 389 } 390 391 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 392 393 if(mpXLink) 394 { 395 return mpXLink->getCx(); 396 } 397 398 // default is 50% 399 return SvgNumber(50.0, Unit_percent); 400 } 401 402 const SvgNumber SvgGradientNode::getCy() const 403 { 404 if(maCy.isSet()) 405 { 406 return maCy; 407 } 408 409 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 410 411 if(mpXLink) 412 { 413 return mpXLink->getCy(); 414 } 415 416 // default is 50% 417 return SvgNumber(50.0, Unit_percent); 418 } 419 420 const SvgNumber SvgGradientNode::getR() const 421 { 422 if(maR.isSet()) 423 { 424 return maR; 425 } 426 427 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 428 429 if(mpXLink) 430 { 431 return mpXLink->getR(); 432 } 433 434 // default is 50% 435 return SvgNumber(50.0, Unit_percent); 436 } 437 438 const SvgNumber* SvgGradientNode::getFx() const 439 { 440 if(maFx.isSet()) 441 { 442 return &maFx; 443 } 444 445 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 446 447 if(mpXLink) 448 { 449 return mpXLink->getFx(); 450 } 451 452 return 0; 453 } 454 455 const SvgNumber* SvgGradientNode::getFy() const 456 { 457 if(maFy.isSet()) 458 { 459 return &maFy; 460 } 461 462 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 463 464 if(mpXLink) 465 { 466 return mpXLink->getFy(); 467 } 468 469 return 0; 470 } 471 472 const basegfx::B2DHomMatrix* SvgGradientNode::getGradientTransform() const 473 { 474 if(mpaGradientTransform) 475 { 476 return mpaGradientTransform; 477 } 478 479 const_cast< SvgGradientNode* >(this)->tryToFindLink(); 480 481 if(mpXLink) 482 { 483 return mpXLink->getGradientTransform(); 484 } 485 486 return 0; 487 } 488 489 void SvgGradientNode::setGradientTransform(const basegfx::B2DHomMatrix* pMatrix) 490 { 491 if(mpaGradientTransform) 492 { 493 delete mpaGradientTransform; 494 mpaGradientTransform = 0; 495 } 496 497 if(pMatrix) 498 { 499 mpaGradientTransform = new basegfx::B2DHomMatrix(*pMatrix); 500 } 501 } 502 503 } // end of namespace svgreader 504 } // end of namespace svgio 505 506 ////////////////////////////////////////////////////////////////////////////// 507 // eof 508