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};
17use core::u32;
18
19use alloc::boxed::Box;
20use alloc::vec;
21use alloc::vec::Vec;
22
23#[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#[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#[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 pub fn builder() -> Builder {
95 NoAttributes::wrap(BuilderImpl::new())
96 }
97
98 pub fn builder_with_attributes(num_attributes: usize) -> BuilderWithAttributes {
101 BuilderWithAttributes::new(num_attributes)
102 }
103
104 pub fn svg_builder() -> WithSvg<BuilderImpl> {
107 WithSvg::new(BuilderImpl::new())
108 }
109
110 #[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 #[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 #[inline]
141 pub fn attributes(&self, endpoint: EndpointId) -> Attributes {
142 interpolated_attributes(self.num_attributes, &self.points, endpoint)
143 }
144
145 pub fn iter(&self) -> Iter {
147 Iter::new(self.num_attributes, &self.points[..], &self.verbs[..])
148 }
149
150 pub fn id_iter(&self) -> IdIter {
152 IdIter::new(self.num_attributes, &self.verbs[..])
153 }
154
155 pub fn iter_with_attributes(&self) -> IterWithAttributes {
157 IterWithAttributes::new(self.num_attributes(), &self.points[..], &self.verbs[..])
158 }
159
160 pub fn transformed<T: Transformation<f32>>(mut self, transform: &T) -> Self {
163 self.apply_transform(transform);
164
165 self
166 }
167
168 pub fn reversed(&self) -> IterNoAttributes<Reversed> {
170 IterNoAttributes(Reversed::new(self.as_slice()))
171 }
172
173 #[inline]
175 pub fn first_endpoint(&self) -> Option<(Point, Attributes)> {
176 self.as_slice().first_endpoint()
177 }
178
179 #[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
286impl<'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 pub fn iter<'a>(&'a self) -> Iter<'l> {
316 Iter::new(self.num_attributes, self.points, self.verbs)
317 }
318
319 pub fn id_iter(&self) -> IdIter {
321 IdIter::new(self.num_attributes, self.verbs)
322 }
323
324 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 #[inline]
335 pub fn attributes(&self, endpoint: EndpointId) -> Attributes<'l> {
336 interpolated_attributes(self.num_attributes, self.points, endpoint)
337 }
338
339 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#[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#[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#[derive(Clone)]
818pub struct Iter<'l> {
819 points: PointIter<'l>,
820 verbs: ::core::slice::Iter<'l, Verb>,
821 current: Point,
822 first: Point,
823 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#[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 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#[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 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 let mut stack_buffer = [0.0; 16];
1012 let mut vec_buffer;
1013 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 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#[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
1309pub 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 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 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 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 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 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]), })
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}