1 | /*! |
2 | * \file path.hpp |
3 | * \brief file path.hpp |
4 | * |
5 | * Copyright 2016 by Intel. |
6 | * |
7 | * Contact: kevin.rogovin@gmail.com |
8 | * |
9 | * This Source Code Form is subject to the |
10 | * terms of the Mozilla Public License, v. 2.0. |
11 | * If a copy of the MPL was not distributed with |
12 | * this file, You can obtain one at |
13 | * http://mozilla.org/MPL/2.0/. |
14 | * |
15 | * \author Kevin Rogovin <kevin.rogovin@gmail.com> |
16 | * |
17 | */ |
18 | |
19 | |
20 | |
21 | #ifndef FASTUIDRAW_PATH_HPP |
22 | #define FASTUIDRAW_PATH_HPP |
23 | |
24 | #include <fastuidraw/util/fastuidraw_memory.hpp> |
25 | #include <fastuidraw/util/vecN.hpp> |
26 | #include <fastuidraw/util/rect.hpp> |
27 | #include <fastuidraw/util/c_array.hpp> |
28 | #include <fastuidraw/util/reference_counted.hpp> |
29 | #include <fastuidraw/path_enums.hpp> |
30 | #include <fastuidraw/tessellated_path.hpp> |
31 | #include <fastuidraw/painter/shader_filled_path.hpp> |
32 | |
33 | namespace fastuidraw { |
34 | |
35 | /*!\addtogroup Paths |
36 | * @{ |
37 | */ |
38 | |
39 | /*! |
40 | * \brief |
41 | * An PathContour represents a single contour within |
42 | * a Path. |
43 | * |
44 | * Closeing a contour (see \ref close(), \ref |
45 | * close_generic() and close_arc()) means to specify |
46 | * the edge from the last point of the PathContour |
47 | * to the first point. |
48 | */ |
49 | class PathContour: |
50 | public reference_counted<PathContour>::non_concurrent |
51 | { |
52 | public: |
53 | /*! |
54 | * \brief |
55 | * Provides an interface to resume from a previous tessellation |
56 | * of a \ref interpolator_base derived object. |
57 | */ |
58 | class tessellation_state: |
59 | public reference_counted<tessellation_state>::non_concurrent |
60 | { |
61 | public: |
62 | /*! |
63 | * To be implemented by a derived class to return the depth |
64 | * of recursion at this objects stage of tessellation. |
65 | */ |
66 | virtual |
67 | unsigned int |
68 | recursion_depth(void) const = 0; |
69 | |
70 | /*! |
71 | * To be implemented by a derived class to resume tessellation |
72 | * and to (try to) achieve the required threshhold within the |
73 | * recursion limits of a \ref TessellatedPath::TessellationParams |
74 | * value. |
75 | * \param tess_params tessellation parameters |
76 | * \param out_data location to which to write the tessellations |
77 | * \param out_max_distance location to which to write an upperbound for the |
78 | * distance between the curve and the tesseallation |
79 | * approximation. |
80 | */ |
81 | virtual |
82 | void |
83 | resume_tessellation(const TessellatedPath::TessellationParams &tess_params, |
84 | TessellatedPath::SegmentStorage *out_data, |
85 | float *out_max_distance) = 0; |
86 | }; |
87 | |
88 | /*! |
89 | * \brief |
90 | * Base class to describe how to interpolate from one |
91 | * point of a PathContour to the next, i.e. describes |
92 | * the shape of an edge. |
93 | */ |
94 | class interpolator_base: |
95 | public reference_counted<interpolator_base>::non_concurrent |
96 | { |
97 | public: |
98 | /*! |
99 | * Ctor. |
100 | * \param contour \ref PathContour to which to add the interpolator. |
101 | * The interpolator is added to the contour at the |
102 | * interpolator's construction. The start point is |
103 | * computed from the current state of the \ref |
104 | * PathContour. |
105 | * \param end end point of the edge of this interpolator |
106 | * \param tp nature the edge represented by this interpolator_base |
107 | */ |
108 | interpolator_base(PathContour &contour, |
109 | const vec2 &end, enum PathEnums::edge_type_t tp); |
110 | |
111 | virtual |
112 | ~interpolator_base(); |
113 | |
114 | /*! |
115 | * Returns the starting point of this interpolator. |
116 | */ |
117 | const vec2& |
118 | start_pt(void) const; |
119 | |
120 | /*! |
121 | * Returns the ending point of this interpolator |
122 | */ |
123 | const vec2& |
124 | end_pt(void) const; |
125 | |
126 | /*! |
127 | * Returns the edge type. |
128 | */ |
129 | enum PathEnums::edge_type_t |
130 | edge_type(void) const; |
131 | |
132 | /*! |
133 | * To be implemented by a derived class to return true if |
134 | * the interpolator is flat, i.e. is just a line segment |
135 | * connecting start_pt() to end_pt(). |
136 | */ |
137 | virtual |
138 | bool |
139 | is_flat(void) const = 0; |
140 | |
141 | /*! |
142 | * To be implemented by a derived class to produce the arc-tessellation |
143 | * from start_pt() to end_pt(). In addition, for recursive tessellation, |
144 | * returns the tessellation state to be queried for recursion depth and |
145 | * reused to refine the tessellation. If the tessellation routine is not |
146 | * recursive in nature, return nullptr. |
147 | * |
148 | * \param tess_params tessellation parameters |
149 | * \param out_data location to which to write the tessellations |
150 | * \param out_max_distance location to which to write an upperbound for the |
151 | * distance between the curve and the tesseallation |
152 | * approximation. |
153 | */ |
154 | virtual |
155 | reference_counted_ptr<tessellation_state> |
156 | produce_tessellation(const TessellatedPath::TessellationParams &tess_params, |
157 | TessellatedPath::SegmentStorage *out_data, |
158 | float *out_max_distance) const = 0; |
159 | |
160 | /*! |
161 | * To be implemented by a derived class to return a fast (and approximate) |
162 | * bounding box for the interpolator. |
163 | * \param out_bb (output) location to which to write the bounding box value |
164 | */ |
165 | virtual |
166 | void |
167 | approximate_bounding_box(Rect *out_bb) const = 0; |
168 | |
169 | /*! |
170 | * To be implemented by a derived class to create and |
171 | * return a deep copy of the interpolator object. |
172 | */ |
173 | virtual |
174 | reference_counted_ptr<interpolator_base> |
175 | deep_copy(PathContour &contour) const = 0; |
176 | |
177 | /*! |
178 | * To be optionally implemented by a derived class to add this |
179 | * interpolator to a \ref ShaderFilledPath::Builder. A return |
180 | * code of \ref routine_fail means that the interpolator cannot |
181 | * be realized in such a way to be added and a \ref Path that |
182 | * includes such an interpolator in a closed contour will |
183 | * be unable to realized a \ref ShaderFilledPath value and |
184 | * \ref Path::shader_filled_path() will return a null handle. |
185 | * Default implementation is to return routine_fail. |
186 | * \param builder object to which to add interpolator. |
187 | * \param tol error goal between the interpolator and how it |
188 | * is realized on the ShaderFilledPath::Builder |
189 | */ |
190 | virtual |
191 | enum return_code |
192 | add_to_builder(ShaderFilledPath::Builder *builder, float tol) const; |
193 | |
194 | private: |
195 | friend class PathContour; |
196 | void *m_d; |
197 | }; |
198 | |
199 | /*! |
200 | * \brief |
201 | * A flat interpolator represents a flat edge. |
202 | */ |
203 | class flat:public interpolator_base |
204 | { |
205 | public: |
206 | /*! |
207 | * Ctor. |
208 | * \param contour \ref PathContour to which to add the interpolator. |
209 | * The interpolator is added to the contour at the |
210 | * interpolator's construction. The start point is |
211 | * computed from the current state of the \ref |
212 | * PathContour |
213 | * \param end end point of the edge of this interpolator |
214 | * \param tp nature the edge represented by this interpolator_base |
215 | */ |
216 | flat(PathContour &contour, |
217 | const vec2 &end, enum PathEnums::edge_type_t tp): |
218 | interpolator_base(contour, end, tp) |
219 | {} |
220 | |
221 | virtual |
222 | bool |
223 | is_flat(void) const; |
224 | |
225 | virtual |
226 | reference_counted_ptr<tessellation_state> |
227 | produce_tessellation(const TessellatedPath::TessellationParams &tess_params, |
228 | TessellatedPath::SegmentStorage *out_data, |
229 | float *out_max_distance) const; |
230 | virtual |
231 | void |
232 | approximate_bounding_box(Rect *out_bb) const; |
233 | |
234 | virtual |
235 | reference_counted_ptr<interpolator_base> |
236 | deep_copy(PathContour &contour) const; |
237 | |
238 | virtual |
239 | enum return_code |
240 | add_to_builder(ShaderFilledPath::Builder *builder, float tol) const; |
241 | }; |
242 | |
243 | /*! |
244 | * \brief |
245 | * Interpolator generic implements tessellation by recursion |
246 | * and relying on analytic derivative provided by derived |
247 | * class. |
248 | */ |
249 | class interpolator_generic:public interpolator_base |
250 | { |
251 | public: |
252 | /*! |
253 | * A tessellated_region is a base class for a cookie |
254 | * used and generated by tessellate(). |
255 | */ |
256 | class tessellated_region: |
257 | public reference_counted<tessellated_region>::non_concurrent |
258 | { |
259 | public: |
260 | /*! |
261 | * To be implemented by a derived class to compute an upper-bound |
262 | * of the distance from the curve restricted to the region to the |
263 | * line segment connecting the end points of the region. |
264 | */ |
265 | virtual |
266 | float |
267 | distance_to_line_segment(void) const = 0; |
268 | |
269 | /*! |
270 | * To be implemented by a derived class to compute an approximate |
271 | * upper-bound for the distance from the curve restricted to the |
272 | * region to a given arc. |
273 | * \param arc_radius radius of the arc |
274 | * \param center center of the circle of the arc |
275 | * \param unit_vector_arc_middle unit vector from center to the midpoint of the arc |
276 | * \param cos_half_arc_angle the cosine of half of the arc-angle |
277 | */ |
278 | virtual |
279 | float |
280 | distance_to_arc(float arc_radius, vec2 center, |
281 | vec2 unit_vector_arc_middle, |
282 | float cos_half_arc_angle) const = 0; |
283 | }; |
284 | |
285 | /*! |
286 | * Ctor. |
287 | * \param contour \ref PathContour to which the interpolator is added, |
288 | * the start point of the interpolator will be ending |
289 | * point of \ref PathContour::prev_interpolator(). |
290 | * \param end end point of the edge of this interpolator |
291 | * \param tp nature the edge represented by this interpolator_base |
292 | */ |
293 | interpolator_generic(PathContour &contour, |
294 | const vec2 &end, enum PathEnums::edge_type_t tp): |
295 | interpolator_base(contour, end, tp) |
296 | {} |
297 | |
298 | virtual |
299 | reference_counted_ptr<tessellation_state> |
300 | produce_tessellation(const TessellatedPath::TessellationParams &tess_params, |
301 | TessellatedPath::SegmentStorage *out_data, |
302 | float *out_max_distance) const; |
303 | |
304 | /*! |
305 | * To be implemented by a derived to assist in recursive tessellation. |
306 | * \param in_region region to divide in half, a nullptr value indicates |
307 | * that the region is the entire interpolator. |
308 | * \param out_regionA location to which to write the first half |
309 | * \param out_regionB location to which to write the second half |
310 | * \param out_p location to which to write the position of the point |
311 | * on the curve in the middle (with repsect to time) of |
312 | * in_region |
313 | */ |
314 | virtual |
315 | void |
316 | tessellate(reference_counted_ptr<tessellated_region> in_region, |
317 | reference_counted_ptr<tessellated_region> *out_regionA, |
318 | reference_counted_ptr<tessellated_region> *out_regionB, |
319 | vec2 *out_p) const = 0; |
320 | |
321 | /*! |
322 | * To be implemented by a derived class to return a reasonable |
323 | * lower bound on the needed number of times the edge should be |
324 | * cut in half in order to capture its shape. |
325 | */ |
326 | virtual |
327 | unsigned int |
328 | minimum_tessellation_recursion(void) const = 0; |
329 | }; |
330 | |
331 | /*! |
332 | * \brief |
333 | * Derived class of interpolator_base to indicate a Bezier curve. |
334 | * Supports Bezier curves of _any_ degree. |
335 | */ |
336 | class bezier:public interpolator_generic |
337 | { |
338 | public: |
339 | /*! |
340 | * Ctor. One control point, thus interpolation is a quadratic curve. |
341 | * \param contour \ref PathContour to which to add the interpolator. |
342 | * The interpolator is added to the contour at the |
343 | * interpolator's construction. The start point is |
344 | * computed from the current state of the \ref |
345 | * PathContour |
346 | * \param ct control point |
347 | * \param end end of curve |
348 | * \param tp nature the edge represented by this interpolator_base |
349 | */ |
350 | bezier(PathContour &contour, |
351 | const vec2 &ct, const vec2 &end, enum PathEnums::edge_type_t tp); |
352 | |
353 | /*! |
354 | * Ctor. Two control points, thus interpolation is a cubic curve. |
355 | * \param contour \ref PathContour to which to add the interpolator. |
356 | * The interpolator is added to the contour at the |
357 | * interpolator's construction. The start point is |
358 | * computed from the current state of the \ref |
359 | * PathContour |
360 | * \param ct1 1st control point |
361 | * \param ct2 2nd control point |
362 | * \param end end point of curve |
363 | * \param tp nature the edge represented by this interpolator_base |
364 | */ |
365 | bezier(PathContour &contour, |
366 | const vec2 &ct1, const vec2 &ct2, const vec2 &end, |
367 | enum PathEnums::edge_type_t tp); |
368 | |
369 | /*! |
370 | * Ctor. Iterator range defines the control points of the bezier curve. |
371 | * \param contour \ref PathContour to which to add the interpolator. |
372 | * The interpolator is added to the contour at the |
373 | * interpolator's construction. The start point is |
374 | * computed from the current state of the \ref |
375 | * PathContour |
376 | * \param control_pts control points of the bezier curve created, |
377 | * can be any size allowing bezier curves of |
378 | * arbitrary degree |
379 | * \param end end point of curve |
380 | * \param tp nature the edge represented by this interpolator_base |
381 | */ |
382 | bezier(PathContour &contour, |
383 | c_array<const vec2> control_pts, const vec2 &end, |
384 | enum PathEnums::edge_type_t tp); |
385 | |
386 | virtual |
387 | ~bezier(); |
388 | |
389 | /*! |
390 | * Returns the control points of the Bezier curve with |
391 | * c_array<const vec2>::front() having the same value as |
392 | * start_pt() and c_array<const vec2>::back() having the |
393 | * same value as end_pt(). |
394 | */ |
395 | c_array<const vec2> |
396 | pts(void) const; |
397 | |
398 | virtual |
399 | bool |
400 | is_flat(void) const; |
401 | |
402 | virtual |
403 | void |
404 | tessellate(reference_counted_ptr<tessellated_region> in_region, |
405 | reference_counted_ptr<tessellated_region> *out_regionA, |
406 | reference_counted_ptr<tessellated_region> *out_regionB, |
407 | vec2 *out_p) const; |
408 | virtual |
409 | void |
410 | approximate_bounding_box(Rect *out_bb) const; |
411 | |
412 | virtual |
413 | reference_counted_ptr<interpolator_base> |
414 | deep_copy(PathContour &contour) const; |
415 | |
416 | virtual |
417 | unsigned int |
418 | minimum_tessellation_recursion(void) const; |
419 | |
420 | virtual |
421 | enum return_code |
422 | add_to_builder(ShaderFilledPath::Builder *builder, float tol) const; |
423 | |
424 | private: |
425 | void *m_d; |
426 | }; |
427 | |
428 | /*! |
429 | * \brief |
430 | * An arc is for connecting one point to the next via an |
431 | * arc of a circle. |
432 | */ |
433 | class arc:public interpolator_base |
434 | { |
435 | public: |
436 | /*! |
437 | * Ctor. |
438 | * \param contour \ref PathContour to which to add the interpolator. |
439 | * The interpolator is added to the contour at the |
440 | * interpolator's construction. The start point is |
441 | * computed from the current state of the \ref |
442 | * PathContour |
443 | * \param angle The angle of the arc in radians, the value must not |
444 | * be a multiple of 2*FASTUIDRAW_PI. Assuming a coordinate system |
445 | * where y-increases vertically and x-increases to the right, |
446 | * a positive value indicates to have the arc go counter-clockwise, |
447 | * a negative angle for the arc to go clockwise. |
448 | * \param end end of curve |
449 | * \param tp nature the edge represented by this interpolator_base |
450 | */ |
451 | arc(PathContour &contour, |
452 | float angle, const vec2 &end, enum PathEnums::edge_type_t tp); |
453 | |
454 | ~arc(); |
455 | |
456 | /*! |
457 | * Returns the center of the arc. |
458 | */ |
459 | vec2 |
460 | center(void) const; |
461 | |
462 | /*! |
463 | * Returns the starting and ending angle of the arc |
464 | * each in radians. |
465 | */ |
466 | range_type<float> |
467 | angle(void) const; |
468 | |
469 | virtual |
470 | bool |
471 | is_flat(void) const; |
472 | |
473 | virtual |
474 | void |
475 | approximate_bounding_box(Rect *out_bb) const; |
476 | |
477 | virtual |
478 | reference_counted_ptr<interpolator_base> |
479 | deep_copy(PathContour &contour) const; |
480 | |
481 | virtual |
482 | reference_counted_ptr<tessellation_state> |
483 | produce_tessellation(const TessellatedPath::TessellationParams &tess_params, |
484 | TessellatedPath::SegmentStorage *out_data, |
485 | float *out_max_distance) const; |
486 | |
487 | virtual |
488 | enum return_code |
489 | add_to_builder(ShaderFilledPath::Builder *builder, float tol) const; |
490 | |
491 | private: |
492 | arc(const arc &q, PathContour &contour); |
493 | |
494 | void *m_d; |
495 | }; |
496 | |
497 | /*! |
498 | * Ctor. |
499 | */ |
500 | explicit |
501 | PathContour(void); |
502 | |
503 | ~PathContour(); |
504 | |
505 | /*! |
506 | * Start the PathContour, may only be called once in the lifetime |
507 | * of a PathContour() and must be called before adding points |
508 | * (to_point()), adding control points (add_control_point()), |
509 | * adding arcs (to_arc()), creating any \ref interpolator_base |
510 | * objects using this \ref PathContour or closing the contour. |
511 | */ |
512 | void |
513 | start(const vec2 &pt); |
514 | |
515 | /*! |
516 | * Close the current edge. |
517 | * \param pt point location of end of edge (and thus start of new edge) |
518 | * \param etp the edge type of the new edge made; if this is the first |
519 | * edge of the contour, the value of etp is ignored and the |
520 | * value \ref PathEnums::starts_new_edge is used. |
521 | */ |
522 | void |
523 | to_point(const vec2 &pt, enum PathEnums::edge_type_t etp); |
524 | |
525 | /*! |
526 | * Add a control point. Will fail if close() was called |
527 | * \param pt location of new control point |
528 | */ |
529 | void |
530 | add_control_point(const vec2 &pt); |
531 | |
532 | /*! |
533 | * Clear any current control points. |
534 | */ |
535 | void |
536 | clear_control_points(void); |
537 | |
538 | /*! |
539 | * Will fail if close() was called of if add_control_point() has been |
540 | * called more recently than to_point(). |
541 | * \param angle angle of arc in radians |
542 | * \param pt point where arc ends (and next edge starts) |
543 | * \param etp the edge type of the new edge made; if this is the first |
544 | * edge of the contour, the value of etp is ignored and the |
545 | * value \ref PathEnums::starts_new_edge is used. |
546 | */ |
547 | void |
548 | to_arc(float angle, const vec2 &pt, enum PathEnums::edge_type_t etp); |
549 | |
550 | /*! |
551 | * End the PathContour without adding a closing edge. |
552 | */ |
553 | void |
554 | end(void); |
555 | |
556 | /*! |
557 | * Closes the \ref PathContour using the last \ref interpolator_base |
558 | * derived object on the \ref PathContour. That interpolator must |
559 | * interpolate to the start point of the \ref PathContour |
560 | */ |
561 | void |
562 | close_generic(void); |
563 | |
564 | /*! |
565 | * Closes with the Bezier curve defined by the current |
566 | * control points added by add_control_point(). |
567 | * \param etp the edge type of the new edge made. |
568 | */ |
569 | void |
570 | close(enum PathEnums::edge_type_t etp); |
571 | |
572 | /*! |
573 | * Closes with an arc. |
574 | * \param angle angle of arc in radians |
575 | * \param etp the edge type of the new edge made. |
576 | */ |
577 | void |
578 | close_arc(float angle, enum PathEnums::edge_type_t etp); |
579 | |
580 | /*! |
581 | * Returns the last interpolator added to this \ref PathContour. |
582 | * If no contours have been added, returns a null reference. |
583 | */ |
584 | const reference_counted_ptr<const interpolator_base>& |
585 | prev_interpolator(void); |
586 | |
587 | /*! |
588 | * Returns true if the PathContour is closed. |
589 | */ |
590 | bool |
591 | closed(void) const; |
592 | |
593 | /*! |
594 | * Returns true if the PathContour is ended, and thus |
595 | * no additional interpolator may be added. |
596 | */ |
597 | bool |
598 | ended(void) const; |
599 | |
600 | /*! |
601 | * Return the I'th point of this PathContour. |
602 | * For I = 0, returns the value passed to start(). |
603 | * \param I index of point. |
604 | */ |
605 | const vec2& |
606 | point(unsigned int I) const; |
607 | |
608 | /*! |
609 | * Returns the number of points of this PathContour. |
610 | */ |
611 | unsigned int |
612 | number_points(void) const; |
613 | |
614 | /*! |
615 | * Returns the number of interpolators of this |
616 | * PathContour. This is equal to number_points() |
617 | * if closed() is true; otherwise it is equal to |
618 | * number_points() - 1. |
619 | */ |
620 | unsigned int |
621 | number_interpolators(void) const; |
622 | |
623 | /*! |
624 | * Returns the interpolator of this PathContour |
625 | * that interpolates from the I'th point to the |
626 | * (I + 1)'th point. When the closed() is true, |
627 | * if I is number_points() - 1, then returns the |
628 | * interpolator from the last point to the first |
629 | * point. When closed() is false, if I has value |
630 | * number_points() - 1, then returns a null reference. |
631 | */ |
632 | const reference_counted_ptr<const interpolator_base>& |
633 | interpolator(unsigned int I) const; |
634 | |
635 | /*! |
636 | * Returns an approximation of the bounding box for |
637 | * this PathContour WITHOUT relying on tessellating |
638 | * the \ref interpolator_base objects of this \ref |
639 | * PathContour. Returns false if the box is empty. |
640 | * \param out_bb (output) location to which to write |
641 | * the bounding box value |
642 | */ |
643 | bool |
644 | approximate_bounding_box(Rect *out_bb) const; |
645 | |
646 | /*! |
647 | * Returns true if each interpolator of the PathContour is |
648 | * flat. |
649 | */ |
650 | bool |
651 | is_flat(void) const; |
652 | |
653 | /*! |
654 | * Create a deep copy of this PathContour. |
655 | */ |
656 | reference_counted_ptr<PathContour> |
657 | deep_copy(void) const; |
658 | |
659 | private: |
660 | void *m_d; |
661 | }; |
662 | |
663 | /*! |
664 | * \brief |
665 | * A Path represents a collection of PathContour |
666 | * objects. |
667 | */ |
668 | class Path:noncopyable |
669 | { |
670 | public: |
671 | /*! |
672 | * \brief |
673 | * Class that wraps a vec2 to mark a point |
674 | * as a control point for a Bezier curve |
675 | */ |
676 | class control_point |
677 | { |
678 | public: |
679 | /*! |
680 | * Ctor |
681 | * \param pt value to which to set \ref m_location |
682 | */ |
683 | explicit |
684 | control_point(const vec2 &pt): |
685 | m_location(pt) |
686 | {} |
687 | |
688 | /*! |
689 | * Ctor |
690 | * \param x value to which to set m_location.x() |
691 | * \param y value to which to set m_location.y() |
692 | */ |
693 | control_point(float x, float y): |
694 | m_location(x,y) |
695 | {} |
696 | |
697 | /*! |
698 | * Position of control point |
699 | */ |
700 | vec2 m_location; |
701 | }; |
702 | |
703 | /*! |
704 | * \brief |
705 | * Wraps the data to specify an arc |
706 | */ |
707 | class arc |
708 | { |
709 | public: |
710 | /*! |
711 | * Ctor |
712 | * \param angle angle of arc in radians |
713 | * \param pt point to which to arc |
714 | */ |
715 | arc(float angle, const vec2 &pt): |
716 | m_angle(angle), m_pt(pt) |
717 | {} |
718 | |
719 | /*! |
720 | * Angle of arc in radians |
721 | */ |
722 | float m_angle; |
723 | |
724 | /*! |
725 | * End point of arc |
726 | */ |
727 | vec2 m_pt; |
728 | }; |
729 | |
730 | /*! |
731 | * \brief |
732 | * Tag class to mark the close of a contour |
733 | */ |
734 | class contour_close |
735 | {}; |
736 | |
737 | /*! |
738 | * \brief |
739 | * Tag class to mark the end of a contour without |
740 | * adding a closing edge of the contour and start |
741 | * a new contour |
742 | */ |
743 | class contour_end |
744 | {}; |
745 | |
746 | /*! |
747 | * \brief |
748 | * Indicates to end the existing contour with adding |
749 | * a closing edge of the contour and start a new contour |
750 | */ |
751 | class contour_start |
752 | { |
753 | public: |
754 | /*! |
755 | * Ctor to indicate to start a new contour |
756 | * without closing the previous contour. |
757 | */ |
758 | explicit |
759 | contour_start(const vec2 &pt): |
760 | m_pt(pt) |
761 | {} |
762 | |
763 | /*! |
764 | * Ctor to indicate to start a new contour |
765 | * without closing the previous contour. |
766 | */ |
767 | explicit |
768 | contour_start(float x, float y): |
769 | m_pt(x, y) |
770 | {} |
771 | |
772 | /*! |
773 | * Location of start of new contour. |
774 | */ |
775 | vec2 m_pt; |
776 | }; |
777 | |
778 | /*! |
779 | * \brief |
780 | * Tag class to mark the close of an contour with an arc |
781 | */ |
782 | class contour_close_arc |
783 | { |
784 | public: |
785 | /*! |
786 | * Ctor |
787 | * \param angle angle of arc in radians |
788 | */ |
789 | explicit |
790 | contour_close_arc(float angle): |
791 | m_angle(angle) |
792 | {} |
793 | |
794 | /*! |
795 | * Angle of arc in radians |
796 | */ |
797 | float m_angle; |
798 | }; |
799 | |
800 | /*! |
801 | * Ctor. |
802 | */ |
803 | explicit |
804 | Path(void); |
805 | |
806 | ~Path(); |
807 | |
808 | /*! |
809 | * Clear the path, i.e. remove all PathContour's from the |
810 | * path |
811 | */ |
812 | void |
813 | clear(void); |
814 | |
815 | /*! |
816 | * Swap contents of Path with another Path |
817 | * \param obj Path with which to swap |
818 | */ |
819 | void |
820 | swap(Path &obj); |
821 | |
822 | /*! |
823 | * Create an arc but specify the angle in degrees. |
824 | * \param angle angle of arc in degrees |
825 | * \param pt point to which to arc |
826 | */ |
827 | static |
828 | arc |
829 | arc_degrees(float angle, const vec2 &pt) |
830 | { |
831 | return arc(angle*float(FASTUIDRAW_PI)/180.0f, pt); |
832 | } |
833 | |
834 | /*! |
835 | * Create an contour_close_arc but specify the angle in degrees. |
836 | * \param angle angle or arc in degrees |
837 | */ |
838 | static |
839 | contour_close_arc |
840 | contour_close_arc_degrees(float angle) |
841 | { |
842 | return contour_close_arc(angle*float(FASTUIDRAW_PI)/180.0f); |
843 | } |
844 | |
845 | /*! |
846 | * Operator overload to add a point of the current |
847 | * contour in the Path. |
848 | * \param pt point to add |
849 | */ |
850 | Path& |
851 | operator<<(const vec2 &pt); |
852 | |
853 | /*! |
854 | * Operator overload to add a control point of the current |
855 | * contour in the Path. |
856 | * \param pt control point to add |
857 | */ |
858 | Path& |
859 | operator<<(const control_point &pt); |
860 | |
861 | /*! |
862 | * Operator overload to add an arc to the current contour |
863 | * in the Path. |
864 | * \param a arc to add |
865 | */ |
866 | Path& |
867 | operator<<(const arc &a); |
868 | |
869 | /*! |
870 | * Operator overload to close the current contour |
871 | */ |
872 | Path& |
873 | operator<<(contour_close); |
874 | |
875 | /*! |
876 | * Operator overload to end the current contour |
877 | */ |
878 | Path& |
879 | operator<<(contour_end); |
880 | |
881 | /*! |
882 | * Operator overload to close the current contour |
883 | * \param a specifies the angle of the arc for closing |
884 | * the current contour |
885 | */ |
886 | Path& |
887 | operator<<(contour_close_arc a); |
888 | |
889 | /*! |
890 | * Operator overload to start a new contour without closing |
891 | * the current contour. |
892 | * \param st specifies the starting point of the new contour |
893 | */ |
894 | Path& |
895 | operator<<(const contour_start &st) |
896 | { |
897 | move(st.m_pt); |
898 | return *this; |
899 | } |
900 | |
901 | /*! |
902 | * Operator overload to control PathEnums::edge_type_t |
903 | * of the next edge made via operator overloads. |
904 | * If no edge is yet present on the current contour, then |
905 | * the value is ignored. The tag is reset back to \ref |
906 | * PathEnums::starts_new_edge after an edge is added. |
907 | * \param etp edge type |
908 | */ |
909 | Path& |
910 | operator<<(enum PathEnums::edge_type_t etp); |
911 | |
912 | /*! |
913 | * Append a line to the current contour. |
914 | * \param pt point to which the line goes |
915 | * \param etp the edge type of the new line made; if this is the first |
916 | * edge of the current contour, the value of etp is ignored |
917 | * and the value \ref PathEnums::starts_new_edge is used. |
918 | */ |
919 | Path& |
920 | line_to(const vec2 &pt, |
921 | enum PathEnums::edge_type_t etp = PathEnums::starts_new_edge); |
922 | |
923 | /*! |
924 | * Append a quadratic Bezier curve to the current contour. |
925 | * \param ct control point of the quadratic Bezier curve |
926 | * \param pt point to which the quadratic Bezier curve goes |
927 | * \param etp the edge type of the new quadratic made; if this is the first |
928 | * edge of the current contour, the value of etp is ignored |
929 | * and the value \ref PathEnums::starts_new_edge is used. |
930 | */ |
931 | Path& |
932 | quadratic_to(const vec2 &ct, const vec2 &pt, |
933 | enum PathEnums::edge_type_t etp = PathEnums::starts_new_edge); |
934 | |
935 | /*! |
936 | * Append a cubic Bezier curve to the current contour. |
937 | * \param ct1 first control point of the cubic Bezier curve |
938 | * \param ct2 second control point of the cubic Bezier curve |
939 | * \param pt point to which the cubic Bezier curve goes |
940 | * \param etp the edge type of the new cubic made; if this is the first |
941 | * edge of the current contour, the value of etp is ignored |
942 | * and the value \ref PathEnums::starts_new_edge is used. |
943 | */ |
944 | Path& |
945 | cubic_to(const vec2 &ct1, const vec2 &ct2, const vec2 &pt, |
946 | enum PathEnums::edge_type_t etp = PathEnums::starts_new_edge); |
947 | |
948 | /*! |
949 | * Append an arc curve to the current contour. |
950 | * \param angle gives the angle of the arc in radians. For a coordinate system |
951 | * where y increases upwards and x increases to the right, a positive |
952 | * value indicates counter-clockwise and a negative value indicates |
953 | * clockwise |
954 | * \param pt point to which the arc curve goes |
955 | * \param etp the edge type of the new arc made; if this is the first |
956 | * edge of the current contour, the value of etp is ignored |
957 | * and the value \ref PathEnums::starts_new_edge is used. |
958 | */ |
959 | Path& |
960 | arc_to(float angle, const vec2 &pt, |
961 | enum PathEnums::edge_type_t etp = PathEnums::starts_new_edge); |
962 | |
963 | /*! |
964 | * Begin a new contour. |
965 | * \param pt point at which the contour begins |
966 | */ |
967 | Path& |
968 | move(const vec2 &pt); |
969 | |
970 | /*! |
971 | * End the current contour without adding a closing edge. |
972 | */ |
973 | Path& |
974 | end_contour(void); |
975 | |
976 | /*! |
977 | * Close the current contour with a line segment. |
978 | * \param etp the edge type of the closing edge made. |
979 | */ |
980 | Path& |
981 | close_contour(enum PathEnums::edge_type_t etp = PathEnums::starts_new_edge); |
982 | |
983 | /*! |
984 | * Close the current contour in an arc |
985 | * \param angle gives the angle of the arc in radians. For a coordinate system |
986 | * where y increases upwards and x increases to the right, a positive |
987 | * value indicates counter-clockwise and a negative value indicates |
988 | * clockwise |
989 | * \param etp the edge type of the closing edge made. |
990 | */ |
991 | Path& |
992 | close_contour_arc(float angle, |
993 | enum PathEnums::edge_type_t etp = PathEnums::starts_new_edge); |
994 | |
995 | /*! |
996 | * Close the current contour in a quadratic Bezier curve |
997 | * \param ct control point of the quadratic Bezier curve |
998 | * \param etp the edge type of the closing edge made. |
999 | */ |
1000 | Path& |
1001 | close_contour_quadratic(const vec2 &ct, |
1002 | enum PathEnums::edge_type_t etp = PathEnums::starts_new_edge); |
1003 | |
1004 | /*! |
1005 | * Close the current contour in a cubic Bezier curve |
1006 | * \param ct1 first control point of the cubic Bezier curve |
1007 | * \param ct2 second control point of the cubic Bezier curve |
1008 | * \param etp the edge type of the closing edge made. |
1009 | */ |
1010 | Path& |
1011 | close_contour_cubic(const vec2 &ct1, const vec2 &ct2, |
1012 | enum PathEnums::edge_type_t etp = PathEnums::starts_new_edge); |
1013 | |
1014 | /*! |
1015 | * The current contour of this \ref Path. Use thie value when creating |
1016 | * \ref PathContour::interpolator_base objects. |
1017 | */ |
1018 | PathContour& |
1019 | current_contour(void); |
1020 | |
1021 | /*! |
1022 | * Adds a PathContour to this Path. The current contour remains |
1023 | * as the current contour though. |
1024 | * \param contour PathContour to add to the Path |
1025 | */ |
1026 | Path& |
1027 | add_contour(const reference_counted_ptr<const PathContour> &contour); |
1028 | |
1029 | /*! |
1030 | * Add all the \ref PathContour objects of a Path into this Path. |
1031 | * \param path Path to add |
1032 | */ |
1033 | Path& |
1034 | add_contours(const Path &path); |
1035 | |
1036 | /*! |
1037 | * Returns the number of contours of the Path. |
1038 | */ |
1039 | unsigned int |
1040 | number_contours(void) const; |
1041 | |
1042 | /*! |
1043 | * Returns the named contour |
1044 | * \param i index of contour to fetch (0 <= i < number_contours()) |
1045 | */ |
1046 | reference_counted_ptr<const PathContour> |
1047 | contour(unsigned int i) const; |
1048 | |
1049 | /*! |
1050 | * Returns true if each PathContour of the Path is flat. |
1051 | */ |
1052 | bool |
1053 | is_flat(void) const; |
1054 | |
1055 | /*! |
1056 | * Returns an approximation of the bounding box for |
1057 | * this Path. Returns false if the Path is empty. |
1058 | * \param out_bb (output) location to which to write |
1059 | * the bounding box value |
1060 | */ |
1061 | bool |
1062 | approximate_bounding_box(Rect *out_bb) const; |
1063 | |
1064 | /*! |
1065 | * Return the tessellation of this Path at a specific |
1066 | * level of detail. The TessellatedPath is constructed |
1067 | * lazily. Additionally, if this Path changes its geometry, |
1068 | * then a new TessellatedPath will be contructed on the |
1069 | * next call to tessellation(). |
1070 | * \param thresh the returned tessellated path will be so that |
1071 | * TessellatedPath::max_distance() is no more than |
1072 | * thresh. A non-positive value will return the |
1073 | * lowest level of detail tessellation. |
1074 | */ |
1075 | const TessellatedPath& |
1076 | tessellation(float thresh) const; |
1077 | |
1078 | /*! |
1079 | * Provided as a conveniance, returns the starting point tessellation. |
1080 | * Equivalent to |
1081 | * \code |
1082 | * tessellation(-1.0f) |
1083 | * \endcode |
1084 | */ |
1085 | const TessellatedPath& |
1086 | tessellation(void) const; |
1087 | |
1088 | /*! |
1089 | * Returns the \ref ShaderFilledPath coming from this |
1090 | * Path. The returned reference will be null if the |
1091 | * Path contains anything besides line segments, |
1092 | * quadratic Bezier curves or cubic Bezier curves. |
1093 | */ |
1094 | const ShaderFilledPath& |
1095 | shader_filled_path(void) const; |
1096 | |
1097 | private: |
1098 | void *m_d; |
1099 | }; |
1100 | |
1101 | /*! @} */ |
1102 | |
1103 | } |
1104 | |
1105 | #endif |
1106 | |