1//! The default path data structure.
2//!
3
4use crate::builder::*;
5use crate::geom::traits::Transformation;
6use crate::geom::{CubicBezierSegment, QuadraticBezierSegment};
7use crate::iterator::NoAttributes as IterNoAttributes;
8use crate::math::*;
9use crate::private::DebugValidator;
10use crate::{
11 AttributeStore, Attributes, ControlPointId, EndpointId, Event, IdEvent, PathEvent,
12 PositionStore, NO_ATTRIBUTES,
13};
14
15use core::fmt;
16use core::iter::{FromIterator, IntoIterator};
17use core::u32;
18
19use alloc::boxed::Box;
20use alloc::vec;
21use alloc::vec::Vec;
22
23/// Enumeration corresponding to the [Event](https://docs.rs/lyon_core/*/lyon_core/events/enum.Event.html) enum
24/// without the parameters.
25///
26/// This is used by the [Path](struct.Path.html) data structure to store path events a tad
27/// more efficiently.
28#[derive(Copy, Clone, Debug, PartialEq, Eq)]
29#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
30pub(crate) enum Verb {
31 LineTo,
32 QuadraticTo,
33 CubicTo,
34 Begin,
35 Close,
36 End,
37}
38
39/// A simple path data structure.
40///
41/// # Custom attributes
42///
43/// Paths can store a fixed number of extra `f32` values per endpoint, called
44/// "custom attributes" or "interpolated attributes" through the documentation.
45/// These can be handy to represent arbitrary attributes such as variable colors,
46/// line width, etc.
47///
48/// See also:
49/// - [`BuilderWithAttributes`](struct.BuilderWithAttributes.html).
50/// - [`Path::builder_with_attributes`](struct.Path.html#method.builder_with_attributes).
51/// - [`Path::attributes`](struct.Path.html#method.attributes).
52///
53/// # Representation
54///
55/// Paths contain two buffers:
56/// - a buffer of commands (Begin, Line, Quadratic, Cubic, Close or End),
57/// - and a buffer of pairs of floats that can be endpoints control points or custom attributes.
58///
59/// The order of storage for points is determined by the sequence of commands.
60/// Custom attributes (if any) always directly follow endpoints. If there is an odd number
61/// of attributes, the last float of the each attribute sequence is set to zero and is not used.
62///
63/// ```ascii
64/// __________________________
65/// | | | |
66/// | Begin | Line |Quadratic| ...
67/// |_______|______|_________|_
68/// __________________________________________________________________________
69/// | | | | | | | |
70/// |start x,y|attributes| to x, y |attributes|ctrl x,y | to x, y |attributes| ...
71/// |_________|__________|_________|__________|_________|_________|__________|_
72/// ```
73///
74#[derive(Clone, Default)]
75#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
76pub struct Path {
77 points: Box<[Point]>,
78 verbs: Box<[Verb]>,
79 num_attributes: usize,
80}
81
82/// A view on a `Path`.
83#[derive(Copy, Clone)]
84pub struct PathSlice<'l> {
85 pub(crate) points: &'l [Point],
86 pub(crate) verbs: &'l [Verb],
87 pub(crate) num_attributes: usize,
88}
89
90pub type Builder = NoAttributes<BuilderImpl>;
91
92impl Path {
93 /// Creates a [Builder](struct.Builder.html) to build a path.
94 pub fn builder() -> Builder {
95 NoAttributes::wrap(BuilderImpl::new())
96 }
97
98 /// Creates a [BuilderWithAttributes](struct.BuilderWithAttributes.html) to build a path
99 /// with custom attributes.
100 pub fn builder_with_attributes(num_attributes: usize) -> BuilderWithAttributes {
101 BuilderWithAttributes::new(num_attributes)
102 }
103
104 /// Creates an [WithSvg](../builder/struct.WithSvg.html) to build a path
105 /// with a rich set of commands.
106 pub fn svg_builder() -> WithSvg<BuilderImpl> {
107 WithSvg::new(BuilderImpl::new())
108 }
109
110 /// Creates an Empty `Path`.
111 #[inline]
112 pub fn new() -> Path {
113 Path {
114 points: Box::new([]),
115 verbs: Box::new([]),
116 num_attributes: 0,
117 }
118 }
119
120 #[inline]
121 pub fn with_attributes(num_attributes: usize) -> Path {
122 Path {
123 points: Box::new([]),
124 verbs: Box::new([]),
125 num_attributes,
126 }
127 }
128
129 /// Returns a view on this `Path`.
130 #[inline]
131 pub fn as_slice(&self) -> PathSlice {
132 PathSlice {
133 points: &self.points[..],
134 verbs: &self.verbs[..],
135 num_attributes: self.num_attributes,
136 }
137 }
138
139 /// Returns a slice over an endpoint's custom attributes.
140 #[inline]
141 pub fn attributes(&self, endpoint: EndpointId) -> Attributes {
142 interpolated_attributes(self.num_attributes, &self.points, endpoint)
143 }
144
145 /// Iterates over the entire `Path`, ignoring custom attributes.
146 pub fn iter(&self) -> Iter {
147 Iter::new(self.num_attributes, &self.points[..], &self.verbs[..])
148 }
149
150 /// Iterates over the endpoint and control point ids of the `Path`.
151 pub fn id_iter(&self) -> IdIter {
152 IdIter::new(self.num_attributes, &self.verbs[..])
153 }
154
155 /// Iterates over the entire `Path` with custom attributes.
156 pub fn iter_with_attributes(&self) -> IterWithAttributes {
157 IterWithAttributes::new(self.num_attributes(), &self.points[..], &self.verbs[..])
158 }
159
160 /// Applies a transform to all endpoints and control points of this path and
161 /// Returns the result.
162 pub fn transformed<T: Transformation<f32>>(mut self, transform: &T) -> Self {
163 self.apply_transform(transform);
164
165 self
166 }
167
168 /// Returns a reversed version of this path in the form of an iterator
169 pub fn reversed(&self) -> IterNoAttributes<Reversed> {
170 IterNoAttributes(Reversed::new(self.as_slice()))
171 }
172
173 /// Returns the first endpoint and its custom attributes if any.
174 #[inline]
175 pub fn first_endpoint(&self) -> Option<(Point, Attributes)> {
176 self.as_slice().first_endpoint()
177 }
178
179 /// Returns the last endpoint and its custom attributes if any.
180 #[inline]
181 pub fn last_endpoint(&self) -> Option<(Point, Attributes)> {
182 self.as_slice().last_endpoint()
183 }
184
185 fn apply_transform<T: Transformation<f32>>(&mut self, transform: &T) {
186 let iter = IdIter::new(self.num_attributes, &self.verbs[..]);
187
188 for evt in iter {
189 match evt {
190 IdEvent::Begin { at } => {
191 self.points[at.to_usize()] =
192 transform.transform_point(self.points[at.to_usize()]);
193 }
194 IdEvent::Line { to, .. } => {
195 self.points[to.to_usize()] =
196 transform.transform_point(self.points[to.to_usize()]);
197 }
198 IdEvent::Quadratic { ctrl, to, .. } => {
199 self.points[ctrl.to_usize()] =
200 transform.transform_point(self.points[ctrl.to_usize()]);
201 self.points[to.to_usize()] =
202 transform.transform_point(self.points[to.to_usize()]);
203 }
204 IdEvent::Cubic {
205 ctrl1, ctrl2, to, ..
206 } => {
207 self.points[ctrl1.to_usize()] =
208 transform.transform_point(self.points[ctrl1.to_usize()]);
209 self.points[ctrl2.to_usize()] =
210 transform.transform_point(self.points[ctrl2.to_usize()]);
211 self.points[to.to_usize()] =
212 transform.transform_point(self.points[to.to_usize()]);
213 }
214 IdEvent::End { .. } => {}
215 }
216 }
217 }
218}
219
220impl FromIterator<PathEvent> for Path {
221 fn from_iter<T: IntoIterator<Item = PathEvent>>(iter: T) -> Path {
222 let mut builder: NoAttributes = Path::builder();
223 for event: Event, …> in iter.into_iter() {
224 builder.path_event(event);
225 }
226
227 builder.build()
228 }
229}
230
231impl core::ops::Index<EndpointId> for Path {
232 type Output = Point;
233 fn index(&self, id: EndpointId) -> &Point {
234 &self.points[id.to_usize()]
235 }
236}
237
238impl core::ops::Index<ControlPointId> for Path {
239 type Output = Point;
240 fn index(&self, id: ControlPointId) -> &Point {
241 &self.points[id.to_usize()]
242 }
243}
244
245impl<'l> IntoIterator for &'l Path {
246 type Item = PathEvent;
247 type IntoIter = Iter<'l>;
248
249 fn into_iter(self) -> Iter<'l> {
250 self.iter()
251 }
252}
253
254impl<'l> From<&'l Path> for PathSlice<'l> {
255 fn from(path: &'l Path) -> Self {
256 path.as_slice()
257 }
258}
259
260impl PositionStore for Path {
261 fn get_endpoint(&self, id: EndpointId) -> Point {
262 self.points[id.to_usize()]
263 }
264
265 fn get_control_point(&self, id: ControlPointId) -> Point {
266 self.points[id.to_usize()]
267 }
268}
269
270impl AttributeStore for Path {
271 fn get(&self, id: EndpointId) -> Attributes {
272 interpolated_attributes(self.num_attributes, &self.points, endpoint:id)
273 }
274
275 fn num_attributes(&self) -> usize {
276 self.num_attributes
277 }
278}
279
280impl fmt::Debug for Path {
281 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
282 self.as_slice().fmt(formatter)
283 }
284}
285
286/// An immutable view over a Path.
287impl<'l> PathSlice<'l> {
288 pub fn first_endpoint(&self) -> Option<(Point, Attributes<'l>)> {
289 if self.points.is_empty() {
290 return None;
291 }
292
293 let pos = self.points[0];
294 let attributes = interpolated_attributes(self.num_attributes, self.points, EndpointId(0));
295
296 Some((pos, attributes))
297 }
298
299 pub fn last_endpoint(&self) -> Option<(Point, Attributes<'l>)> {
300 if self.points.is_empty() {
301 return None;
302 }
303
304 let attrib_stride = (self.num_attributes() + 1) / 2;
305 let offset = self.points.len() - attrib_stride - 1;
306
307 let pos = self.points[offset];
308 let attributes =
309 interpolated_attributes(self.num_attributes, self.points, EndpointId(offset as u32));
310
311 Some((pos, attributes))
312 }
313
314 /// Iterates over the path.
315 pub fn iter<'a>(&'a self) -> Iter<'l> {
316 Iter::new(self.num_attributes, self.points, self.verbs)
317 }
318
319 /// Iterates over the endpoint and control point ids of the `Path`.
320 pub fn id_iter(&self) -> IdIter {
321 IdIter::new(self.num_attributes, self.verbs)
322 }
323
324 /// Iterates over the entire `Path` with custom attributes.
325 pub fn iter_with_attributes(&self) -> IterWithAttributes {
326 IterWithAttributes::new(self.num_attributes(), self.points, self.verbs)
327 }
328
329 pub fn is_empty(&self) -> bool {
330 self.verbs.is_empty()
331 }
332
333 /// Returns a slice over an endpoint's custom attributes.
334 #[inline]
335 pub fn attributes(&self, endpoint: EndpointId) -> Attributes<'l> {
336 interpolated_attributes(self.num_attributes, self.points, endpoint)
337 }
338
339 /// Returns a reversed version of this path in the form of an iterator
340 pub fn reversed(&self) -> IterNoAttributes<Reversed> {
341 IterNoAttributes(Reversed::new(*self))
342 }
343}
344
345impl<'l> fmt::Debug for PathSlice<'l> {
346 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
347 fn write_point(formatter: &mut fmt::Formatter, point: Point) -> fmt::Result {
348 write!(formatter, " ")?;
349 fmt::Debug::fmt(&point.x, formatter)?;
350 write!(formatter, " ")?;
351 fmt::Debug::fmt(&point.y, formatter)
352 }
353
354 fn write_attributes(formatter: &mut fmt::Formatter, attributes: Attributes) -> fmt::Result {
355 for val in attributes {
356 write!(formatter, " ")?;
357 fmt::Debug::fmt(val, formatter)?;
358 }
359
360 Ok(())
361 }
362
363 write!(formatter, "\"")?;
364
365 for evt in self.iter_with_attributes() {
366 match evt {
367 Event::Begin {
368 at: (at, attributes),
369 } => {
370 write!(formatter, " M")?;
371 write_point(formatter, at)?;
372 write_attributes(formatter, attributes)?;
373 }
374 Event::End { close, .. } => {
375 if close {
376 write!(formatter, " Z")?;
377 }
378 }
379 Event::Line {
380 to: (to, attributes),
381 ..
382 } => {
383 write!(formatter, " L")?;
384 write_point(formatter, to)?;
385 write_attributes(formatter, attributes)?;
386 }
387 Event::Quadratic {
388 ctrl,
389 to: (to, attributes),
390 ..
391 } => {
392 write!(formatter, " Q")?;
393 write_point(formatter, ctrl)?;
394 write_point(formatter, to)?;
395 write_attributes(formatter, attributes)?;
396 }
397 Event::Cubic {
398 ctrl1,
399 ctrl2,
400 to: (to, attributes),
401 ..
402 } => {
403 write!(formatter, " C")?;
404 write_point(formatter, ctrl1)?;
405 write_point(formatter, ctrl2)?;
406 write_point(formatter, to)?;
407 write_attributes(formatter, attributes)?;
408 }
409 }
410 }
411
412 write!(formatter, "\"")
413 }
414}
415
416impl<'l> core::ops::Index<EndpointId> for PathSlice<'l> {
417 type Output = Point;
418 fn index(&self, id: EndpointId) -> &Point {
419 &self.points[id.to_usize()]
420 }
421}
422
423impl<'l> core::ops::Index<ControlPointId> for PathSlice<'l> {
424 type Output = Point;
425 fn index(&self, id: ControlPointId) -> &Point {
426 &self.points[id.to_usize()]
427 }
428}
429
430impl<'l> IntoIterator for PathSlice<'l> {
431 type Item = PathEvent;
432 type IntoIter = Iter<'l>;
433
434 fn into_iter(self) -> Iter<'l> {
435 self.iter()
436 }
437}
438
439impl<'l, 'a> IntoIterator for &'a PathSlice<'l> {
440 type Item = PathEvent;
441 type IntoIter = Iter<'l>;
442
443 fn into_iter(self) -> Iter<'l> {
444 self.iter()
445 }
446}
447
448impl<'l> PositionStore for PathSlice<'l> {
449 fn get_endpoint(&self, id: EndpointId) -> Point {
450 self.points[id.to_usize()]
451 }
452
453 fn get_control_point(&self, id: ControlPointId) -> Point {
454 self.points[id.to_usize()]
455 }
456}
457
458impl<'l> AttributeStore for PathSlice<'l> {
459 fn get(&self, id: EndpointId) -> Attributes<'l> {
460 interpolated_attributes(self.num_attributes, self.points, endpoint:id)
461 }
462
463 fn num_attributes(&self) -> usize {
464 self.num_attributes
465 }
466}
467
468// TODO: measure the overhead of building no attributes and
469// see if BuilderImpl and BuilderWithAttributes can be merged.
470
471/// The default builder for `Path`.
472#[derive(Clone)]
473pub struct BuilderImpl {
474 pub(crate) points: Vec<Point>,
475 pub(crate) verbs: Vec<Verb>,
476 first: Point,
477 validator: DebugValidator,
478}
479
480impl BuilderImpl {
481 pub fn new() -> Self {
482 BuilderImpl {
483 points: Vec::new(),
484 verbs: Vec::new(),
485 first: point(0.0, 0.0),
486 validator: DebugValidator::new(),
487 }
488 }
489
490 pub fn with_capacity(points: usize, edges: usize) -> Self {
491 BuilderImpl {
492 points: Vec::with_capacity(points),
493 verbs: Vec::with_capacity(edges),
494 first: point(0.0, 0.0),
495 validator: DebugValidator::new(),
496 }
497 }
498
499 pub fn with_svg(self) -> WithSvg<Self> {
500 assert!(self.verbs.is_empty());
501 WithSvg::new(self)
502 }
503
504 #[inline]
505 pub fn extend_from_paths(&mut self, paths: &[PathSlice]) {
506 concatenate_paths(&mut self.points, &mut self.verbs, paths, 0);
507 }
508}
509
510impl NoAttributes<BuilderImpl> {
511 #[inline]
512 pub fn extend_from_paths(&mut self, paths: &[PathSlice]) {
513 concatenate_paths(&mut self.inner.points, &mut self.inner.verbs, paths, num_attributes:0);
514 }
515}
516
517impl PathBuilder for BuilderImpl {
518 fn num_attributes(&self) -> usize {
519 0
520 }
521
522 fn begin(&mut self, at: Point, _attributes: Attributes) -> EndpointId {
523 self.validator.begin();
524 nan_check(at);
525
526 let id = EndpointId(self.points.len() as u32);
527
528 self.first = at;
529 self.points.push(at);
530 self.verbs.push(Verb::Begin);
531
532 id
533 }
534
535 fn end(&mut self, close: bool) {
536 self.validator.end();
537
538 if close {
539 self.points.push(self.first);
540 }
541
542 self.verbs.push(if close { Verb::Close } else { Verb::End });
543 }
544
545 fn line_to(&mut self, to: Point, _attributes: Attributes) -> EndpointId {
546 self.validator.edge();
547 nan_check(to);
548
549 let id = EndpointId(self.points.len() as u32);
550 self.points.push(to);
551 self.verbs.push(Verb::LineTo);
552
553 id
554 }
555
556 fn quadratic_bezier_to(
557 &mut self,
558 ctrl: Point,
559 to: Point,
560 _attributes: Attributes,
561 ) -> EndpointId {
562 self.validator.edge();
563 nan_check(ctrl);
564 nan_check(to);
565
566 self.points.push(ctrl);
567 let id = EndpointId(self.points.len() as u32);
568 self.points.push(to);
569 self.verbs.push(Verb::QuadraticTo);
570
571 id
572 }
573
574 fn cubic_bezier_to(
575 &mut self,
576 ctrl1: Point,
577 ctrl2: Point,
578 to: Point,
579 _attributes: Attributes,
580 ) -> EndpointId {
581 self.validator.edge();
582 nan_check(ctrl1);
583 nan_check(ctrl2);
584 nan_check(to);
585
586 self.points.push(ctrl1);
587 self.points.push(ctrl2);
588 let id = EndpointId(self.points.len() as u32);
589 self.points.push(to);
590 self.verbs.push(Verb::CubicTo);
591
592 id
593 }
594
595 fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
596 self.points.reserve(endpoints + ctrl_points);
597 self.verbs.reserve(endpoints);
598 }
599}
600
601impl Build for BuilderImpl {
602 type PathType = Path;
603
604 fn build(self) -> Path {
605 self.validator.build();
606 Path {
607 points: self.points.into_boxed_slice(),
608 verbs: self.verbs.into_boxed_slice(),
609 num_attributes: 0,
610 }
611 }
612}
613
614impl Default for BuilderImpl {
615 fn default() -> Self {
616 BuilderImpl::new()
617 }
618}
619
620/// A builder for `Path` with custom attributes.
621///
622/// Custom attributes are a fixed number of `f32` values associated with each endpoint.
623/// All endpoints must have the same number of custom attributes,
624#[derive(Clone)]
625pub struct BuilderWithAttributes {
626 pub(crate) builder: BuilderImpl,
627 pub(crate) num_attributes: usize,
628 pub(crate) first_attributes: Vec<f32>,
629}
630
631impl BuilderWithAttributes {
632 pub fn new(num_attributes: usize) -> Self {
633 BuilderWithAttributes {
634 builder: BuilderImpl::new(),
635 num_attributes,
636 first_attributes: vec![0.0; num_attributes],
637 }
638 }
639
640 #[inline]
641 pub fn extend_from_paths(&mut self, paths: &[PathSlice]) {
642 concatenate_paths(
643 &mut self.builder.points,
644 &mut self.builder.verbs,
645 paths,
646 self.num_attributes,
647 );
648 }
649
650 #[inline(always)]
651 fn push_attributes_impl(
652 points: &mut Vec<Point>,
653 num_attributes: usize,
654 attributes: Attributes,
655 ) {
656 assert_eq!(attributes.len(), num_attributes);
657 for i in 0..(num_attributes / 2) {
658 let x = attributes[i * 2];
659 let y = attributes[i * 2 + 1];
660 points.push(point(x, y));
661 }
662 if num_attributes % 2 == 1 {
663 let x = attributes[num_attributes - 1];
664 points.push(point(x, 0.0));
665 }
666 }
667
668 fn push_attributes(&mut self, attributes: Attributes) {
669 Self::push_attributes_impl(&mut self.builder.points, self.num_attributes, attributes);
670 }
671
672 #[inline]
673 pub fn num_attributes(&self) -> usize {
674 self.num_attributes
675 }
676
677 #[inline]
678 pub fn begin(&mut self, at: Point, attributes: Attributes) -> EndpointId {
679 let id = self.builder.begin(at, attributes);
680 self.push_attributes(attributes);
681
682 self.first_attributes.copy_from_slice(attributes);
683
684 id
685 }
686
687 #[inline]
688 pub fn end(&mut self, close: bool) {
689 self.builder.end(close);
690
691 if close {
692 Self::push_attributes_impl(
693 &mut self.builder.points,
694 self.num_attributes,
695 &self.first_attributes,
696 );
697 }
698 }
699
700 #[inline]
701 pub fn line_to(&mut self, to: Point, attributes: Attributes) -> EndpointId {
702 let id = self.builder.line_to(to, attributes);
703 self.push_attributes(attributes);
704
705 id
706 }
707
708 #[inline]
709 pub fn quadratic_bezier_to(
710 &mut self,
711 ctrl: Point,
712 to: Point,
713 attributes: Attributes,
714 ) -> EndpointId {
715 let id = self.builder.quadratic_bezier_to(ctrl, to, attributes);
716 self.push_attributes(attributes);
717
718 id
719 }
720
721 #[inline]
722 pub fn cubic_bezier_to(
723 &mut self,
724 ctrl1: Point,
725 ctrl2: Point,
726 to: Point,
727 attributes: Attributes,
728 ) -> EndpointId {
729 let id = self.builder.cubic_bezier_to(ctrl1, ctrl2, to, attributes);
730 self.push_attributes(attributes);
731
732 id
733 }
734
735 #[inline]
736 pub fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
737 let attr = self.num_attributes / 2 + self.num_attributes % 2;
738 let n_points = endpoints * (1 + attr) + ctrl_points;
739 self.builder.points.reserve(n_points);
740 self.builder.verbs.reserve(endpoints);
741 }
742
743 #[inline]
744 pub fn build(self) -> Path {
745 self.builder.validator.build();
746 Path {
747 points: self.builder.points.into_boxed_slice(),
748 verbs: self.builder.verbs.into_boxed_slice(),
749 num_attributes: self.num_attributes,
750 }
751 }
752}
753
754impl PathBuilder for BuilderWithAttributes {
755 #[inline]
756 fn num_attributes(&self) -> usize {
757 self.num_attributes()
758 }
759
760 #[inline]
761 fn begin(&mut self, at: Point, attributes: Attributes) -> EndpointId {
762 self.begin(at, attributes)
763 }
764
765 #[inline]
766 fn end(&mut self, close: bool) {
767 self.end(close);
768 }
769
770 #[inline]
771 fn line_to(&mut self, to: Point, attributes: Attributes) -> EndpointId {
772 self.line_to(to, attributes)
773 }
774
775 #[inline]
776 fn quadratic_bezier_to(
777 &mut self,
778 ctrl: Point,
779 to: Point,
780 attributes: Attributes,
781 ) -> EndpointId {
782 self.quadratic_bezier_to(ctrl, to, attributes)
783 }
784
785 #[inline]
786 fn cubic_bezier_to(
787 &mut self,
788 ctrl1: Point,
789 ctrl2: Point,
790 to: Point,
791 attributes: Attributes,
792 ) -> EndpointId {
793 self.cubic_bezier_to(ctrl1, ctrl2, to, attributes)
794 }
795
796 #[inline]
797 fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
798 self.reserve(endpoints, ctrl_points)
799 }
800}
801
802impl Build for BuilderWithAttributes {
803 type PathType = Path;
804
805 fn build(self) -> Path {
806 self.build()
807 }
808}
809
810#[inline]
811fn nan_check(p: Point) {
812 debug_assert!(p.x.is_finite());
813 debug_assert!(p.y.is_finite());
814}
815
816/// An iterator for `Path` and `PathSlice`.
817#[derive(Clone)]
818pub struct Iter<'l> {
819 points: PointIter<'l>,
820 verbs: ::core::slice::Iter<'l, Verb>,
821 current: Point,
822 first: Point,
823 // Number of slots in the points array occupied by the custom attributes.
824 attrib_stride: usize,
825}
826
827impl<'l> Iter<'l> {
828 fn new(num_attributes: usize, points: &'l [Point], verbs: &'l [Verb]) -> Self {
829 Iter {
830 points: PointIter::new(slice:points),
831 verbs: verbs.iter(),
832 current: point(x:0.0, y:0.0),
833 first: point(x:0.0, y:0.0),
834 attrib_stride: (num_attributes + 1) / 2,
835 }
836 }
837
838 #[inline]
839 fn skip_attributes(&mut self) {
840 self.points.advance_n(self.attrib_stride);
841 }
842}
843
844impl<'l> Iterator for Iter<'l> {
845 type Item = PathEvent;
846 #[inline]
847 fn next(&mut self) -> Option<PathEvent> {
848 match self.verbs.next() {
849 Some(&Verb::Begin) => {
850 self.current = self.points.next();
851 self.skip_attributes();
852 self.first = self.current;
853 Some(PathEvent::Begin { at: self.current })
854 }
855 Some(&Verb::LineTo) => {
856 let from = self.current;
857 self.current = self.points.next();
858 self.skip_attributes();
859 Some(PathEvent::Line {
860 from,
861 to: self.current,
862 })
863 }
864 Some(&Verb::QuadraticTo) => {
865 let from = self.current;
866 let ctrl = self.points.next();
867 self.current = self.points.next();
868 self.skip_attributes();
869 Some(PathEvent::Quadratic {
870 from,
871 ctrl,
872 to: self.current,
873 })
874 }
875 Some(&Verb::CubicTo) => {
876 let from = self.current;
877 let ctrl1 = self.points.next();
878 let ctrl2 = self.points.next();
879 self.current = self.points.next();
880 self.skip_attributes();
881 Some(PathEvent::Cubic {
882 from,
883 ctrl1,
884 ctrl2,
885 to: self.current,
886 })
887 }
888 Some(&Verb::Close) => {
889 let last = self.current;
890 let _ = self.points.next();
891 self.skip_attributes();
892 Some(PathEvent::End {
893 last,
894 first: self.first,
895 close: true,
896 })
897 }
898 Some(&Verb::End) => {
899 let last = self.current;
900 self.current = self.first;
901 Some(PathEvent::End {
902 last,
903 first: self.first,
904 close: false,
905 })
906 }
907 None => None,
908 }
909 }
910}
911
912/// Manually implemented to avoid iterator overhead when skipping over
913/// several points where the custom attributes are stored.
914///
915/// It makes an unfortunately large difference (the simple iterator
916/// benchmarks are 2 to 3 times faster).
917#[derive(Copy, Clone)]
918struct PointIter<'l> {
919 ptr: *const Point,
920 end: *const Point,
921 _marker: core::marker::PhantomData<&'l Point>,
922}
923
924impl<'l> PointIter<'l> {
925 fn new(slice: &'l [Point]) -> Self {
926 let ptr = slice.as_ptr();
927 let end = unsafe { ptr.add(slice.len()) };
928 PointIter {
929 ptr,
930 end,
931 _marker: core::marker::PhantomData,
932 }
933 }
934
935 #[inline]
936 fn remaining_len(&self) -> usize {
937 (self.end as usize - self.ptr as usize) / core::mem::size_of::<Point>()
938 }
939
940 #[inline]
941 fn next(&mut self) -> Point {
942 // Don't bother panicking here. calls to next
943 // are always followed by advance_n which will
944 // catch the issue and panic.
945 if self.ptr >= self.end {
946 return point(f32::NAN, f32::NAN);
947 }
948
949 unsafe {
950 let output = *self.ptr;
951 self.ptr = self.ptr.offset(1);
952
953 output
954 }
955 }
956
957 #[inline]
958 fn advance_n(&mut self, n: usize) {
959 unsafe {
960 assert!(self.remaining_len() >= n);
961 self.ptr = self.ptr.add(n);
962 }
963 }
964}
965
966/// An iterator for `Path` and `PathSlice`.
967#[derive(Clone)]
968pub struct IterWithAttributes<'l> {
969 points: PointIter<'l>,
970 verbs: ::core::slice::Iter<'l, Verb>,
971 current: (Point, Attributes<'l>),
972 first: (Point, Attributes<'l>),
973 num_attributes: usize,
974 attrib_stride: usize,
975}
976
977impl<'l> IterWithAttributes<'l> {
978 fn new(num_attributes: usize, points: &'l [Point], verbs: &'l [Verb]) -> Self {
979 IterWithAttributes {
980 points: PointIter::new(points),
981 verbs: verbs.iter(),
982 current: (point(0.0, 0.0), NO_ATTRIBUTES),
983 first: (point(0.0, 0.0), NO_ATTRIBUTES),
984 num_attributes,
985 attrib_stride: (num_attributes + 1) / 2,
986 }
987 }
988
989 pub fn points(self) -> Iter<'l> {
990 Iter {
991 points: self.points,
992 verbs: self.verbs,
993 current: self.current.0,
994 first: self.first.0,
995 attrib_stride: self.attrib_stride,
996 }
997 }
998
999 /// Iterate on a flattened approximation of the path with interpolated custom attributes
1000 /// using callbacks.
1001 ///
1002 /// At the time of writing, it is impossible to implement this efficiently
1003 /// with the `Iterator` trait, because of the need to express some lifetime
1004 /// constraints in an associated type, see #701.
1005 pub fn for_each_flattened<F>(self, tolerance: f32, callback: &mut F)
1006 where
1007 F: FnMut(&Event<(Point, Attributes), Point>),
1008 {
1009 let num_attributes = self.num_attributes;
1010 // Some scratch space for writing the interpolated custom attributes.
1011 let mut stack_buffer = [0.0; 16];
1012 let mut vec_buffer;
1013 // No need to allocate memory if the number of custom attributes is small,
1014 // which is likely the common case.
1015 let buffer = if num_attributes <= 8 {
1016 &mut stack_buffer[..]
1017 } else {
1018 vec_buffer = vec![0.0; num_attributes * 2];
1019 &mut vec_buffer[..]
1020 };
1021
1022 for evt in self {
1023 match evt {
1024 Event::Begin { at } => {
1025 callback(&Event::Begin { at });
1026 }
1027 Event::End { last, first, close } => {
1028 callback(&Event::End { last, first, close });
1029 }
1030 Event::Line { from, to } => {
1031 callback(&Event::Line { from, to });
1032 }
1033 Event::Quadratic { from, ctrl, to } => {
1034 let from_attr = from.1;
1035 let to_attr = to.1;
1036 let curve = QuadraticBezierSegment {
1037 from: from.0,
1038 ctrl,
1039 to: to.0,
1040 };
1041 let mut offset = num_attributes;
1042 buffer[0..num_attributes].copy_from_slice(from_attr);
1043 curve.for_each_flattened_with_t(tolerance, &mut |line, t| {
1044 for i in 0..num_attributes {
1045 buffer[offset + i] = (1.0 - t.end) * from_attr[i] + t.end * to_attr[i];
1046 }
1047
1048 let next_offset = if offset == 0 { num_attributes } else { 0 };
1049
1050 callback(&Event::Line {
1051 from: (
1052 line.from,
1053 &buffer[next_offset..(next_offset + num_attributes)],
1054 ),
1055 to: (line.to, &buffer[offset..(offset + num_attributes)]),
1056 });
1057
1058 offset = next_offset;
1059 });
1060 }
1061 Event::Cubic {
1062 from,
1063 ctrl1,
1064 ctrl2,
1065 to,
1066 } => {
1067 let from_attr = from.1;
1068 let to_attr = to.1;
1069 let curve = CubicBezierSegment {
1070 from: from.0,
1071 ctrl1,
1072 ctrl2,
1073 to: to.0,
1074 };
1075 let mut offset = num_attributes;
1076 buffer[0..num_attributes].copy_from_slice(from_attr);
1077 curve.for_each_flattened_with_t(tolerance, &mut |line, t| {
1078 for i in 0..num_attributes {
1079 buffer[offset + i] = (1.0 - t.end) * from_attr[i] + t.end * to_attr[i];
1080 }
1081
1082 let next_offset = if offset == 0 { num_attributes } else { 0 };
1083
1084 callback(&Event::Line {
1085 from: (
1086 line.from,
1087 &buffer[next_offset..(next_offset + num_attributes)],
1088 ),
1089 to: (line.to, &buffer[offset..(offset + num_attributes)]),
1090 });
1091
1092 offset = next_offset;
1093 });
1094 }
1095 }
1096 }
1097 }
1098
1099 #[inline]
1100 fn pop_endpoint(&mut self) -> (Point, Attributes<'l>) {
1101 let position = self.points.next();
1102 let attributes_ptr = self.points.ptr as *const f32;
1103 self.points.advance_n(self.attrib_stride);
1104 let attributes = unsafe {
1105 // SAFETY: advance_n would have panicked if the slice is out of bounds
1106 core::slice::from_raw_parts(attributes_ptr, self.num_attributes)
1107 };
1108
1109 (position, attributes)
1110 }
1111}
1112
1113impl<'l> Iterator for IterWithAttributes<'l> {
1114 type Item = Event<(Point, Attributes<'l>), Point>;
1115 #[inline]
1116 fn next(&mut self) -> Option<Self::Item> {
1117 match self.verbs.next() {
1118 Some(&Verb::Begin) => {
1119 self.current = self.pop_endpoint();
1120 self.first = self.current;
1121 Some(Event::Begin { at: self.current })
1122 }
1123 Some(&Verb::LineTo) => {
1124 let from = self.current;
1125 self.current = self.pop_endpoint();
1126 Some(Event::Line {
1127 from,
1128 to: self.current,
1129 })
1130 }
1131 Some(&Verb::QuadraticTo) => {
1132 let from = self.current;
1133 let ctrl = self.points.next();
1134 self.current = self.pop_endpoint();
1135 Some(Event::Quadratic {
1136 from,
1137 ctrl,
1138 to: self.current,
1139 })
1140 }
1141 Some(&Verb::CubicTo) => {
1142 let from = self.current;
1143 let ctrl1 = self.points.next();
1144 let ctrl2 = self.points.next();
1145 self.current = self.pop_endpoint();
1146 Some(Event::Cubic {
1147 from,
1148 ctrl1,
1149 ctrl2,
1150 to: self.current,
1151 })
1152 }
1153 Some(&Verb::Close) => {
1154 let last = self.current;
1155 self.current = self.pop_endpoint();
1156 Some(Event::End {
1157 last,
1158 first: self.first,
1159 close: true,
1160 })
1161 }
1162 Some(&Verb::End) => {
1163 let last = self.current;
1164 self.current = self.first;
1165 Some(Event::End {
1166 last,
1167 first: self.first,
1168 close: false,
1169 })
1170 }
1171 None => None,
1172 }
1173 }
1174}
1175
1176/// An iterator of endpoint and control point ids for `Path` and `PathSlice`.
1177#[derive(Clone, Debug)]
1178pub struct IdIter<'l> {
1179 verbs: ::core::slice::Iter<'l, Verb>,
1180 current: u32,
1181 first: u32,
1182 evt: u32,
1183 endpoint_stride: u32,
1184}
1185
1186impl<'l> IdIter<'l> {
1187 fn new(num_attributes: usize, verbs: &'l [Verb]) -> Self {
1188 IdIter {
1189 verbs: verbs.iter(),
1190 current: 0,
1191 first: 0,
1192 evt: 0,
1193 endpoint_stride: (num_attributes as u32 + 1) / 2 + 1,
1194 }
1195 }
1196}
1197
1198impl<'l> Iterator for IdIter<'l> {
1199 type Item = IdEvent;
1200 #[inline]
1201 fn next(&mut self) -> Option<IdEvent> {
1202 match self.verbs.next() {
1203 Some(&Verb::Begin) => {
1204 let at = self.current;
1205 self.first = at;
1206 Some(IdEvent::Begin { at: EndpointId(at) })
1207 }
1208 Some(&Verb::LineTo) => {
1209 let from = EndpointId(self.current);
1210 self.current += self.endpoint_stride;
1211 let to = EndpointId(self.current);
1212 self.evt += 1;
1213 Some(IdEvent::Line { from, to })
1214 }
1215 Some(&Verb::QuadraticTo) => {
1216 let from = EndpointId(self.current);
1217 let base = self.current + self.endpoint_stride;
1218 let ctrl = ControlPointId(base);
1219 let to = EndpointId(base + 1);
1220 self.current = base + 1;
1221 self.evt += 1;
1222 Some(IdEvent::Quadratic { from, ctrl, to })
1223 }
1224 Some(&Verb::CubicTo) => {
1225 let from = EndpointId(self.current);
1226 let base = self.current + self.endpoint_stride;
1227 let ctrl1 = ControlPointId(base);
1228 let ctrl2 = ControlPointId(base + 1);
1229 let to = EndpointId(base + 2);
1230 self.current = base + 2;
1231 self.evt += 1;
1232 Some(IdEvent::Cubic {
1233 from,
1234 ctrl1,
1235 ctrl2,
1236 to,
1237 })
1238 }
1239 Some(&Verb::Close) => {
1240 let last = EndpointId(self.current);
1241 let first = EndpointId(self.first);
1242 self.current += self.endpoint_stride * 2;
1243 self.evt += 1;
1244 Some(IdEvent::End {
1245 last,
1246 first,
1247 close: true,
1248 })
1249 }
1250 Some(&Verb::End) => {
1251 let last = EndpointId(self.current);
1252 let first = EndpointId(self.first);
1253 self.current += self.endpoint_stride;
1254 self.evt += 1;
1255 Some(IdEvent::End {
1256 last,
1257 first,
1258 close: false,
1259 })
1260 }
1261 None => None,
1262 }
1263 }
1264}
1265
1266#[inline]
1267fn interpolated_attributes(
1268 num_attributes: usize,
1269 points: &[Point],
1270 endpoint: EndpointId,
1271) -> Attributes {
1272 if num_attributes == 0 {
1273 return &[];
1274 }
1275
1276 let idx: usize = endpoint.0 as usize + 1;
1277 assert!(idx + (num_attributes + 1) / 2 <= points.len());
1278
1279 unsafe {
1280 let ptr: *const f32 = &points[idx].x as *const f32;
1281 core::slice::from_raw_parts(data:ptr, len:num_attributes)
1282 }
1283}
1284
1285fn concatenate_paths(
1286 points: &mut Vec<Point>,
1287 verbs: &mut Vec<Verb>,
1288 paths: &[PathSlice],
1289 num_attributes: usize,
1290) {
1291 let mut np: usize = 0;
1292 let mut nv: usize = 0;
1293
1294 for path: &PathSlice<'_> in paths {
1295 assert_eq!(path.num_attributes(), num_attributes);
1296 np += path.points.len();
1297 nv += path.verbs.len();
1298 }
1299
1300 verbs.reserve(additional:nv);
1301 points.reserve(additional:np);
1302
1303 for path: &PathSlice<'_> in paths {
1304 verbs.extend_from_slice(path.verbs);
1305 points.extend_from_slice(path.points);
1306 }
1307}
1308
1309/// An iterator of over a `Path` traversing the path in reverse.
1310pub struct Reversed<'l> {
1311 verbs: core::iter::Rev<core::slice::Iter<'l, Verb>>,
1312 path: PathSlice<'l>,
1313 num_attributes: usize,
1314 attrib_stride: usize,
1315 p: usize,
1316 need_close: bool,
1317 first: Option<(Point, Attributes<'l>)>,
1318}
1319
1320impl<'l> Reversed<'l> {
1321 fn new(path: PathSlice<'l>) -> Self {
1322 Reversed {
1323 verbs: path.verbs.iter().rev(),
1324 num_attributes: path.num_attributes(),
1325 attrib_stride: (path.num_attributes() + 1) / 2,
1326 path,
1327 p: path.points.len(),
1328 need_close: false,
1329 first: None,
1330 }
1331 }
1332
1333 /// Builds a `Path` from This iterator.
1334 ///
1335 /// The iterator must be at the beginning.
1336 pub fn into_path(self) -> Path {
1337 let mut builder = Path::builder_with_attributes(self.num_attributes);
1338 for event in self {
1339 builder.event(event);
1340 }
1341
1342 builder.build()
1343 }
1344}
1345
1346impl<'l> Iterator for Reversed<'l> {
1347 type Item = Event<(Point, Attributes<'l>), Point>;
1348 fn next(&mut self) -> Option<Self::Item> {
1349 // At the beginning of each iteration, `self.p` points to the index
1350 // directly after the endpoint of the current verb.
1351 let endpoint_stride = self.attrib_stride + 1;
1352 let v = self.verbs.next()?;
1353 let event = match v {
1354 Verb::Close => {
1355 self.need_close = true;
1356 // Close event contain the first endpoint, so skip over that by
1357 // offsetting by an extra endpoint stride.
1358 let idx = self.p - 2 * endpoint_stride;
1359 let first = (
1360 self.path.points[idx],
1361 self.path.attributes(EndpointId(idx as u32)),
1362 );
1363 self.first = Some(first);
1364 Event::Begin { at: first }
1365 }
1366 Verb::End => {
1367 // End events don't push an endpoint, the current endpoint
1368 // is the one of the previous command (or next going in reverse).
1369 let idx = self.p - endpoint_stride;
1370 self.need_close = false;
1371 let first = (
1372 self.path.points[idx],
1373 self.path.attributes(EndpointId(idx as u32)),
1374 );
1375 self.first = Some(first);
1376 Event::Begin { at: first }
1377 }
1378 Verb::Begin => {
1379 let close = self.need_close;
1380 self.need_close = false;
1381 let idx = self.p - endpoint_stride;
1382 Event::End {
1383 last: (
1384 self.path.points[idx],
1385 self.path.attributes(EndpointId(idx as u32)),
1386 ),
1387 first: self.first.take().unwrap(),
1388 close,
1389 }
1390 }
1391 Verb::LineTo => {
1392 let from = self.p - endpoint_stride;
1393 let to = from - endpoint_stride;
1394 Event::Line {
1395 from: (
1396 self.path.points[from],
1397 self.path.attributes(EndpointId(from as u32)),
1398 ),
1399 to: (
1400 self.path.points[to],
1401 self.path.attributes(EndpointId(to as u32)),
1402 ),
1403 }
1404 }
1405 Verb::QuadraticTo => {
1406 let from = self.p - endpoint_stride;
1407 let ctrl = from - 1;
1408 let to = ctrl - endpoint_stride;
1409 Event::Quadratic {
1410 from: (
1411 self.path.points[from],
1412 self.path.attributes(EndpointId(from as u32)),
1413 ),
1414 ctrl: self.path.points[ctrl],
1415 to: (
1416 self.path.points[to],
1417 self.path.attributes(EndpointId(to as u32)),
1418 ),
1419 }
1420 }
1421 Verb::CubicTo => {
1422 let from = self.p - endpoint_stride;
1423 let ctrl1 = from - 1;
1424 let ctrl2 = ctrl1 - 1;
1425 let to = ctrl2 - endpoint_stride;
1426 Event::Cubic {
1427 from: (
1428 self.path.points[from],
1429 self.path.attributes(EndpointId(from as u32)),
1430 ),
1431 ctrl1: self.path.points[ctrl1],
1432 ctrl2: self.path.points[ctrl2],
1433 to: (
1434 self.path.points[to],
1435 self.path.attributes(EndpointId(to as u32)),
1436 ),
1437 }
1438 }
1439 };
1440
1441 self.p -= n_stored_points(*v, self.attrib_stride);
1442
1443 Some(event)
1444 }
1445}
1446
1447fn n_stored_points(verb: Verb, attrib_stride: usize) -> usize {
1448 match verb {
1449 Verb::Begin => attrib_stride + 1,
1450 Verb::LineTo => attrib_stride + 1,
1451 Verb::QuadraticTo => attrib_stride + 2,
1452 Verb::CubicTo => attrib_stride + 3,
1453 Verb::Close => attrib_stride + 1,
1454 Verb::End => 0,
1455 }
1456}
1457
1458#[cfg(test)]
1459fn slice(a: &[f32]) -> &[f32] {
1460 a
1461}
1462
1463#[test]
1464fn test_reverse_path_simple() {
1465 let mut builder = Path::builder_with_attributes(1);
1466 builder.begin(point(0.0, 0.0), &[1.0]);
1467 builder.line_to(point(1.0, 0.0), &[2.0]);
1468 builder.line_to(point(1.0, 1.0), &[3.0]);
1469 builder.line_to(point(0.0, 1.0), &[4.0]);
1470 builder.end(false);
1471
1472 let p1 = builder.build();
1473 let p2 = p1.reversed().with_attributes().into_path();
1474
1475 let mut it = p2.iter_with_attributes();
1476
1477 // Using a function that explicits the argument types works around type inference issue.
1478 fn check<'l>(
1479 a: Option<Event<(Point, Attributes<'l>), Point>>,
1480 b: Option<Event<(Point, Attributes<'l>), Point>>,
1481 ) -> bool {
1482 if a != b {
1483 std::println!("left: {a:?}");
1484 std::println!("right: {b:?}");
1485 }
1486
1487 a == b
1488 }
1489
1490 assert!(check(
1491 it.next(),
1492 Some(Event::Begin {
1493 at: (point(0.0, 1.0), &[4.0])
1494 })
1495 ));
1496 assert!(check(
1497 it.next(),
1498 Some(Event::Line {
1499 from: (point(0.0, 1.0), &[4.0]),
1500 to: (point(1.0, 1.0), &[3.0]),
1501 })
1502 ));
1503 assert!(check(
1504 it.next(),
1505 Some(Event::Line {
1506 from: (point(1.0, 1.0), &[3.0]),
1507 to: (point(1.0, 0.0), &[2.0]),
1508 })
1509 ));
1510 assert!(check(
1511 it.next(),
1512 Some(Event::Line {
1513 from: (point(1.0, 0.0), &[2.0]),
1514 to: (point(0.0, 0.0), &[1.0]),
1515 })
1516 ));
1517 assert!(check(
1518 it.next(),
1519 Some(Event::End {
1520 last: (point(0.0, 0.0), &[1.0]),
1521 first: (point(0.0, 1.0), &[4.0]),
1522 close: false
1523 })
1524 ));
1525
1526 assert!(check(it.next(), None));
1527}
1528
1529#[test]
1530fn test_reverse_path_1() {
1531 let mut builder = Path::builder_with_attributes(1);
1532 builder.begin(point(0.0, 0.0), &[1.0]);
1533 builder.line_to(point(1.0, 0.0), &[2.0]);
1534 builder.line_to(point(1.0, 1.0), &[3.0]);
1535 builder.line_to(point(0.0, 1.0), &[4.0]);
1536 builder.end(false);
1537
1538 builder.begin(point(10.0, 0.0), &[5.0]);
1539 builder.line_to(point(11.0, 0.0), &[6.0]);
1540 builder.line_to(point(11.0, 1.0), &[7.0]);
1541 builder.line_to(point(10.0, 1.0), &[8.0]);
1542 builder.end(true);
1543
1544 builder.begin(point(20.0, 0.0), &[9.0]);
1545 builder.quadratic_bezier_to(point(21.0, 0.0), point(21.0, 1.0), &[10.0]);
1546 builder.end(false);
1547
1548 builder.begin(point(20.0, 0.0), &[9.0]);
1549 builder.quadratic_bezier_to(point(21.0, 0.0), point(21.0, 1.0), &[10.0]);
1550 builder.end(true);
1551
1552 let p1 = builder.build();
1553
1554 let mut it = p1.reversed().with_attributes();
1555
1556 // Using a function that explicits the argument types works around type inference issue.
1557 fn check<'l>(
1558 a: Option<Event<(Point, Attributes<'l>), Point>>,
1559 b: Option<Event<(Point, Attributes<'l>), Point>>,
1560 ) -> bool {
1561 if a != b {
1562 std::println!("left: {a:?}");
1563 std::println!("right: {b:?}");
1564 }
1565
1566 a == b
1567 }
1568
1569 assert!(check(
1570 it.next(),
1571 Some(Event::Begin {
1572 at: (point(21.0, 1.0), &[10.0]),
1573 })
1574 ));
1575 assert!(check(
1576 it.next(),
1577 Some(Event::Quadratic {
1578 from: (point(21.0, 1.0), &[10.0]),
1579 ctrl: point(21.0, 0.0),
1580 to: (point(20.0, 0.0), &[9.0]),
1581 })
1582 ));
1583 assert!(check(
1584 it.next(),
1585 Some(Event::End {
1586 last: (point(20.0, 0.0), &[9.0]),
1587 first: (point(21.0, 1.0), &[10.0]),
1588 close: true
1589 })
1590 ));
1591
1592 assert!(check(
1593 it.next(),
1594 Some(Event::Begin {
1595 at: (point(21.0, 1.0), &[10.0]),
1596 })
1597 ));
1598 assert!(check(
1599 it.next(),
1600 Some(Event::Quadratic {
1601 from: (point(21.0, 1.0), &[10.0]),
1602 ctrl: point(21.0, 0.0),
1603 to: (point(20.0, 0.0), &[9.0]),
1604 })
1605 ));
1606 assert!(check(
1607 it.next(),
1608 Some(Event::End {
1609 last: (point(20.0, 0.0), &[9.0]),
1610 first: (point(21.0, 1.0), &[10.0]),
1611 close: false
1612 })
1613 ));
1614
1615 assert!(check(
1616 it.next(),
1617 Some(Event::Begin {
1618 at: (point(10.0, 1.0), &[8.0]), // <--
1619 })
1620 ));
1621 assert!(check(
1622 it.next(),
1623 Some(Event::Line {
1624 from: (point(10.0, 1.0), &[8.0]),
1625 to: (point(11.0, 1.0), &[7.0]),
1626 })
1627 ));
1628 assert!(check(
1629 it.next(),
1630 Some(Event::Line {
1631 from: (point(11.0, 1.0), &[7.0]),
1632 to: (point(11.0, 0.0), &[6.0]),
1633 })
1634 ));
1635 assert!(check(
1636 it.next(),
1637 Some(Event::Line {
1638 from: (point(11.0, 0.0), &[6.0]),
1639 to: (point(10.0, 0.0), &[5.0]),
1640 })
1641 ));
1642 assert!(check(
1643 it.next(),
1644 Some(Event::End {
1645 last: (point(10.0, 0.0), &[5.0]),
1646 first: (point(10.0, 1.0), &[8.0]),
1647 close: true
1648 })
1649 ));
1650
1651 assert!(check(
1652 it.next(),
1653 Some(Event::Begin {
1654 at: (point(0.0, 1.0), &[4.0]),
1655 })
1656 ));
1657 assert!(check(
1658 it.next(),
1659 Some(Event::Line {
1660 from: (point(0.0, 1.0), &[4.0]),
1661 to: (point(1.0, 1.0), &[3.0]),
1662 })
1663 ));
1664 assert!(check(
1665 it.next(),
1666 Some(Event::Line {
1667 from: (point(1.0, 1.0), &[3.0]),
1668 to: (point(1.0, 0.0), &[2.0]),
1669 })
1670 ));
1671 assert!(check(
1672 it.next(),
1673 Some(Event::Line {
1674 from: (point(1.0, 0.0), &[2.0]),
1675 to: (point(0.0, 0.0), &[1.0]),
1676 })
1677 ));
1678 assert!(check(
1679 it.next(),
1680 Some(Event::End {
1681 last: (point(0.0, 0.0), &[1.0]),
1682 first: (point(0.0, 1.0), &[4.0]),
1683 close: false
1684 })
1685 ));
1686
1687 assert!(check(it.next(), None));
1688}
1689
1690#[test]
1691fn test_reverse_path_no_close() {
1692 let mut builder = Path::builder();
1693 builder.begin(point(0.0, 0.0));
1694 builder.line_to(point(1.0, 0.0));
1695 builder.line_to(point(1.0, 1.0));
1696 builder.end(false);
1697
1698 let p1 = builder.build();
1699
1700 let mut it = p1.reversed();
1701
1702 assert_eq!(
1703 it.next(),
1704 Some(PathEvent::Begin {
1705 at: point(1.0, 1.0)
1706 })
1707 );
1708 assert_eq!(
1709 it.next(),
1710 Some(PathEvent::Line {
1711 from: point(1.0, 1.0),
1712 to: point(1.0, 0.0)
1713 })
1714 );
1715 assert_eq!(
1716 it.next(),
1717 Some(PathEvent::Line {
1718 from: point(1.0, 0.0),
1719 to: point(0.0, 0.0)
1720 })
1721 );
1722 assert_eq!(
1723 it.next(),
1724 Some(PathEvent::End {
1725 last: point(0.0, 0.0),
1726 first: point(1.0, 1.0),
1727 close: false
1728 })
1729 );
1730 assert_eq!(it.next(), None);
1731}
1732
1733#[test]
1734fn test_reverse_empty_path() {
1735 let p: Path = Path::builder().build();
1736 assert_eq!(p.reversed().next(), None);
1737}
1738
1739#[test]
1740fn test_reverse_single_point() {
1741 let mut builder: NoAttributes = Path::builder();
1742 builder.begin(at:point(x:0.0, y:0.0));
1743 builder.end(close:false);
1744
1745 let p1: Path = builder.build();
1746 let mut it: NoAttributes> = p1.reversed();
1747 assert_eq!(
1748 it.next(),
1749 Some(PathEvent::Begin {
1750 at: point(0.0, 0.0)
1751 })
1752 );
1753 assert_eq!(
1754 it.next(),
1755 Some(PathEvent::End {
1756 last: point(0.0, 0.0),
1757 first: point(0.0, 0.0),
1758 close: false
1759 })
1760 );
1761 assert_eq!(it.next(), None);
1762}
1763
1764#[test]
1765fn test_path_builder_1() {
1766 let mut p = BuilderWithAttributes::new(1);
1767 p.begin(point(0.0, 0.0), &[0.0]);
1768 p.line_to(point(1.0, 0.0), &[1.0]);
1769 p.line_to(point(2.0, 0.0), &[2.0]);
1770 p.line_to(point(3.0, 0.0), &[3.0]);
1771 p.quadratic_bezier_to(point(4.0, 0.0), point(4.0, 1.0), &[4.0]);
1772 p.cubic_bezier_to(point(5.0, 0.0), point(5.0, 1.0), point(5.0, 2.0), &[5.0]);
1773 p.end(true);
1774
1775 p.begin(point(10.0, 0.0), &[6.0]);
1776 p.line_to(point(11.0, 0.0), &[7.0]);
1777 p.line_to(point(12.0, 0.0), &[8.0]);
1778 p.line_to(point(13.0, 0.0), &[9.0]);
1779 p.quadratic_bezier_to(point(14.0, 0.0), point(14.0, 1.0), &[10.0]);
1780 p.cubic_bezier_to(
1781 point(15.0, 0.0),
1782 point(15.0, 1.0),
1783 point(15.0, 2.0),
1784 &[11.0],
1785 );
1786 p.end(true);
1787
1788 p.begin(point(1.0, 1.0), &[12.0]);
1789 p.end(false);
1790 p.begin(point(2.0, 2.0), &[13.0]);
1791 p.end(false);
1792 p.begin(point(3.0, 3.0), &[14.0]);
1793 p.line_to(point(4.0, 4.0), &[15.0]);
1794 p.end(false);
1795
1796 let path = p.build();
1797
1798 let mut it = path.iter_with_attributes();
1799 assert_eq!(
1800 it.next(),
1801 Some(Event::Begin {
1802 at: (point(0.0, 0.0), slice(&[0.0])),
1803 })
1804 );
1805 assert_eq!(
1806 it.next(),
1807 Some(Event::Line {
1808 from: (point(0.0, 0.0), slice(&[0.0])),
1809 to: (point(1.0, 0.0), slice(&[1.0])),
1810 })
1811 );
1812 assert_eq!(
1813 it.next(),
1814 Some(Event::Line {
1815 from: (point(1.0, 0.0), slice(&[1.0])),
1816 to: (point(2.0, 0.0), slice(&[2.0])),
1817 })
1818 );
1819 assert_eq!(
1820 it.next(),
1821 Some(Event::Line {
1822 from: (point(2.0, 0.0), slice(&[2.0])),
1823 to: (point(3.0, 0.0), slice(&[3.0])),
1824 })
1825 );
1826 assert_eq!(
1827 it.next(),
1828 Some(Event::Quadratic {
1829 from: (point(3.0, 0.0), slice(&[3.0])),
1830 ctrl: point(4.0, 0.0),
1831 to: (point(4.0, 1.0), slice(&[4.0])),
1832 })
1833 );
1834 assert_eq!(
1835 it.next(),
1836 Some(Event::Cubic {
1837 from: (point(4.0, 1.0), slice(&[4.0])),
1838 ctrl1: point(5.0, 0.0),
1839 ctrl2: point(5.0, 1.0),
1840 to: (point(5.0, 2.0), slice(&[5.0])),
1841 })
1842 );
1843 assert_eq!(
1844 it.next(),
1845 Some(Event::End {
1846 last: (point(5.0, 2.0), slice(&[5.0])),
1847 first: (point(0.0, 0.0), slice(&[0.0])),
1848 close: true
1849 })
1850 );
1851
1852 assert_eq!(
1853 it.next(),
1854 Some(Event::Begin {
1855 at: (point(10.0, 0.0), slice(&[6.0])),
1856 })
1857 );
1858 assert_eq!(
1859 it.next(),
1860 Some(Event::Line {
1861 from: (point(10.0, 0.0), slice(&[6.0])),
1862 to: (point(11.0, 0.0), slice(&[7.0])),
1863 })
1864 );
1865 assert_eq!(
1866 it.next(),
1867 Some(Event::Line {
1868 from: (point(11.0, 0.0), slice(&[7.0])),
1869 to: (point(12.0, 0.0), slice(&[8.0])),
1870 })
1871 );
1872 assert_eq!(
1873 it.next(),
1874 Some(Event::Line {
1875 from: (point(12.0, 0.0), slice(&[8.0])),
1876 to: (point(13.0, 0.0), slice(&[9.0])),
1877 })
1878 );
1879 assert_eq!(
1880 it.next(),
1881 Some(Event::Quadratic {
1882 from: (point(13.0, 0.0), slice(&[9.0])),
1883 ctrl: point(14.0, 0.0),
1884 to: (point(14.0, 1.0), slice(&[10.0])),
1885 })
1886 );
1887 assert_eq!(
1888 it.next(),
1889 Some(Event::Cubic {
1890 from: (point(14.0, 1.0), slice(&[10.0])),
1891 ctrl1: point(15.0, 0.0),
1892 ctrl2: point(15.0, 1.0),
1893 to: (point(15.0, 2.0), slice(&[11.0])),
1894 })
1895 );
1896 assert_eq!(
1897 it.next(),
1898 Some(Event::End {
1899 last: (point(15.0, 2.0), slice(&[11.0])),
1900 first: (point(10.0, 0.0), slice(&[6.0])),
1901 close: true
1902 })
1903 );
1904
1905 assert_eq!(
1906 it.next(),
1907 Some(Event::Begin {
1908 at: (point(1.0, 1.0), slice(&[12.0]))
1909 })
1910 );
1911 assert_eq!(
1912 it.next(),
1913 Some(Event::End {
1914 last: (point(1.0, 1.0), slice(&[12.0])),
1915 first: (point(1.0, 1.0), slice(&[12.0])),
1916 close: false
1917 })
1918 );
1919 assert_eq!(
1920 it.next(),
1921 Some(Event::Begin {
1922 at: (point(2.0, 2.0), slice(&[13.0])),
1923 })
1924 );
1925 assert_eq!(
1926 it.next(),
1927 Some(Event::End {
1928 last: (point(2.0, 2.0), slice(&[13.0])),
1929 first: (point(2.0, 2.0), slice(&[13.0])),
1930 close: false
1931 })
1932 );
1933 assert_eq!(
1934 it.next(),
1935 Some(Event::Begin {
1936 at: (point(3.0, 3.0), slice(&[14.0])),
1937 })
1938 );
1939 assert_eq!(
1940 it.next(),
1941 Some(Event::Line {
1942 from: (point(3.0, 3.0), slice(&[14.0])),
1943 to: (point(4.0, 4.0), slice(&[15.0])),
1944 })
1945 );
1946 assert_eq!(
1947 it.next(),
1948 Some(Event::End {
1949 last: (point(4.0, 4.0), slice(&[15.0])),
1950 first: (point(3.0, 3.0), slice(&[14.0])),
1951 close: false
1952 })
1953 );
1954 assert_eq!(it.next(), None);
1955 assert_eq!(it.next(), None);
1956 assert_eq!(it.next(), None);
1957}
1958
1959#[test]
1960fn test_path_builder_empty() {
1961 let path: Path = Path::builder_with_attributes(num_attributes:5).build();
1962 let mut it: Iter<'_> = path.iter();
1963 assert_eq!(it.next(), None);
1964 assert_eq!(it.next(), None);
1965}
1966
1967#[test]
1968fn test_path_builder_empty_begin() {
1969 let mut p = Path::builder_with_attributes(1);
1970 p.begin(point(1.0, 2.0), &[0.0]);
1971 p.end(false);
1972 p.begin(point(3.0, 4.0), &[1.0]);
1973 p.end(false);
1974 p.begin(point(5.0, 6.0), &[2.0]);
1975 p.end(false);
1976
1977 let path = p.build();
1978 let mut it = path.iter();
1979 assert_eq!(
1980 it.next(),
1981 Some(PathEvent::Begin {
1982 at: point(1.0, 2.0)
1983 })
1984 );
1985 assert_eq!(
1986 it.next(),
1987 Some(PathEvent::End {
1988 last: point(1.0, 2.0),
1989 first: point(1.0, 2.0),
1990 close: false,
1991 })
1992 );
1993 assert_eq!(
1994 it.next(),
1995 Some(PathEvent::Begin {
1996 at: point(3.0, 4.0)
1997 })
1998 );
1999 assert_eq!(
2000 it.next(),
2001 Some(PathEvent::End {
2002 last: point(3.0, 4.0),
2003 first: point(3.0, 4.0),
2004 close: false,
2005 })
2006 );
2007 assert_eq!(
2008 it.next(),
2009 Some(PathEvent::Begin {
2010 at: point(5.0, 6.0)
2011 })
2012 );
2013 assert_eq!(
2014 it.next(),
2015 Some(PathEvent::End {
2016 last: point(5.0, 6.0),
2017 first: point(5.0, 6.0),
2018 close: false,
2019 })
2020 );
2021 assert_eq!(it.next(), None);
2022 assert_eq!(it.next(), None);
2023}
2024
2025#[test]
2026fn test_extend_from_paths() {
2027 let mut builder = Path::builder();
2028 builder.begin(point(0.0, 0.0));
2029 builder.line_to(point(5.0, 0.0));
2030 builder.line_to(point(5.0, 5.0));
2031 builder.end(true);
2032
2033 let path1 = builder.build();
2034
2035 let mut builder = Path::builder();
2036 builder.begin(point(1.0, 1.0));
2037 builder.line_to(point(4.0, 0.0));
2038 builder.line_to(point(4.0, 4.0));
2039 builder.end(true);
2040
2041 let path2 = builder.build();
2042
2043 let mut builder = Path::builder();
2044 builder.extend_from_paths(&[path1.as_slice(), path2.as_slice()]);
2045 let path = builder.build();
2046
2047 let mut it = path.iter();
2048 assert_eq!(
2049 it.next(),
2050 Some(PathEvent::Begin {
2051 at: point(0.0, 0.0)
2052 })
2053 );
2054 assert_eq!(
2055 it.next(),
2056 Some(PathEvent::Line {
2057 from: point(0.0, 0.0),
2058 to: point(5.0, 0.0)
2059 })
2060 );
2061 assert_eq!(
2062 it.next(),
2063 Some(PathEvent::Line {
2064 from: point(5.0, 0.0),
2065 to: point(5.0, 5.0)
2066 })
2067 );
2068 assert_eq!(
2069 it.next(),
2070 Some(PathEvent::End {
2071 last: point(5.0, 5.0),
2072 first: point(0.0, 0.0),
2073 close: true
2074 })
2075 );
2076 assert_eq!(
2077 it.next(),
2078 Some(PathEvent::Begin {
2079 at: point(1.0, 1.0)
2080 })
2081 );
2082 assert_eq!(
2083 it.next(),
2084 Some(PathEvent::Line {
2085 from: point(1.0, 1.0),
2086 to: point(4.0, 0.0)
2087 })
2088 );
2089 assert_eq!(
2090 it.next(),
2091 Some(PathEvent::Line {
2092 from: point(4.0, 0.0),
2093 to: point(4.0, 4.0)
2094 })
2095 );
2096 assert_eq!(
2097 it.next(),
2098 Some(PathEvent::End {
2099 last: point(4.0, 4.0),
2100 first: point(1.0, 1.0),
2101 close: true
2102 })
2103 );
2104 assert_eq!(it.next(), None);
2105}
2106
2107#[test]
2108fn flattened_custom_attributes() {
2109 let mut path = Path::builder_with_attributes(1);
2110 path.begin(point(0.0, 0.0), &[0.0]);
2111 path.quadratic_bezier_to(point(1.0, 0.0), point(1.0, 1.0), &[1.0]);
2112 path.cubic_bezier_to(point(1.0, 2.0), point(0.0, 2.0), point(0.0, 1.0), &[2.0]);
2113 path.end(false);
2114
2115 let path = path.build();
2116
2117 let mut prev = -1.0;
2118 path.iter_with_attributes()
2119 .for_each_flattened(0.01, &mut |evt| {
2120 let attribute = match evt {
2121 Event::Begin { at: (_, attr) } => attr[0],
2122 Event::Line {
2123 from: (_, from_attr),
2124 to: (_, to_attr),
2125 } => {
2126 assert_eq!(from_attr[0], prev);
2127 to_attr[0]
2128 }
2129 Event::End {
2130 last: (_, last_attr),
2131 ..
2132 } => {
2133 assert_eq!(last_attr[0], prev);
2134 return;
2135 }
2136 Event::Quadratic { .. } | Event::Cubic { .. } => {
2137 panic!("Should not get a curve in for_each_flattened");
2138 }
2139 };
2140
2141 assert!(attribute > prev);
2142 prev = attribute;
2143 });
2144}
2145
2146#[test]
2147fn first_last() {
2148 let mut path = Path::builder_with_attributes(1);
2149 path.begin(point(0.0, 0.0), &[1.0]);
2150 path.line_to(point(2.0, 2.0), &[3.0]);
2151 path.line_to(point(4.0, 4.0), &[5.0]);
2152 path.end(false);
2153 let path = path.build();
2154
2155 assert_eq!(
2156 path.first_endpoint(),
2157 Some((point(0.0, 0.0), slice(&[1.0])))
2158 );
2159 assert_eq!(path.last_endpoint(), Some((point(4.0, 4.0), slice(&[5.0]))));
2160
2161 let mut path = Path::builder_with_attributes(1);
2162 path.begin(point(0.0, 0.0), &[1.0]);
2163 path.line_to(point(2.0, 2.0), &[3.0]);
2164 path.line_to(point(4.0, 4.0), &[5.0]);
2165 path.end(true);
2166 let path = path.build();
2167
2168 assert_eq!(
2169 path.first_endpoint(),
2170 Some((point(0.0, 0.0), slice(&[1.0])))
2171 );
2172 assert_eq!(path.last_endpoint(), Some((point(0.0, 0.0), slice(&[1.0]))));
2173}
2174
2175#[test]
2176fn id_events() {
2177 let mut path = Path::builder_with_attributes(1);
2178 let e1 = path.begin(point(0.0, 0.0), &[1.0]);
2179 let e2 = path.line_to(point(2.0, 2.0), &[3.0]);
2180 let e3 = path.line_to(point(4.0, 4.0), &[5.0]);
2181 path.end(false);
2182
2183 let e4 = path.begin(point(6.0, 6.0), &[7.0]);
2184 let e5 = path.line_to(point(8.0, 8.0), &[9.0]);
2185 let e6 = path.line_to(point(10.0, 10.0), &[11.0]);
2186 path.end(true);
2187
2188 let e7 = path.begin(point(12.0, 12.0), &[13.0]);
2189 let e8 = path.line_to(point(14.0, 14.0), &[15.0]);
2190 path.end(false);
2191
2192 let path = path.build();
2193
2194 let mut iter = path.id_iter();
2195
2196 assert_eq!(iter.next().unwrap(), Event::Begin { at: e1 });
2197 assert_eq!(iter.next().unwrap(), Event::Line { from: e1, to: e2 });
2198 assert_eq!(iter.next().unwrap(), Event::Line { from: e2, to: e3 });
2199 assert_eq!(
2200 iter.next().unwrap(),
2201 Event::End {
2202 last: e3,
2203 first: e1,
2204 close: false
2205 }
2206 );
2207
2208 assert_eq!(iter.next().unwrap(), Event::Begin { at: e4 });
2209 assert_eq!(iter.next().unwrap(), Event::Line { from: e4, to: e5 });
2210 assert_eq!(iter.next().unwrap(), Event::Line { from: e5, to: e6 });
2211 assert_eq!(
2212 iter.next().unwrap(),
2213 Event::End {
2214 last: e6,
2215 first: e4,
2216 close: true
2217 }
2218 );
2219
2220 assert_eq!(iter.next().unwrap(), Event::Begin { at: e7 });
2221 assert_eq!(iter.next().unwrap(), Event::Line { from: e7, to: e8 });
2222 assert_eq!(
2223 iter.next().unwrap(),
2224 Event::End {
2225 last: e8,
2226 first: e7,
2227 close: false
2228 }
2229 );
2230
2231 assert_eq!(iter.next(), None);
2232}
2233