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 <svgpatternnode.hxx>
21 #include <svgdocument.hxx>
22 #include <o3tl/string_view.hxx>
24 namespace svgio::svgreader
26 void SvgPatternNode::tryToFindLink()
28 if(!mpXLink
&& !maXLink
.isEmpty())
30 mpXLink
= dynamic_cast< const SvgPatternNode
* >(getDocument().findSvgNodeById(maXLink
));
34 SvgPatternNode::SvgPatternNode(
35 SvgDocument
& rDocument
,
37 : SvgNode(SVGToken::Pattern
, rDocument
, pParent
),
38 maSvgStyleAttributes(*this),
39 mbResolvingLink(false),
44 SvgPatternNode::~SvgPatternNode()
48 const SvgStyleAttributes
* SvgPatternNode::getSvgStyleAttributes() const
50 return checkForCssStyle("pattern", maSvgStyleAttributes
);
53 void SvgPatternNode::parseAttribute(const OUString
& rTokenName
, SVGToken aSVGToken
, const OUString
& aContent
)
56 SvgNode::parseAttribute(rTokenName
, aSVGToken
, aContent
);
58 // read style attributes
59 maSvgStyleAttributes
.parseStyleAttribute(aSVGToken
, aContent
);
66 readLocalCssStyle(aContent
);
69 case SVGToken::ViewBox
:
71 const basegfx::B2DRange
aRange(readViewBox(aContent
, *this));
79 case SVGToken::PreserveAspectRatio
:
81 maSvgAspectRatio
= readSvgAspectRatio(aContent
);
88 if(readSingleNumber(aContent
, aNum
))
98 if(readSingleNumber(aContent
, aNum
))
104 case SVGToken::Width
:
108 if(readSingleNumber(aContent
, aNum
))
110 if(aNum
.isPositive())
117 case SVGToken::Height
:
121 if(readSingleNumber(aContent
, aNum
))
123 if(aNum
.isPositive())
130 case SVGToken::PatternUnits
:
132 if(!aContent
.isEmpty())
134 if(o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent
), commonStrings::aStrUserSpaceOnUse
))
136 setPatternUnits(SvgUnits::userSpaceOnUse
);
138 else if(o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent
), commonStrings::aStrObjectBoundingBox
))
140 setPatternUnits(SvgUnits::objectBoundingBox
);
145 case SVGToken::PatternContentUnits
:
147 if(!aContent
.isEmpty())
149 if(o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent
), commonStrings::aStrUserSpaceOnUse
))
151 setPatternContentUnits(SvgUnits::userSpaceOnUse
);
153 else if(o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent
), commonStrings::aStrObjectBoundingBox
))
155 setPatternContentUnits(SvgUnits::objectBoundingBox
);
160 case SVGToken::PatternTransform
:
162 const basegfx::B2DHomMatrix
aMatrix(readTransform(aContent
, *this));
164 if(!aMatrix
.isIdentity())
166 setPatternTransform(aMatrix
);
171 case SVGToken::XlinkHref
:
173 readLocalLink(aContent
, maXLink
);
184 void SvgPatternNode::getValuesRelative(double& rfX
, double& rfY
, double& rfW
, double& rfH
, const basegfx::B2DRange
& rGeoRange
, SvgNode
const & rUser
) const
186 double fTargetWidth(rGeoRange
.getWidth());
187 double fTargetHeight(rGeoRange
.getHeight());
189 if(fTargetWidth
<= 0.0 || fTargetHeight
<= 0.0)
192 const SvgUnits
aPatternUnits(getPatternUnits() ? *getPatternUnits() : SvgUnits::objectBoundingBox
);
194 if (SvgUnits::objectBoundingBox
== aPatternUnits
)
196 rfW
= (getWidth().isSet()) ? getWidth().getNumber() : 0.0;
197 rfH
= (getHeight().isSet()) ? getHeight().getNumber() : 0.0;
199 if(SvgUnit::percent
== getWidth().getUnit())
204 if(SvgUnit::percent
== getHeight().getUnit())
211 rfW
= (getWidth().isSet()) ? getWidth().solve(rUser
, NumberType::xcoordinate
) : 0.0;
212 rfH
= (getHeight().isSet()) ? getHeight().solve(rUser
, NumberType::ycoordinate
) : 0.0;
214 // make relative to rGeoRange
216 rfH
/= fTargetHeight
;
219 if(rfW
<= 0.0 || rfH
<= 0.0)
222 if (SvgUnits::objectBoundingBox
== aPatternUnits
)
224 rfX
= (getX().isSet()) ? getX().getNumber() : 0.0;
225 rfY
= (getY().isSet()) ? getY().getNumber() : 0.0;
227 if(SvgUnit::percent
== getX().getUnit())
232 if(SvgUnit::percent
== getY().getUnit())
239 rfX
= (getX().isSet()) ? getX().solve(rUser
, NumberType::xcoordinate
) : 0.0;
240 rfY
= (getY().isSet()) ? getY().solve(rUser
, NumberType::ycoordinate
) : 0.0;
242 // make relative to rGeoRange
243 rfX
= (rfX
- rGeoRange
.getMinX()) / fTargetWidth
;
244 rfY
= (rfY
- rGeoRange
.getMinY()) / fTargetHeight
;
248 const drawinglayer::primitive2d::Primitive2DContainer
& SvgPatternNode::getPatternPrimitives() const
250 if(aPrimitives
.empty() && Display::None
!= getDisplay())
252 decomposeSvgNode(const_cast< SvgPatternNode
* >(this)->aPrimitives
, true);
255 if(aPrimitives
.empty() && !maXLink
.isEmpty())
257 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
259 if (mpXLink
&& !mbResolvingLink
)
261 mbResolvingLink
= true;
262 const drawinglayer::primitive2d::Primitive2DContainer
& ret
= mpXLink
->getPatternPrimitives();
263 mbResolvingLink
= false;
271 basegfx::B2DRange
SvgPatternNode::getCurrentViewPort() const
275 return *(getViewBox());
279 return SvgNode::getCurrentViewPort();
283 const basegfx::B2DRange
* SvgPatternNode::getViewBox() const
287 return mpViewBox
.get();
290 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
292 if (mpXLink
&& !mbResolvingLink
)
294 mbResolvingLink
= true;
295 auto ret
= mpXLink
->getViewBox();
296 mbResolvingLink
= false;
303 const SvgAspectRatio
& SvgPatternNode::getSvgAspectRatio() const
305 if(maSvgAspectRatio
.isSet())
307 return maSvgAspectRatio
;
310 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
312 if (mpXLink
&& !mbResolvingLink
)
314 mbResolvingLink
= true;
315 const SvgAspectRatio
& ret
= mpXLink
->getSvgAspectRatio();
316 mbResolvingLink
= false;
320 return maSvgAspectRatio
;
323 const SvgNumber
& SvgPatternNode::getX() const
330 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
332 if (mpXLink
&& !mbResolvingLink
)
334 mbResolvingLink
= true;
335 const SvgNumber
& ret
= mpXLink
->getX();
336 mbResolvingLink
= false;
343 const SvgNumber
& SvgPatternNode::getY() const
350 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
352 if (mpXLink
&& !mbResolvingLink
)
354 mbResolvingLink
= true;
355 const SvgNumber
& ret
= mpXLink
->getY();
356 mbResolvingLink
= false;
363 const SvgNumber
& SvgPatternNode::getWidth() const
370 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
372 if (mpXLink
&& !mbResolvingLink
)
374 mbResolvingLink
= true;
375 const SvgNumber
& ret
= mpXLink
->getWidth();
376 mbResolvingLink
= false;
383 const SvgNumber
& SvgPatternNode::getHeight() const
390 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
392 if (mpXLink
&& !mbResolvingLink
)
394 mbResolvingLink
= true;
395 const SvgNumber
& ret
= mpXLink
->getHeight();
396 mbResolvingLink
= false;
403 const SvgUnits
* SvgPatternNode::getPatternUnits() const
407 return mpPatternUnits
.get();
410 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
412 if (mpXLink
&& !mbResolvingLink
)
414 mbResolvingLink
= true;
415 auto ret
= mpXLink
->getPatternUnits();
416 mbResolvingLink
= false;
423 const SvgUnits
* SvgPatternNode::getPatternContentUnits() const
425 if(mpPatternContentUnits
)
427 return mpPatternContentUnits
.get();
430 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
432 if (mpXLink
&& !mbResolvingLink
)
434 mbResolvingLink
= true;
435 auto ret
= mpXLink
->getPatternContentUnits();
436 mbResolvingLink
= false;
443 std::optional
<basegfx::B2DHomMatrix
> SvgPatternNode::getPatternTransform() const
445 if(mpaPatternTransform
)
447 return mpaPatternTransform
;
450 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
452 if (mpXLink
&& !mbResolvingLink
)
454 mbResolvingLink
= true;
455 auto ret
= mpXLink
->getPatternTransform();
456 mbResolvingLink
= false;
463 } // end of namespace svgio::svgreader
465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */