1 | /*! |
2 | * \file tessellated_path.hpp |
3 | * \brief file tessellated_path.hpp |
4 | * |
5 | * Copyright 2018 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 | #ifndef FASTUIDRAW_TESSELLATED_PATH_HPP |
21 | #define FASTUIDRAW_TESSELLATED_PATH_HPP |
22 | |
23 | |
24 | #include <fastuidraw/util/fastuidraw_memory.hpp> |
25 | #include <fastuidraw/util/rect.hpp> |
26 | #include <fastuidraw/util/vecN.hpp> |
27 | #include <fastuidraw/util/c_array.hpp> |
28 | #include <fastuidraw/util/reference_counted.hpp> |
29 | #include <fastuidraw/path_enums.hpp> |
30 | |
31 | namespace fastuidraw { |
32 | |
33 | ///@cond |
34 | class Path; |
35 | class StrokedPath; |
36 | class FilledPath; |
37 | class PartitionedTessellatedPath; |
38 | ///@endcond |
39 | |
40 | /*!\addtogroup Paths |
41 | * @{ |
42 | */ |
43 | |
44 | /*! |
45 | * \brief |
46 | * An TessellatedPath represents the tessellation of a Path |
47 | * into line segments and arcs. |
48 | * |
49 | * A single contour of a TessellatedPath is constructed from |
50 | * a single \ref PathContour of the source \ref Path. Each |
51 | * edge of a contour of a TessellatedPath is contructed from |
52 | * a single \ref PathContour::interpolator_base of the source \ref |
53 | * PathContour. The ordering of the contours of a |
54 | * TessellatedPath is the same ordering as the source |
55 | * \ref PathContour objects of the source \ref Path. Also, |
56 | * the ordering of edges within a contour is the same ordering |
57 | * as the \ref PathContour::interpolator_base objects of |
58 | * the source \ref PathContour. In particular, for each contour |
59 | * of a TessellatedPath, if an edge is closed, the closing edge |
60 | * is the last edge. |
61 | */ |
62 | class TessellatedPath: |
63 | public reference_counted<TessellatedPath>::non_concurrent |
64 | { |
65 | public: |
66 | /*! |
67 | * \brief |
68 | * Enumeration to identify the type of a \ref segment |
69 | */ |
70 | enum segment_type_t |
71 | { |
72 | /*! |
73 | * Indicates that the segment is an arc segment, |
74 | * i.e. it connects two point via an arc of a |
75 | * circle |
76 | */ |
77 | arc_segment, |
78 | |
79 | /*! |
80 | * Indicates that the segment is a line segment |
81 | * i.e. it connects two point via a line. |
82 | */ |
83 | line_segment, |
84 | }; |
85 | |
86 | /*! |
87 | * Enumeration to describe if a segment is split |
88 | */ |
89 | enum split_t |
90 | { |
91 | /*! |
92 | * Indicates that entire segment is before |
93 | * the split value |
94 | */ |
95 | segment_completey_before_split, |
96 | |
97 | /*! |
98 | * Indicates that entire segment is after |
99 | * the split value |
100 | */ |
101 | segment_completey_after_split, |
102 | |
103 | /*! |
104 | * indicates that the \ref segment was split |
105 | * with the segment starting before the split |
106 | * point. |
107 | */ |
108 | segment_split_start_before, |
109 | |
110 | /*! |
111 | * indicates that the \ref segment was split |
112 | * with the segment starting after the split |
113 | * point. |
114 | */ |
115 | segment_split_start_after, |
116 | }; |
117 | |
118 | /*! |
119 | * \brief |
120 | * A TessellationParams stores how finely to tessellate |
121 | * the curves of a path. |
122 | */ |
123 | class TessellationParams |
124 | { |
125 | public: |
126 | /*! |
127 | * Ctor, initializes values. |
128 | */ |
129 | TessellationParams(void): |
130 | m_max_distance(-1.0f), |
131 | m_max_recursion(5) |
132 | {} |
133 | |
134 | /*! |
135 | * Provided as a conveniance. Equivalent to |
136 | * \code |
137 | * m_max_distance = tp; |
138 | * \endcode |
139 | * \param p value to which to assign to \ref m_max_distance |
140 | */ |
141 | TessellationParams& |
142 | max_distance(float p) |
143 | { |
144 | m_max_distance = p; |
145 | return *this; |
146 | } |
147 | |
148 | /*! |
149 | * Set the value of \ref m_max_recursion. |
150 | * \param v value to which to assign to \ref m_max_recursion |
151 | */ |
152 | TessellationParams& |
153 | max_recursion(unsigned int v) |
154 | { |
155 | m_max_recursion = v; |
156 | return *this; |
157 | } |
158 | |
159 | /*! |
160 | * Maximum distance to attempt between the actual curve and the |
161 | * tessellation. A value less than or equal to zero indicates to |
162 | * accept any distance value between the tessellation and the |
163 | * curve. Default value is -1.0 (i.e. accept any distance value). |
164 | */ |
165 | float m_max_distance; |
166 | |
167 | /*! |
168 | * Maximum number of times to perform recursion to tessellate an edge. |
169 | * Default value is 5. |
170 | */ |
171 | unsigned int m_max_recursion; |
172 | }; |
173 | |
174 | /*! |
175 | * \brief |
176 | * Represents segment of a tessellated or arc-tessellated path. |
177 | */ |
178 | class segment |
179 | { |
180 | public: |
181 | /*! |
182 | * Specifies the segment type. |
183 | */ |
184 | enum segment_type_t m_type; |
185 | |
186 | /*! |
187 | * Gives the start point on the path of the segment. |
188 | */ |
189 | vec2 m_start_pt; |
190 | |
191 | /*! |
192 | * Gives the end point on the path of the segment. |
193 | */ |
194 | vec2 m_end_pt; |
195 | |
196 | /*! |
197 | * Only valid if \ref m_type is \ref arc_segment; gives |
198 | * the center of the arc. |
199 | */ |
200 | vec2 m_center; |
201 | |
202 | /*! |
203 | * Only valid if \ref m_type is \ref arc_segment; gives |
204 | * the angle range of the arc. |
205 | */ |
206 | range_type<float> m_arc_angle; |
207 | |
208 | /*! |
209 | * Only valid if \ref m_type is \ref arc_segment; gives |
210 | * the radius of the arc. |
211 | */ |
212 | float m_radius; |
213 | |
214 | /*! |
215 | * Gives the length of the segment. |
216 | */ |
217 | float m_length; |
218 | |
219 | /*! |
220 | * Gives the distance of the start of the segment from |
221 | * the start of the edge (i.e PathContour::interpolator_base). |
222 | */ |
223 | float m_distance_from_edge_start; |
224 | |
225 | /*! |
226 | * Gives the distance of the start of segment to the |
227 | * start of the -contour-. |
228 | */ |
229 | float m_distance_from_contour_start; |
230 | |
231 | /*! |
232 | * Gives the length of the edge (i.e. |
233 | * PathContour::interpolator_base) on which the |
234 | * segment lies. This value is the same for all |
235 | * segments along a fixed edge. |
236 | */ |
237 | float m_edge_length; |
238 | |
239 | /*! |
240 | * Gives the length of the contour on which this |
241 | * segment lies. This value is the same for all |
242 | * segments along a fixed contour. |
243 | */ |
244 | float m_contour_length; |
245 | |
246 | /*! |
247 | * Gives the unit-vector of the path entering the segment. |
248 | */ |
249 | vec2 m_enter_segment_unit_vector; |
250 | |
251 | /*! |
252 | * Gives the unit-vector of the path leaving the segment. |
253 | */ |
254 | vec2 m_leaving_segment_unit_vector; |
255 | |
256 | /*! |
257 | * If true, indicates that the arc is a continuation of |
258 | * its predecessor. This happens when TessellatedPath |
259 | * breaks a \ref segment into smaller pieces to make its |
260 | * angle smaller, to make it monotonic or if it is the |
261 | * second portion of a split segment as calculated from |
262 | * \ref compute_split_x() or \ref compute_split_y(). |
263 | */ |
264 | bool m_continuation_with_predecessor; |
265 | |
266 | /*! |
267 | * The contour from which the \ref segment originates, |
268 | * i.e. the \ref segment originates from the \ref |
269 | * PathContour::interpolator_base \ref |
270 | * PathContour::interpolator(\ref m_edge_id) of the |
271 | * \ref PathContour of \ref Path::contour(\ref m_contour_id). |
272 | */ |
273 | unsigned int m_contour_id; |
274 | |
275 | /*! |
276 | * The edge from which the \ref segment originates, |
277 | * i.e. the \ref segment originates from the \ref |
278 | * PathContour::interpolator_base \ref |
279 | * PathContour::interpolator(\ref m_edge_id) of the |
280 | * \ref PathContour of \ref Path::contour(\ref m_contour_id). |
281 | */ |
282 | unsigned int m_edge_id; |
283 | |
284 | /*! |
285 | * Indicates the this segment is the first segment of |
286 | * an edge |
287 | */ |
288 | bool m_first_segment_of_edge; |
289 | |
290 | /*! |
291 | * Indicates the this segment is the last segment of |
292 | * an edge |
293 | */ |
294 | bool m_last_segment_of_edge; |
295 | |
296 | /*! |
297 | * Returns the normal vector to the path at the start of the segment. |
298 | */ |
299 | vec2 |
300 | enter_segment_normal(void) const |
301 | { |
302 | return vec2(-m_enter_segment_unit_vector.y(), |
303 | +m_enter_segment_unit_vector.x()); |
304 | } |
305 | |
306 | /*! |
307 | * Returns the normal vector to the path at the end of the segment. |
308 | */ |
309 | vec2 |
310 | leaving_segment_normal(void) const |
311 | { |
312 | return vec2(-m_leaving_segment_unit_vector.y(), |
313 | +m_leaving_segment_unit_vector.x()); |
314 | } |
315 | |
316 | /*! |
317 | * Split this \ref segment at a time t where the start |
318 | * of the segment is at t = 0 and the end of the segment |
319 | * is t = 1. |
320 | * \param t time to split the segment, must have that 0 <= t <= 1 |
321 | * \param dst_0_t location to which to write the portion of |
322 | * this \ref segment on the interval [0, t]. |
323 | * \param dst_t_1 location to which to write the portion of |
324 | * this \ref segment on the interval [t, 1]. |
325 | */ |
326 | void |
327 | split_segment(float t, |
328 | segment *dst_0_t, |
329 | segment *dst_t_1) const; |
330 | |
331 | /*! |
332 | * Compute the splitting splitting of this \ref segment |
333 | * against a vertical line with the given x-coordinate |
334 | * \param x_split x-coordinate of vertical splitting line |
335 | * \param dst_before_split location to which to write |
336 | * the portion of the segment that |
337 | * comes before the splitting line |
338 | * \param dst_after_split location to which to write |
339 | * the portion of the segment that |
340 | * comes after the splitting line |
341 | * \returns how the segment was split. Note that if the return |
342 | * value is \ref segment_completey_before_split or |
343 | * \ref segment_completey_after_split then neither |
344 | * of dst_before_split and dst_after_split are |
345 | * written to. |
346 | */ |
347 | enum split_t |
348 | compute_split_x(float x_split, |
349 | segment *dst_before_split, |
350 | segment *dst_after_split) const; |
351 | |
352 | /*! |
353 | * Compute the splitting splitting of this \ref segment |
354 | * against a horizontal line with the given y-coordinate |
355 | * \param y_split y-coordinate of horizontal splitting line |
356 | * \param dst_before_split location to which to write |
357 | * the portion of the segment that |
358 | * comes before the splitting line |
359 | * \param dst_after_split location to which to write |
360 | * the portion of the segment that |
361 | * comes after the splitting line |
362 | * \returns how the segment was split. Note that if the return |
363 | * value is \ref segment_completey_before_split or |
364 | * \ref segment_completey_after_split then neither |
365 | * of dst_before_split and dst_after_split are |
366 | * written to. |
367 | */ |
368 | enum split_t |
369 | compute_split_y(float y_split, |
370 | segment *dst_before_split, |
371 | segment *dst_after_split) const; |
372 | |
373 | /*! |
374 | * Compute the splitting splitting of this \ref segment |
375 | * against a horizontal or vertical line with the given |
376 | * coordinate. Provided as a conveniance, equivalent to |
377 | * \code |
378 | * if (splitting_coordinate == 0) |
379 | * { |
380 | * compute_split_x(split, dst_before_split, dst_after_split); |
381 | * } |
382 | * else |
383 | * { |
384 | * compute_split_y(split, dst_before_split, dst_after_split); |
385 | * } |
386 | * \endcode |
387 | * \param split x-coordinate or y-coordinate of splitting line |
388 | * \param dst_before_split location to which to write |
389 | * the portion of the segment that |
390 | * comes before the splitting line |
391 | * \param dst_after_split location to which to write |
392 | * the portion of the segment that |
393 | * comes after the splitting line |
394 | * \param splitting_coordinate determines if to split by a vertical |
395 | * line or a horizontal line. |
396 | * \returns how the segment was split. Note that if the return |
397 | * value is \ref segment_completey_before_split or |
398 | * \ref segment_completey_after_split then neither |
399 | * of dst_before_split and dst_after_split are |
400 | * written to. |
401 | */ |
402 | enum split_t |
403 | compute_split(float split, |
404 | segment *dst_before_split, |
405 | segment *dst_after_split, |
406 | int splitting_coordinate) const; |
407 | }; |
408 | |
409 | /*! |
410 | * A \ref segment_chain is a sequence of \ref |
411 | * segment values where successive elements are |
412 | * neighbors of the same edge in the source \ref |
413 | * Path. It is possible to split edges and keep |
414 | * neighbor information via the field \ref |
415 | * m_prev_to_start |
416 | */ |
417 | class segment_chain |
418 | { |
419 | public: |
420 | /*! |
421 | * The chain of \ref segment values |
422 | */ |
423 | c_array<const segment> m_segments; |
424 | |
425 | /*! |
426 | * if non-null, gives the segment just |
427 | * before the first element of \ref |
428 | * m_segments. If null, then there is |
429 | * no segment just before \ref m_segments. |
430 | */ |
431 | const segment *m_prev_to_start; |
432 | }; |
433 | |
434 | /*! |
435 | * \brief |
436 | * Represents the geometric data for a join |
437 | */ |
438 | class join |
439 | { |
440 | public: |
441 | /*! |
442 | * Default ctor that does NOT initialize any of the fields |
443 | * of \ref join |
444 | */ |
445 | join(void) |
446 | {} |
447 | |
448 | /*! |
449 | * Ctor that initializes the values of a join to be the |
450 | * values of where two \ref segment values meet. |
451 | * \param into_join the \ref segment value into the join, |
452 | * it is required that into_join.m_end_pt |
453 | * has the same value as from_join.m_start_pt |
454 | * \param from_join the \ref segment value leaving from the join, |
455 | * it is required that into_join.m_end_pt |
456 | * has the same value as from_join.m_start_pt |
457 | */ |
458 | join(const segment &into_join, |
459 | const segment &from_join); |
460 | |
461 | /*! |
462 | * Gives the position of the join |
463 | */ |
464 | vec2 m_position; |
465 | |
466 | /*! |
467 | * Gives the unit-vector of the path entering the join. |
468 | */ |
469 | vec2 m_enter_join_unit_vector; |
470 | |
471 | /*! |
472 | * Gives the unit-vector of the path leaving the join. |
473 | */ |
474 | vec2 m_leaving_join_unit_vector; |
475 | |
476 | /*! |
477 | * Gives the distance of the join from the previous join. |
478 | */ |
479 | float m_distance_from_previous_join; |
480 | |
481 | /*! |
482 | * Gives the distance of the join from the start |
483 | * of the -contour- on which the point resides. |
484 | */ |
485 | float m_distance_from_contour_start; |
486 | |
487 | /*! |
488 | * Length of the contour on which the join resides. |
489 | */ |
490 | float m_contour_length; |
491 | |
492 | /*! |
493 | * Gives the contour from which the join originates, |
494 | * following the same convention as \ref |
495 | * segment::m_contour_id. |
496 | */ |
497 | unsigned int m_contour_id; |
498 | |
499 | /*! |
500 | * Gives the interpolator that goes into the join, |
501 | * following the same convention as \ref |
502 | * segment::m_edge_id. |
503 | */ |
504 | unsigned int m_edge_into_join_id; |
505 | |
506 | /*! |
507 | * Gives the interpolator that leaves the join, |
508 | * following the same convention as \ref |
509 | * segment::m_edge_id. |
510 | */ |
511 | unsigned int m_edge_leaving_join_id; |
512 | |
513 | /*! |
514 | * When stroking a join, one needs to know what side of the |
515 | * edge gets the join. For example a bevel join is formed by |
516 | * the triangle formed from the three points: the outer edge |
517 | * at the join of the segment going into the join, the outer |
518 | * edge of the segment leaving the join and the point where |
519 | * the segments meet. The value of lambda() gives the sign to |
520 | * apply to \ref enter_join_normal() and \ref leaving_join_normal() |
521 | * to get the unit vector from where the segments meet to the |
522 | * outer edge. |
523 | */ |
524 | float m_lambda; |
525 | |
526 | /*! |
527 | * If this join is realized as a miter-join, returns the distance |
528 | * from the point of the join (i.e. where the segments intersect) |
529 | * to the tip of the miter join. If the path enter and leaving |
530 | * the join are parallel or anti-parallel, then return -1.0. |
531 | */ |
532 | float m_miter_distance; |
533 | |
534 | /*! |
535 | * This gives the angle (in degrees) between the start and |
536 | * end points of the join. |
537 | */ |
538 | float m_join_angle; |
539 | |
540 | /*! |
541 | * Gives the normal vector to going into the join |
542 | */ |
543 | vec2 |
544 | enter_join_normal(void) const |
545 | { |
546 | return vec2(-m_enter_join_unit_vector.y(), m_enter_join_unit_vector.x()); |
547 | } |
548 | |
549 | /*! |
550 | * Gives the normal vector to leaving from the join |
551 | */ |
552 | vec2 |
553 | leaving_join_normal(void) const |
554 | { |
555 | return vec2(-m_leaving_join_unit_vector.y(), m_leaving_join_unit_vector.x()); |
556 | } |
557 | }; |
558 | |
559 | /*! |
560 | * \brief |
561 | * Represents the geometric data for a cap |
562 | */ |
563 | class cap |
564 | { |
565 | public: |
566 | /*! |
567 | * Default ctor that does NOT initialize any of the fields |
568 | * of \ref cap |
569 | */ |
570 | cap(void) |
571 | {} |
572 | |
573 | /*! |
574 | * Ctor that initializes the values of a cap to be values |
575 | * of where a segment starts or ends. |
576 | * \param seg the \ref segment value |
577 | * \param is_start_cap if true indicates to give the cap |
578 | * the value as a cap at the start of |
579 | * the \ref segment, if false, then at |
580 | * the end of the \ref segment. |
581 | */ |
582 | cap(const segment &seg, bool is_start_cap); |
583 | |
584 | /*! |
585 | * Gives the position of the cap |
586 | */ |
587 | vec2 m_position; |
588 | |
589 | /*! |
590 | * Gives the unit-vector into the cap |
591 | */ |
592 | vec2 m_unit_vector; |
593 | |
594 | /*! |
595 | * Length of the contour on which the cap resides. |
596 | */ |
597 | float m_contour_length; |
598 | |
599 | /*! |
600 | * Length of the edge on which the cap resides. |
601 | */ |
602 | float m_edge_length; |
603 | |
604 | /*! |
605 | * Gives the distance of the cap from the start of the edge |
606 | * on which the cap resides. |
607 | */ |
608 | float m_distance_from_edge_start; |
609 | |
610 | /*! |
611 | * Gives the distance of the cap start of the -contour-. |
612 | * For \ref cap values of a \ref TessellatedPath, this is |
613 | * 0 for a starting cap and \ref m_contour_length for |
614 | * an ending cap. |
615 | */ |
616 | float m_distance_from_contour_start; |
617 | |
618 | /*! |
619 | * True if the cap is from the start of a contour |
620 | */ |
621 | bool m_is_starting_cap; |
622 | |
623 | /*! |
624 | * Gives the contour from which the join originates, |
625 | * following the same convention as \ref |
626 | * segment::m_contour_id. |
627 | */ |
628 | unsigned int m_contour_id; |
629 | }; |
630 | |
631 | /*! |
632 | * \brief |
633 | * A wrapper over a dynamic array of \ref segment objects; |
634 | * segment values added to SegmentStorage must be added |
635 | * in order of time along the domain of a \ref |
636 | * PathContour::interpolator_base |
637 | */ |
638 | class SegmentStorage:fastuidraw::noncopyable |
639 | { |
640 | public: |
641 | /*! |
642 | * Add a \ref segment to the SegmentStorage that is a |
643 | * line segment between two points. |
644 | * \param start the starting point of the segment |
645 | * \param end the ending point of the segment |
646 | */ |
647 | void |
648 | add_line_segment(vec2 start, vec2 end); |
649 | |
650 | /*! |
651 | * Add a \ref segment to the SegmentStorage that is an |
652 | * arc segment. If necessary, An arc-segment will be broken |
653 | * into multiple segments to that each segment is monotonic |
654 | * in the x and y coordiantes and each segment's arc-angle |
655 | * is no more than FASTUIDRAW_PI / 4.0 radians (45 degrees). |
656 | * \param start gives the start point of the arc on the path |
657 | * \param end gives the end point of the arc on the path |
658 | * \param center is the center of the circle that defines the arc |
659 | * \param radius is the radius of the circle that defines the arc |
660 | * \param arc_angle is the arc-angle range that defines the arc |
661 | */ |
662 | void |
663 | add_arc_segment(vec2 start, vec2 end, |
664 | vec2 center, float radius, |
665 | range_type<float> arc_angle); |
666 | |
667 | private: |
668 | SegmentStorage(void) {} |
669 | ~SegmentStorage() {} |
670 | |
671 | friend class TessellatedPath; |
672 | void *m_d; |
673 | }; |
674 | |
675 | /*! |
676 | * A Refiner is stateful object that creates new TessellatedPath |
677 | * objects from a starting TessellatedPath where the tessellation |
678 | * is made finer. |
679 | */ |
680 | class Refiner: |
681 | public reference_counted<Refiner>::non_concurrent |
682 | { |
683 | public: |
684 | virtual |
685 | ~Refiner(); |
686 | |
687 | /*! |
688 | * Update the TessellatedPath returned by tessellated_path() by |
689 | * refining the current value returned by tessellated_path(). |
690 | * \param max_distance new maximum distance to aim for |
691 | * \param additional_recursion amount by which to additionally recurse |
692 | * when tessellating. |
693 | */ |
694 | void |
695 | refine_tessellation(float max_distance, |
696 | unsigned int additional_recursion); |
697 | |
698 | /*! |
699 | * Returns the current TessellatedPath of this Refiner. |
700 | */ |
701 | reference_counted_ptr<TessellatedPath> |
702 | tessellated_path(void) const; |
703 | |
704 | private: |
705 | friend class TessellatedPath; |
706 | Refiner(TessellatedPath *p, const Path &path); |
707 | |
708 | void *m_d; |
709 | }; |
710 | |
711 | /*! |
712 | * Ctor. Construct a TessellatedPath from a Path |
713 | * \param input source path to tessellate |
714 | * \param P parameters on how to tessellate the source Path |
715 | * \param ref if non-NULL, construct a Refiner object and return |
716 | * the value via upading the value of ref. |
717 | */ |
718 | TessellatedPath(const Path &input, TessellationParams P, |
719 | reference_counted_ptr<Refiner> *ref = nullptr); |
720 | |
721 | ~TessellatedPath(); |
722 | |
723 | /*! |
724 | * Returns the tessellation parameters used to construct |
725 | * this TessellatedPath. |
726 | */ |
727 | const TessellationParams& |
728 | tessellation_parameters(void) const; |
729 | |
730 | /*! |
731 | * Returns true if and only if there is a \ref segment |
732 | * in segment_data() for which segment::m_type is |
733 | * \ref arc_segment. |
734 | */ |
735 | bool |
736 | has_arcs(void) const; |
737 | |
738 | /*! |
739 | * Returns the maximum across all edges of all contours |
740 | * of the distance between the tessellation and the actual |
741 | * path. |
742 | */ |
743 | float |
744 | max_distance(void) const; |
745 | |
746 | /*! |
747 | * Returns the maximum recursion employed by any edge |
748 | */ |
749 | unsigned int |
750 | max_recursion(void) const; |
751 | |
752 | /*! |
753 | * Returns all the segment data of the entire path. |
754 | */ |
755 | c_array<const segment> |
756 | segment_data(void) const; |
757 | |
758 | /*! |
759 | * Returns the array of \ref segment_chain objects |
760 | * of the entire path. |
761 | */ |
762 | c_array<const segment_chain> |
763 | segment_chain_data(void) const; |
764 | |
765 | /*! |
766 | * Returns all the join data |
767 | */ |
768 | c_array<const join> |
769 | join_data(void) const; |
770 | |
771 | /*! |
772 | * Returns all the cap data |
773 | */ |
774 | c_array<const cap> |
775 | cap_data(void) const; |
776 | |
777 | /*! |
778 | * Returns the number of contours |
779 | */ |
780 | unsigned int |
781 | number_contours(void) const; |
782 | |
783 | /*! |
784 | * Returns true if the named contour was closed |
785 | * \param contour which path contour to query, must have |
786 | * that 0 <= contour < number_contours() |
787 | */ |
788 | bool |
789 | contour_closed(unsigned int contour) const; |
790 | |
791 | /*! |
792 | * Returns the range into segment_data() for the named |
793 | * contour. |
794 | * \param contour which path contour to query, must have |
795 | * that 0 <= contour < number_contours() |
796 | */ |
797 | range_type<unsigned int> |
798 | contour_range(unsigned int contour) const; |
799 | |
800 | /*! |
801 | * Returns the segment data of the named contour. |
802 | * Provided as a conveniance equivalent to |
803 | * \code |
804 | * segment_data().sub_array(contour_range(contour)) |
805 | * \endcode |
806 | * \param contour which path contour to query, must have |
807 | * that 0 <= contour < number_contours() |
808 | */ |
809 | c_array<const segment> |
810 | contour_segment_data(unsigned int contour) const; |
811 | |
812 | /*! |
813 | * Returns the array of \ref segment_chain objects |
814 | * of a contour. |
815 | * \param contour which path contour to query, must have |
816 | * that 0 <= contour < number_contours() |
817 | */ |
818 | c_array<const segment_chain> |
819 | contour_chains(unsigned int contour) const; |
820 | |
821 | /*! |
822 | * Returns the number of edges for the named contour |
823 | * \param contour which path contour to query, must have |
824 | * that 0 <= contour < number_contours() |
825 | */ |
826 | unsigned int |
827 | number_edges(unsigned int contour) const; |
828 | |
829 | /*! |
830 | * Returns the range into segment_data(void) |
831 | * for the named edge of the named contour. |
832 | * \param contour which path contour to query, must have |
833 | * that 0 <= contour < number_contours() |
834 | * \param edge which edge of the contour to query, must |
835 | * have that 0 <= edge < number_edges(contour) |
836 | */ |
837 | range_type<unsigned int> |
838 | edge_range(unsigned int contour, unsigned int edge) const; |
839 | |
840 | /*! |
841 | * Returns the segment data of the named edge of the |
842 | * named contour, provided as a conveniance, equivalent |
843 | * to |
844 | * \code |
845 | * segment_data().sub_array(edge_range(contour, edge)) |
846 | * \endcode |
847 | * \param contour which path contour to query, must have |
848 | * that 0 <= contour < number_contours() |
849 | * \param edge which edge of the contour to query, must |
850 | * have that 0 <= edge < number_edges(contour) |
851 | */ |
852 | c_array<const segment> |
853 | edge_segment_data(unsigned int contour, unsigned int edge) const; |
854 | |
855 | /*! |
856 | * Returns the edge type of the named edge of the named contour |
857 | * of the source Path. |
858 | * \param contour which path contour to query, must have |
859 | * that 0 <= contour < number_contours() |
860 | * \param edge which edge of the contour to query, must |
861 | * have that 0 <= edge < number_edges(contour) |
862 | */ |
863 | enum PathEnums::edge_type_t |
864 | edge_type(unsigned int contour, unsigned int edge) const; |
865 | |
866 | /*! |
867 | * Returns the named edge as a \ref segment_chain taking |
868 | * correctly into account the value of \ref edge_type() |
869 | * in setting \ref segment_chain::m_prev_to_start. |
870 | * \param contour which path contour to query, must have |
871 | * that 0 <= contour < number_contours() |
872 | * \param edge which edge of the contour to query, must |
873 | * have that 0 <= edge < number_edges(contour) |
874 | */ |
875 | segment_chain |
876 | edge_segment_chain(unsigned int contour, unsigned int edge) const; |
877 | |
878 | /*! |
879 | * Returns the bounding box of the tessellation. |
880 | */ |
881 | const Rect& |
882 | bounding_box(void) const; |
883 | |
884 | /*! |
885 | * Returns this \ref TessellatedPath where any arcs are |
886 | * realized as segments. If this \ref TessellatedPath has |
887 | * no arcs, returns this object. If a non-positive value |
888 | * is passed, returns a linearization where arc-segments |
889 | * are tessellated into very few line segments. |
890 | * \param thresh threshhold at which to linearize |
891 | * arc-segments. |
892 | */ |
893 | const TessellatedPath& |
894 | linearization(float thresh) const; |
895 | |
896 | /*! |
897 | * Provided as a conveniance, returns the starting point tessellation. |
898 | * Equivalent to |
899 | * \code |
900 | * linearization(-1.0f) |
901 | * \endcode |
902 | */ |
903 | const TessellatedPath& |
904 | linearization(void) const; |
905 | |
906 | /*! |
907 | * Returns this \ref TessellatedPath stroked. The \ref |
908 | * StrokedPath object is constructed lazily. |
909 | */ |
910 | const StrokedPath& |
911 | stroked(void) const; |
912 | |
913 | /*! |
914 | * Returns this \ref TessellatedPath filled. If this |
915 | * \ref TessellatedPath has arcs will return |
916 | * the fill associated to the linearization() of |
917 | * this \ref TessellatedPath. If a non-positive value |
918 | * is passed, returns the fill of the linearization |
919 | * where arc-segments are tessellated into very few |
920 | * line segments. |
921 | * \param thresh threshhold at which to linearize |
922 | * arc-segments. |
923 | */ |
924 | const FilledPath& |
925 | filled(float thresh) const; |
926 | |
927 | /*! |
928 | * Provided as a conveniance, returns the starting point tessellation. |
929 | * Equivalent to |
930 | * \code |
931 | * filled(-1.0f) |
932 | * \endcode |
933 | */ |
934 | const FilledPath& |
935 | filled(void) const; |
936 | |
937 | /*! |
938 | * Returns the partitioning of this \ref TessellatedPath. |
939 | */ |
940 | const PartitionedTessellatedPath& |
941 | partitioned(void) const; |
942 | |
943 | private: |
944 | TessellatedPath(Refiner *p, float threshhold, |
945 | unsigned int additional_recursion_count); |
946 | |
947 | TessellatedPath(const TessellatedPath &with_arcs, |
948 | float thresh); |
949 | |
950 | void *m_d; |
951 | }; |
952 | |
953 | /*! @} */ |
954 | |
955 | } |
956 | |
957 | #endif |
958 | |