lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / svgio / source / svgreader / svggradientnode.cxx
blob5399ef35443ad97ffcc002c2b65667a19873acf3
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
26 namespace svgreader
28 void SvgGradientNode::tryToFindLink()
30 if(!mpXLink && !maXLink.isEmpty())
32 mpXLink = dynamic_cast< const SvgGradientNode* >(getDocument().findSvgNodeById(maXLink));
36 SvgGradientNode::SvgGradientNode(
37 SVGToken aType,
38 SvgDocument& rDocument,
39 SvgNode* pParent)
40 : SvgNode(aType, rDocument, pParent),
41 maSvgStyleAttributes(*this),
42 maX1(),
43 maY1(),
44 maX2(),
45 maY2(),
46 maCx(),
47 maCy(),
48 maR(),
49 maFx(),
50 maFy(),
51 maGradientUnits(objectBoundingBox),
52 maSpreadMethod(drawinglayer::primitive2d::SpreadMethod::Pad),
53 mbResolvingLink(false),
54 maXLink(),
55 mpXLink(nullptr)
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)
74 // call parent
75 SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
77 // read style attributes
78 maSvgStyleAttributes.parseStyleAttribute(aSVGToken, aContent, false);
80 // parse own
81 switch(aSVGToken)
83 case SVGTokenStyle:
85 readLocalCssStyle(aContent);
86 break;
88 case SVGTokenX1:
90 SvgNumber aNum;
92 if(readSingleNumber(aContent, aNum))
94 maX1 = aNum;
96 break;
98 case SVGTokenY1:
100 SvgNumber aNum;
102 if(readSingleNumber(aContent, aNum))
104 maY1 = aNum;
106 break;
108 case SVGTokenX2:
110 SvgNumber aNum;
112 if(readSingleNumber(aContent, aNum))
114 maX2 = aNum;
116 break;
118 case SVGTokenY2:
120 SvgNumber aNum;
122 if(readSingleNumber(aContent, aNum))
124 maY2 = aNum;
126 break;
128 case SVGTokenCx:
130 SvgNumber aNum;
132 if(readSingleNumber(aContent, aNum))
134 maCx = aNum;
136 break;
138 case SVGTokenCy:
140 SvgNumber aNum;
142 if(readSingleNumber(aContent, aNum))
144 maCy = aNum;
146 break;
148 case SVGTokenFx:
150 SvgNumber aNum;
152 if(readSingleNumber(aContent, aNum))
154 maFx = aNum;
156 break;
158 case SVGTokenFy:
160 SvgNumber aNum;
162 if(readSingleNumber(aContent, aNum))
164 maFy = aNum;
166 break;
168 case SVGTokenR:
170 SvgNumber aNum;
172 if(readSingleNumber(aContent, aNum))
174 if(aNum.isPositive())
176 maR = aNum;
179 break;
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);
194 break;
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);
213 break;
215 case SVGTokenGradientTransform:
217 const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this));
219 if(!aMatrix.isIdentity())
221 setGradientTransform(&aMatrix);
223 break;
225 case SVGTokenXlinkHref:
227 const sal_Int32 nLen(aContent.getLength());
229 if(nLen && '#' == aContent[0])
231 maXLink = aContent.copy(1);
232 tryToFindLink();
234 break;
236 default:
238 break;
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;
256 else
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());
264 if(pCandidate)
266 const SvgStyleAttributes* pStyle = pCandidate->getSvgStyleAttributes();
268 if(pStyle)
270 const SvgNumber aOffset(pCandidate->getOffset());
271 double fOffset(0.0);
273 if(Unit_percent == aOffset.getUnit())
275 // percent is not relative to distances in ColorStop context, solve locally
276 fOffset = aOffset.getNumber() * 0.01;
278 else
280 fOffset = aOffset.solve(*this);
283 if(fOffset < 0.0)
285 OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)");
286 fOffset = 0.0;
288 else if(fOffset > 1.0)
290 OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)");
291 fOffset = 1.0;
294 aVector.emplace_back(
295 fOffset,
296 pStyle->getStopColor(),
297 pStyle->getStopOpacity().solve(*this));
299 else
301 OSL_ENSURE(false, "OOps, SvgGradientStopNode without Style (!)");
308 const SvgNumber SvgGradientNode::getX1() const
310 if(maX1.isSet())
312 return maX1;
315 const_cast< SvgGradientNode* >(this)->tryToFindLink();
317 if (mpXLink && !mbResolvingLink)
319 mbResolvingLink = true;
320 auto ret = mpXLink->getX1();
321 mbResolvingLink = false;
322 return ret;
325 // default is 0%
326 return SvgNumber(0.0, Unit_percent);
329 const SvgNumber SvgGradientNode::getY1() const
331 if(maY1.isSet())
333 return maY1;
336 const_cast< SvgGradientNode* >(this)->tryToFindLink();
338 if (mpXLink && !mbResolvingLink)
340 mbResolvingLink = true;
341 auto ret = mpXLink->getY1();
342 mbResolvingLink = false;
343 return ret;
346 // default is 0%
347 return SvgNumber(0.0, Unit_percent);
350 const SvgNumber SvgGradientNode::getX2() const
352 if(maX2.isSet())
354 return maX2;
357 const_cast< SvgGradientNode* >(this)->tryToFindLink();
359 if (mpXLink && !mbResolvingLink)
361 mbResolvingLink = true;
362 auto ret = mpXLink->getX2();
363 mbResolvingLink = false;
364 return ret;
367 // default is 100%
368 return SvgNumber(100.0, Unit_percent);
371 const SvgNumber SvgGradientNode::getY2() const
373 if(maY2.isSet())
375 return maY2;
378 const_cast< SvgGradientNode* >(this)->tryToFindLink();
380 if (mpXLink && !mbResolvingLink)
382 mbResolvingLink = true;
383 auto ret = mpXLink->getY2();
384 mbResolvingLink = false;
385 return ret;
388 // default is 0%
389 return SvgNumber(0.0, Unit_percent);
392 const SvgNumber SvgGradientNode::getCx() const
394 if(maCx.isSet())
396 return maCx;
399 const_cast< SvgGradientNode* >(this)->tryToFindLink();
401 if (mpXLink && !mbResolvingLink)
403 mbResolvingLink = true;
404 auto ret = mpXLink->getCx();
405 mbResolvingLink = false;
406 return ret;
409 // default is 50%
410 return SvgNumber(50.0, Unit_percent);
413 const SvgNumber SvgGradientNode::getCy() const
415 if(maCy.isSet())
417 return maCy;
420 const_cast< SvgGradientNode* >(this)->tryToFindLink();
422 if (mpXLink && !mbResolvingLink)
424 mbResolvingLink = true;
425 auto ret = mpXLink->getCy();
426 mbResolvingLink = false;
427 return ret;
430 // default is 50%
431 return SvgNumber(50.0, Unit_percent);
434 const SvgNumber SvgGradientNode::getR() const
436 if(maR.isSet())
438 return maR;
441 const_cast< SvgGradientNode* >(this)->tryToFindLink();
443 if (mpXLink && !mbResolvingLink)
445 mbResolvingLink = true;
446 auto ret = mpXLink->getR();
447 mbResolvingLink = false;
448 return ret;
451 // default is 50%
452 return SvgNumber(50.0, Unit_percent);
455 const SvgNumber* SvgGradientNode::getFx() const
457 if(maFx.isSet())
459 return &maFx;
462 const_cast< SvgGradientNode* >(this)->tryToFindLink();
464 if (mpXLink && !mbResolvingLink)
466 mbResolvingLink = true;
467 auto ret = mpXLink->getFx();
468 mbResolvingLink = false;
469 return ret;
472 return nullptr;
475 const SvgNumber* SvgGradientNode::getFy() const
477 if(maFy.isSet())
479 return &maFy;
482 const_cast< SvgGradientNode* >(this)->tryToFindLink();
484 if (mpXLink && !mbResolvingLink)
486 mbResolvingLink = true;
487 auto ret = mpXLink->getFy();
488 mbResolvingLink = false;
489 return ret;
492 return nullptr;
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;
509 return ret;
512 return nullptr;
515 void SvgGradientNode::setGradientTransform(const basegfx::B2DHomMatrix* pMatrix)
517 mpaGradientTransform.reset();
519 if(pMatrix)
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: */