1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
28 void SvgGradientNode::tryToFindLink()
30 if(!mpXLink
&& !maXLink
.isEmpty())
32 mpXLink
= dynamic_cast< const SvgGradientNode
* >(getDocument().findSvgNodeById(maXLink
));
36 SvgGradientNode::SvgGradientNode(
38 SvgDocument
& rDocument
,
40 : SvgNode(aType
, rDocument
, pParent
),
41 maSvgStyleAttributes(*this),
51 maGradientUnits(objectBoundingBox
),
52 maSpreadMethod(drawinglayer::primitive2d::SpreadMethod::Pad
),
53 mbResolvingLink(false),
57 OSL_ENSURE(aType
== SVGTokenLinearGradient
|| aType
== SVGTokenRadialGradient
, "SvgGradientNode should only be used for Linear and Radial gradient (!)");
60 SvgGradientNode::~SvgGradientNode()
62 // do NOT delete mpXLink, it's only referenced, not owned
65 const SvgStyleAttributes
* SvgGradientNode::getSvgStyleAttributes() const
67 return checkForCssStyle(
68 SVGTokenLinearGradient
== getType() ? OUString("linearGradient") : OUString("radialGradient"),
69 maSvgStyleAttributes
);
72 void SvgGradientNode::parseAttribute(const OUString
& rTokenName
, SVGToken aSVGToken
, const OUString
& aContent
)
75 SvgNode::parseAttribute(rTokenName
, aSVGToken
, aContent
);
77 // read style attributes
78 maSvgStyleAttributes
.parseStyleAttribute(aSVGToken
, aContent
, false);
85 readLocalCssStyle(aContent
);
92 if(readSingleNumber(aContent
, aNum
))
102 if(readSingleNumber(aContent
, aNum
))
112 if(readSingleNumber(aContent
, aNum
))
122 if(readSingleNumber(aContent
, aNum
))
132 if(readSingleNumber(aContent
, aNum
))
142 if(readSingleNumber(aContent
, aNum
))
152 if(readSingleNumber(aContent
, aNum
))
162 if(readSingleNumber(aContent
, aNum
))
172 if(readSingleNumber(aContent
, aNum
))
174 if(aNum
.isPositive())
181 case SVGTokenGradientUnits
:
183 if(!aContent
.isEmpty())
185 if(aContent
.match(commonStrings::aStrUserSpaceOnUse
))
187 setGradientUnits(userSpaceOnUse
);
189 else if(aContent
.match(commonStrings::aStrObjectBoundingBox
))
191 setGradientUnits(objectBoundingBox
);
196 case SVGTokenSpreadMethod
:
198 if(!aContent
.isEmpty())
200 if(aContent
.startsWith("pad"))
202 setSpreadMethod(drawinglayer::primitive2d::SpreadMethod::Pad
);
204 else if(aContent
.startsWith("reflect"))
206 setSpreadMethod(drawinglayer::primitive2d::SpreadMethod::Reflect
);
208 else if(aContent
.startsWith("repeat"))
210 setSpreadMethod(drawinglayer::primitive2d::SpreadMethod::Repeat
);
215 case SVGTokenGradientTransform
:
217 const basegfx::B2DHomMatrix
aMatrix(readTransform(aContent
, *this));
219 if(!aMatrix
.isIdentity())
221 setGradientTransform(&aMatrix
);
225 case SVGTokenXlinkHref
:
227 const sal_Int32
nLen(aContent
.getLength());
229 if(nLen
&& '#' == aContent
[0])
231 maXLink
= aContent
.copy(1);
243 void SvgGradientNode::collectGradientEntries(drawinglayer::primitive2d::SvgGradientEntryVector
& aVector
) const
245 if(getChildren().empty())
247 const_cast< SvgGradientNode
* >(this)->tryToFindLink();
249 if (mpXLink
&& !mbResolvingLink
)
251 mbResolvingLink
= true;
252 mpXLink
->collectGradientEntries(aVector
);
253 mbResolvingLink
= false;
258 const sal_uInt32
nCount(getChildren().size());
260 for(sal_uInt32
a(0); a
< nCount
; a
++)
262 const SvgGradientStopNode
* pCandidate
= dynamic_cast< const SvgGradientStopNode
* >(getChildren()[a
].get());
266 const SvgStyleAttributes
* pStyle
= pCandidate
->getSvgStyleAttributes();
270 const SvgNumber
aOffset(pCandidate
->getOffset());
273 if(Unit_percent
== aOffset
.getUnit())
275 // percent is not relative to distances in ColorStop context, solve locally
276 fOffset
= aOffset
.getNumber() * 0.01;
280 fOffset
= aOffset
.solve(*this);
285 OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)");
288 else if(fOffset
> 1.0)
290 OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)");
294 aVector
.emplace_back(
296 pStyle
->getStopColor(),
297 pStyle
->getStopOpacity().solve(*this));
301 OSL_ENSURE(false, "OOps, SvgGradientStopNode without Style (!)");
308 const SvgNumber
SvgGradientNode::getX1() const
315 const_cast< SvgGradientNode
* >(this)->tryToFindLink();
317 if (mpXLink
&& !mbResolvingLink
)
319 mbResolvingLink
= true;
320 auto ret
= mpXLink
->getX1();
321 mbResolvingLink
= false;
326 return SvgNumber(0.0, Unit_percent
);
329 const SvgNumber
SvgGradientNode::getY1() const
336 const_cast< SvgGradientNode
* >(this)->tryToFindLink();
338 if (mpXLink
&& !mbResolvingLink
)
340 mbResolvingLink
= true;
341 auto ret
= mpXLink
->getY1();
342 mbResolvingLink
= false;
347 return SvgNumber(0.0, Unit_percent
);
350 const SvgNumber
SvgGradientNode::getX2() const
357 const_cast< SvgGradientNode
* >(this)->tryToFindLink();
359 if (mpXLink
&& !mbResolvingLink
)
361 mbResolvingLink
= true;
362 auto ret
= mpXLink
->getX2();
363 mbResolvingLink
= false;
368 return SvgNumber(100.0, Unit_percent
);
371 const SvgNumber
SvgGradientNode::getY2() const
378 const_cast< SvgGradientNode
* >(this)->tryToFindLink();
380 if (mpXLink
&& !mbResolvingLink
)
382 mbResolvingLink
= true;
383 auto ret
= mpXLink
->getY2();
384 mbResolvingLink
= false;
389 return SvgNumber(0.0, Unit_percent
);
392 const SvgNumber
SvgGradientNode::getCx() const
399 const_cast< SvgGradientNode
* >(this)->tryToFindLink();
401 if (mpXLink
&& !mbResolvingLink
)
403 mbResolvingLink
= true;
404 auto ret
= mpXLink
->getCx();
405 mbResolvingLink
= false;
410 return SvgNumber(50.0, Unit_percent
);
413 const SvgNumber
SvgGradientNode::getCy() const
420 const_cast< SvgGradientNode
* >(this)->tryToFindLink();
422 if (mpXLink
&& !mbResolvingLink
)
424 mbResolvingLink
= true;
425 auto ret
= mpXLink
->getCy();
426 mbResolvingLink
= false;
431 return SvgNumber(50.0, Unit_percent
);
434 const SvgNumber
SvgGradientNode::getR() const
441 const_cast< SvgGradientNode
* >(this)->tryToFindLink();
443 if (mpXLink
&& !mbResolvingLink
)
445 mbResolvingLink
= true;
446 auto ret
= mpXLink
->getR();
447 mbResolvingLink
= false;
452 return SvgNumber(50.0, Unit_percent
);
455 const SvgNumber
* SvgGradientNode::getFx() const
462 const_cast< SvgGradientNode
* >(this)->tryToFindLink();
464 if (mpXLink
&& !mbResolvingLink
)
466 mbResolvingLink
= true;
467 auto ret
= mpXLink
->getFx();
468 mbResolvingLink
= false;
475 const SvgNumber
* SvgGradientNode::getFy() const
482 const_cast< SvgGradientNode
* >(this)->tryToFindLink();
484 if (mpXLink
&& !mbResolvingLink
)
486 mbResolvingLink
= true;
487 auto ret
= mpXLink
->getFy();
488 mbResolvingLink
= false;
495 const basegfx::B2DHomMatrix
* SvgGradientNode::getGradientTransform() const
497 if(mpaGradientTransform
)
499 return mpaGradientTransform
.get();
502 const_cast< SvgGradientNode
* >(this)->tryToFindLink();
504 if (mpXLink
&& !mbResolvingLink
)
506 mbResolvingLink
= true;
507 auto ret
= mpXLink
->getGradientTransform();
508 mbResolvingLink
= false;
515 void SvgGradientNode::setGradientTransform(const basegfx::B2DHomMatrix
* pMatrix
)
517 mpaGradientTransform
.reset();
521 mpaGradientTransform
.reset(new basegfx::B2DHomMatrix(*pMatrix
) );
525 } // end of namespace svgreader
526 } // end of namespace svgio
528 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */