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};
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 = Path::builder();
223        for 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, 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, 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, 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(points),
831            verbs: verbs.iter(),
832            current: point(0.0, 0.0),
833            first: point(0.0, 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 = endpoint.0 as usize + 1;
1277    assert!(idx + (num_attributes + 1) / 2 <= points.len());
1278
1279    unsafe {
1280        let ptr = &points[idx].x as *const f32;
1281        core::slice::from_raw_parts(ptr, 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 = 0;
1292    let mut nv = 0;
1293
1294    for path 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(nv);
1301    points.reserve(np);
1302
1303    for path 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 explicitly states 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    fn check<'l>(
1557        a: Option<Event<(Point, Attributes<'l>), Point>>,
1558        b: Option<Event<(Point, Attributes<'l>), Point>>,
1559    ) -> bool {
1560        if a != b {
1561            std::println!("left: {a:?}");
1562            std::println!("right: {b:?}");
1563        }
1564
1565        a == b
1566    }
1567
1568    assert!(check(
1569        it.next(),
1570        Some(Event::Begin {
1571            at: (point(21.0, 1.0), &[10.0]),
1572        })
1573    ));
1574    assert!(check(
1575        it.next(),
1576        Some(Event::Quadratic {
1577            from: (point(21.0, 1.0), &[10.0]),
1578            ctrl: point(21.0, 0.0),
1579            to: (point(20.0, 0.0), &[9.0]),
1580        })
1581    ));
1582    assert!(check(
1583        it.next(),
1584        Some(Event::End {
1585            last: (point(20.0, 0.0), &[9.0]),
1586            first: (point(21.0, 1.0), &[10.0]),
1587            close: true
1588        })
1589    ));
1590
1591    assert!(check(
1592        it.next(),
1593        Some(Event::Begin {
1594            at: (point(21.0, 1.0), &[10.0]),
1595        })
1596    ));
1597    assert!(check(
1598        it.next(),
1599        Some(Event::Quadratic {
1600            from: (point(21.0, 1.0), &[10.0]),
1601            ctrl: point(21.0, 0.0),
1602            to: (point(20.0, 0.0), &[9.0]),
1603        })
1604    ));
1605    assert!(check(
1606        it.next(),
1607        Some(Event::End {
1608            last: (point(20.0, 0.0), &[9.0]),
1609            first: (point(21.0, 1.0), &[10.0]),
1610            close: false
1611        })
1612    ));
1613
1614    assert!(check(
1615        it.next(),
1616        Some(Event::Begin {
1617            at: (point(10.0, 1.0), &[8.0]), // <--
1618        })
1619    ));
1620    assert!(check(
1621        it.next(),
1622        Some(Event::Line {
1623            from: (point(10.0, 1.0), &[8.0]),
1624            to: (point(11.0, 1.0), &[7.0]),
1625        })
1626    ));
1627    assert!(check(
1628        it.next(),
1629        Some(Event::Line {
1630            from: (point(11.0, 1.0), &[7.0]),
1631            to: (point(11.0, 0.0), &[6.0]),
1632        })
1633    ));
1634    assert!(check(
1635        it.next(),
1636        Some(Event::Line {
1637            from: (point(11.0, 0.0), &[6.0]),
1638            to: (point(10.0, 0.0), &[5.0]),
1639        })
1640    ));
1641    assert!(check(
1642        it.next(),
1643        Some(Event::End {
1644            last: (point(10.0, 0.0), &[5.0]),
1645            first: (point(10.0, 1.0), &[8.0]),
1646            close: true
1647        })
1648    ));
1649
1650    assert!(check(
1651        it.next(),
1652        Some(Event::Begin {
1653            at: (point(0.0, 1.0), &[4.0]),
1654        })
1655    ));
1656    assert!(check(
1657        it.next(),
1658        Some(Event::Line {
1659            from: (point(0.0, 1.0), &[4.0]),
1660            to: (point(1.0, 1.0), &[3.0]),
1661        })
1662    ));
1663    assert!(check(
1664        it.next(),
1665        Some(Event::Line {
1666            from: (point(1.0, 1.0), &[3.0]),
1667            to: (point(1.0, 0.0), &[2.0]),
1668        })
1669    ));
1670    assert!(check(
1671        it.next(),
1672        Some(Event::Line {
1673            from: (point(1.0, 0.0), &[2.0]),
1674            to: (point(0.0, 0.0), &[1.0]),
1675        })
1676    ));
1677    assert!(check(
1678        it.next(),
1679        Some(Event::End {
1680            last: (point(0.0, 0.0), &[1.0]),
1681            first: (point(0.0, 1.0), &[4.0]),
1682            close: false
1683        })
1684    ));
1685
1686    assert!(check(it.next(), None));
1687}
1688
1689#[test]
1690fn test_reverse_path_no_close() {
1691    let mut builder = Path::builder();
1692    builder.begin(point(0.0, 0.0));
1693    builder.line_to(point(1.0, 0.0));
1694    builder.line_to(point(1.0, 1.0));
1695    builder.end(false);
1696
1697    let p1 = builder.build();
1698
1699    let mut it = p1.reversed();
1700
1701    assert_eq!(
1702        it.next(),
1703        Some(PathEvent::Begin {
1704            at: point(1.0, 1.0)
1705        })
1706    );
1707    assert_eq!(
1708        it.next(),
1709        Some(PathEvent::Line {
1710            from: point(1.0, 1.0),
1711            to: point(1.0, 0.0)
1712        })
1713    );
1714    assert_eq!(
1715        it.next(),
1716        Some(PathEvent::Line {
1717            from: point(1.0, 0.0),
1718            to: point(0.0, 0.0)
1719        })
1720    );
1721    assert_eq!(
1722        it.next(),
1723        Some(PathEvent::End {
1724            last: point(0.0, 0.0),
1725            first: point(1.0, 1.0),
1726            close: false
1727        })
1728    );
1729    assert_eq!(it.next(), None);
1730}
1731
1732#[test]
1733fn test_reverse_empty_path() {
1734    let p = Path::builder().build();
1735    assert_eq!(p.reversed().next(), None);
1736}
1737
1738#[test]
1739fn test_reverse_single_point() {
1740    let mut builder = Path::builder();
1741    builder.begin(point(0.0, 0.0));
1742    builder.end(false);
1743
1744    let p1 = builder.build();
1745    let mut it = p1.reversed();
1746    assert_eq!(
1747        it.next(),
1748        Some(PathEvent::Begin {
1749            at: point(0.0, 0.0)
1750        })
1751    );
1752    assert_eq!(
1753        it.next(),
1754        Some(PathEvent::End {
1755            last: point(0.0, 0.0),
1756            first: point(0.0, 0.0),
1757            close: false
1758        })
1759    );
1760    assert_eq!(it.next(), None);
1761}
1762
1763#[test]
1764fn test_path_builder_1() {
1765    let mut p = BuilderWithAttributes::new(1);
1766    p.begin(point(0.0, 0.0), &[0.0]);
1767    p.line_to(point(1.0, 0.0), &[1.0]);
1768    p.line_to(point(2.0, 0.0), &[2.0]);
1769    p.line_to(point(3.0, 0.0), &[3.0]);
1770    p.quadratic_bezier_to(point(4.0, 0.0), point(4.0, 1.0), &[4.0]);
1771    p.cubic_bezier_to(point(5.0, 0.0), point(5.0, 1.0), point(5.0, 2.0), &[5.0]);
1772    p.end(true);
1773
1774    p.begin(point(10.0, 0.0), &[6.0]);
1775    p.line_to(point(11.0, 0.0), &[7.0]);
1776    p.line_to(point(12.0, 0.0), &[8.0]);
1777    p.line_to(point(13.0, 0.0), &[9.0]);
1778    p.quadratic_bezier_to(point(14.0, 0.0), point(14.0, 1.0), &[10.0]);
1779    p.cubic_bezier_to(
1780        point(15.0, 0.0),
1781        point(15.0, 1.0),
1782        point(15.0, 2.0),
1783        &[11.0],
1784    );
1785    p.end(true);
1786
1787    p.begin(point(1.0, 1.0), &[12.0]);
1788    p.end(false);
1789    p.begin(point(2.0, 2.0), &[13.0]);
1790    p.end(false);
1791    p.begin(point(3.0, 3.0), &[14.0]);
1792    p.line_to(point(4.0, 4.0), &[15.0]);
1793    p.end(false);
1794
1795    let path = p.build();
1796
1797    let mut it = path.iter_with_attributes();
1798    assert_eq!(
1799        it.next(),
1800        Some(Event::Begin {
1801            at: (point(0.0, 0.0), slice(&[0.0])),
1802        })
1803    );
1804    assert_eq!(
1805        it.next(),
1806        Some(Event::Line {
1807            from: (point(0.0, 0.0), slice(&[0.0])),
1808            to: (point(1.0, 0.0), slice(&[1.0])),
1809        })
1810    );
1811    assert_eq!(
1812        it.next(),
1813        Some(Event::Line {
1814            from: (point(1.0, 0.0), slice(&[1.0])),
1815            to: (point(2.0, 0.0), slice(&[2.0])),
1816        })
1817    );
1818    assert_eq!(
1819        it.next(),
1820        Some(Event::Line {
1821            from: (point(2.0, 0.0), slice(&[2.0])),
1822            to: (point(3.0, 0.0), slice(&[3.0])),
1823        })
1824    );
1825    assert_eq!(
1826        it.next(),
1827        Some(Event::Quadratic {
1828            from: (point(3.0, 0.0), slice(&[3.0])),
1829            ctrl: point(4.0, 0.0),
1830            to: (point(4.0, 1.0), slice(&[4.0])),
1831        })
1832    );
1833    assert_eq!(
1834        it.next(),
1835        Some(Event::Cubic {
1836            from: (point(4.0, 1.0), slice(&[4.0])),
1837            ctrl1: point(5.0, 0.0),
1838            ctrl2: point(5.0, 1.0),
1839            to: (point(5.0, 2.0), slice(&[5.0])),
1840        })
1841    );
1842    assert_eq!(
1843        it.next(),
1844        Some(Event::End {
1845            last: (point(5.0, 2.0), slice(&[5.0])),
1846            first: (point(0.0, 0.0), slice(&[0.0])),
1847            close: true
1848        })
1849    );
1850
1851    assert_eq!(
1852        it.next(),
1853        Some(Event::Begin {
1854            at: (point(10.0, 0.0), slice(&[6.0])),
1855        })
1856    );
1857    assert_eq!(
1858        it.next(),
1859        Some(Event::Line {
1860            from: (point(10.0, 0.0), slice(&[6.0])),
1861            to: (point(11.0, 0.0), slice(&[7.0])),
1862        })
1863    );
1864    assert_eq!(
1865        it.next(),
1866        Some(Event::Line {
1867            from: (point(11.0, 0.0), slice(&[7.0])),
1868            to: (point(12.0, 0.0), slice(&[8.0])),
1869        })
1870    );
1871    assert_eq!(
1872        it.next(),
1873        Some(Event::Line {
1874            from: (point(12.0, 0.0), slice(&[8.0])),
1875            to: (point(13.0, 0.0), slice(&[9.0])),
1876        })
1877    );
1878    assert_eq!(
1879        it.next(),
1880        Some(Event::Quadratic {
1881            from: (point(13.0, 0.0), slice(&[9.0])),
1882            ctrl: point(14.0, 0.0),
1883            to: (point(14.0, 1.0), slice(&[10.0])),
1884        })
1885    );
1886    assert_eq!(
1887        it.next(),
1888        Some(Event::Cubic {
1889            from: (point(14.0, 1.0), slice(&[10.0])),
1890            ctrl1: point(15.0, 0.0),
1891            ctrl2: point(15.0, 1.0),
1892            to: (point(15.0, 2.0), slice(&[11.0])),
1893        })
1894    );
1895    assert_eq!(
1896        it.next(),
1897        Some(Event::End {
1898            last: (point(15.0, 2.0), slice(&[11.0])),
1899            first: (point(10.0, 0.0), slice(&[6.0])),
1900            close: true
1901        })
1902    );
1903
1904    assert_eq!(
1905        it.next(),
1906        Some(Event::Begin {
1907            at: (point(1.0, 1.0), slice(&[12.0]))
1908        })
1909    );
1910    assert_eq!(
1911        it.next(),
1912        Some(Event::End {
1913            last: (point(1.0, 1.0), slice(&[12.0])),
1914            first: (point(1.0, 1.0), slice(&[12.0])),
1915            close: false
1916        })
1917    );
1918    assert_eq!(
1919        it.next(),
1920        Some(Event::Begin {
1921            at: (point(2.0, 2.0), slice(&[13.0])),
1922        })
1923    );
1924    assert_eq!(
1925        it.next(),
1926        Some(Event::End {
1927            last: (point(2.0, 2.0), slice(&[13.0])),
1928            first: (point(2.0, 2.0), slice(&[13.0])),
1929            close: false
1930        })
1931    );
1932    assert_eq!(
1933        it.next(),
1934        Some(Event::Begin {
1935            at: (point(3.0, 3.0), slice(&[14.0])),
1936        })
1937    );
1938    assert_eq!(
1939        it.next(),
1940        Some(Event::Line {
1941            from: (point(3.0, 3.0), slice(&[14.0])),
1942            to: (point(4.0, 4.0), slice(&[15.0])),
1943        })
1944    );
1945    assert_eq!(
1946        it.next(),
1947        Some(Event::End {
1948            last: (point(4.0, 4.0), slice(&[15.0])),
1949            first: (point(3.0, 3.0), slice(&[14.0])),
1950            close: false
1951        })
1952    );
1953    assert_eq!(it.next(), None);
1954    assert_eq!(it.next(), None);
1955    assert_eq!(it.next(), None);
1956}
1957
1958#[test]
1959fn test_path_builder_empty() {
1960    let path = Path::builder_with_attributes(5).build();
1961    let mut it = path.iter();
1962    assert_eq!(it.next(), None);
1963    assert_eq!(it.next(), None);
1964}
1965
1966#[test]
1967fn test_path_builder_empty_begin() {
1968    let mut p = Path::builder_with_attributes(1);
1969    p.begin(point(1.0, 2.0), &[0.0]);
1970    p.end(false);
1971    p.begin(point(3.0, 4.0), &[1.0]);
1972    p.end(false);
1973    p.begin(point(5.0, 6.0), &[2.0]);
1974    p.end(false);
1975
1976    let path = p.build();
1977    let mut it = path.iter();
1978    assert_eq!(
1979        it.next(),
1980        Some(PathEvent::Begin {
1981            at: point(1.0, 2.0)
1982        })
1983    );
1984    assert_eq!(
1985        it.next(),
1986        Some(PathEvent::End {
1987            last: point(1.0, 2.0),
1988            first: point(1.0, 2.0),
1989            close: false,
1990        })
1991    );
1992    assert_eq!(
1993        it.next(),
1994        Some(PathEvent::Begin {
1995            at: point(3.0, 4.0)
1996        })
1997    );
1998    assert_eq!(
1999        it.next(),
2000        Some(PathEvent::End {
2001            last: point(3.0, 4.0),
2002            first: point(3.0, 4.0),
2003            close: false,
2004        })
2005    );
2006    assert_eq!(
2007        it.next(),
2008        Some(PathEvent::Begin {
2009            at: point(5.0, 6.0)
2010        })
2011    );
2012    assert_eq!(
2013        it.next(),
2014        Some(PathEvent::End {
2015            last: point(5.0, 6.0),
2016            first: point(5.0, 6.0),
2017            close: false,
2018        })
2019    );
2020    assert_eq!(it.next(), None);
2021    assert_eq!(it.next(), None);
2022}
2023
2024#[test]
2025fn test_extend_from_paths() {
2026    let mut builder = Path::builder();
2027    builder.begin(point(0.0, 0.0));
2028    builder.line_to(point(5.0, 0.0));
2029    builder.line_to(point(5.0, 5.0));
2030    builder.end(true);
2031
2032    let path1 = builder.build();
2033
2034    let mut builder = Path::builder();
2035    builder.begin(point(1.0, 1.0));
2036    builder.line_to(point(4.0, 0.0));
2037    builder.line_to(point(4.0, 4.0));
2038    builder.end(true);
2039
2040    let path2 = builder.build();
2041
2042    let mut builder = Path::builder();
2043    builder.extend_from_paths(&[path1.as_slice(), path2.as_slice()]);
2044    let path = builder.build();
2045
2046    let mut it = path.iter();
2047    assert_eq!(
2048        it.next(),
2049        Some(PathEvent::Begin {
2050            at: point(0.0, 0.0)
2051        })
2052    );
2053    assert_eq!(
2054        it.next(),
2055        Some(PathEvent::Line {
2056            from: point(0.0, 0.0),
2057            to: point(5.0, 0.0)
2058        })
2059    );
2060    assert_eq!(
2061        it.next(),
2062        Some(PathEvent::Line {
2063            from: point(5.0, 0.0),
2064            to: point(5.0, 5.0)
2065        })
2066    );
2067    assert_eq!(
2068        it.next(),
2069        Some(PathEvent::End {
2070            last: point(5.0, 5.0),
2071            first: point(0.0, 0.0),
2072            close: true
2073        })
2074    );
2075    assert_eq!(
2076        it.next(),
2077        Some(PathEvent::Begin {
2078            at: point(1.0, 1.0)
2079        })
2080    );
2081    assert_eq!(
2082        it.next(),
2083        Some(PathEvent::Line {
2084            from: point(1.0, 1.0),
2085            to: point(4.0, 0.0)
2086        })
2087    );
2088    assert_eq!(
2089        it.next(),
2090        Some(PathEvent::Line {
2091            from: point(4.0, 0.0),
2092            to: point(4.0, 4.0)
2093        })
2094    );
2095    assert_eq!(
2096        it.next(),
2097        Some(PathEvent::End {
2098            last: point(4.0, 4.0),
2099            first: point(1.0, 1.0),
2100            close: true
2101        })
2102    );
2103    assert_eq!(it.next(), None);
2104}
2105
2106#[test]
2107fn flattened_custom_attributes() {
2108    let mut path = Path::builder_with_attributes(1);
2109    path.begin(point(0.0, 0.0), &[0.0]);
2110    path.quadratic_bezier_to(point(1.0, 0.0), point(1.0, 1.0), &[1.0]);
2111    path.cubic_bezier_to(point(1.0, 2.0), point(0.0, 2.0), point(0.0, 1.0), &[2.0]);
2112    path.end(false);
2113
2114    let path = path.build();
2115
2116    let mut prev = -1.0;
2117    path.iter_with_attributes()
2118        .for_each_flattened(0.01, &mut |evt| {
2119            let attribute = match evt {
2120                Event::Begin { at: (_, attr) } => attr[0],
2121                Event::Line {
2122                    from: (_, from_attr),
2123                    to: (_, to_attr),
2124                } => {
2125                    assert_eq!(from_attr[0], prev);
2126                    to_attr[0]
2127                }
2128                Event::End {
2129                    last: (_, last_attr),
2130                    ..
2131                } => {
2132                    assert_eq!(last_attr[0], prev);
2133                    return;
2134                }
2135                Event::Quadratic { .. } | Event::Cubic { .. } => {
2136                    panic!("Should not get a curve in for_each_flattened");
2137                }
2138            };
2139
2140            assert!(attribute > prev);
2141            prev = attribute;
2142        });
2143}
2144
2145#[test]
2146fn first_last() {
2147    let mut path = Path::builder_with_attributes(1);
2148    path.begin(point(0.0, 0.0), &[1.0]);
2149    path.line_to(point(2.0, 2.0), &[3.0]);
2150    path.line_to(point(4.0, 4.0), &[5.0]);
2151    path.end(false);
2152    let path = path.build();
2153
2154    assert_eq!(
2155        path.first_endpoint(),
2156        Some((point(0.0, 0.0), slice(&[1.0])))
2157    );
2158    assert_eq!(path.last_endpoint(), Some((point(4.0, 4.0), slice(&[5.0]))));
2159
2160    let mut path = Path::builder_with_attributes(1);
2161    path.begin(point(0.0, 0.0), &[1.0]);
2162    path.line_to(point(2.0, 2.0), &[3.0]);
2163    path.line_to(point(4.0, 4.0), &[5.0]);
2164    path.end(true);
2165    let path = path.build();
2166
2167    assert_eq!(
2168        path.first_endpoint(),
2169        Some((point(0.0, 0.0), slice(&[1.0])))
2170    );
2171    assert_eq!(path.last_endpoint(), Some((point(0.0, 0.0), slice(&[1.0]))));
2172}
2173
2174#[test]
2175fn id_events() {
2176    let mut path = Path::builder_with_attributes(1);
2177    let e1 = path.begin(point(0.0, 0.0), &[1.0]);
2178    let e2 = path.line_to(point(2.0, 2.0), &[3.0]);
2179    let e3 = path.line_to(point(4.0, 4.0), &[5.0]);
2180    path.end(false);
2181
2182    let e4 = path.begin(point(6.0, 6.0), &[7.0]);
2183    let e5 = path.line_to(point(8.0, 8.0), &[9.0]);
2184    let e6 = path.line_to(point(10.0, 10.0), &[11.0]);
2185    path.end(true);
2186
2187    let e7 = path.begin(point(12.0, 12.0), &[13.0]);
2188    let e8 = path.line_to(point(14.0, 14.0), &[15.0]);
2189    path.end(false);
2190
2191    let path = path.build();
2192
2193    let mut iter = path.id_iter();
2194
2195    assert_eq!(iter.next().unwrap(), Event::Begin { at: e1 });
2196    assert_eq!(iter.next().unwrap(), Event::Line { from: e1, to: e2 });
2197    assert_eq!(iter.next().unwrap(), Event::Line { from: e2, to: e3 });
2198    assert_eq!(
2199        iter.next().unwrap(),
2200        Event::End {
2201            last: e3,
2202            first: e1,
2203            close: false
2204        }
2205    );
2206
2207    assert_eq!(iter.next().unwrap(), Event::Begin { at: e4 });
2208    assert_eq!(iter.next().unwrap(), Event::Line { from: e4, to: e5 });
2209    assert_eq!(iter.next().unwrap(), Event::Line { from: e5, to: e6 });
2210    assert_eq!(
2211        iter.next().unwrap(),
2212        Event::End {
2213            last: e6,
2214            first: e4,
2215            close: true
2216        }
2217    );
2218
2219    assert_eq!(iter.next().unwrap(), Event::Begin { at: e7 });
2220    assert_eq!(iter.next().unwrap(), Event::Line { from: e7, to: e8 });
2221    assert_eq!(
2222        iter.next().unwrap(),
2223        Event::End {
2224            last: e8,
2225            first: e7,
2226            close: false
2227        }
2228    );
2229
2230    assert_eq!(iter.next(), None);
2231}