Line data Source code
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 <svgio/svgreader/svgpatternnode.hxx>
21 : #include <svgio/svgreader/svgdocument.hxx>
22 :
23 : //////////////////////////////////////////////////////////////////////////////
24 :
25 : namespace svgio
26 : {
27 : namespace svgreader
28 : {
29 0 : void SvgPatternNode::tryToFindLink()
30 : {
31 0 : if(!mpXLink && maXLink.getLength())
32 : {
33 0 : mpXLink = dynamic_cast< const SvgPatternNode* >(getDocument().findSvgNodeById(maXLink));
34 : }
35 0 : }
36 :
37 0 : SvgPatternNode::SvgPatternNode(
38 : SvgDocument& rDocument,
39 : SvgNode* pParent)
40 : : SvgNode(SVGTokenPattern, rDocument, pParent),
41 : aPrimitives(),
42 : maSvgStyleAttributes(*this),
43 : mpViewBox(0),
44 : maSvgAspectRatio(),
45 : maX(),
46 : maY(),
47 : maWidth(),
48 : maHeight(),
49 : mpPatternUnits(0),
50 : mpPatternContentUnits(0),
51 : mpaPatternTransform(0),
52 : maXLink(),
53 0 : mpXLink(0)
54 : {
55 0 : }
56 :
57 0 : SvgPatternNode::~SvgPatternNode()
58 : {
59 0 : if(mpViewBox) delete mpViewBox;
60 0 : if(mpaPatternTransform) delete mpaPatternTransform;
61 0 : if(mpPatternUnits) delete mpPatternUnits;
62 0 : if(mpPatternContentUnits) delete mpPatternContentUnits;
63 0 : }
64 :
65 0 : const SvgStyleAttributes* SvgPatternNode::getSvgStyleAttributes() const
66 : {
67 0 : static rtl::OUString aClassStr(rtl::OUString::createFromAscii("pattern"));
68 0 : maSvgStyleAttributes.checkForCssStyle(aClassStr);
69 :
70 0 : return &maSvgStyleAttributes;
71 : }
72 :
73 0 : void SvgPatternNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent)
74 : {
75 : // call parent
76 0 : SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
77 :
78 : // read style attributes
79 0 : maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent);
80 :
81 : // parse own
82 0 : switch(aSVGToken)
83 : {
84 : case SVGTokenStyle:
85 : {
86 0 : maSvgStyleAttributes.readStyle(aContent);
87 0 : break;
88 : }
89 : case SVGTokenViewBox:
90 : {
91 0 : const basegfx::B2DRange aRange(readViewBox(aContent, *this));
92 :
93 0 : if(!aRange.isEmpty())
94 : {
95 0 : setViewBox(&aRange);
96 : }
97 : break;
98 : }
99 : case SVGTokenPreserveAspectRatio:
100 : {
101 0 : setSvgAspectRatio(readSvgAspectRatio(aContent));
102 0 : break;
103 : }
104 : case SVGTokenX:
105 : {
106 0 : SvgNumber aNum;
107 :
108 0 : if(readSingleNumber(aContent, aNum))
109 : {
110 0 : setX(aNum);
111 : }
112 : break;
113 : }
114 : case SVGTokenY:
115 : {
116 0 : SvgNumber aNum;
117 :
118 0 : if(readSingleNumber(aContent, aNum))
119 : {
120 0 : setY(aNum);
121 : }
122 : break;
123 : }
124 : case SVGTokenWidth:
125 : {
126 0 : SvgNumber aNum;
127 :
128 0 : if(readSingleNumber(aContent, aNum))
129 : {
130 0 : if(aNum.isPositive())
131 : {
132 0 : setWidth(aNum);
133 : }
134 : }
135 : break;
136 : }
137 : case SVGTokenHeight:
138 : {
139 0 : SvgNumber aNum;
140 :
141 0 : if(readSingleNumber(aContent, aNum))
142 : {
143 0 : if(aNum.isPositive())
144 : {
145 0 : setHeight(aNum);
146 : }
147 : }
148 : break;
149 : }
150 : case SVGTokenPatternUnits:
151 : {
152 0 : if(aContent.getLength())
153 : {
154 0 : if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0))
155 : {
156 0 : setPatternUnits(userSpaceOnUse);
157 : }
158 0 : else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0))
159 : {
160 0 : setPatternUnits(objectBoundingBox);
161 : }
162 : }
163 0 : break;
164 : }
165 : case SVGTokenPatternContentUnits:
166 : {
167 0 : if(aContent.getLength())
168 : {
169 0 : if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0))
170 : {
171 0 : setPatternContentUnits(userSpaceOnUse);
172 : }
173 0 : else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0))
174 : {
175 0 : setPatternContentUnits(objectBoundingBox);
176 : }
177 : }
178 0 : break;
179 : }
180 : case SVGTokenPatternTransform:
181 : {
182 0 : const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this));
183 :
184 0 : if(!aMatrix.isIdentity())
185 : {
186 0 : setPatternTransform(&aMatrix);
187 : }
188 0 : break;
189 : }
190 : case SVGTokenXlinkHref:
191 : {
192 0 : const sal_Int32 nLen(aContent.getLength());
193 :
194 0 : if(nLen && sal_Unicode('#') == aContent[0])
195 : {
196 0 : maXLink = aContent.copy(1);
197 0 : tryToFindLink();
198 : }
199 0 : break;
200 : }
201 : default:
202 : {
203 0 : break;
204 : }
205 : }
206 0 : }
207 :
208 0 : void SvgPatternNode::getValuesRelative(double& rfX, double& rfY, double& rfW, double& rfH, const basegfx::B2DRange& rGeoRange, SvgNode& rUser) const
209 : {
210 0 : double fTargetWidth(rGeoRange.getWidth());
211 0 : double fTargetHeight(rGeoRange.getHeight());
212 :
213 0 : if(fTargetWidth > 0.0 && fTargetHeight > 0.0)
214 : {
215 0 : const SvgUnits aPatternUnits(getPatternUnits() ? *getPatternUnits() : objectBoundingBox);
216 :
217 0 : if(objectBoundingBox == aPatternUnits)
218 : {
219 0 : rfW = (getWidth().isSet()) ? getWidth().getNumber() : 0.0;
220 0 : rfH = (getHeight().isSet()) ? getHeight().getNumber() : 0.0;
221 :
222 0 : if(Unit_percent == getWidth().getUnit())
223 : {
224 0 : rfW *= 0.01;
225 : }
226 :
227 0 : if(Unit_percent == getHeight().getUnit())
228 : {
229 0 : rfH *= 0.01;
230 : }
231 : }
232 : else
233 : {
234 0 : rfW = (getWidth().isSet()) ? getWidth().solve(rUser, xcoordinate) : 0.0;
235 0 : rfH = (getHeight().isSet()) ? getHeight().solve(rUser, ycoordinate) : 0.0;
236 :
237 : // make relative to rGeoRange
238 0 : rfW /= fTargetWidth;
239 0 : rfH /= fTargetHeight;
240 : }
241 :
242 0 : if(rfW > 0.0 && rfH > 0.0)
243 : {
244 0 : if(objectBoundingBox == aPatternUnits)
245 : {
246 0 : rfX = (getX().isSet()) ? getX().getNumber() : 0.0;
247 0 : rfY = (getY().isSet()) ? getY().getNumber() : 0.0;
248 :
249 0 : if(Unit_percent == getX().getUnit())
250 : {
251 0 : rfX *= 0.01;
252 : }
253 :
254 0 : if(Unit_percent == getY().getUnit())
255 : {
256 0 : rfY *= 0.01;
257 : }
258 : }
259 : else
260 : {
261 0 : rfX = (getX().isSet()) ? getX().solve(rUser, xcoordinate) : 0.0;
262 0 : rfY = (getY().isSet()) ? getY().solve(rUser, ycoordinate) : 0.0;
263 :
264 : // make relative to rGeoRange
265 0 : rfX = (rfX - rGeoRange.getMinX()) / fTargetWidth;
266 0 : rfY = (rfY - rGeoRange.getMinY()) / fTargetHeight;
267 : }
268 : }
269 : }
270 0 : }
271 :
272 0 : const drawinglayer::primitive2d::Primitive2DSequence& SvgPatternNode::getPatternPrimitives() const
273 : {
274 0 : if(!aPrimitives.hasElements())
275 : {
276 0 : decomposeSvgNode(const_cast< SvgPatternNode* >(this)->aPrimitives, true);
277 : }
278 :
279 0 : if(!aPrimitives.hasElements() && maXLink.getLength())
280 : {
281 0 : const_cast< SvgPatternNode* >(this)->tryToFindLink();
282 :
283 0 : if(mpXLink)
284 : {
285 0 : return mpXLink->getPatternPrimitives();
286 : }
287 : }
288 :
289 0 : return aPrimitives;
290 : }
291 :
292 0 : const basegfx::B2DRange* SvgPatternNode::getCurrentViewPort() const
293 : {
294 0 : if(getViewBox())
295 : {
296 0 : return getViewBox();
297 : }
298 : else
299 : {
300 0 : return SvgNode::getCurrentViewPort();
301 : }
302 : }
303 :
304 0 : const basegfx::B2DRange* SvgPatternNode::getViewBox() const
305 : {
306 0 : if(mpViewBox)
307 : {
308 0 : return mpViewBox;
309 : }
310 :
311 0 : const_cast< SvgPatternNode* >(this)->tryToFindLink();
312 :
313 0 : if(mpXLink)
314 : {
315 0 : return mpXLink->getViewBox();
316 : }
317 :
318 0 : return 0;
319 : }
320 :
321 0 : const SvgAspectRatio& SvgPatternNode::getSvgAspectRatio() const
322 : {
323 0 : if(maSvgAspectRatio.isSet())
324 : {
325 0 : return maSvgAspectRatio;
326 : }
327 :
328 0 : const_cast< SvgPatternNode* >(this)->tryToFindLink();
329 :
330 0 : if(mpXLink)
331 : {
332 0 : return mpXLink->getSvgAspectRatio();
333 : }
334 :
335 0 : return maSvgAspectRatio;
336 : }
337 :
338 0 : const SvgNumber& SvgPatternNode::getX() const
339 : {
340 0 : if(maX.isSet())
341 : {
342 0 : return maX;
343 : }
344 :
345 0 : const_cast< SvgPatternNode* >(this)->tryToFindLink();
346 :
347 0 : if(mpXLink)
348 : {
349 0 : return mpXLink->getX();
350 : }
351 :
352 0 : return maX;
353 : }
354 :
355 0 : const SvgNumber& SvgPatternNode::getY() const
356 : {
357 0 : if(maY.isSet())
358 : {
359 0 : return maY;
360 : }
361 :
362 0 : const_cast< SvgPatternNode* >(this)->tryToFindLink();
363 :
364 0 : if(mpXLink)
365 : {
366 0 : return mpXLink->getY();
367 : }
368 :
369 0 : return maY;
370 : }
371 :
372 0 : const SvgNumber& SvgPatternNode::getWidth() const
373 : {
374 0 : if(maWidth.isSet())
375 : {
376 0 : return maWidth;
377 : }
378 :
379 0 : const_cast< SvgPatternNode* >(this)->tryToFindLink();
380 :
381 0 : if(mpXLink)
382 : {
383 0 : return mpXLink->getWidth();
384 : }
385 :
386 0 : return maWidth;
387 : }
388 :
389 0 : const SvgNumber& SvgPatternNode::getHeight() const
390 : {
391 0 : if(maHeight.isSet())
392 : {
393 0 : return maHeight;
394 : }
395 :
396 0 : const_cast< SvgPatternNode* >(this)->tryToFindLink();
397 :
398 0 : if(mpXLink)
399 : {
400 0 : return mpXLink->getHeight();
401 : }
402 :
403 0 : return maHeight;
404 : }
405 :
406 0 : const SvgUnits* SvgPatternNode::getPatternUnits() const
407 : {
408 0 : if(mpPatternUnits)
409 : {
410 0 : return mpPatternUnits;
411 : }
412 :
413 0 : const_cast< SvgPatternNode* >(this)->tryToFindLink();
414 :
415 0 : if(mpXLink)
416 : {
417 0 : return mpXLink->getPatternUnits();
418 : }
419 :
420 0 : return 0;
421 : }
422 :
423 0 : const SvgUnits* SvgPatternNode::getPatternContentUnits() const
424 : {
425 0 : if(mpPatternContentUnits)
426 : {
427 0 : return mpPatternContentUnits;
428 : }
429 :
430 0 : const_cast< SvgPatternNode* >(this)->tryToFindLink();
431 :
432 0 : if(mpXLink)
433 : {
434 0 : return mpXLink->getPatternContentUnits();
435 : }
436 :
437 0 : return 0;
438 : }
439 :
440 0 : const basegfx::B2DHomMatrix* SvgPatternNode::getPatternTransform() const
441 : {
442 0 : if(mpaPatternTransform)
443 : {
444 0 : return mpaPatternTransform;
445 : }
446 :
447 0 : const_cast< SvgPatternNode* >(this)->tryToFindLink();
448 :
449 0 : if(mpXLink)
450 : {
451 0 : return mpXLink->getPatternTransform();
452 : }
453 :
454 0 : return 0;
455 : }
456 :
457 : } // end of namespace svgreader
458 : } // end of namespace svgio
459 :
460 : //////////////////////////////////////////////////////////////////////////////
461 : // eof
462 :
463 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|