1use 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#[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#[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#[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 pub fn builder() -> Builder {
94 NoAttributes::wrap(BuilderImpl::new())
95 }
96
97 pub fn builder_with_attributes(num_attributes: usize) -> BuilderWithAttributes {
100 BuilderWithAttributes::new(num_attributes)
101 }
102
103 pub fn svg_builder() -> WithSvg<BuilderImpl> {
106 WithSvg::new(BuilderImpl::new())
107 }
108
109 #[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 #[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 #[inline]
140 pub fn attributes(&self, endpoint: EndpointId) -> Attributes {
141 interpolated_attributes(self.num_attributes, &self.points, endpoint)
142 }
143
144 pub fn iter(&self) -> Iter {
146 Iter::new(self.num_attributes, &self.points[..], &self.verbs[..])
147 }
148
149 pub fn id_iter(&self) -> IdIter {
151 IdIter::new(self.num_attributes, &self.verbs[..])
152 }
153
154 pub fn iter_with_attributes(&self) -> IterWithAttributes {
156 IterWithAttributes::new(self.num_attributes(), &self.points[..], &self.verbs[..])
157 }
158
159 pub fn transformed<T: Transformation<f32>>(mut self, transform: &T) -> Self {
162 self.apply_transform(transform);
163
164 self
165 }
166
167 pub fn reversed(&self) -> IterNoAttributes<Reversed> {
169 IterNoAttributes(Reversed::new(self.as_slice()))
170 }
171
172 #[inline]
174 pub fn first_endpoint(&self) -> Option<(Point, Attributes)> {
175 self.as_slice().first_endpoint()
176 }
177
178 #[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
285impl<'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 pub fn iter<'a>(&'a self) -> Iter<'l> {
315 Iter::new(self.num_attributes, self.points, self.verbs)
316 }
317
318 pub fn id_iter(&self) -> IdIter {
320 IdIter::new(self.num_attributes, self.verbs)
321 }
322
323 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 #[inline]
334 pub fn attributes(&self, endpoint: EndpointId) -> Attributes<'l> {
335 interpolated_attributes(self.num_attributes, self.points, endpoint)
336 }
337
338 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#[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#[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#[derive(Clone)]
817pub struct Iter<'l> {
818 points: PointIter<'l>,
819 verbs: ::core::slice::Iter<'l, Verb>,
820 current: Point,
821 first: Point,
822 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#[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 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#[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 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 let mut stack_buffer = [0.0; 16];
1011 let mut vec_buffer;
1012 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 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#[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
1308pub 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 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 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 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 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 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]), })
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}