bump product version to 7.2.5.1
[LibreOffice.git] / svgio / source / svgreader / svggradientnode.cxx
blob8aa4371e0cfc8a65af743a37ff1407fd35f8e23f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svggradientnode.hxx>
21 #include <svgdocument.hxx>
22 #include <svggradientstopnode.hxx>
24 namespace svgio::svgreader
26 void SvgGradientNode::tryToFindLink()
28 if(!mpXLink && !maXLink.isEmpty())
30 mpXLink = dynamic_cast< const SvgGradientNode* >(getDocument().findSvgNodeById(maXLink));
34 SvgGradientNode::SvgGradientNode(
35 SVGToken aType,
36 SvgDocument& rDocument,
37 SvgNode* pParent)
38 : SvgNode(aType, rDocument, pParent),
39 maSvgStyleAttributes(*this),
40 maX1(),
41 maY1(),
42 maX2(),
43 maY2(),
44 maCx(),
45 maCy(),
46 maR(),
47 maFx(),
48 maFy(),
49 maGradientUnits(SvgUnits::objectBoundingBox),
50 maSpreadMethod(drawinglayer::primitive2d::SpreadMethod::Pad),
51 mbResolvingLink(false),
52 maXLink(),
53 mpXLink(nullptr)
55 OSL_ENSURE(aType == SVGToken::LinearGradient || aType == SVGToken::RadialGradient, "SvgGradientNode should only be used for Linear and Radial gradient (!)");
58 SvgGradientNode::~SvgGradientNode()
60 // do NOT delete mpXLink, it's only referenced, not owned
63 const SvgStyleAttributes* SvgGradientNode::getSvgStyleAttributes() const
65 return checkForCssStyle(
66 SVGToken::LinearGradient == getType() ? OUString("linearGradient") : OUString("radialGradient"),
67 maSvgStyleAttributes);
70 void SvgGradientNode::parseAttribute(const OUString& rTokenName, SVGToken aSVGToken, const OUString& aContent)
72 // call parent
73 SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
75 // read style attributes
76 maSvgStyleAttributes.parseStyleAttribute(aSVGToken, aContent, false);
78 // parse own
79 switch(aSVGToken)
81 case SVGToken::Style:
83 readLocalCssStyle(aContent);
84 break;
86 case SVGToken::X1:
88 SvgNumber aNum;
90 if(readSingleNumber(aContent, aNum))
92 maX1 = aNum;
94 break;
96 case SVGToken::Y1:
98 SvgNumber aNum;
100 if(readSingleNumber(aContent, aNum))
102 maY1 = aNum;
104 break;
106 case SVGToken::X2:
108 SvgNumber aNum;
110 if(readSingleNumber(aContent, aNum))
112 maX2 = aNum;
114 break;
116 case SVGToken::Y2:
118 SvgNumber aNum;
120 if(readSingleNumber(aContent, aNum))
122 maY2 = aNum;
124 break;
126 case SVGToken::Cx:
128 SvgNumber aNum;
130 if(readSingleNumber(aContent, aNum))
132 maCx = aNum;
134 break;
136 case SVGToken::Cy:
138 SvgNumber aNum;
140 if(readSingleNumber(aContent, aNum))
142 maCy = aNum;
144 break;
146 case SVGToken::Fx:
148 SvgNumber aNum;
150 if(readSingleNumber(aContent, aNum))
152 maFx = aNum;
154 break;
156 case SVGToken::Fy:
158 SvgNumber aNum;
160 if(readSingleNumber(aContent, aNum))
162 maFy = aNum;
164 break;
166 case SVGToken::R:
168 SvgNumber aNum;
170 if(readSingleNumber(aContent, aNum))
172 if(aNum.isPositive())
174 maR = aNum;
177 break;
179 case SVGToken::GradientUnits:
181 if(!aContent.isEmpty())
183 if(aContent.match(commonStrings::aStrUserSpaceOnUse))
185 setGradientUnits(SvgUnits::userSpaceOnUse);
187 else if(aContent.match(commonStrings::aStrObjectBoundingBox))
189 setGradientUnits(SvgUnits::objectBoundingBox);
192 break;
194 case SVGToken::SpreadMethod:
196 if(!aContent.isEmpty())
198 if(aContent.startsWith("pad"))
200 setSpreadMethod(drawinglayer::primitive2d::SpreadMethod::Pad);
202 else if(aContent.startsWith("reflect"))
204 setSpreadMethod(drawinglayer::primitive2d::SpreadMethod::Reflect);
206 else if(aContent.startsWith("repeat"))
208 setSpreadMethod(drawinglayer::primitive2d::SpreadMethod::Repeat);
211 break;
213 case SVGToken::GradientTransform:
215 const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this));
217 if(!aMatrix.isIdentity())
219 setGradientTransform(&aMatrix);
221 break;
223 case SVGToken::XlinkHref:
225 const sal_Int32 nLen(aContent.getLength());
227 if(nLen && '#' == aContent[0])
229 maXLink = aContent.copy(1);
230 tryToFindLink();
232 break;
234 default:
236 break;
241 void SvgGradientNode::collectGradientEntries(drawinglayer::primitive2d::SvgGradientEntryVector& aVector) const
243 if(getChildren().empty())
245 const_cast< SvgGradientNode* >(this)->tryToFindLink();
247 if (mpXLink && !mbResolvingLink)
249 mbResolvingLink = true;
250 mpXLink->collectGradientEntries(aVector);
251 mbResolvingLink = false;
254 else
256 const sal_uInt32 nCount(getChildren().size());
258 for(sal_uInt32 a(0); a < nCount; a++)
260 const SvgGradientStopNode* pCandidate = dynamic_cast< const SvgGradientStopNode* >(getChildren()[a].get());
262 if(pCandidate)
264 const SvgStyleAttributes* pStyle = pCandidate->getSvgStyleAttributes();
266 if(pStyle)
268 const SvgNumber aOffset(pCandidate->getOffset());
269 double fOffset(0.0);
271 if(SvgUnit::percent == aOffset.getUnit())
273 // percent is not relative to distances in ColorStop context, solve locally
274 fOffset = aOffset.getNumber() * 0.01;
276 else
278 fOffset = aOffset.solve(*this);
281 if(fOffset < 0.0)
283 OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)");
284 fOffset = 0.0;
286 else if(fOffset > 1.0)
288 OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)");
289 fOffset = 1.0;
292 aVector.emplace_back(
293 fOffset,
294 pStyle->getStopColor(),
295 pStyle->getStopOpacity().solve(*this));
297 else
299 OSL_ENSURE(false, "OOps, SvgGradientStopNode without Style (!)");
306 SvgNumber SvgGradientNode::getX1() const
308 if(maX1.isSet())
310 return maX1;
313 const_cast< SvgGradientNode* >(this)->tryToFindLink();
315 if (mpXLink && !mbResolvingLink)
317 mbResolvingLink = true;
318 auto ret = mpXLink->getX1();
319 mbResolvingLink = false;
320 return ret;
323 // default is 0%
324 return SvgNumber(0.0, SvgUnit::percent);
327 SvgNumber SvgGradientNode::getY1() const
329 if(maY1.isSet())
331 return maY1;
334 const_cast< SvgGradientNode* >(this)->tryToFindLink();
336 if (mpXLink && !mbResolvingLink)
338 mbResolvingLink = true;
339 auto ret = mpXLink->getY1();
340 mbResolvingLink = false;
341 return ret;
344 // default is 0%
345 return SvgNumber(0.0, SvgUnit::percent);
348 SvgNumber SvgGradientNode::getX2() const
350 if(maX2.isSet())
352 return maX2;
355 const_cast< SvgGradientNode* >(this)->tryToFindLink();
357 if (mpXLink && !mbResolvingLink)
359 mbResolvingLink = true;
360 auto ret = mpXLink->getX2();
361 mbResolvingLink = false;
362 return ret;
365 // default is 100%
366 return SvgNumber(100.0, SvgUnit::percent);
369 SvgNumber SvgGradientNode::getY2() const
371 if(maY2.isSet())
373 return maY2;
376 const_cast< SvgGradientNode* >(this)->tryToFindLink();
378 if (mpXLink && !mbResolvingLink)
380 mbResolvingLink = true;
381 auto ret = mpXLink->getY2();
382 mbResolvingLink = false;
383 return ret;
386 // default is 0%
387 return SvgNumber(0.0, SvgUnit::percent);
390 SvgNumber SvgGradientNode::getCx() const
392 if(maCx.isSet())
394 return maCx;
397 const_cast< SvgGradientNode* >(this)->tryToFindLink();
399 if (mpXLink && !mbResolvingLink)
401 mbResolvingLink = true;
402 auto ret = mpXLink->getCx();
403 mbResolvingLink = false;
404 return ret;
407 // default is 50%
408 return SvgNumber(50.0, SvgUnit::percent);
411 SvgNumber SvgGradientNode::getCy() const
413 if(maCy.isSet())
415 return maCy;
418 const_cast< SvgGradientNode* >(this)->tryToFindLink();
420 if (mpXLink && !mbResolvingLink)
422 mbResolvingLink = true;
423 auto ret = mpXLink->getCy();
424 mbResolvingLink = false;
425 return ret;
428 // default is 50%
429 return SvgNumber(50.0, SvgUnit::percent);
432 SvgNumber SvgGradientNode::getR() const
434 if(maR.isSet())
436 return maR;
439 const_cast< SvgGradientNode* >(this)->tryToFindLink();
441 if (mpXLink && !mbResolvingLink)
443 mbResolvingLink = true;
444 auto ret = mpXLink->getR();
445 mbResolvingLink = false;
446 return ret;
449 // default is 50%
450 return SvgNumber(50.0, SvgUnit::percent);
453 const SvgNumber* SvgGradientNode::getFx() const
455 if(maFx.isSet())
457 return &maFx;
460 const_cast< SvgGradientNode* >(this)->tryToFindLink();
462 if (mpXLink && !mbResolvingLink)
464 mbResolvingLink = true;
465 auto ret = mpXLink->getFx();
466 mbResolvingLink = false;
467 return ret;
470 return nullptr;
473 const SvgNumber* SvgGradientNode::getFy() const
475 if(maFy.isSet())
477 return &maFy;
480 const_cast< SvgGradientNode* >(this)->tryToFindLink();
482 if (mpXLink && !mbResolvingLink)
484 mbResolvingLink = true;
485 auto ret = mpXLink->getFy();
486 mbResolvingLink = false;
487 return ret;
490 return nullptr;
493 const basegfx::B2DHomMatrix* SvgGradientNode::getGradientTransform() const
495 if(mpaGradientTransform)
497 return mpaGradientTransform.get();
500 const_cast< SvgGradientNode* >(this)->tryToFindLink();
502 if (mpXLink && !mbResolvingLink)
504 mbResolvingLink = true;
505 auto ret = mpXLink->getGradientTransform();
506 mbResolvingLink = false;
507 return ret;
510 return nullptr;
513 void SvgGradientNode::setGradientTransform(const basegfx::B2DHomMatrix* pMatrix)
515 mpaGradientTransform.reset();
517 if(pMatrix)
519 mpaGradientTransform.reset(new basegfx::B2DHomMatrix(*pMatrix) );
523 } // end of namespace svgio::svgreader
525 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */