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>
27 void SvgPatternNode::tryToFindLink()
29 if(!mpXLink
&& !maXLink
.isEmpty())
31 mpXLink
= dynamic_cast< const SvgPatternNode
* >(getDocument().findSvgNodeById(maXLink
));
35 SvgPatternNode::SvgPatternNode(
36 SvgDocument
& rDocument
,
38 : SvgNode(SVGTokenPattern
, rDocument
, pParent
),
40 maSvgStyleAttributes(*this),
46 mbResolvingLink(false),
52 SvgPatternNode::~SvgPatternNode()
56 const SvgStyleAttributes
* SvgPatternNode::getSvgStyleAttributes() const
58 return checkForCssStyle("pattern", maSvgStyleAttributes
);
61 void SvgPatternNode::parseAttribute(const OUString
& rTokenName
, SVGToken aSVGToken
, const OUString
& aContent
)
64 SvgNode::parseAttribute(rTokenName
, aSVGToken
, aContent
);
66 // read style attributes
67 maSvgStyleAttributes
.parseStyleAttribute(aSVGToken
, aContent
, false);
74 readLocalCssStyle(aContent
);
79 const basegfx::B2DRange
aRange(readViewBox(aContent
, *this));
87 case SVGTokenPreserveAspectRatio
:
89 maSvgAspectRatio
= readSvgAspectRatio(aContent
);
96 if(readSingleNumber(aContent
, aNum
))
106 if(readSingleNumber(aContent
, aNum
))
116 if(readSingleNumber(aContent
, aNum
))
118 if(aNum
.isPositive())
129 if(readSingleNumber(aContent
, aNum
))
131 if(aNum
.isPositive())
138 case SVGTokenPatternUnits
:
140 if(!aContent
.isEmpty())
142 if(aContent
.match(commonStrings::aStrUserSpaceOnUse
))
144 setPatternUnits(userSpaceOnUse
);
146 else if(aContent
.match(commonStrings::aStrObjectBoundingBox
))
148 setPatternUnits(objectBoundingBox
);
153 case SVGTokenPatternContentUnits
:
155 if(!aContent
.isEmpty())
157 if(aContent
.match(commonStrings::aStrUserSpaceOnUse
))
159 setPatternContentUnits(userSpaceOnUse
);
161 else if(aContent
.match(commonStrings::aStrObjectBoundingBox
))
163 setPatternContentUnits(objectBoundingBox
);
168 case SVGTokenPatternTransform
:
170 const basegfx::B2DHomMatrix
aMatrix(readTransform(aContent
, *this));
172 if(!aMatrix
.isIdentity())
174 setPatternTransform(&aMatrix
);
178 case SVGTokenXlinkHref
:
180 const sal_Int32
nLen(aContent
.getLength());
182 if(nLen
&& '#' == aContent
[0])
184 maXLink
= aContent
.copy(1);
196 void SvgPatternNode::getValuesRelative(double& rfX
, double& rfY
, double& rfW
, double& rfH
, const basegfx::B2DRange
& rGeoRange
, SvgNode
const & rUser
) const
198 double fTargetWidth(rGeoRange
.getWidth());
199 double fTargetHeight(rGeoRange
.getHeight());
201 if(!(fTargetWidth
> 0.0 && fTargetHeight
> 0.0))
204 const SvgUnits
aPatternUnits(getPatternUnits() ? *getPatternUnits() : objectBoundingBox
);
206 if(objectBoundingBox
== aPatternUnits
)
208 rfW
= (getWidth().isSet()) ? getWidth().getNumber() : 0.0;
209 rfH
= (getHeight().isSet()) ? getHeight().getNumber() : 0.0;
211 if(Unit_percent
== getWidth().getUnit())
216 if(Unit_percent
== getHeight().getUnit())
223 rfW
= (getWidth().isSet()) ? getWidth().solve(rUser
, xcoordinate
) : 0.0;
224 rfH
= (getHeight().isSet()) ? getHeight().solve(rUser
, ycoordinate
) : 0.0;
226 // make relative to rGeoRange
228 rfH
/= fTargetHeight
;
231 if(!(rfW
> 0.0 && rfH
> 0.0))
234 if(objectBoundingBox
== aPatternUnits
)
236 rfX
= (getX().isSet()) ? getX().getNumber() : 0.0;
237 rfY
= (getY().isSet()) ? getY().getNumber() : 0.0;
239 if(Unit_percent
== getX().getUnit())
244 if(Unit_percent
== getY().getUnit())
251 rfX
= (getX().isSet()) ? getX().solve(rUser
, xcoordinate
) : 0.0;
252 rfY
= (getY().isSet()) ? getY().solve(rUser
, ycoordinate
) : 0.0;
254 // make relative to rGeoRange
255 rfX
= (rfX
- rGeoRange
.getMinX()) / fTargetWidth
;
256 rfY
= (rfY
- rGeoRange
.getMinY()) / fTargetHeight
;
260 const drawinglayer::primitive2d::Primitive2DContainer
& SvgPatternNode::getPatternPrimitives() const
262 if(aPrimitives
.empty() && Display_none
!= getDisplay())
264 decomposeSvgNode(const_cast< SvgPatternNode
* >(this)->aPrimitives
, true);
267 if(aPrimitives
.empty() && !maXLink
.isEmpty())
269 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
271 if (mpXLink
&& !mbResolvingLink
)
273 mbResolvingLink
= true;
274 const drawinglayer::primitive2d::Primitive2DContainer
& ret
= mpXLink
->getPatternPrimitives();
275 mbResolvingLink
= false;
283 basegfx::B2DRange
SvgPatternNode::getCurrentViewPort() const
287 return *(getViewBox());
291 return SvgNode::getCurrentViewPort();
295 const basegfx::B2DRange
* SvgPatternNode::getViewBox() const
299 return mpViewBox
.get();
302 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
304 if (mpXLink
&& !mbResolvingLink
)
306 mbResolvingLink
= true;
307 auto ret
= mpXLink
->getViewBox();
308 mbResolvingLink
= false;
315 const SvgAspectRatio
& SvgPatternNode::getSvgAspectRatio() const
317 if(maSvgAspectRatio
.isSet())
319 return maSvgAspectRatio
;
322 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
324 if (mpXLink
&& !mbResolvingLink
)
326 mbResolvingLink
= true;
327 const SvgAspectRatio
& ret
= mpXLink
->getSvgAspectRatio();
328 mbResolvingLink
= false;
332 return maSvgAspectRatio
;
335 const SvgNumber
& SvgPatternNode::getX() const
342 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
344 if (mpXLink
&& !mbResolvingLink
)
346 mbResolvingLink
= true;
347 const SvgNumber
& ret
= mpXLink
->getX();
348 mbResolvingLink
= false;
355 const SvgNumber
& SvgPatternNode::getY() const
362 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
364 if (mpXLink
&& !mbResolvingLink
)
366 mbResolvingLink
= true;
367 const SvgNumber
& ret
= mpXLink
->getY();
368 mbResolvingLink
= false;
375 const SvgNumber
& SvgPatternNode::getWidth() const
382 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
384 if (mpXLink
&& !mbResolvingLink
)
386 mbResolvingLink
= true;
387 const SvgNumber
& ret
= mpXLink
->getWidth();
388 mbResolvingLink
= false;
395 const SvgNumber
& SvgPatternNode::getHeight() const
402 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
404 if (mpXLink
&& !mbResolvingLink
)
406 mbResolvingLink
= true;
407 const SvgNumber
& ret
= mpXLink
->getHeight();
408 mbResolvingLink
= false;
415 const SvgUnits
* SvgPatternNode::getPatternUnits() const
419 return mpPatternUnits
.get();
422 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
424 if (mpXLink
&& !mbResolvingLink
)
426 mbResolvingLink
= true;
427 auto ret
= mpXLink
->getPatternUnits();
428 mbResolvingLink
= false;
435 const SvgUnits
* SvgPatternNode::getPatternContentUnits() const
437 if(mpPatternContentUnits
)
439 return mpPatternContentUnits
.get();
442 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
444 if (mpXLink
&& !mbResolvingLink
)
446 mbResolvingLink
= true;
447 auto ret
= mpXLink
->getPatternContentUnits();
448 mbResolvingLink
= false;
455 const basegfx::B2DHomMatrix
* SvgPatternNode::getPatternTransform() const
457 if(mpaPatternTransform
)
459 return mpaPatternTransform
.get();
462 const_cast< SvgPatternNode
* >(this)->tryToFindLink();
464 if (mpXLink
&& !mbResolvingLink
)
466 mbResolvingLink
= true;
467 auto ret
= mpXLink
->getPatternTransform();
468 mbResolvingLink
= false;
475 } // end of namespace svgreader
476 } // end of namespace svgio
478 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */