LibreOffice Module svgio (master) 1
svgpatternnode.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <svgpatternnode.hxx>
21#include <svgdocument.hxx>
22#include <o3tl/string_view.hxx>
23
24namespace svgio::svgreader
25{
27 {
28 if(!mpXLink && !maXLink.isEmpty())
29 {
30 mpXLink = dynamic_cast< const SvgPatternNode* >(getDocument().findSvgNodeById(maXLink));
31 }
32 }
33
35 SvgDocument& rDocument,
36 SvgNode* pParent)
37 : SvgNode(SVGToken::Pattern, rDocument, pParent),
38 maSvgStyleAttributes(*this),
39 mbResolvingLink(false),
40 mpXLink(nullptr)
41 {
42 }
43
45 {
46 }
47
49 {
51 }
52
53 void SvgPatternNode::parseAttribute(const OUString& rTokenName, SVGToken aSVGToken, const OUString& aContent)
54 {
55 // call parent
56 SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
57
58 // read style attributes
59 maSvgStyleAttributes.parseStyleAttribute(aSVGToken, aContent);
60
61 // parse own
62 switch(aSVGToken)
63 {
64 case SVGToken::Style:
65 {
66 readLocalCssStyle(aContent);
67 break;
68 }
70 {
71 const basegfx::B2DRange aRange(readViewBox(aContent, *this));
72
73 if(!aRange.isEmpty())
74 {
75 setViewBox(&aRange);
76 }
77 break;
78 }
80 {
82 break;
83 }
84 case SVGToken::X:
85 {
86 SvgNumber aNum;
87
88 if(readSingleNumber(aContent, aNum))
89 {
90 maX = aNum;
91 }
92 break;
93 }
94 case SVGToken::Y:
95 {
96 SvgNumber aNum;
97
98 if(readSingleNumber(aContent, aNum))
99 {
100 maY = aNum;
101 }
102 break;
103 }
104 case SVGToken::Width:
105 {
106 SvgNumber aNum;
107
108 if(readSingleNumber(aContent, aNum))
109 {
110 if(aNum.isPositive())
111 {
112 maWidth = aNum;
113 }
114 }
115 break;
116 }
117 case SVGToken::Height:
118 {
119 SvgNumber aNum;
120
121 if(readSingleNumber(aContent, aNum))
122 {
123 if(aNum.isPositive())
124 {
125 maHeight = aNum;
126 }
127 }
128 break;
129 }
131 {
132 if(!aContent.isEmpty())
133 {
135 {
137 }
139 {
141 }
142 }
143 break;
144 }
146 {
147 if(!aContent.isEmpty())
148 {
150 {
152 }
154 {
156 }
157 }
158 break;
159 }
161 {
162 const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this));
163
164 if(!aMatrix.isIdentity())
165 {
166 setPatternTransform(aMatrix);
167 }
168 break;
169 }
170 case SVGToken::Href:
172 {
173 readLocalLink(aContent, maXLink);
175 break;
176 }
177 default:
178 {
179 break;
180 }
181 }
182 }
183
184 void SvgPatternNode::getValuesRelative(double& rfX, double& rfY, double& rfW, double& rfH, const basegfx::B2DRange& rGeoRange, SvgNode const & rUser) const
185 {
186 double fTargetWidth(rGeoRange.getWidth());
187 double fTargetHeight(rGeoRange.getHeight());
188
189 if(fTargetWidth <= 0.0 || fTargetHeight <= 0.0)
190 return;
191
193
194 if (SvgUnits::objectBoundingBox == aPatternUnits)
195 {
196 rfW = (getWidth().isSet()) ? getWidth().getNumber() : 0.0;
197 rfH = (getHeight().isSet()) ? getHeight().getNumber() : 0.0;
198
200 {
201 rfW *= 0.01;
202 }
203
205 {
206 rfH *= 0.01;
207 }
208 }
209 else
210 {
211 rfW = (getWidth().isSet()) ? getWidth().solve(rUser, NumberType::xcoordinate) : 0.0;
212 rfH = (getHeight().isSet()) ? getHeight().solve(rUser, NumberType::ycoordinate) : 0.0;
213
214 // make relative to rGeoRange
215 rfW /= fTargetWidth;
216 rfH /= fTargetHeight;
217 }
218
219 if(rfW <= 0.0 || rfH <= 0.0)
220 return;
221
222 if (SvgUnits::objectBoundingBox == aPatternUnits)
223 {
224 rfX = (getX().isSet()) ? getX().getNumber() : 0.0;
225 rfY = (getY().isSet()) ? getY().getNumber() : 0.0;
226
227 if(SvgUnit::percent == getX().getUnit())
228 {
229 rfX *= 0.01;
230 }
231
232 if(SvgUnit::percent == getY().getUnit())
233 {
234 rfY *= 0.01;
235 }
236 }
237 else
238 {
239 rfX = (getX().isSet()) ? getX().solve(rUser, NumberType::xcoordinate) : 0.0;
240 rfY = (getY().isSet()) ? getY().solve(rUser, NumberType::ycoordinate) : 0.0;
241
242 // make relative to rGeoRange
243 rfX = (rfX - rGeoRange.getMinX()) / fTargetWidth;
244 rfY = (rfY - rGeoRange.getMinY()) / fTargetHeight;
245 }
246 }
247
249 {
250 if(aPrimitives.empty() && Display::None != getDisplay())
251 {
252 decomposeSvgNode(const_cast< SvgPatternNode* >(this)->aPrimitives, true);
253 }
254
255 if(aPrimitives.empty() && !maXLink.isEmpty())
256 {
257 const_cast< SvgPatternNode* >(this)->tryToFindLink();
258
259 if (mpXLink && !mbResolvingLink)
260 {
261 mbResolvingLink = true;
263 mbResolvingLink = false;
264 return ret;
265 }
266 }
267
268 return aPrimitives;
269 }
270
272 {
273 if(getViewBox())
274 {
275 return *(getViewBox());
276 }
277 else
278 {
280 }
281 }
282
284 {
285 if(mpViewBox)
286 {
287 return mpViewBox.get();
288 }
289
290 const_cast< SvgPatternNode* >(this)->tryToFindLink();
291
292 if (mpXLink && !mbResolvingLink)
293 {
294 mbResolvingLink = true;
295 auto ret = mpXLink->getViewBox();
296 mbResolvingLink = false;
297 return ret;
298 }
299
300 return nullptr;
301 }
302
304 {
306 {
307 return maSvgAspectRatio;
308 }
309
310 const_cast< SvgPatternNode* >(this)->tryToFindLink();
311
312 if (mpXLink && !mbResolvingLink)
313 {
314 mbResolvingLink = true;
316 mbResolvingLink = false;
317 return ret;
318 }
319
320 return maSvgAspectRatio;
321 }
322
324 {
325 if(maX.isSet())
326 {
327 return maX;
328 }
329
330 const_cast< SvgPatternNode* >(this)->tryToFindLink();
331
332 if (mpXLink && !mbResolvingLink)
333 {
334 mbResolvingLink = true;
335 const SvgNumber& ret = mpXLink->getX();
336 mbResolvingLink = false;
337 return ret;
338 }
339
340 return maX;
341 }
342
344 {
345 if(maY.isSet())
346 {
347 return maY;
348 }
349
350 const_cast< SvgPatternNode* >(this)->tryToFindLink();
351
352 if (mpXLink && !mbResolvingLink)
353 {
354 mbResolvingLink = true;
355 const SvgNumber& ret = mpXLink->getY();
356 mbResolvingLink = false;
357 return ret;
358 }
359
360 return maY;
361 }
362
364 {
365 if(maWidth.isSet())
366 {
367 return maWidth;
368 }
369
370 const_cast< SvgPatternNode* >(this)->tryToFindLink();
371
372 if (mpXLink && !mbResolvingLink)
373 {
374 mbResolvingLink = true;
375 const SvgNumber& ret = mpXLink->getWidth();
376 mbResolvingLink = false;
377 return ret;
378 }
379
380 return maWidth;
381 }
382
384 {
385 if(maHeight.isSet())
386 {
387 return maHeight;
388 }
389
390 const_cast< SvgPatternNode* >(this)->tryToFindLink();
391
392 if (mpXLink && !mbResolvingLink)
393 {
394 mbResolvingLink = true;
395 const SvgNumber& ret = mpXLink->getHeight();
396 mbResolvingLink = false;
397 return ret;
398 }
399
400 return maHeight;
401 }
402
404 {
406 {
407 return &*moPatternUnits;
408 }
409
410 const_cast< SvgPatternNode* >(this)->tryToFindLink();
411
412 if (mpXLink && !mbResolvingLink)
413 {
414 mbResolvingLink = true;
415 auto ret = mpXLink->getPatternUnits();
416 mbResolvingLink = false;
417 return ret;
418 }
419
420 return nullptr;
421 }
422
424 {
426 {
427 return &*moPatternContentUnits;
428 }
429
430 const_cast< SvgPatternNode* >(this)->tryToFindLink();
431
432 if (mpXLink && !mbResolvingLink)
433 {
434 mbResolvingLink = true;
435 auto ret = mpXLink->getPatternContentUnits();
436 mbResolvingLink = false;
437 return ret;
438 }
439
440 return nullptr;
441 }
442
443 std::optional<basegfx::B2DHomMatrix> SvgPatternNode::getPatternTransform() const
444 {
446 {
447 return mpaPatternTransform;
448 }
449
450 const_cast< SvgPatternNode* >(this)->tryToFindLink();
451
452 if (mpXLink && !mbResolvingLink)
453 {
454 mbResolvingLink = true;
455 auto ret = mpXLink->getPatternTransform();
456 mbResolvingLink = false;
457 return ret;
458 }
459
460 return std::nullopt;
461 }
462
463} // end of namespace svgio::svgreader
464
465/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool isIdentity() const
TYPE getWidth() const
TYPE getMinX() const
TYPE getMinY() const
bool isEmpty() const
TYPE getHeight() const
const SvgNode * findSvgNodeById(const OUString &rStr) const
find a node by its Id
Definition: svgdocument.cxx:56
Display getDisplay() const
Display access #i121656#.
Definition: svgnode.hxx:182
virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DContainer &rTarget, bool bReferenced) const
Definition: svgnode.cxx:584
const SvgStyleAttributes * checkForCssStyle(const SvgStyleAttributes &rOriginal) const
helper to evtl. link to css style
Definition: svgnode.cxx:335
virtual basegfx::B2DRange getCurrentViewPort() const override
InfoProvider support for %, em and ex values.
Definition: svgnode.cxx:702
virtual void parseAttribute(const OUString &rTokenName, SVGToken aSVGToken, const OUString &aContent)
Definition: svgnode.cxx:534
void readLocalCssStyle(std::u16string_view aContent)
scan helper to read and interpret a local CssStyle to mpLocalCssStyle
Definition: svgnode.cxx:412
const SvgDocument & getDocument() const
Definition: svgnode.hxx:157
SvgUnit getUnit() const
Definition: SvgNumber.hxx:90
double solve(const InfoProvider &rInfoProvider, NumberType aNumberType=NumberType::length) const
Definition: SvgNumber.cxx:69
double getNumber() const
Definition: SvgNumber.hxx:85
void tryToFindLink()
link on demand
const SvgUnits * getPatternContentUnits() const
PatternContentUnits content.
virtual basegfx::B2DRange getCurrentViewPort() const override
InfoProvider support for % values.
const SvgAspectRatio & getSvgAspectRatio() const
SvgAspectRatio content.
std::unique_ptr< basegfx::B2DRange > mpViewBox
variable scan values, dependent of given XAttributeList
const SvgUnits * getPatternUnits() const
PatternUnits content.
std::optional< basegfx::B2DHomMatrix > getPatternTransform() const
PatternTransform content.
void setViewBox(const basegfx::B2DRange *pViewBox)
std::optional< basegfx::B2DHomMatrix > mpaPatternTransform
const basegfx::B2DRange * getViewBox() const
viewBox content
SvgPatternNode(SvgDocument &rDocument, SvgNode *pParent)
SvgStyleAttributes maSvgStyleAttributes
use styles
std::optional< SvgUnits > moPatternContentUnits
virtual const SvgStyleAttributes * getSvgStyleAttributes() const override
const SvgNumber & getY() const
Y content, set if found in current context.
const SvgNumber & getHeight() const
Height content, set if found in current context.
void setPatternTransform(const std::optional< basegfx::B2DHomMatrix > &pMatrix)
drawinglayer::primitive2d::Primitive2DContainer aPrimitives
buffered decomposition
const SvgPatternNode * mpXLink
const SvgNumber & getWidth() const
Width content, set if found in current context.
void getValuesRelative(double &rfX, double &rfY, double &rfW, double &rfH, const basegfx::B2DRange &rGeoRange, SvgNode const &rUser) const
global helpers
void setPatternContentUnits(const SvgUnits aPatternContentUnits)
std::optional< SvgUnits > moPatternUnits
const SvgNumber & getX() const
X content, set if found in current context.
virtual void parseAttribute(const OUString &rTokenName, SVGToken aSVGToken, const OUString &aContent) override
const drawinglayer::primitive2d::Primitive2DContainer & getPatternPrimitives() const
get pattern primitives buffered, uses decomposeSvgNode internally
void setPatternUnits(const SvgUnits aPatternUnits)
bool mbResolvingLink
link to another pattern used as style.
void parseStyleAttribute(SVGToken aSVGToken, const OUString &rContent)
local attribute scanner
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
bool readLocalLink(std::u16string_view rCandidate, OUString &rURL)
Definition: svgtools.cxx:1084
bool readSingleNumber(std::u16string_view rCandidate, SvgNumber &aNum)
Definition: svgtools.cxx:1076
basegfx::B2DHomMatrix readTransform(std::u16string_view rCandidate, InfoProvider const &rInfoProvider)
Definition: svgtools.cxx:871
SvgAspectRatio readSvgAspectRatio(std::u16string_view rCandidate)
Definition: svgtools.cxx:1197
basegfx::B2DRange readViewBox(std::u16string_view rCandidate, InfoProvider const &rInfoProvider)
Definition: svgtools.cxx:808
static constexpr OUStringLiteral aStrUserSpaceOnUse
Definition: svgtools.hxx:38
static constexpr OUStringLiteral aStrObjectBoundingBox
Definition: svgtools.hxx:39