Path.h
1 /* Copyright (C) 2017 Marc Boris Duerner
2  Copyright (C) 2017 Aloysius Indrayanto
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License as published by the Free Software Foundation; either
7  version 2.1 of the License, or (at your option) any later version.
8 
9  As a special exception, you may use this file as part of a free
10  software library without restriction. Specifically, if other files
11  instantiate templates or use macros or inline functions from this
12  file, or you compile this file and link it with other files to
13  produce an executable, this file does not by itself cause the
14  resulting executable to be covered by the GNU General Public
15  License. This exception does not however invalidate any other
16  reasons why the executable file might be covered by the GNU Library
17  General Public License.
18 
19  This library is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  Lesser General Public License for more details.
23 
24  You should have received a copy of the GNU Lesser General Public
25  License along with this library; if not, write to the Free Software
26  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27  MA 02110-1301 USA
28 */
29 
30 #ifndef PT_GFX_PATH_H
31 #define PT_GFX_PATH_H
32 
33 #include <Pt/Gfx/Api.h>
34 #include <Pt/Gfx/FillRule.h>
35 #include <Pt/Gfx/Point.h>
36 #include <Pt/Gfx/Rect.h>
37 #include <Pt/Gfx/Polygon.h>
38 #include <Pt/Gfx/Transform.h>
39 #include <Pt/SmartPtr.h>
40 
41 #include <vector>
42 #include <iterator>
43 #include <cstddef>
44 
45 namespace Pt {
46 
47 namespace Gfx {
48 
49 class PathData;
50 class PathElement;
51 class PathIterator;
52 
60 class PT_GFX_API Path
61 {
62  public:
66  {
67  MoveTo,
68  LineTo,
69  QuadTo,
70  CubicTo,
71  Close
72  };
73 
74  typedef PathIterator Iterator;
75  typedef PathElement Element;
76 
77  public:
80  Path();
81 
84  Path(const Path& other);
85 
88  Path& operator=(const Path& other);
89 
92  ~Path();
93 
96  std::size_t size() const;
97 
100  bool isEmpty() const;
101 
104  Iterator begin() const;
105 
108  Iterator end() const;
109 
112  void clear();
113 
117 
124  bool contains(const PointF& point, FillRule rule = FillRule::NonZero) const;
125 
132  bool contains(const RectF& rect, FillRule rule = FillRule::NonZero) const;
133 
141  bool intersects(const RectF& rect, FillRule rule = FillRule::NonZero) const;
142 
145  const PointF& currentPosition() const;
146 
149  void moveTo(const PointF& p);
150 
153  void lineTo(const PointF& p);
154 
157  void quadTo(const PointF &cp, const PointF& to);
158 
161  void cubicTo(const PointF &cp1, const PointF &cp2, const PointF& to);
162 
171  void arcTo(const PointF& topLeft, const SizeF& size,
172  double degBegin, double degEnd);
173 
176  void close();
177 
180  void addPath(const Path& p);
181 
184  void addRect(const RectF& rect);
185 
188  void addRoundedRect(const RectF& rect, double radius);
189 
194  void addRoundedRect(const RectF& rect, double rx, double ry);
195 
198  void addEllipse(const PointF& topLeft, const SizeF& size);
199 
205  void addArc(const PointF& topLeft, const SizeF& size,
206  double degBegin, double degEnd);
207 
210  void addPie(const PointF& topLeft, const SizeF& size,
211  double degBegin, double degEnd);
212 
215  void addChord(const PointF& topLeft, const SizeF& size,
216  double degBegin, double degEnd);
217 
220  void addPolyline(const PointF* points, std::size_t count);
221 
224  void addPolygon(const PointF* points, std::size_t count);
225 
228  void transform(const Transform& transform);
229 
232  Path toTransformed(const Transform& transform) const;
233 
243  Iterator getPolygon(Iterator it, Polygon& polygon, float tolerance = 0.25f) const;
244 
245  private:
246  void detach();
247 
248  private:
249  SmartPtr<PathData> _pathData;
250 };
251 
252 /* @internal @brief Path entry.
253 */
254 class PathEntry
255 {
256  public:
257  typedef Path::ElementType Type;
258 
259  public:
260  PathEntry(Type type, std::size_t n)
261  : _type(type)
262  , _size(n)
263  {
264  }
265 
266  Type type() const
267  {
268  return _type;
269  }
270 
271  std::size_t size() const
272  {
273  return _size;
274  }
275 
276  private:
277  Type _type;
278  std::size_t _size;
279 };
280 
285 {
286  friend class PathIterator;
287 
288  protected:
289  PathElement(const PathEntry* entry, const PointF* points)
290  : _entry(entry)
291  , _pos(0.0, 0.0)
292  , _points(points)
293  {
294  }
295 
296  void setPosition(const PointF& pos)
297  {
298  _pos = pos;
299  }
300 
301  void setEntry(const PathEntry* entry, const PointF* points)
302  {
303  _entry = entry;
304  _points = points;
305  }
306 
307  public:
311  {
312  return _entry->type();
313  }
314 
317  std::size_t size() const
318  {
319  return _entry->size();
320  }
321 
324  const PointF& position() const
325  {
326  return _pos;
327  }
328 
331  const PointF& point(std::size_t n) const
332  {
333  return _points[n];
334  }
335 
338  void flatten(Polygon& points, double tolerance = 0.25) const;
339 
340  private:
341  const PathEntry* _entry;
342  PointF _pos;
343  const PointF* _points;
344 };
345 
350 {
351  public:
352  using iterator_category = std::forward_iterator_tag;
353  using value_type = Path::Element;
354  using difference_type = std::ptrdiff_t;
355  using pointer = const Path::Element*;
356  using reference = const Path::Element&;
357 
361  : _entry(0)
362  , _points(0)
363  , _element(0, 0)
364  {
365  }
366 
369  PathIterator(const PathEntry* entry, const PointF* points)
370  : _entry(entry)
371  , _points(points)
372  , _element(_entry, _points)
373  {
374  }
375 
378  const Path::Element& operator*() const
379  {
380  return _element;
381  }
382 
385  const Path::Element* operator->() const
386  {
387  return &_element;
388  }
389 
393  {
394  if( _entry->size() > 0)
395  {
396  const PointF& pos = _points[ _entry->size() - 1 ];
397  _element.setPosition(pos);
398  }
399 
400  _points += _entry->size();
401  ++_entry;
402 
403  _element.setEntry(_entry, _points);
404  return *this;
405  }
406 
410  {
411  PathIterator tmp = *this;
412  ++(*this);
413  return tmp;
414  }
415 
418  bool operator == (const PathIterator& other) const
419  {
420  return _entry == other._entry;
421  }
422 
425  bool operator != (const PathIterator& other) const
426  {
427  return _entry != other._entry;
428  }
429 
432  bool operator < (const PathIterator & other) const
433  {
434  return _entry < other._entry;
435  }
436 
437  private:
438  const PathEntry* _entry;
439  const PointF* _points;
440  Path::Element _element;
441 };
442 
443 /* @internal Path data.
444 */
445 class PathData
446 {
447  public:
448  PathData()
449  { }
450 
451  ~PathData()
452  { }
453 
454  const PointF& currentPosition() const
455  {
456  return _position;
457  }
458 
459  void setCurrentPosition(const PointF& p)
460  {
461  _position = p;
462  }
463 
464  Path::Iterator begin() const
465  {
466  return Path::Iterator( _entries.data(), _points.data() );
467  }
468 
469  Path::Iterator end() const
470  {
471  return Path::Iterator(_entries.data() + _entries.size(), _points.data() + _points.size());
472  }
473 
474  std::size_t size() const
475  {
476  return _entries.size();
477  }
478 
479  bool isEmpty() const
480  {
481  return _entries.empty();
482  }
483 
484  void clear()
485  {
486  _entries.clear();
487  _points.clear();
488  _start = PointF();
489  _position = PointF();
490  }
491 
492  void append(const PathData& path);
493 
494  void moveTo(const PointF& pos);
495 
496  void lineTo(const PointF& pos);
497 
498  void quadTo(const PointF& cp, const PointF& to);
499 
500  void cubicTo(const PointF& cp1, const PointF& cp2, const PointF& to);
501 
502  void close();
503 
504  void transform(const Transform& tform);
505 
506  private:
507  std::vector<PathEntry> _entries;
508  std::vector<PointF> _points;
509  PointF _start;
510  PointF _position;
511 };
512 
513 } // namespace
514 
515 } // namespace
516 
517 #endif
Core module.
Definition: pt-gfx-images.dox:14
const PointF & currentPosition() const
Returns the current drawing position.
Read-only view of a path element.
Definition: Path.h:285
void addPolygon(const PointF *points, std::size_t count)
Adds a polygon as a new closed subpath.
void arcTo(const PointF &topLeft, const SizeF &size, double degBegin, double degEnd)
Adds an arc segment to the current subpath.
~Path()
Destroys the path.
PathIterator operator++(int)
Advances to the next path element and returns the previous iterator.
Definition: Path.h:409
Path(const Path &other)
Copies another path.
void addRoundedRect(const RectF &rect, double radius)
Adds a rounded rectangle as a new subpath.
ElementType
Identifies the command stored in a path element.
Definition: Path.h:66
PathIterator & operator++()
Advances to the next path element.
Definition: Path.h:392
const Path::Element & operator*() const
Returns the current path element.
Definition: Path.h:378
RectF boundingRect() const
Returns the bounding rectangle of the path.
std::size_t size() const
Returns the number of path elements.
void addChord(const PointF &topLeft, const SizeF &size, double degBegin, double degEnd)
Adds a chord as a new subpath.
Path & operator=(const Path &other)
Replaces the path contents.
Path::ElementType type() const
Returns the element type.
Definition: Path.h:310
Iterator begin() const
Returns an iterator to the first element.
void close()
Closes the current subpath.
bool contains(const PointF &point, FillRule rule=FillRule::NonZero) const
Returns true if the point lies inside the filled area of the path.
Size with floating-point width and height.
Definition: Size.h:45
Point with floating-point X and Y coordinates.
Definition: Point.h:45
void addPolyline(const PointF *points, std::size_t count)
Adds a polyline as a new subpath.
FillRule
Determines how overlapping subpaths of a filled shape are painted.
Definition: FillRule.h:45
bool operator<(const PathIterator &other) const
Returns true if this iterator precedes the other iterator.
Definition: Path.h:432
Iterator getPolygon(Iterator it, Polygon &polygon, float tolerance=0.25f) const
Flattens one subpath into polygon starting at it.
void moveTo(const PointF &p)
Starts a new subpath at the given point.
const PointF & point(std::size_t n) const
Returns one point of the element.
Definition: Path.h:331
const Path::Element * operator->() const
Returns a pointer to the current path element.
Definition: Path.h:385
Affine transform for drawing coordinates.
Definition: Transform.h:49
void flatten(Polygon &points, double tolerance=0.25) const
Flattens the element into polygon points.
Vector path for drawing outlines and filled shapes.
Definition: Path.h:61
Forward iterator over path elements.
Definition: Path.h:350
bool intersects(const RectF &rect, FillRule rule=FillRule::NonZero) const
Returns true if the filled area of the path overlaps rect.
Iterator end() const
Returns an iterator past the last element.
PathIterator(const PathEntry *entry, const PointF *points)
Constructs an iterator for the given storage pointers.
Definition: Path.h:369
bool operator!=(const PathIterator &other) const
Returns true if both iterators refer to different elements.
Definition: Path.h:425
void addRect(const RectF &rect)
Adds a rectangle as a new subpath.
void addPie(const PointF &topLeft, const SizeF &size, double degBegin, double degEnd)
Adds a pie segment as a new subpath.
bool operator==(const PathIterator &other) const
Returns true if both iterators refer to the same element.
Definition: Path.h:418
std::size_t size() const
Returns the number of points stored in the element.
Definition: Path.h:317
Path()
Constructs an empty path.
void addArc(const PointF &topLeft, const SizeF &size, double degBegin, double degEnd)
Adds an arc as a new subpath.
bool contains(const RectF &rect, FillRule rule=FillRule::NonZero) const
Returns true if the rectangle lies entirely inside the filled area.
void quadTo(const PointF &cp, const PointF &to)
Adds a quadratic Bezier segment.
void clear()
Removes all path elements.
void addRoundedRect(const RectF &rect, double rx, double ry)
Adds a rounded rectangle with elliptical corners as a new subpath.
Rect with floating-point coordinates.
Definition: Rect.h:45
void addEllipse(const PointF &topLeft, const SizeF &size)
Adds an ellipse as a new subpath.
Path toTransformed(const Transform &transform) const
Returns a copy of the path with the transform applied.
void transform(const Transform &transform)
Applies a transform to all path coordinates.
bool isEmpty() const
Returns true if the path has no elements.
void addPath(const Path &p)
Appends all elements of p to this path.
void cubicTo(const PointF &cp1, const PointF &cp2, const PointF &to)
Adds a cubic Bezier segment.
const PointF & position() const
Returns the current path position before the element.
Definition: Path.h:324
void lineTo(const PointF &p)
Adds a straight line to the given point.
PathIterator()
Constructs an end iterator.
Definition: Path.h:360