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/svggradientnode.hxx>
21 : #include <svgio/svgreader/svgdocument.hxx>
22 : #include <svgio/svgreader/svggradientstopnode.hxx>
23 :
24 :
25 :
26 : namespace svgio
27 : {
28 : namespace svgreader
29 : {
30 0 : void SvgGradientNode::tryToFindLink()
31 : {
32 0 : if(!mpXLink && !maXLink.isEmpty())
33 : {
34 0 : mpXLink = dynamic_cast< const SvgGradientNode* >(getDocument().findSvgNodeById(maXLink));
35 : }
36 0 : }
37 :
38 0 : SvgGradientNode::SvgGradientNode(
39 : SVGToken aType,
40 : SvgDocument& rDocument,
41 : SvgNode* pParent)
42 : : SvgNode(aType, rDocument, pParent),
43 : maSvgStyleAttributes(*this),
44 : maX1(),
45 : maY1(),
46 : maX2(),
47 : maY2(),
48 : maCx(),
49 : maCy(),
50 : maR(),
51 : maFx(),
52 : maFy(),
53 : maGradientUnits(objectBoundingBox),
54 : maSpreadMethod(drawinglayer::primitive2d::Spread_pad),
55 : mpaGradientTransform(0),
56 : maXLink(),
57 0 : mpXLink(0)
58 : {
59 0 : }
60 :
61 0 : SvgGradientNode::~SvgGradientNode()
62 : {
63 0 : if(mpaGradientTransform) delete mpaGradientTransform;
64 : // do NOT delete mpXLink, it's only referenced, not owned
65 0 : }
66 :
67 0 : const SvgStyleAttributes* SvgGradientNode::getSvgStyleAttributes() const
68 : {
69 0 : return &maSvgStyleAttributes;
70 : }
71 :
72 0 : void SvgGradientNode::parseAttribute(const OUString& rTokenName, SVGToken aSVGToken, const OUString& aContent)
73 : {
74 : // call parent
75 0 : SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
76 :
77 : // read style attributes
78 0 : maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent);
79 :
80 : // parse own
81 0 : switch(aSVGToken)
82 : {
83 : case SVGTokenStyle:
84 : {
85 0 : maSvgStyleAttributes.readStyle(aContent);
86 0 : break;
87 : }
88 : case SVGTokenX1:
89 : {
90 0 : SvgNumber aNum;
91 :
92 0 : if(readSingleNumber(aContent, aNum))
93 : {
94 0 : setX1(aNum);
95 : }
96 0 : break;
97 : }
98 : case SVGTokenY1:
99 : {
100 0 : SvgNumber aNum;
101 :
102 0 : if(readSingleNumber(aContent, aNum))
103 : {
104 0 : setY1(aNum);
105 : }
106 0 : break;
107 : }
108 : case SVGTokenX2:
109 : {
110 0 : SvgNumber aNum;
111 :
112 0 : if(readSingleNumber(aContent, aNum))
113 : {
114 0 : setX2(aNum);
115 : }
116 0 : break;
117 : }
118 : case SVGTokenY2:
119 : {
120 0 : SvgNumber aNum;
121 :
122 0 : if(readSingleNumber(aContent, aNum))
123 : {
124 0 : setY2(aNum);
125 : }
126 0 : break;
127 : }
128 : case SVGTokenCx:
129 : {
130 0 : SvgNumber aNum;
131 :
132 0 : if(readSingleNumber(aContent, aNum))
133 : {
134 0 : setCx(aNum);
135 : }
136 0 : break;
137 : }
138 : case SVGTokenCy:
139 : {
140 0 : SvgNumber aNum;
141 :
142 0 : if(readSingleNumber(aContent, aNum))
143 : {
144 0 : setCy(aNum);
145 : }
146 0 : break;
147 : }
148 : case SVGTokenFx:
149 : {
150 0 : SvgNumber aNum;
151 :
152 0 : if(readSingleNumber(aContent, aNum))
153 : {
154 0 : setFx(aNum);
155 : }
156 0 : break;
157 : }
158 : case SVGTokenFy:
159 : {
160 0 : SvgNumber aNum;
161 :
162 0 : if(readSingleNumber(aContent, aNum))
163 : {
164 0 : setFy(aNum);
165 : }
166 0 : break;
167 : }
168 : case SVGTokenR:
169 : {
170 0 : SvgNumber aNum;
171 :
172 0 : if(readSingleNumber(aContent, aNum))
173 : {
174 0 : if(aNum.isPositive())
175 : {
176 0 : setR(aNum);
177 : }
178 : }
179 0 : break;
180 : }
181 : case SVGTokenGradientUnits:
182 : {
183 0 : if(!aContent.isEmpty())
184 : {
185 0 : if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0))
186 : {
187 0 : setGradientUnits(userSpaceOnUse);
188 : }
189 0 : else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0))
190 : {
191 0 : setGradientUnits(objectBoundingBox);
192 : }
193 : }
194 0 : break;
195 : }
196 : case SVGTokenSpreadMethod:
197 : {
198 0 : if(!aContent.isEmpty())
199 : {
200 0 : if(aContent.startsWith("pad"))
201 : {
202 0 : setSpreadMethod(drawinglayer::primitive2d::Spread_pad);
203 : }
204 0 : else if(aContent.startsWith("reflect"))
205 : {
206 0 : setSpreadMethod(drawinglayer::primitive2d::Spread_reflect);
207 : }
208 0 : else if(aContent.startsWith("repeat"))
209 : {
210 0 : setSpreadMethod(drawinglayer::primitive2d::Spread_repeat);
211 : }
212 : }
213 0 : break;
214 : }
215 : case SVGTokenGradientTransform:
216 : {
217 0 : const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this));
218 :
219 0 : if(!aMatrix.isIdentity())
220 : {
221 0 : setGradientTransform(&aMatrix);
222 : }
223 0 : break;
224 : }
225 : case SVGTokenXlinkHref:
226 : {
227 0 : const sal_Int32 nLen(aContent.getLength());
228 :
229 0 : if(nLen && '#' == aContent[0])
230 : {
231 0 : maXLink = aContent.copy(1);
232 0 : tryToFindLink();
233 : }
234 0 : break;
235 : }
236 : default:
237 : {
238 0 : break;
239 : }
240 : }
241 0 : }
242 :
243 0 : void SvgGradientNode::collectGradientEntries(drawinglayer::primitive2d::SvgGradientEntryVector& aVector) const
244 : {
245 0 : if(getChildren().empty())
246 : {
247 0 : const_cast< SvgGradientNode* >(this)->tryToFindLink();
248 :
249 0 : if(mpXLink)
250 : {
251 0 : mpXLink->collectGradientEntries(aVector);
252 : }
253 : }
254 : else
255 : {
256 0 : const sal_uInt32 nCount(getChildren().size());
257 :
258 0 : for(sal_uInt32 a(0); a < nCount; a++)
259 : {
260 0 : const SvgGradientStopNode* pCandidate = dynamic_cast< const SvgGradientStopNode* >(getChildren()[a]);
261 :
262 0 : if(pCandidate)
263 : {
264 0 : const SvgStyleAttributes* pStyle = pCandidate->getSvgStyleAttributes();
265 :
266 0 : if(pStyle)
267 : {
268 0 : const SvgNumber aOffset(pCandidate->getOffset());
269 0 : double fOffset(0.0);
270 :
271 0 : if(Unit_percent == aOffset.getUnit())
272 : {
273 : // percent is not relative to distances in ColorStop context, solve locally
274 0 : fOffset = aOffset.getNumber() * 0.01;
275 : }
276 : else
277 : {
278 0 : fOffset = aOffset.solve(*this);
279 : }
280 :
281 0 : if(fOffset < 0.0)
282 : {
283 : OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)");
284 0 : fOffset = 0.0;
285 : }
286 0 : else if(fOffset > 1.0)
287 : {
288 : OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)");
289 0 : fOffset = 1.0;
290 : }
291 :
292 : aVector.push_back(
293 : drawinglayer::primitive2d::SvgGradientEntry(
294 : fOffset,
295 0 : pStyle->getStopColor(),
296 0 : pStyle->getStopOpacity().solve(*this)));
297 : }
298 : else
299 : {
300 : OSL_ENSURE(false, "OOps, SvgGradientStopNode without Style (!)");
301 : }
302 : }
303 : }
304 : }
305 0 : }
306 :
307 0 : const SvgNumber SvgGradientNode::getX1() const
308 : {
309 0 : if(maX1.isSet())
310 : {
311 0 : return maX1;
312 : }
313 :
314 0 : const_cast< SvgGradientNode* >(this)->tryToFindLink();
315 :
316 0 : if(mpXLink)
317 : {
318 0 : return mpXLink->getX1();
319 : }
320 :
321 : // default is 0%
322 0 : return SvgNumber(0.0, Unit_percent);
323 : }
324 :
325 0 : const SvgNumber SvgGradientNode::getY1() const
326 : {
327 0 : if(maY1.isSet())
328 : {
329 0 : return maY1;
330 : }
331 :
332 0 : const_cast< SvgGradientNode* >(this)->tryToFindLink();
333 :
334 0 : if(mpXLink)
335 : {
336 0 : return mpXLink->getY1();
337 : }
338 :
339 : // default is 0%
340 0 : return SvgNumber(0.0, Unit_percent);
341 : }
342 :
343 0 : const SvgNumber SvgGradientNode::getX2() const
344 : {
345 0 : if(maX2.isSet())
346 : {
347 0 : return maX2;
348 : }
349 :
350 0 : const_cast< SvgGradientNode* >(this)->tryToFindLink();
351 :
352 0 : if(mpXLink)
353 : {
354 0 : return mpXLink->getX2();
355 : }
356 :
357 : // default is 100%
358 0 : return SvgNumber(100.0, Unit_percent);
359 : }
360 :
361 0 : const SvgNumber SvgGradientNode::getY2() const
362 : {
363 0 : if(maY2.isSet())
364 : {
365 0 : return maY2;
366 : }
367 :
368 0 : const_cast< SvgGradientNode* >(this)->tryToFindLink();
369 :
370 0 : if(mpXLink)
371 : {
372 0 : return mpXLink->getY2();
373 : }
374 :
375 : // default is 0%
376 0 : return SvgNumber(0.0, Unit_percent);
377 : }
378 :
379 0 : const SvgNumber SvgGradientNode::getCx() const
380 : {
381 0 : if(maCx.isSet())
382 : {
383 0 : return maCx;
384 : }
385 :
386 0 : const_cast< SvgGradientNode* >(this)->tryToFindLink();
387 :
388 0 : if(mpXLink)
389 : {
390 0 : return mpXLink->getCx();
391 : }
392 :
393 : // default is 50%
394 0 : return SvgNumber(50.0, Unit_percent);
395 : }
396 :
397 0 : const SvgNumber SvgGradientNode::getCy() const
398 : {
399 0 : if(maCy.isSet())
400 : {
401 0 : return maCy;
402 : }
403 :
404 0 : const_cast< SvgGradientNode* >(this)->tryToFindLink();
405 :
406 0 : if(mpXLink)
407 : {
408 0 : return mpXLink->getCy();
409 : }
410 :
411 : // default is 50%
412 0 : return SvgNumber(50.0, Unit_percent);
413 : }
414 :
415 0 : const SvgNumber SvgGradientNode::getR() const
416 : {
417 0 : if(maR.isSet())
418 : {
419 0 : return maR;
420 : }
421 :
422 0 : const_cast< SvgGradientNode* >(this)->tryToFindLink();
423 :
424 0 : if(mpXLink)
425 : {
426 0 : return mpXLink->getR();
427 : }
428 :
429 : // default is 50%
430 0 : return SvgNumber(50.0, Unit_percent);
431 : }
432 :
433 0 : const SvgNumber* SvgGradientNode::getFx() const
434 : {
435 0 : if(maFx.isSet())
436 : {
437 0 : return &maFx;
438 : }
439 :
440 0 : const_cast< SvgGradientNode* >(this)->tryToFindLink();
441 :
442 0 : if(mpXLink)
443 : {
444 0 : return mpXLink->getFx();
445 : }
446 :
447 0 : return 0;
448 : }
449 :
450 0 : const SvgNumber* SvgGradientNode::getFy() const
451 : {
452 0 : if(maFy.isSet())
453 : {
454 0 : return &maFy;
455 : }
456 :
457 0 : const_cast< SvgGradientNode* >(this)->tryToFindLink();
458 :
459 0 : if(mpXLink)
460 : {
461 0 : return mpXLink->getFy();
462 : }
463 :
464 0 : return 0;
465 : }
466 :
467 0 : const basegfx::B2DHomMatrix* SvgGradientNode::getGradientTransform() const
468 : {
469 0 : if(mpaGradientTransform)
470 : {
471 0 : return mpaGradientTransform;
472 : }
473 :
474 0 : const_cast< SvgGradientNode* >(this)->tryToFindLink();
475 :
476 0 : if(mpXLink)
477 : {
478 0 : return mpXLink->getGradientTransform();
479 : }
480 :
481 0 : return 0;
482 : }
483 :
484 0 : void SvgGradientNode::setGradientTransform(const basegfx::B2DHomMatrix* pMatrix)
485 : {
486 0 : if(mpaGradientTransform)
487 : {
488 0 : delete mpaGradientTransform;
489 0 : mpaGradientTransform = 0;
490 : }
491 :
492 0 : if(pMatrix)
493 : {
494 0 : mpaGradientTransform = new basegfx::B2DHomMatrix(*pMatrix);
495 : }
496 0 : }
497 :
498 : } // end of namespace svgreader
499 : } // end of namespace svgio
500 :
501 :
502 : // eof
503 :
504 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|