Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* libcdr
3 : * Version: MPL 1.1 / GPLv2+ / LGPLv2+
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License or as specified alternatively below. You may obtain a copy of
8 : * the License at http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * Major Contributor(s):
16 : * Copyright (C) 2012 Fridrich Strba <fridrich.strba@bluewin.ch>
17 : *
18 : *
19 : * All Rights Reserved.
20 : *
21 : * For minor contributions see the git repository.
22 : *
23 : * Alternatively, the contents of this file may be used under the terms of
24 : * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
25 : * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
26 : * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
27 : * instead of those above.
28 : */
29 :
30 : #include <math.h>
31 : #include "CDRPath.h"
32 :
33 : #ifndef M_PI
34 : #define M_PI 3.14159265358979323846
35 : #endif
36 :
37 : namespace libcdr
38 : {
39 :
40 : class CDRMoveToElement : public CDRPathElement
41 : {
42 : public:
43 0 : CDRMoveToElement(double x, double y)
44 : : m_x(x),
45 0 : m_y(y) {}
46 0 : ~CDRMoveToElement() {}
47 : void writeOut(WPXPropertyListVector &vec) const;
48 : void transform(const CDRTransforms &trafos);
49 : void transform(const CDRTransform &trafo);
50 : CDRPathElement *clone();
51 : private:
52 : double m_x;
53 : double m_y;
54 : };
55 :
56 : class CDRLineToElement : public CDRPathElement
57 : {
58 : public:
59 0 : CDRLineToElement(double x, double y)
60 : : m_x(x),
61 0 : m_y(y) {}
62 0 : ~CDRLineToElement() {}
63 : void writeOut(WPXPropertyListVector &vec) const;
64 : void transform(const CDRTransforms &trafos);
65 : void transform(const CDRTransform &trafo);
66 : CDRPathElement *clone();
67 : private:
68 : double m_x;
69 : double m_y;
70 : };
71 :
72 : class CDRCubicBezierToElement : public CDRPathElement
73 : {
74 : public:
75 0 : CDRCubicBezierToElement(double x1, double y1, double x2, double y2, double x, double y)
76 : : m_x1(x1),
77 : m_y1(y1),
78 : m_x2(x2),
79 : m_y2(y2),
80 : m_x(x),
81 0 : m_y(y) {}
82 0 : ~CDRCubicBezierToElement() {}
83 : void writeOut(WPXPropertyListVector &vec) const;
84 : void transform(const CDRTransforms &trafos);
85 : void transform(const CDRTransform &trafo);
86 : CDRPathElement *clone();
87 : private:
88 : double m_x1;
89 : double m_y1;
90 : double m_x2;
91 : double m_y2;
92 : double m_x;
93 : double m_y;
94 : };
95 :
96 : class CDRQuadraticBezierToElement : public CDRPathElement
97 : {
98 : public:
99 0 : CDRQuadraticBezierToElement(double x1, double y1, double x, double y)
100 : : m_x1(x1),
101 : m_y1(y1),
102 : m_x(x),
103 0 : m_y(y) {}
104 0 : ~CDRQuadraticBezierToElement() {}
105 : void writeOut(WPXPropertyListVector &vec) const;
106 : void transform(const CDRTransforms &trafos);
107 : void transform(const CDRTransform &trafo);
108 : CDRPathElement *clone();
109 : private:
110 : double m_x1;
111 : double m_y1;
112 : double m_x;
113 : double m_y;
114 : };
115 :
116 : class CDRSplineToElement : public CDRPathElement
117 : {
118 : public:
119 0 : CDRSplineToElement(const std::vector<std::pair<double, double> > &points)
120 0 : : m_points(points) {}
121 0 : ~CDRSplineToElement() {}
122 : void writeOut(WPXPropertyListVector &vec) const;
123 : void transform(const CDRTransforms &trafos);
124 : void transform(const CDRTransform &trafo);
125 : CDRPathElement *clone();
126 : private:
127 : std::vector<std::pair<double, double> > m_points;
128 : };
129 :
130 : class CDRArcToElement : public CDRPathElement
131 : {
132 : public:
133 0 : CDRArcToElement(double rx, double ry, double rotation, bool largeArc, bool sweep, double x, double y)
134 : : m_rx(rx),
135 : m_ry(ry),
136 : m_rotation(rotation),
137 : m_largeArc(largeArc),
138 : m_sweep(sweep),
139 : m_x(x),
140 0 : m_y(y) {}
141 0 : ~CDRArcToElement() {}
142 : void writeOut(WPXPropertyListVector &vec) const;
143 : void transform(const CDRTransforms &trafos);
144 : void transform(const CDRTransform &trafo);
145 : CDRPathElement *clone();
146 : private:
147 : double m_rx;
148 : double m_ry;
149 : double m_rotation;
150 : bool m_largeArc;
151 : bool m_sweep;
152 : double m_x;
153 : double m_y;
154 : };
155 :
156 : } // namespace libcdr
157 :
158 :
159 0 : void libcdr::CDRMoveToElement::writeOut(WPXPropertyListVector &vec) const
160 : {
161 0 : WPXPropertyList node;
162 0 : node.insert("libwpg:path-action", "M");
163 0 : node.insert("svg:x", m_x);
164 0 : node.insert("svg:y", m_y);
165 0 : vec.append(node);
166 0 : }
167 :
168 0 : void libcdr::CDRMoveToElement::transform(const CDRTransforms &trafos)
169 : {
170 0 : trafos.applyToPoint(m_x,m_y);
171 0 : }
172 :
173 0 : void libcdr::CDRMoveToElement::transform(const CDRTransform &trafo)
174 : {
175 0 : trafo.applyToPoint(m_x,m_y);
176 0 : }
177 :
178 0 : libcdr::CDRPathElement *libcdr::CDRMoveToElement::clone()
179 : {
180 0 : return new CDRMoveToElement(m_x, m_y);
181 : }
182 :
183 0 : void libcdr::CDRLineToElement::writeOut(WPXPropertyListVector &vec) const
184 : {
185 0 : WPXPropertyList node;
186 0 : node.insert("libwpg:path-action", "L");
187 0 : node.insert("svg:x", m_x);
188 0 : node.insert("svg:y", m_y);
189 0 : vec.append(node);
190 0 : }
191 :
192 0 : void libcdr::CDRLineToElement::transform(const CDRTransforms &trafos)
193 : {
194 0 : trafos.applyToPoint(m_x,m_y);
195 0 : }
196 :
197 0 : void libcdr::CDRLineToElement::transform(const CDRTransform &trafo)
198 : {
199 0 : trafo.applyToPoint(m_x,m_y);
200 0 : }
201 :
202 0 : libcdr::CDRPathElement *libcdr::CDRLineToElement::clone()
203 : {
204 0 : return new CDRLineToElement(m_x, m_y);
205 : }
206 :
207 0 : void libcdr::CDRCubicBezierToElement::writeOut(WPXPropertyListVector &vec) const
208 : {
209 0 : WPXPropertyList node;
210 0 : node.insert("libwpg:path-action", "C");
211 0 : node.insert("svg:x1", m_x1);
212 0 : node.insert("svg:y1", m_y1);
213 0 : node.insert("svg:x2", m_x2);
214 0 : node.insert("svg:y2", m_y2);
215 0 : node.insert("svg:x", m_x);
216 0 : node.insert("svg:y", m_y);
217 0 : vec.append(node);
218 0 : }
219 :
220 0 : void libcdr::CDRCubicBezierToElement::transform(const CDRTransforms &trafos)
221 : {
222 0 : trafos.applyToPoint(m_x1,m_y1);
223 0 : trafos.applyToPoint(m_x2,m_y2);
224 0 : trafos.applyToPoint(m_x,m_y);
225 0 : }
226 :
227 0 : void libcdr::CDRCubicBezierToElement::transform(const CDRTransform &trafo)
228 : {
229 0 : trafo.applyToPoint(m_x1,m_y1);
230 0 : trafo.applyToPoint(m_x2,m_y2);
231 0 : trafo.applyToPoint(m_x,m_y);
232 0 : }
233 :
234 0 : libcdr::CDRPathElement *libcdr::CDRCubicBezierToElement::clone()
235 : {
236 0 : return new CDRCubicBezierToElement(m_x1, m_y1, m_x2, m_y2, m_x, m_y);
237 : }
238 :
239 0 : void libcdr::CDRQuadraticBezierToElement::writeOut(WPXPropertyListVector &vec) const
240 : {
241 0 : WPXPropertyList node;
242 0 : node.insert("libwpg:path-action", "Q");
243 0 : node.insert("svg:x1", m_x1);
244 0 : node.insert("svg:y1", m_y1);
245 0 : node.insert("svg:x", m_x);
246 0 : node.insert("svg:y", m_y);
247 0 : vec.append(node);
248 0 : }
249 :
250 0 : void libcdr::CDRQuadraticBezierToElement::transform(const CDRTransforms &trafos)
251 : {
252 0 : trafos.applyToPoint(m_x1,m_y1);
253 0 : trafos.applyToPoint(m_x,m_y);
254 0 : }
255 :
256 0 : void libcdr::CDRQuadraticBezierToElement::transform(const CDRTransform &trafo)
257 : {
258 0 : trafo.applyToPoint(m_x1,m_y1);
259 0 : trafo.applyToPoint(m_x,m_y);
260 0 : }
261 :
262 0 : libcdr::CDRPathElement *libcdr::CDRQuadraticBezierToElement::clone()
263 : {
264 0 : return new CDRQuadraticBezierToElement(m_x1, m_y1, m_x, m_y);
265 : }
266 :
267 0 : void libcdr::CDRSplineToElement::writeOut(WPXPropertyListVector &vec) const
268 : {
269 0 : WPXPropertyList node;
270 :
271 : #if 0
272 : node.insert("libwpg:path-action", "M");
273 : node.insert("svg:x", m_points[0].first);
274 : node.insert("svg:y", m_points[0].second);
275 : vec.append(node);
276 :
277 : for (unsigned j = 0; j < m_points.size(); ++j)
278 : {
279 : node.clear();
280 : node.insert("libwpg:path-action", "L");
281 : node.insert("svg:x", m_points[j].first);
282 : node.insert("svg:y", m_points[j].second);
283 : vec.append(node);
284 : }
285 :
286 : node.clear();
287 : node.insert("libwpg:path-action", "M");
288 : node.insert("svg:x", m_points[0].first);
289 : node.insert("svg:y", m_points[0].second);
290 : vec.append(node);
291 : #endif
292 0 : for (unsigned i = 1; i < m_points.size()-1; i++)
293 : {
294 0 : node.clear();
295 0 : node.insert("libwpg:path-action", "Q");
296 0 : node.insert("svg:x1", m_points[i].first);
297 0 : node.insert("svg:y1", m_points[i].second);
298 0 : if (i < m_points.size() - 2)
299 : {
300 0 : node.insert("svg:x", (m_points[i].first+m_points[i+1].first)/2.0);
301 0 : node.insert("svg:y", (m_points[i].second+m_points[i+1].second)/2.0);
302 : }
303 : else
304 : {
305 0 : node.insert("svg:x", m_points[i+1].first);
306 0 : node.insert("svg:y", m_points[i+1].second);
307 : }
308 0 : vec.append(node);
309 : }
310 :
311 : // For the while, just move to the end point
312 0 : node.clear();
313 0 : node.insert("libwpg:path-action", "L");
314 0 : node.insert("svg:x", m_points.back().first);
315 0 : node.insert("svg:y", m_points.back().second);
316 0 : vec.append(node);
317 0 : }
318 :
319 0 : void libcdr::CDRSplineToElement::transform(const CDRTransforms &trafos)
320 : {
321 0 : for (std::vector<std::pair<double, double> >::iterator iter = m_points.begin();
322 0 : iter != m_points.end(); ++iter)
323 0 : trafos.applyToPoint(iter->first, iter->second);
324 0 : }
325 :
326 0 : void libcdr::CDRSplineToElement::transform(const CDRTransform &trafo)
327 : {
328 0 : for (std::vector<std::pair<double, double> >::iterator iter = m_points.begin();
329 0 : iter != m_points.end(); ++iter)
330 0 : trafo.applyToPoint(iter->first, iter->second);
331 0 : }
332 :
333 0 : libcdr::CDRPathElement *libcdr::CDRSplineToElement::clone()
334 : {
335 0 : return new CDRSplineToElement(m_points);
336 : }
337 :
338 0 : void libcdr::CDRArcToElement::writeOut(WPXPropertyListVector &vec) const
339 : {
340 0 : WPXPropertyList node;
341 0 : node.insert("libwpg:path-action", "A");
342 0 : node.insert("svg:rx", m_rx);
343 0 : node.insert("svg:ry", m_ry);
344 0 : node.insert("libwpg:rotate", m_rotation * 180 / M_PI, WPX_GENERIC);
345 0 : node.insert("libwpg:large-arc", m_largeArc);
346 0 : node.insert("libwpg:sweep", m_sweep);
347 0 : node.insert("svg:x", m_x);
348 0 : node.insert("svg:y", m_y);
349 0 : vec.append(node);
350 0 : }
351 :
352 0 : void libcdr::CDRArcToElement::transform(const CDRTransforms &trafos)
353 : {
354 0 : trafos.applyToArc(m_rx, m_ry, m_rotation, m_sweep, m_x, m_y);
355 0 : }
356 :
357 0 : void libcdr::CDRArcToElement::transform(const CDRTransform &trafo)
358 : {
359 0 : trafo.applyToArc(m_rx, m_ry, m_rotation, m_sweep, m_x, m_y);
360 0 : }
361 :
362 0 : libcdr::CDRPathElement *libcdr::CDRArcToElement::clone()
363 : {
364 0 : return new CDRArcToElement(m_rx, m_ry, m_rotation, m_largeArc, m_sweep, m_x, m_y);
365 : }
366 :
367 0 : void libcdr::CDRPath::appendMoveTo(double x, double y)
368 : {
369 0 : m_elements.push_back(new libcdr::CDRMoveToElement(x, y));
370 0 : }
371 :
372 0 : void libcdr::CDRPath::appendLineTo(double x, double y)
373 : {
374 0 : m_elements.push_back(new libcdr::CDRLineToElement(x, y));
375 0 : }
376 :
377 0 : void libcdr::CDRPath::appendCubicBezierTo(double x1, double y1, double x2, double y2, double x, double y)
378 : {
379 0 : m_elements.push_back(new libcdr::CDRCubicBezierToElement(x1, y1, x2, y2, x, y));
380 0 : }
381 :
382 0 : void libcdr::CDRPath::appendQuadraticBezierTo(double x1, double y1, double x, double y)
383 : {
384 0 : m_elements.push_back(new libcdr::CDRQuadraticBezierToElement(x1, y1, x, y));
385 0 : }
386 :
387 0 : void libcdr::CDRPath::appendArcTo(double rx, double ry, double rotation, bool longAngle, bool sweep, double x, double y)
388 : {
389 0 : m_elements.push_back(new libcdr::CDRArcToElement(rx, ry, rotation, longAngle, sweep, x, y));
390 0 : }
391 :
392 0 : void libcdr::CDRPath::appendSplineTo(std::vector<std::pair<double, double> > &points)
393 : {
394 0 : m_elements.push_back(new libcdr::CDRSplineToElement(points));
395 0 : }
396 :
397 0 : void libcdr::CDRPath::appendClosePath()
398 : {
399 0 : m_isClosed = true;
400 0 : }
401 :
402 0 : libcdr::CDRPath::CDRPath(const libcdr::CDRPath &path) : m_elements(), m_isClosed(false)
403 : {
404 0 : for (std::vector<CDRPathElement *>::const_iterator iter = path.m_elements.begin(); iter != path.m_elements.end(); ++iter)
405 0 : m_elements.push_back((*iter)->clone());
406 0 : m_isClosed = path.isClosed();
407 0 : }
408 :
409 0 : libcdr::CDRPath::~CDRPath()
410 : {
411 0 : clear();
412 0 : }
413 :
414 0 : void libcdr::CDRPath::appendPath(const CDRPath &path)
415 : {
416 0 : for (std::vector<CDRPathElement *>::const_iterator iter = path.m_elements.begin(); iter != path.m_elements.end(); ++iter)
417 0 : m_elements.push_back((*iter)->clone());
418 0 : }
419 :
420 0 : void libcdr::CDRPath::writeOut(WPXPropertyListVector &vec) const
421 : {
422 0 : for (std::vector<CDRPathElement *>::const_iterator iter = m_elements.begin(); iter != m_elements.end(); ++iter)
423 0 : (*iter)->writeOut(vec);
424 0 : }
425 :
426 0 : void libcdr::CDRPath::transform(const CDRTransforms &trafos)
427 : {
428 0 : for (std::vector<CDRPathElement *>::iterator iter = m_elements.begin(); iter != m_elements.end(); ++iter)
429 0 : (*iter)->transform(trafos);
430 0 : }
431 :
432 0 : void libcdr::CDRPath::transform(const CDRTransform &trafo)
433 : {
434 0 : for (std::vector<CDRPathElement *>::iterator iter = m_elements.begin(); iter != m_elements.end(); ++iter)
435 0 : (*iter)->transform(trafo);
436 0 : }
437 :
438 0 : libcdr::CDRPathElement *libcdr::CDRPath::clone()
439 : {
440 0 : return new CDRPath(*this);
441 : }
442 :
443 0 : void libcdr::CDRPath::clear()
444 : {
445 0 : for (std::vector<CDRPathElement *>::iterator iter = m_elements.begin(); iter != m_elements.end(); ++iter)
446 0 : if (*iter)
447 0 : delete(*iter);
448 0 : m_elements.clear();
449 0 : m_isClosed = false;
450 0 : }
451 :
452 0 : bool libcdr::CDRPath::empty() const
453 : {
454 0 : return m_elements.empty();
455 : }
456 :
457 0 : bool libcdr::CDRPath::isClosed() const
458 : {
459 0 : return m_isClosed;
460 : }
461 :
462 : /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
|