lyon_path/
path.rs

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