1use crate::event_queue::*;
2use crate::geom::LineSegment;
3use crate::math::*;
4use crate::monotone::*;
5use crate::path::polygon::Polygon;
6use crate::path::traits::{Build, PathBuilder};
7use crate::path::{
8 builder::NoAttributes, AttributeStore, Attributes, EndpointId, FillRule, IdEvent, PathEvent,
9 PathSlice, PositionStore, Winding, NO_ATTRIBUTES,
10};
11use crate::{FillGeometryBuilder, Orientation, VertexId};
12use crate::{
13 FillOptions, InternalError, SimpleAttributeStore, TessellationError, TessellationResult,
14 UnsupportedParamater, VertexSource,
15};
16use float_next_after::NextAfter;
17use core::cmp::Ordering;
18use core::f32::consts::FRAC_1_SQRT_2;
19use core::mem;
20use core::ops::Range;
21use alloc::boxed::Box;
22use alloc::vec::Vec;
23
24#[cfg(not(feature = "std"))]
25use num_traits::Float;
26
27#[derive(Copy, Clone, Debug, PartialEq, Eq)]
28pub(crate) enum Side {
29 Left,
30 Right,
31}
32
33impl Side {
34 pub fn opposite(self) -> Self {
35 match self {
36 Side::Left => Side::Right,
37 Side::Right => Side::Left,
38 }
39 }
40
41 pub fn is_left(self) -> bool {
42 self == Side::Left
43 }
44
45 pub fn is_right(self) -> bool {
46 self == Side::Right
47 }
48}
49
50type SpanIdx = i32;
51type ActiveEdgeIdx = usize;
52
53#[inline(always)]
56fn fmax(a: f32, b: f32) -> f32 {
57 if a > b {
58 a
59 } else {
60 b
61 }
62}
63
64fn slope(v: Vector) -> f32 {
65 v.x / (v.y.max(f32::MIN))
66}
67
68#[cfg(all(debug_assertions, feature = "std"))]
69macro_rules! tess_log {
70 ($obj:ident, $fmt:expr) => (
71 if $obj.log {
72 std::println!($fmt);
73 }
74 );
75 ($obj:ident, $fmt:expr, $($arg:tt)*) => (
76 if $obj.log {
77 std::println!($fmt, $($arg)*);
78 }
79 );
80}
81
82#[cfg(not(all(debug_assertions, feature = "std")))]
83macro_rules! tess_log {
84 ($obj:ident, $fmt:expr) => {};
85 ($obj:ident, $fmt:expr, $($arg:tt)*) => {};
86}
87
88#[derive(Copy, Clone, Debug)]
89struct WindingState {
90 span_index: SpanIdx,
91 number: i16,
92 is_in: bool,
93}
94
95impl WindingState {
96 fn new() -> Self {
97 WindingState {
100 span_index: -1,
101 number: 0,
102 is_in: false,
103 }
104 }
105
106 fn update(&mut self, fill_rule: FillRule, edge_winding: i16) {
107 self.number += edge_winding;
108 self.is_in = fill_rule.is_in(self.number);
109 if self.is_in {
110 self.span_index += 1;
111 }
112 }
113}
114
115struct ActiveEdgeScan {
116 vertex_events: Vec<(SpanIdx, Side)>,
117 edges_to_split: Vec<ActiveEdgeIdx>,
118 spans_to_end: Vec<SpanIdx>,
119 merge_event: bool,
120 split_event: bool,
121 merge_split_event: bool,
122 above: Range<ActiveEdgeIdx>,
123 winding_before_point: WindingState,
124}
125
126impl ActiveEdgeScan {
127 fn new() -> Self {
128 ActiveEdgeScan {
129 vertex_events: Vec::new(),
130 edges_to_split: Vec::new(),
131 spans_to_end: Vec::new(),
132 merge_event: false,
133 split_event: false,
134 merge_split_event: false,
135 above: 0..0,
136 winding_before_point: WindingState::new(),
137 }
138 }
139
140 fn reset(&mut self) {
141 self.vertex_events.clear();
142 self.edges_to_split.clear();
143 self.spans_to_end.clear();
144 self.merge_event = false;
145 self.split_event = false;
146 self.merge_split_event = false;
147 self.above = 0..0;
148 self.winding_before_point = WindingState::new();
149 }
150}
151
152#[derive(Copy, Clone, Debug)]
153struct ActiveEdge {
154 from: Point,
155 to: Point,
156
157 winding: i16,
158 is_merge: bool,
159
160 from_id: VertexId,
161 src_edge: TessEventId,
162
163 range_end: f32,
164}
165
166#[test]
167fn active_edge_size() {
168 assert_eq!(std::mem::size_of::<ActiveEdge>(), 32);
170}
171
172impl ActiveEdge {
173 #[inline(always)]
174 fn min_x(&self) -> f32 {
175 self.from.x.min(self.to.x)
176 }
177
178 #[inline(always)]
179 fn max_x(&self) -> f32 {
180 fmax(self.from.x, self.to.x)
181 }
182}
183
184impl ActiveEdge {
185 fn solve_x_for_y(&self, y: f32) -> f32 {
186 LineSegment {
191 from: self.from,
192 to: self.to,
193 }
194 .solve_x_for_y(y)
195 .max(self.min_x())
196 .min(self.max_x())
197 }
198}
199
200struct ActiveEdges {
201 edges: Vec<ActiveEdge>,
202}
203
204struct Span {
205 tess: Option<Box<MonotoneTessellator>>,
208}
209
210impl Span {
211 fn tess(&mut self) -> &mut MonotoneTessellator {
212 match self.tess.as_mut() {
214 None => {
215 debug_assert!(false);
216 unreachable!();
217 }
218 Some(tess) => tess,
219 }
220 }
221}
222
223struct Spans {
224 spans: Vec<Span>,
225
226 #[allow(clippy::vec_box)]
229 pool: Vec<Box<MonotoneTessellator>>,
230}
231
232impl Spans {
233 fn begin_span(&mut self, span_idx: SpanIdx, position: &Point, vertex: VertexId) {
234 let mut tess = self
235 .pool
236 .pop()
237 .unwrap_or_else(|| Box::new(MonotoneTessellator::new()));
238 tess.begin(*position, vertex);
239
240 self.spans
241 .insert(span_idx as usize, Span { tess: Some(tess) });
242 }
243
244 fn end_span(
245 &mut self,
246 span_idx: SpanIdx,
247 position: &Point,
248 id: VertexId,
249 output: &mut dyn FillGeometryBuilder,
250 ) {
251 let idx = span_idx as usize;
252
253 let span = &mut self.spans[idx];
254 if let Some(mut tess) = span.tess.take() {
255 tess.end(*position, id);
256 tess.flush(output);
257 self.pool.push(tess);
259 } else {
260 debug_assert!(false);
261 unreachable!();
262 }
263 }
264
265 fn merge_spans(
266 &mut self,
267 left_span_idx: SpanIdx,
268 current_position: &Point,
269 current_vertex: VertexId,
270 merge_position: &Point,
271 merge_vertex: VertexId,
272 output: &mut dyn FillGeometryBuilder,
273 ) {
274 let right_span_idx = left_span_idx + 1;
280
281 self.spans[left_span_idx as usize].tess().vertex(
282 *merge_position,
283 merge_vertex,
284 Side::Right,
285 );
286
287 self.spans[right_span_idx as usize].tess().vertex(
288 *merge_position,
289 merge_vertex,
290 Side::Left,
291 );
292
293 self.end_span(left_span_idx, current_position, current_vertex, output);
294 }
295
296 fn cleanup_spans(&mut self) {
297 self.spans.retain(|span| span.tess.is_some());
299 }
300}
301
302#[derive(Copy, Clone, Debug)]
303struct PendingEdge {
304 to: Point,
305 sort_key: f32,
306 src_edge: TessEventId,
308 winding: i16,
309 range_end: f32,
310}
311
312pub struct FillTessellator {
524 current_position: Point,
525 current_vertex: VertexId,
526 current_event_id: TessEventId,
527 active: ActiveEdges,
528 edges_below: Vec<PendingEdge>,
529 fill_rule: FillRule,
530 orientation: Orientation,
531 tolerance: f32,
532 fill: Spans,
533 log: bool,
534 assume_no_intersection: bool,
535 attrib_buffer: Vec<f32>,
536
537 scan: ActiveEdgeScan,
538 events: EventQueue,
539}
540
541impl Default for FillTessellator {
542 fn default() -> Self {
543 Self::new()
544 }
545}
546
547impl FillTessellator {
548 pub fn new() -> Self {
550 #[cfg(all(debug_assertions, feature = "std"))]
551 let log = std::env::var("LYON_FORCE_LOGGING").is_ok();
552 #[cfg(not(all(debug_assertions, feature = "std")))]
553 let log = false;
554
555 FillTessellator {
556 current_position: point(f32::MIN, f32::MIN),
557 current_vertex: VertexId::INVALID,
558 current_event_id: INVALID_EVENT_ID,
559 active: ActiveEdges { edges: Vec::new() },
560 edges_below: Vec::new(),
561 fill_rule: FillRule::EvenOdd,
562 orientation: Orientation::Vertical,
563 tolerance: FillOptions::DEFAULT_TOLERANCE,
564 fill: Spans {
565 spans: Vec::new(),
566 pool: Vec::new(),
567 },
568 log,
569 assume_no_intersection: false,
570 attrib_buffer: Vec::new(),
571
572 scan: ActiveEdgeScan::new(),
573 events: EventQueue::new(),
574 }
575 }
576
577 pub fn tessellate(
579 &mut self,
580 path: impl IntoIterator<Item = PathEvent>,
581 options: &FillOptions,
582 output: &mut dyn FillGeometryBuilder,
583 ) -> TessellationResult {
584 let event_queue = core::mem::replace(&mut self.events, EventQueue::new());
585 let mut queue_builder = event_queue.into_builder(options.tolerance);
586
587 queue_builder.set_path(
588 options.tolerance,
589 options.sweep_orientation,
590 path.into_iter(),
591 );
592
593 self.events = queue_builder.build();
594
595 self.tessellate_impl(options, None, output)
596 }
597
598 pub fn tessellate_with_ids(
602 &mut self,
603 path: impl IntoIterator<Item = IdEvent>,
604 positions: &impl PositionStore,
605 custom_attributes: Option<&dyn AttributeStore>,
606 options: &FillOptions,
607 output: &mut dyn FillGeometryBuilder,
608 ) -> TessellationResult {
609 let event_queue = core::mem::replace(&mut self.events, EventQueue::new());
610 let mut queue_builder = event_queue.into_builder(options.tolerance);
611
612 queue_builder.set_path_with_ids(
613 options.tolerance,
614 options.sweep_orientation,
615 path.into_iter(),
616 positions,
617 );
618
619 self.events = queue_builder.build();
620
621 self.tessellate_impl(options, custom_attributes, output)
622 }
623
624 pub fn tessellate_path<'l>(
629 &'l mut self,
630 path: impl Into<PathSlice<'l>>,
631 options: &'l FillOptions,
632 builder: &'l mut dyn FillGeometryBuilder,
633 ) -> TessellationResult {
634 let path = path.into();
635
636 if path.num_attributes() > 0 {
637 self.tessellate_with_ids(path.id_iter(), &path, Some(&path), options, builder)
638 } else {
639 self.tessellate(path.iter(), options, builder)
640 }
641 }
642
643 pub fn tessellate_polygon(
645 &mut self,
646 polygon: Polygon<Point>,
647 options: &FillOptions,
648 output: &mut dyn FillGeometryBuilder,
649 ) -> TessellationResult {
650 self.tessellate(polygon.path_events(), options, output)
651 }
652
653 pub fn tessellate_rectangle(
655 &mut self,
656 rect: &Box2D,
657 _options: &FillOptions,
658 output: &mut dyn FillGeometryBuilder,
659 ) -> TessellationResult {
660 crate::basic_shapes::fill_rectangle(rect, output)
661 }
662
663 pub fn tessellate_circle(
665 &mut self,
666 center: Point,
667 radius: f32,
668 options: &FillOptions,
669 output: &mut dyn FillGeometryBuilder,
670 ) -> TessellationResult {
671 crate::basic_shapes::fill_circle(center, radius, options, output)
672 }
673
674 pub fn tessellate_ellipse(
676 &mut self,
677 center: Point,
678 radii: Vector,
679 x_rotation: Angle,
680 winding: Winding,
681 options: &FillOptions,
682 output: &mut dyn FillGeometryBuilder,
683 ) -> TessellationResult {
684 let options = (*options).with_intersections(false);
685
686 let mut builder = self.builder(&options, output);
687 builder.add_ellipse(center, radii, x_rotation, winding);
688
689 builder.build()
690 }
691
692 pub fn builder<'l>(
729 &'l mut self,
730 options: &'l FillOptions,
731 output: &'l mut dyn FillGeometryBuilder,
732 ) -> NoAttributes<FillBuilder<'l>> {
733 NoAttributes::wrap(FillBuilder::new(0, self, options, output))
734 }
735
736 pub fn builder_with_attributes<'l>(
741 &'l mut self,
742 num_attributes: usize,
743 options: &'l FillOptions,
744 output: &'l mut dyn FillGeometryBuilder,
745 ) -> FillBuilder<'l> {
746 FillBuilder::new(num_attributes, self, options, output)
747 }
748
749 fn tessellate_impl(
750 &mut self,
751 options: &FillOptions,
752 attrib_store: Option<&dyn AttributeStore>,
753 builder: &mut dyn FillGeometryBuilder,
754 ) -> TessellationResult {
755 if options.tolerance.is_nan() || options.tolerance <= 0.0 {
756 return Err(TessellationError::UnsupportedParamater(
757 UnsupportedParamater::ToleranceIsNaN,
758 ));
759 }
760
761 self.reset();
762
763 if let Some(store) = attrib_store {
764 self.attrib_buffer.resize(store.num_attributes(), 0.0);
765 } else {
766 self.attrib_buffer.clear();
767 }
768
769 self.fill_rule = options.fill_rule;
770 self.orientation = options.sweep_orientation;
771 self.tolerance = options.tolerance * 0.5;
772 self.assume_no_intersection = !options.handle_intersections;
773
774 builder.begin_geometry();
775
776 let mut scan = mem::replace(&mut self.scan, ActiveEdgeScan::new());
777
778 let result = self.tessellator_loop(attrib_store, &mut scan, builder);
779
780 mem::swap(&mut self.scan, &mut scan);
781
782 if let Err(e) = result {
783 tess_log!(self, "Tessellation failed with error: {}.", e);
784 builder.abort_geometry();
785
786 return Err(e);
787 }
788
789 if !self.assume_no_intersection {
790 debug_assert!(self.active.edges.is_empty());
791 debug_assert!(self.fill.spans.is_empty());
792 }
793
794 for span in &mut self.fill.spans {
798 if let Some(tess) = span.tess.as_mut() {
799 tess.flush(builder);
800 }
801 }
802
803 self.fill.spans.clear();
804
805 builder.end_geometry();
806
807 Ok(())
808 }
809
810 pub fn set_logging(&mut self, is_enabled: bool) {
813 #[cfg(all(debug_assertions, feature = "std"))]
814 let forced = std::env::var("LYON_FORCE_LOGGING").is_ok();
815
816 #[cfg(not(all(debug_assertions, feature = "std")))]
817 let forced = false;
818
819 self.log = is_enabled || forced;
820 }
821
822 #[cfg_attr(feature = "profiling", inline(never))]
823 fn tessellator_loop(
824 &mut self,
825 attrib_store: Option<&dyn AttributeStore>,
826 scan: &mut ActiveEdgeScan,
827 output: &mut dyn FillGeometryBuilder,
828 ) -> Result<(), TessellationError> {
829 log_svg_preamble(self);
830
831 let mut _prev_position = point(f32::MIN, f32::MIN);
832 self.current_event_id = self.events.first_id();
833 while self.events.valid_id(self.current_event_id) {
834 self.initialize_events(attrib_store, output)?;
835
836 debug_assert!(is_after(self.current_position, _prev_position));
837 _prev_position = self.current_position;
838
839 if let Err(e) = self.process_events(scan, output) {
840 self.recover_from_error(e, output);
843 self.process_events(scan, output)?
845 }
846
847 #[cfg(debug_assertions)]
848 self.check_active_edges();
849
850 self.current_event_id = self.events.next_id(self.current_event_id);
851 }
852
853 Ok(())
854 }
855
856 fn initialize_events(
857 &mut self,
858 attrib_store: Option<&dyn AttributeStore>,
859 output: &mut dyn FillGeometryBuilder,
860 ) -> Result<(), TessellationError> {
861 let current_event = self.current_event_id;
862
863 tess_log!(
864 self,
865 "\n\n<!-- event #{} -->",
866 current_event
867 );
868
869 self.current_position = self.events.position(current_event);
870
871 if self.current_position.x.is_nan() || self.current_position.y.is_nan() {
872 return Err(TessellationError::UnsupportedParamater(
873 UnsupportedParamater::PositionIsNaN,
874 ));
875 }
876
877 let position = match self.orientation {
878 Orientation::Vertical => self.current_position,
879 Orientation::Horizontal => reorient(self.current_position),
880 };
881
882 self.current_vertex = output.add_fill_vertex(FillVertex {
883 position,
884 events: &self.events,
885 current_event,
886 attrib_store,
887 attrib_buffer: &mut self.attrib_buffer,
888 })?;
889
890 let mut current_sibling = current_event;
891 while self.events.valid_id(current_sibling) {
892 let edge = &self.events.edge_data[current_sibling as usize];
893 if edge.is_edge {
897 let to = edge.to;
898 debug_assert!(is_after(to, self.current_position));
899 self.edges_below.push(PendingEdge {
900 to,
901 sort_key: slope(to - self.current_position), src_edge: current_sibling,
903 winding: edge.winding,
904 range_end: edge.range.end,
905 });
906 }
907
908 current_sibling = self.events.next_sibling_id(current_sibling);
909 }
910
911 Ok(())
912 }
913
914 #[cfg_attr(feature = "profiling", inline(never))]
916 fn process_events(
917 &mut self,
918 scan: &mut ActiveEdgeScan,
919 output: &mut dyn FillGeometryBuilder,
920 ) -> Result<(), InternalError> {
921 tess_log!(self, "<!--");
922 tess_log!(
923 self,
924 " events at {:?} {:?} {} edges below",
925 self.current_position,
926 self.current_vertex,
927 self.edges_below.len(),
928 );
929
930 tess_log!(self, "edges below (initially): {:#?}", self.edges_below);
931
932 self.scan_active_edges(scan)?;
935
936 self.process_edges_above(scan, output);
938
939 self.process_edges_below(scan);
941
942 self.update_active_edges(scan);
945
946 tess_log!(self, "-->");
947
948 #[cfg(debug_assertions)]
949 self.log_active_edges();
950
951 Ok(())
952 }
953
954 #[cfg(debug_assertions)]
955 fn log_active_edges(&self) {
956 tess_log!(self, r#"<g class="active-edges">"#);
957 tess_log!(
958 self,
959 r#"<path d="M 0 {} L 1000 {}" class="sweep-line"/>"#,
960 self.current_position.y,
961 self.current_position.y
962 );
963 tess_log!(self, "<!-- active edges: -->");
964 for e in &self.active.edges {
965 if e.is_merge {
966 tess_log!(
967 self,
968 r#" <circle cx="{}" cy="{}" r="3px" class="merge"/>"#,
969 e.from.x,
970 e.from.y
971 );
972 } else {
973 tess_log!(
974 self,
975 r#" <path d="M {:.5?} {:.5?} L {:.5?} {:.5?}" class="edge", winding="{:>2}"/>"#,
976 e.from.x,
977 e.from.y,
978 e.to.x,
979 e.to.y,
980 e.winding,
981 );
982 }
983 }
984 tess_log!(self, "<!-- spans: {}-->", self.fill.spans.len());
985 tess_log!(self, "</g>");
986 }
987
988 #[cfg(debug_assertions)]
989 fn check_active_edges(&self) {
990 let mut winding = WindingState::new();
991 for (idx, edge) in self.active.edges.iter().enumerate() {
992 winding.update(self.fill_rule, edge.winding);
993 if edge.is_merge {
994 assert!(self.fill_rule.is_in(winding.number));
995 } else {
996 assert!(
997 !is_after(self.current_position, edge.to),
998 "error at edge {}, position {:.6?} (current: {:.6?}",
999 idx,
1000 edge.to,
1001 self.current_position,
1002 );
1003 }
1004 }
1005 assert_eq!(winding.number, 0);
1006 let expected_span_count = (winding.span_index + 1) as usize;
1007 assert_eq!(self.fill.spans.len(), expected_span_count);
1008 }
1009
1010 #[cfg_attr(feature = "profiling", inline(never))]
1025 fn scan_active_edges(&self, scan: &mut ActiveEdgeScan) -> Result<(), InternalError> {
1026 scan.reset();
1027
1028 let current_x = self.current_position.x;
1029 let mut connecting_edges = false;
1030 let mut active_edge_idx = 0;
1031 let mut winding = WindingState::new();
1032 let mut previous_was_merge = false;
1033
1034 for active_edge in &self.active.edges {
1036 if active_edge.is_merge {
1037 winding.span_index += 1;
1047 active_edge_idx += 1;
1048 previous_was_merge = true;
1049
1050 continue;
1051 }
1052
1053 let edge_is_before_current_point =
1054 if points_are_equal(self.current_position, active_edge.to) {
1055 connecting_edges = true;
1058 false
1059 } else if active_edge.max_x() < current_x {
1060 true
1061 } else if active_edge.min_x() > current_x {
1062 tess_log!(
1063 self,
1064 "min_x({:?}) > current_x({:?})",
1065 active_edge.min_x(),
1066 current_x
1067 );
1068 false
1069 } else if active_edge.from.y == active_edge.to.y {
1070 connecting_edges = true;
1071 false
1072 } else {
1073 let ex = active_edge.solve_x_for_y(self.current_position.y);
1074
1075 if (ex - current_x).abs() <= self.tolerance {
1076 connecting_edges = true;
1077 false
1078 } else if ex > current_x {
1079 tess_log!(self, "ex({:?}) > current_x({:?})", ex, current_x);
1080 false
1081 } else {
1082 true
1083 }
1084 };
1085
1086 if !edge_is_before_current_point {
1087 break;
1088 }
1089
1090 winding.update(self.fill_rule, active_edge.winding);
1091 previous_was_merge = false;
1092 active_edge_idx += 1;
1093
1094 tess_log!(
1095 self,
1096 " > span: {}, in: {}",
1097 winding.span_index,
1098 winding.is_in
1099 );
1100 }
1101
1102 scan.above.start = active_edge_idx;
1103 scan.winding_before_point = winding;
1104
1105 if previous_was_merge {
1106 scan.winding_before_point.span_index -= 1;
1107 scan.above.start -= 1;
1108
1109 if !connecting_edges {
1121 scan.vertex_events
1134 .push((winding.span_index - 1, Side::Right));
1135 scan.vertex_events.push((winding.span_index, Side::Left));
1136 scan.merge_split_event = true;
1137 tess_log!(self, "split+merge");
1138 }
1139 }
1140
1141 scan.split_event = !connecting_edges && winding.is_in && !scan.merge_split_event;
1145
1146 tess_log!(
1149 self,
1150 "connecting_edges {} | edge {} | span {}",
1151 connecting_edges,
1152 active_edge_idx,
1153 winding.span_index
1154 );
1155 if connecting_edges {
1156 let in_before_vertex = winding.is_in;
1157 let mut first_connecting_edge = !previous_was_merge;
1158
1159 for active_edge in &self.active.edges[active_edge_idx..] {
1160 if active_edge.is_merge {
1161 if !winding.is_in {
1162 return Err(InternalError::MergeVertexOutside);
1163 }
1164
1165 scan.spans_to_end.push(winding.span_index);
1182
1183 winding.span_index += 1;
1196 active_edge_idx += 1;
1197 first_connecting_edge = false;
1198
1199 continue;
1200 }
1201
1202 if !self.is_edge_connecting(active_edge, active_edge_idx, scan)? {
1203 break;
1204 }
1205
1206 if !first_connecting_edge && winding.is_in {
1207 scan.spans_to_end.push(winding.span_index);
1214 }
1215
1216 winding.update(self.fill_rule, active_edge.winding);
1217
1218 tess_log!(
1219 self,
1220 " x span: {} in: {}",
1221 winding.span_index,
1222 winding.is_in
1223 );
1224
1225 if winding.is_in && winding.span_index >= self.fill.spans.len() as i32 {
1226 return Err(InternalError::InsufficientNumberOfSpans);
1227 }
1228
1229 active_edge_idx += 1;
1230 first_connecting_edge = false;
1231 }
1232
1233 let in_after_vertex = winding.is_in;
1234
1235 let vertex_is_merge_event = in_before_vertex
1236 && in_after_vertex
1237 && self.edges_below.is_empty()
1238 && scan.edges_to_split.is_empty();
1239
1240 if vertex_is_merge_event {
1241 scan.merge_event = true;
1246 }
1247
1248 if in_before_vertex {
1249 let first_span_index = scan.winding_before_point.span_index;
1253 scan.vertex_events.push((first_span_index, Side::Right));
1254 }
1255
1256 if in_after_vertex {
1257 scan.vertex_events.push((winding.span_index, Side::Left));
1261 }
1262 }
1263
1264 tess_log!(self, "edges after | {}", active_edge_idx);
1265
1266 scan.above.end = active_edge_idx;
1267
1268 self.check_remaining_edges(active_edge_idx, current_x)
1271 }
1272
1273 #[cfg_attr(feature = "profiling", inline(never))]
1274 #[cfg_attr(not(feature = "profiling"), inline(always))]
1275 fn check_remaining_edges(
1276 &self,
1277 active_edge_idx: usize,
1278 current_x: f32,
1279 ) -> Result<(), InternalError> {
1280 for active_edge in &self.active.edges[active_edge_idx..] {
1284 if active_edge.is_merge {
1285 continue;
1286 }
1287
1288 if active_edge.max_x() < current_x {
1289 return Err(InternalError::IncorrectActiveEdgeOrder(1));
1290 }
1291
1292 if points_are_equal(self.current_position, active_edge.to) {
1293 return Err(InternalError::IncorrectActiveEdgeOrder(2));
1294 }
1295
1296 if active_edge.min_x() < current_x
1297 && active_edge.solve_x_for_y(self.current_position.y) < current_x
1298 {
1299 return Err(InternalError::IncorrectActiveEdgeOrder(3));
1300 }
1301 }
1302
1303 Ok(())
1304 }
1305
1306 fn is_edge_connecting(
1309 &self,
1310 active_edge: &ActiveEdge,
1311 active_edge_idx: usize,
1312 scan: &mut ActiveEdgeScan,
1313 ) -> Result<bool, InternalError> {
1314 if points_are_equal(self.current_position, active_edge.to) {
1315 return Ok(true);
1316 }
1317
1318 let current_x = self.current_position.x;
1319 let threshold = self.tolerance;
1320
1321 let min_x = active_edge.min_x();
1322 let max_x = active_edge.max_x();
1323
1324 if max_x + threshold < current_x || active_edge.to.y < self.current_position.y {
1325 return Err(InternalError::IncorrectActiveEdgeOrder(4));
1326 }
1327
1328 if min_x > current_x {
1329 return Ok(false);
1330 }
1331
1332 let ex = if active_edge.from.y != active_edge.to.y {
1333 active_edge.solve_x_for_y(self.current_position.y)
1334 } else if max_x >= current_x && min_x <= current_x {
1335 current_x
1336 } else {
1337 active_edge.to.x
1338 };
1339
1340 if (ex - current_x).abs() <= threshold {
1341 tess_log!(
1342 self,
1343 "vertex on an edge! {:?} -> {:?}",
1344 active_edge.from,
1345 active_edge.to
1346 );
1347 scan.edges_to_split.push(active_edge_idx);
1348 return Ok(true);
1349 }
1350
1351 if ex < current_x {
1352 return Err(InternalError::IncorrectActiveEdgeOrder(5));
1353 }
1354
1355 tess_log!(self, "ex = {:?} (diff={})", ex, ex - current_x);
1356
1357 Ok(false)
1358 }
1359
1360 #[cfg_attr(feature = "profiling", inline(never))]
1361 fn process_edges_above(
1362 &mut self,
1363 scan: &mut ActiveEdgeScan,
1364 output: &mut dyn FillGeometryBuilder,
1365 ) {
1366 for &(span_index, side) in &scan.vertex_events {
1367 tess_log!(
1368 self,
1369 " -> Vertex event, span: {:?} / {:?} / id: {:?}",
1370 span_index,
1371 side,
1372 self.current_vertex
1373 );
1374 self.fill.spans[span_index as usize].tess().vertex(
1375 self.current_position,
1376 self.current_vertex,
1377 side,
1378 );
1379 }
1380
1381 for &span_index in &scan.spans_to_end {
1382 tess_log!(self, " -> End span {:?}", span_index);
1383 self.fill.end_span(
1384 span_index,
1385 &self.current_position,
1386 self.current_vertex,
1387 output,
1388 );
1389 }
1390
1391 self.fill.cleanup_spans();
1392
1393 for &edge_idx in &scan.edges_to_split {
1394 let active_edge = &mut self.active.edges[edge_idx];
1395 let to = active_edge.to;
1396
1397 self.edges_below.push(PendingEdge {
1398 to,
1399 sort_key: slope(to - self.current_position),
1400 src_edge: active_edge.src_edge,
1401 winding: active_edge.winding,
1402 range_end: active_edge.range_end,
1403 });
1404 tess_log!(
1405 self,
1406 "split {:?}, add edge below {:?} -> {:?} ({:?})",
1407 edge_idx,
1408 self.current_position,
1409 self.edges_below.last().unwrap().to,
1410 active_edge.winding,
1411 );
1412
1413 active_edge.to = self.current_position;
1414 }
1415
1416 if scan.merge_event {
1417 let edge = &mut self.active.edges[scan.above.start];
1424 edge.is_merge = true;
1425 edge.from = edge.to;
1426 edge.winding = 0;
1427 edge.from_id = self.current_vertex;
1428
1429 scan.above.start += 1;
1431 }
1432 }
1433
1434 #[cfg_attr(feature = "profiling", inline(never))]
1435 fn process_edges_below(&mut self, scan: &mut ActiveEdgeScan) {
1436 let mut winding = scan.winding_before_point;
1437
1438 tess_log!(
1439 self,
1440 "connecting edges: {}..{} in: {:?}",
1441 scan.above.start,
1442 scan.above.end,
1443 winding.is_in
1444 );
1445 tess_log!(self, "winding state before point: {:?}", winding);
1446 tess_log!(self, "edges below: {:#?}", self.edges_below);
1447
1448 self.sort_edges_below();
1449
1450 self.handle_coincident_edges_below();
1451
1452 if scan.split_event {
1453 tess_log!(self, "split event");
1462
1463 let left_enclosing_edge_idx = scan.above.start - 1;
1464 self.split_event(left_enclosing_edge_idx, winding.span_index);
1465 }
1466
1467 let mut first_pending_edge = true;
1471 for pending_edge in &self.edges_below {
1472 if !first_pending_edge && winding.is_in {
1473 tess_log!(
1481 self,
1482 " begin span {} ({})",
1483 winding.span_index,
1484 self.fill.spans.len()
1485 );
1486
1487 self.fill.begin_span(
1488 winding.span_index,
1489 &self.current_position,
1490 self.current_vertex,
1491 );
1492 }
1493 winding.update(self.fill_rule, pending_edge.winding);
1494
1495 tess_log!(
1496 self,
1497 "edge below: span: {}, in: {}",
1498 winding.span_index,
1499 winding.is_in
1500 );
1501
1502 first_pending_edge = false;
1503 }
1504 }
1505
1506 #[cfg_attr(feature = "profiling", inline(never))]
1507 fn update_active_edges(&mut self, scan: &ActiveEdgeScan) {
1508 let above = scan.above.start..scan.above.end;
1509
1510 tess_log!(
1511 self,
1512 " remove {} edges ({}..{})",
1513 above.end - above.start,
1514 above.start,
1515 above.end
1516 );
1517
1518 if !self.assume_no_intersection {
1519 self.handle_intersections(above.clone());
1520 }
1521
1522 #[cfg(debug_assertions)]
1523 for active_edge in &self.active.edges[above.clone()] {
1524 debug_assert!(active_edge.is_merge || !is_after(self.current_position, active_edge.to));
1525 }
1526
1527 let from = self.current_position;
1528 let from_id = self.current_vertex;
1529 self.active.edges.splice(
1530 above,
1531 self.edges_below.drain(..).map(|edge| ActiveEdge {
1532 from,
1533 to: edge.to,
1534 winding: edge.winding,
1535 is_merge: false,
1536 from_id,
1537 src_edge: edge.src_edge,
1538 range_end: edge.range_end,
1539 }),
1540 );
1541 }
1542
1543 fn split_event(&mut self, left_enclosing_edge_idx: ActiveEdgeIdx, left_span_idx: SpanIdx) {
1544 let right_enclosing_edge_idx = left_enclosing_edge_idx + 1;
1545
1546 let upper_left = self.active.edges[left_enclosing_edge_idx].from;
1547 let upper_right = self.active.edges[right_enclosing_edge_idx].from;
1548
1549 let right_span_idx = left_span_idx + 1;
1550
1551 let (upper_position, upper_id, new_span_idx) = if is_after(upper_left, upper_right) {
1552 (
1558 upper_left,
1559 self.active.edges[left_enclosing_edge_idx].from_id,
1560 left_span_idx,
1561 )
1562 } else {
1563 (
1569 upper_right,
1570 self.active.edges[right_enclosing_edge_idx].from_id,
1571 right_span_idx,
1572 )
1573 };
1574
1575 self.fill
1576 .begin_span(new_span_idx, &upper_position, upper_id);
1577
1578 self.fill.spans[left_span_idx as usize].tess().vertex(
1579 self.current_position,
1580 self.current_vertex,
1581 Side::Right,
1582 );
1583 self.fill.spans[right_span_idx as usize].tess().vertex(
1584 self.current_position,
1585 self.current_vertex,
1586 Side::Left,
1587 );
1588 }
1589
1590 #[cfg_attr(feature = "profiling", inline(never))]
1591 fn handle_intersections(&mut self, skip_range: Range<usize>) {
1592 let mut edges_below = mem::take(&mut self.edges_below);
1610 for edge_below in &mut edges_below {
1611 let below_min_x = self.current_position.x.min(edge_below.to.x);
1612 let below_max_x = fmax(self.current_position.x, edge_below.to.x);
1613
1614 let below_segment = LineSegment {
1615 from: self.current_position.to_f64(),
1616 to: edge_below.to.to_f64(),
1617 };
1618
1619 let mut tb_min = 1.0;
1620 let mut intersection = None;
1621 for (i, active_edge) in self.active.edges.iter().enumerate() {
1622 if skip_range.contains(&i) {
1623 continue;
1624 }
1625 if active_edge.is_merge || below_min_x > active_edge.max_x() {
1626 continue;
1627 }
1628
1629 if below_max_x < active_edge.min_x() {
1630 continue;
1643 }
1644
1645 let active_segment = LineSegment {
1646 from: active_edge.from.to_f64(),
1647 to: active_edge.to.to_f64(),
1648 };
1649
1650 if let Some((ta, tb)) = active_segment.intersection_t(&below_segment) {
1651 if tb < tb_min && tb > 0.0 && ta > 0.0 && ta <= 1.0 {
1652 tb_min = tb;
1654 intersection = Some((ta, tb, i));
1655 }
1656 }
1657 }
1658
1659 if let Some((ta, tb, active_edge_idx)) = intersection {
1660 self.process_intersection(ta, tb, active_edge_idx, edge_below, &below_segment);
1661 }
1662 }
1663 self.edges_below = edges_below;
1664
1665 }
1667
1668 #[inline(never)]
1669 fn process_intersection(
1670 &mut self,
1671 ta: f64,
1672 tb: f64,
1673 active_edge_idx: usize,
1674 edge_below: &mut PendingEdge,
1675 below_segment: &LineSegment<f64>,
1676 ) {
1677 let mut intersection_position = below_segment.sample(tb).to_f32();
1678 tess_log!(
1679 self,
1680 "-> intersection at: {:?} t={:?}|{:?}",
1681 intersection_position,
1682 ta,
1683 tb
1684 );
1685 tess_log!(
1686 self,
1687 " from {:?}->{:?} and {:?}->{:?}",
1688 self.active.edges[active_edge_idx].from,
1689 self.active.edges[active_edge_idx].to,
1690 self.current_position,
1691 edge_below.to,
1692 );
1693
1694 let active_edge = &mut self.active.edges[active_edge_idx];
1695
1696 if self.current_position == intersection_position {
1697 active_edge.from = intersection_position;
1698 let src_range = &mut self.events.edge_data[active_edge.src_edge as usize].range;
1699 let remapped_ta = remap_t_in_range(ta as f32, src_range.start..active_edge.range_end);
1700 src_range.start = remapped_ta;
1701
1702 return;
1703 }
1704
1705 if !is_after(intersection_position, self.current_position) {
1706 tess_log!(self, "fixup the intersection");
1707 intersection_position.y = self.current_position.y.next_after(f32::INFINITY);
1708 }
1709
1710 assert!(
1711 is_after(intersection_position, self.current_position),
1712 "!!! {:.9?} {:.9?}",
1713 intersection_position,
1714 self.current_position
1715 );
1716
1717 if is_near(intersection_position, edge_below.to) {
1718 tess_log!(self, "intersection near below.to");
1719 intersection_position = edge_below.to;
1720 } else if is_near(intersection_position, active_edge.to) {
1721 tess_log!(self, "intersection near active_edge.to");
1722 intersection_position = active_edge.to;
1723 }
1724
1725 let a_src_edge_data = self.events.edge_data[active_edge.src_edge as usize].clone();
1726 let b_src_edge_data = self.events.edge_data[edge_below.src_edge as usize].clone();
1727
1728 let mut inserted_evt = None;
1729 let mut flipped_active = false;
1730
1731 if active_edge.to != intersection_position && active_edge.from != intersection_position {
1732 let remapped_ta = remap_t_in_range(
1733 ta as f32,
1734 a_src_edge_data.range.start..active_edge.range_end,
1735 );
1736
1737 if is_after(active_edge.to, intersection_position) {
1738 inserted_evt = Some(self.events.insert_sorted(
1740 intersection_position,
1741 EdgeData {
1742 range: remapped_ta..active_edge.range_end,
1743 winding: active_edge.winding,
1744 to: active_edge.to,
1745 is_edge: true,
1746 ..a_src_edge_data
1747 },
1748 self.current_event_id,
1749 ));
1750 } else {
1751 tess_log!(self, "flip active edge after intersection");
1752 flipped_active = true;
1753 self.events.insert_sorted(
1754 active_edge.to,
1755 EdgeData {
1756 range: active_edge.range_end..remapped_ta,
1757 winding: -active_edge.winding,
1758 to: intersection_position,
1759 is_edge: true,
1760 ..a_src_edge_data
1761 },
1762 self.current_event_id,
1763 );
1764 }
1765
1766 active_edge.to = intersection_position;
1767 active_edge.range_end = remapped_ta;
1768 }
1769
1770 if edge_below.to != intersection_position && self.current_position != intersection_position
1771 {
1772 let remapped_tb =
1773 remap_t_in_range(tb as f32, b_src_edge_data.range.start..edge_below.range_end);
1774
1775 if is_after(edge_below.to, intersection_position) {
1776 let edge_data = EdgeData {
1777 range: remapped_tb..edge_below.range_end,
1778 winding: edge_below.winding,
1779 to: edge_below.to,
1780 is_edge: true,
1781 ..b_src_edge_data
1782 };
1783
1784 if let Some(idx) = inserted_evt {
1785 self.events
1787 .insert_sibling(idx, intersection_position, edge_data);
1788 } else {
1789 self.events.insert_sorted(
1790 intersection_position,
1791 edge_data,
1792 self.current_event_id,
1793 );
1794 }
1795 } else {
1796 tess_log!(self, "flip edge below after intersection");
1797 self.events.insert_sorted(
1798 edge_below.to,
1799 EdgeData {
1800 range: edge_below.range_end..remapped_tb,
1801 winding: -edge_below.winding,
1802 to: intersection_position,
1803 is_edge: true,
1804 ..b_src_edge_data
1805 },
1806 self.current_event_id,
1807 );
1808
1809 if flipped_active {
1810 self.events.vertex_event_sorted(
1816 intersection_position,
1817 b_src_edge_data.to_id,
1818 self.current_event_id,
1819 );
1820 }
1821 }
1822
1823 edge_below.to = intersection_position;
1824 edge_below.range_end = remapped_tb;
1825 }
1826 }
1827
1828 fn sort_active_edges(&mut self) {
1829 let y = self.current_position.y;
1838
1839 let mut keys = Vec::with_capacity(self.active.edges.len());
1840
1841 let mut has_merge_vertex = false;
1842 let mut prev_x = f32::NAN;
1843 for (i, edge) in self.active.edges.iter().enumerate() {
1844 if edge.is_merge {
1845 debug_assert!(!prev_x.is_nan());
1846 has_merge_vertex = true;
1847 keys.push((prev_x, i));
1848 } else {
1849 debug_assert!(!is_after(self.current_position, edge.to));
1850
1851 let eq_to = edge.to.y == y;
1852 let eq_from = edge.from.y == y;
1853
1854 let x = if eq_to && eq_from {
1855 let current_x = self.current_position.x;
1856 if edge.max_x() >= current_x && edge.min_x() <= current_x {
1857 self.current_position.x
1858 } else {
1859 edge.min_x()
1860 }
1861 } else if eq_from {
1862 edge.from.x
1863 } else if eq_to {
1864 edge.to.x
1865 } else {
1866 edge.solve_x_for_y(y)
1867 };
1868
1869 keys.push((fmax(x, edge.min_x()), i));
1870 prev_x = x;
1871 }
1872 }
1873
1874 keys.sort_by(|a, b| match a.0.partial_cmp(&b.0).unwrap() {
1875 Ordering::Less => Ordering::Less,
1876 Ordering::Greater => Ordering::Greater,
1877 Ordering::Equal => {
1878 let a = &self.active.edges[a.1];
1879 let b = &self.active.edges[b.1];
1880 match (a.is_merge, b.is_merge) {
1881 (false, false) => {
1882 let slope_a = slope(a.to - a.from);
1883 let slope_b = slope(b.to - b.from);
1884 slope_b.partial_cmp(&slope_a).unwrap_or(Ordering::Equal)
1885 }
1886 (true, false) => Ordering::Greater,
1887 (false, true) => Ordering::Less,
1888 (true, true) => Ordering::Equal,
1889 }
1890 }
1891 });
1892
1893 let mut new_active_edges = Vec::with_capacity(self.active.edges.len());
1894 for &(_, idx) in &keys {
1895 new_active_edges.push(self.active.edges[idx]);
1896 }
1897
1898 self.active.edges = new_active_edges;
1899
1900 if !has_merge_vertex {
1901 return;
1902 }
1903
1904 let mut winding_number = 0;
1905 for i in 0..self.active.edges.len() {
1906 let needs_swap = {
1907 let edge = &self.active.edges[i];
1908 if edge.is_merge {
1909 !self.fill_rule.is_in(winding_number)
1910 } else {
1911 winding_number += edge.winding;
1912 false
1913 }
1914 };
1915
1916 if needs_swap {
1917 let mut w = winding_number;
1918 tess_log!(self, "Fixing up merge vertex after sort.");
1919 let mut idx = i;
1920 loop {
1921 w -= self.active.edges[idx - 1].winding;
1923 self.active.edges.swap(idx, idx - 1);
1924
1925 if self.fill_rule.is_in(w) {
1926 break;
1927 }
1928
1929 idx -= 1;
1930 }
1931 }
1932 }
1933 }
1934
1935 #[inline(never)]
1936 fn recover_from_error(&mut self, _error: InternalError, output: &mut dyn FillGeometryBuilder) {
1937 tess_log!(self, "Attempt to recover error {:?}", _error);
1938
1939 self.sort_active_edges();
1940
1941 debug_assert!(self
1942 .active
1943 .edges
1944 .first()
1945 .map(|e| !e.is_merge)
1946 .unwrap_or(true));
1947 let len = self.active.edges.len();
1957 if len > 1 && self.active.edges[len - 1].is_merge {
1958 self.active.edges.swap(len - 1, len - 2);
1959 }
1960
1961 let mut winding = WindingState::new();
1962
1963 for edge in &self.active.edges {
1964 if edge.is_merge {
1965 winding.span_index += 1;
1966 } else {
1967 winding.update(self.fill_rule, edge.winding);
1968 }
1969
1970 if winding.span_index >= self.fill.spans.len() as i32 {
1971 self.fill
1972 .begin_span(winding.span_index, &edge.from, edge.from_id);
1973 }
1974 }
1975
1976 while self.fill.spans.len() > (winding.span_index + 1) as usize {
1977 self.fill.spans.last_mut().unwrap().tess().flush(output);
1978 self.fill.spans.pop();
1979 }
1980
1981 tess_log!(self, "-->");
1982
1983 #[cfg(debug_assertions)]
1984 self.log_active_edges();
1985 }
1986
1987 #[cfg_attr(feature = "profiling", inline(never))]
1988 fn sort_edges_below(&mut self) {
1989 self.edges_below
1990 .sort_unstable_by(|a, b| a.sort_key.partial_cmp(&b.sort_key).unwrap_or(Ordering::Equal));
1991 }
1992
1993 #[cfg_attr(feature = "profiling", inline(never))]
1994 fn handle_coincident_edges_below(&mut self) {
1995 if self.edges_below.len() < 2 {
1996 return;
1997 }
1998
1999 for idx in (0..(self.edges_below.len() - 1)).rev() {
2000 let a_idx = idx;
2001 let b_idx = idx + 1;
2002
2003 let a_slope = self.edges_below[a_idx].sort_key;
2004 let b_slope = self.edges_below[b_idx].sort_key;
2005
2006 const THRESHOLD: f32 = 0.00005;
2007
2008 let angle_is_close = if a_slope.abs() <= 1.0 {
2012 (a_slope - b_slope).abs() < THRESHOLD
2013 } else {
2014 (1.0 / a_slope - 1.0 / b_slope).abs() < THRESHOLD
2015 };
2016
2017 if angle_is_close {
2018 self.merge_coincident_edges(a_idx, b_idx);
2019 }
2020 }
2021 }
2022
2023 #[cold]
2024 fn merge_coincident_edges(&mut self, a_idx: usize, b_idx: usize) {
2025 let a_to = self.edges_below[a_idx].to;
2026 let b_to = self.edges_below[b_idx].to;
2027
2028 let (lower_idx, upper_idx, split) = match compare_positions(a_to, b_to) {
2029 Ordering::Greater => (a_idx, b_idx, true),
2030 Ordering::Less => (b_idx, a_idx, true),
2031 Ordering::Equal => (a_idx, b_idx, false),
2032 };
2033
2034 tess_log!(
2035 self,
2036 "coincident edges {:?} -> {:?} / {:?}",
2037 self.current_position,
2038 a_to,
2039 b_to
2040 );
2041
2042 tess_log!(
2043 self,
2044 "update winding: {:?} -> {:?}",
2045 self.edges_below[upper_idx].winding,
2046 self.edges_below[upper_idx].winding + self.edges_below[lower_idx].winding
2047 );
2048 self.edges_below[upper_idx].winding += self.edges_below[lower_idx].winding;
2049 let split_point = self.edges_below[upper_idx].to;
2050
2051 tess_log!(
2052 self,
2053 "remove coincident edge {:?}, split:{:?}",
2054 a_idx,
2055 split
2056 );
2057 let edge = self.edges_below.remove(lower_idx);
2058
2059 if !split {
2060 return;
2061 }
2062
2063 let src_edge_data = self.events.edge_data[edge.src_edge as usize].clone();
2064
2065 let t = LineSegment {
2066 from: self.current_position,
2067 to: edge.to,
2068 }
2069 .solve_t_for_y(split_point.y);
2070
2071 let src_range = src_edge_data.range.start..edge.range_end;
2072 let t_remapped = remap_t_in_range(t, src_range);
2073
2074 let edge_data = EdgeData {
2075 range: t_remapped..edge.range_end,
2076 winding: edge.winding,
2077 to: edge.to,
2078 is_edge: true,
2079 ..src_edge_data
2080 };
2081
2082 self.events
2083 .insert_sorted(split_point, edge_data, self.current_event_id);
2084 }
2085
2086 fn reset(&mut self) {
2087 self.current_position = point(f32::MIN, f32::MIN);
2088 self.current_vertex = VertexId::INVALID;
2089 self.current_event_id = INVALID_EVENT_ID;
2090 self.active.edges.clear();
2091 self.edges_below.clear();
2092 self.fill.spans.clear();
2093 }
2094}
2095
2096pub(crate) fn points_are_equal(a: Point, b: Point) -> bool {
2097 a == b
2098}
2099
2100pub(crate) fn compare_positions(a: Point, b: Point) -> Ordering {
2101 if a.y > b.y {
2106 return Ordering::Greater;
2107 }
2108 if a.y < b.y {
2109 return Ordering::Less;
2110 }
2111 if a.x > b.x {
2112 return Ordering::Greater;
2113 }
2114 if a.x < b.x {
2115 return Ordering::Less;
2116 }
2117
2118 Ordering::Equal
2119}
2120
2121#[inline]
2122pub(crate) fn is_after(a: Point, b: Point) -> bool {
2123 a.y > b.y || (a.y == b.y && a.x > b.x)
2124}
2125
2126#[inline]
2127pub(crate) fn is_near(a: Point, b: Point) -> bool {
2128 (a - b).square_length() < 0.000000001
2129}
2130
2131#[inline]
2132fn reorient(p: Point) -> Point {
2133 point(p.y, -p.x)
2134}
2135
2136pub struct FillVertex<'l> {
2138 pub(crate) position: Point,
2139 pub(crate) events: &'l EventQueue,
2140 pub(crate) current_event: TessEventId,
2141 pub(crate) attrib_buffer: &'l mut [f32],
2142 pub(crate) attrib_store: Option<&'l dyn AttributeStore>,
2143}
2144
2145impl<'l> FillVertex<'l> {
2146 pub fn position(&self) -> Point {
2147 self.position
2148 }
2149
2150 pub fn sources(&self) -> VertexSourceIterator {
2152 VertexSourceIterator {
2153 events: self.events,
2154 id: self.current_event,
2155 prev: None,
2156 }
2157 }
2158
2159 pub fn as_endpoint_id(&self) -> Option<EndpointId> {
2169 let mut current = self.current_event;
2170 while self.events.valid_id(current) {
2171 let edge = &self.events.edge_data[current as usize];
2172 let t = edge.range.start;
2173 if t == 0.0 {
2174 return Some(edge.from_id);
2175 }
2176 if t == 1.0 {
2177 return Some(edge.to_id);
2178 }
2179
2180 current = self.events.next_sibling_id(current)
2181 }
2182
2183 None
2184 }
2185
2186 pub fn interpolated_attributes(&mut self) -> Attributes {
2188 if self.attrib_store.is_none() {
2189 return NO_ATTRIBUTES;
2190 }
2191
2192 let store = self.attrib_store.unwrap();
2193
2194 let mut sources = VertexSourceIterator {
2195 events: self.events,
2196 id: self.current_event,
2197 prev: None,
2198 };
2199
2200 let num_attributes = store.num_attributes();
2201
2202 let first = sources.next().unwrap();
2203 let mut next = sources.next();
2204
2205 if next.is_none() {
2207 if let VertexSource::Endpoint { id } = first {
2208 return store.get(id);
2209 }
2210 }
2211
2212 match first {
2214 VertexSource::Endpoint { id } => {
2215 let a = store.get(id);
2216 assert_eq!(a.len(), num_attributes);
2217 assert_eq!(self.attrib_buffer.len(), num_attributes);
2218 self.attrib_buffer[..num_attributes].clone_from_slice(&a[..num_attributes]);
2219 }
2220 VertexSource::Edge { from, to, t } => {
2221 let a = store.get(from);
2222 let b = store.get(to);
2223 assert_eq!(a.len(), num_attributes);
2224 assert_eq!(b.len(), num_attributes);
2225 assert_eq!(self.attrib_buffer.len(), num_attributes);
2226 for i in 0..num_attributes {
2227 self.attrib_buffer[i] = a[i] * (1.0 - t) + b[i] * t;
2228 }
2229 }
2230 }
2231
2232 let mut div = 1.0;
2233 loop {
2234 match next {
2235 Some(VertexSource::Endpoint { id }) => {
2236 let a = store.get(id);
2237 assert_eq!(a.len(), num_attributes);
2238 assert_eq!(self.attrib_buffer.len(), num_attributes);
2239 for (i, &att) in a.iter().enumerate() {
2240 self.attrib_buffer[i] += att;
2241 }
2242 }
2243 Some(VertexSource::Edge { from, to, t }) => {
2244 let a = store.get(from);
2245 let b = store.get(to);
2246 assert_eq!(a.len(), num_attributes);
2247 assert_eq!(b.len(), num_attributes);
2248 assert_eq!(self.attrib_buffer.len(), num_attributes);
2249 for i in 0..num_attributes {
2250 self.attrib_buffer[i] += a[i] * (1.0 - t) + b[i] * t;
2251 }
2252 }
2253 None => {
2254 break;
2255 }
2256 }
2257 div += 1.0;
2258 next = sources.next();
2259 }
2260
2261 if div > 1.0 {
2262 for attribute in self.attrib_buffer.iter_mut() {
2263 *attribute /= div;
2264 }
2265 }
2266
2267 self.attrib_buffer
2268 }
2269}
2270
2271#[derive(Clone)]
2273pub struct VertexSourceIterator<'l> {
2274 events: &'l EventQueue,
2275 id: TessEventId,
2276 prev: Option<VertexSource>,
2277}
2278
2279impl<'l> Iterator for VertexSourceIterator<'l> {
2280 type Item = VertexSource;
2281 #[inline]
2282 fn next(&mut self) -> Option<VertexSource> {
2283 let mut src;
2284 loop {
2285 if self.id == INVALID_EVENT_ID {
2286 return None;
2287 }
2288
2289 let edge = &self.events.edge_data[self.id as usize];
2290
2291 self.id = self.events.next_sibling_id(self.id);
2292
2293 let t = edge.range.start;
2294
2295 src = if t == 0.0 {
2296 Some(VertexSource::Endpoint { id: edge.from_id })
2297 } else if t == 1.0 {
2298 Some(VertexSource::Endpoint { id: edge.to_id })
2299 } else {
2300 Some(VertexSource::Edge {
2301 from: edge.from_id,
2302 to: edge.to_id,
2303 t,
2304 })
2305 };
2306
2307 if src != self.prev {
2308 break;
2309 }
2310 }
2311
2312 self.prev = src;
2313 src
2314 }
2315}
2316
2317fn remap_t_in_range(val: f32, range: Range<f32>) -> f32 {
2318 if range.end > range.start {
2319 let d = range.end - range.start;
2320 range.start + val * d
2321 } else {
2322 let d = range.start - range.end;
2323 range.end + (1.0 - val) * d
2324 }
2325}
2326
2327pub struct FillBuilder<'l> {
2328 events: EventQueueBuilder,
2329 next_id: EndpointId,
2330 first_id: EndpointId,
2331 first_position: Point,
2332 horizontal_sweep: bool,
2333 attrib_store: SimpleAttributeStore,
2334 tessellator: &'l mut FillTessellator,
2335 output: &'l mut dyn FillGeometryBuilder,
2336 options: &'l FillOptions,
2337}
2338
2339impl<'l> FillBuilder<'l> {
2340 fn new(
2341 num_attributes: usize,
2342 tessellator: &'l mut FillTessellator,
2343 options: &'l FillOptions,
2344 output: &'l mut dyn FillGeometryBuilder,
2345 ) -> Self {
2346 let events = core::mem::replace(&mut tessellator.events, EventQueue::new())
2347 .into_builder(options.tolerance);
2348
2349 FillBuilder {
2350 events,
2351 next_id: EndpointId(0),
2352 first_id: EndpointId(0),
2353 horizontal_sweep: options.sweep_orientation == Orientation::Horizontal,
2354 first_position: point(0.0, 0.0),
2355 tessellator,
2356 options,
2357 output,
2358 attrib_store: SimpleAttributeStore::new(num_attributes),
2359 }
2360 }
2361
2362 #[inline]
2363 fn position(&self, p: Point) -> Point {
2364 if self.horizontal_sweep {
2365 point(-p.y, p.x)
2366 } else {
2367 p
2368 }
2369 }
2370
2371 pub fn num_attributes(&self) -> usize {
2372 self.attrib_store.num_attributes()
2373 }
2374
2375 pub fn begin(&mut self, at: Point, attributes: Attributes) -> EndpointId {
2376 let at = self.position(at);
2377 let id = self.attrib_store.add(attributes);
2378 self.first_id = id;
2379 self.first_position = at;
2380 self.events.begin(at, id);
2381
2382 id
2383 }
2384
2385 pub fn end(&mut self, _close: bool) {
2386 self.events.end(self.first_position, self.first_id);
2387 }
2388
2389 pub fn line_to(&mut self, to: Point, attributes: Attributes) -> EndpointId {
2390 let to = self.position(to);
2391 let id = self.attrib_store.add(attributes);
2392 self.events.line_segment(to, id, 0.0, 1.0);
2393
2394 id
2395 }
2396
2397 pub fn quadratic_bezier_to(
2398 &mut self,
2399 ctrl: Point,
2400 to: Point,
2401 attributes: Attributes,
2402 ) -> EndpointId {
2403 let ctrl = self.position(ctrl);
2404 let to = self.position(to);
2405 let id = self.attrib_store.add(attributes);
2406 self.events.quadratic_bezier_segment(ctrl, to, id);
2407
2408 id
2409 }
2410
2411 pub fn cubic_bezier_to(
2412 &mut self,
2413 ctrl1: Point,
2414 ctrl2: Point,
2415 to: Point,
2416 attributes: Attributes,
2417 ) -> EndpointId {
2418 let ctrl1 = self.position(ctrl1);
2419 let ctrl2 = self.position(ctrl2);
2420 let to = self.position(to);
2421 let id = self.attrib_store.add(attributes);
2422 self.events.cubic_bezier_segment(ctrl1, ctrl2, to, id);
2423
2424 id
2425 }
2426
2427 pub fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
2428 self.attrib_store.reserve(endpoints);
2429 self.events.reserve(endpoints + ctrl_points * 2);
2430 }
2431
2432 pub fn add_circle(
2433 &mut self,
2434 center: Point,
2435 radius: f32,
2436 winding: Winding,
2437 attributes: Attributes,
2438 ) {
2439 let radius = radius.abs();
2447 let dir = match winding {
2448 Winding::Positive => 1.0,
2449 Winding::Negative => -1.0,
2450 };
2451
2452 self.reserve(16, 8);
2453
2454 let tan_pi_over_8 = 0.41421357;
2455 let d = radius * tan_pi_over_8;
2456
2457 let start = center + vector(-radius, 0.0);
2458 self.begin(start, attributes);
2459 let ctrl_0 = center + vector(-radius, -d * dir);
2460 let mid_0 = center + vector(-1.0, -dir) * radius * FRAC_1_SQRT_2;
2461 let ctrl_1 = center + vector(-d, -radius * dir);
2462 let mid_1 = center + vector(0.0, -radius * dir);
2463 self.quadratic_bezier_to(ctrl_0, mid_0, attributes);
2464 self.end(false);
2465 self.begin(mid_0, attributes);
2466 self.quadratic_bezier_to(ctrl_1, mid_1, attributes);
2467 self.end(false);
2468
2469 self.begin(mid_1, attributes);
2470 let ctrl_0 = center + vector(d, -radius * dir);
2471 let mid_2 = center + vector(1.0, -dir) * radius * FRAC_1_SQRT_2;
2472 let ctrl_1 = center + vector(radius, -d * dir);
2473 let mid_3 = center + vector(radius, 0.0);
2474 self.quadratic_bezier_to(ctrl_0, mid_2, attributes);
2475 self.end(false);
2476 self.begin(mid_2, attributes);
2477 self.quadratic_bezier_to(ctrl_1, mid_3, attributes);
2478 self.end(false);
2479
2480 self.begin(mid_3, attributes);
2481 let ctrl_0 = center + vector(radius, d * dir);
2482 let mid_4 = center + vector(1.0, dir) * radius * FRAC_1_SQRT_2;
2483 let ctrl_1 = center + vector(d, radius * dir);
2484 let mid_5 = center + vector(0.0, radius * dir);
2485 self.quadratic_bezier_to(ctrl_0, mid_4, attributes);
2486 self.end(false);
2487 self.begin(mid_4, attributes);
2488 self.quadratic_bezier_to(ctrl_1, mid_5, attributes);
2489 self.end(false);
2490
2491 self.begin(mid_5, attributes);
2492 let ctrl_0 = center + vector(-d, radius * dir);
2493 let mid_6 = center + vector(-1.0, dir) * radius * FRAC_1_SQRT_2;
2494 let ctrl_1 = center + vector(-radius, d * dir);
2495 self.quadratic_bezier_to(ctrl_0, mid_6, attributes);
2496 self.end(false);
2497 self.begin(mid_6, attributes);
2498 self.quadratic_bezier_to(ctrl_1, start, attributes);
2499 self.end(false);
2500
2501 self.begin(start, attributes);
2502 self.line_to(mid_0, attributes);
2503 self.line_to(mid_1, attributes);
2504 self.line_to(mid_2, attributes);
2505 self.line_to(mid_3, attributes);
2506 self.line_to(mid_4, attributes);
2507 self.line_to(mid_5, attributes);
2508 self.line_to(mid_6, attributes);
2509 self.close();
2510 }
2511
2512 pub fn build(self) -> TessellationResult {
2513 let mut event_queue = self.events.build();
2514 core::mem::swap(&mut self.tessellator.events, &mut event_queue);
2515
2516 let attrib_store = if self.attrib_store.num_attributes > 0 {
2517 Some(&self.attrib_store as &dyn AttributeStore)
2518 } else {
2519 None
2520 };
2521
2522 self.tessellator
2523 .tessellate_impl(self.options, attrib_store, self.output)
2524 }
2525}
2526
2527impl<'l> PathBuilder for FillBuilder<'l> {
2528 fn num_attributes(&self) -> usize {
2529 self.attrib_store.num_attributes()
2530 }
2531
2532 fn begin(&mut self, at: Point, attributes: Attributes) -> EndpointId {
2533 self.begin(at, attributes)
2534 }
2535
2536 fn end(&mut self, close: bool) {
2537 self.end(close)
2538 }
2539
2540 fn line_to(&mut self, to: Point, attributes: Attributes) -> EndpointId {
2541 self.line_to(to, attributes)
2542 }
2543
2544 fn quadratic_bezier_to(
2545 &mut self,
2546 ctrl: Point,
2547 to: Point,
2548 attributes: Attributes,
2549 ) -> EndpointId {
2550 self.quadratic_bezier_to(ctrl, to, attributes)
2551 }
2552
2553 fn cubic_bezier_to(
2554 &mut self,
2555 ctrl1: Point,
2556 ctrl2: Point,
2557 to: Point,
2558 attributes: Attributes,
2559 ) -> EndpointId {
2560 self.cubic_bezier_to(ctrl1, ctrl2, to, attributes)
2561 }
2562
2563 fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
2564 self.reserve(endpoints, ctrl_points)
2565 }
2566
2567 fn add_circle(&mut self, center: Point, radius: f32, winding: Winding, attributes: Attributes) {
2568 self.add_circle(center, radius, winding, attributes)
2569 }
2570}
2571
2572impl<'l> Build for FillBuilder<'l> {
2573 type PathType = TessellationResult;
2574
2575 #[inline]
2576 fn build(self) -> TessellationResult {
2577 self.build()
2578 }
2579}
2580
2581fn log_svg_preamble(_tess: &FillTessellator) {
2582 tess_log!(
2583 _tess,
2584 r#"
2585<svg viewBox="0 0 1000 1000">
2586
2587<style type="text/css">
2588<![CDATA[
2589 path.sweep-line {{
2590 stroke: red;
2591 fill: none;
2592 }}
2593
2594 path.edge {{
2595 stroke: blue;
2596 fill: none;
2597 }}
2598
2599 path.edge.select {{
2600 stroke: green;
2601 fill: none;
2602 }}
2603
2604 circle.merge {{
2605 fill: yellow;
2606 stroke: orange;
2607 fill-opacity: 1;
2608 }}
2609
2610 circle.current {{
2611 fill: white;
2612 stroke: grey;
2613 fill-opacity: 1;
2614 }}
2615
2616 g.active-edges {{
2617 opacity: 0;
2618 }}
2619
2620 g.active-edges.select {{
2621 opacity: 1;
2622 }}
2623]]>
2624</style>
2625"#
2626 );
2627}
2628
2629#[cfg(test)]
2630use crate::geometry_builder::*;
2631
2632#[cfg(test)]
2633fn eq(a: Point, b: Point) -> bool {
2634 (a.x - b.x).abs() < 0.00001 && (a.y - b.y).abs() < 0.00001
2635}
2636
2637#[cfg(test)]
2638fn at_endpoint(src: &VertexSource, endpoint: EndpointId) -> bool {
2639 match src {
2640 VertexSource::Edge { .. } => false,
2641 VertexSource::Endpoint { id } => *id == endpoint,
2642 }
2643}
2644
2645#[cfg(test)]
2646fn on_edge(src: &VertexSource, from_id: EndpointId, to_id: EndpointId, d: f32) -> bool {
2647 match src {
2648 VertexSource::Edge { t, from, to, .. } => {
2649 *from == from_id
2650 && *to == to_id
2651 && ((d - *t).abs() < 0.00001 || (1.0 - d - *t).abs() <= 0.00001)
2652 }
2653 VertexSource::Endpoint { .. } => false,
2654 }
2655}
2656
2657#[test]
2658fn fill_vertex_source_01() {
2659 use crate::path::commands::PathCommands;
2660 use crate::path::AttributeSlice;
2661
2662 let endpoints: &[Point] = &[point(0.0, 0.0), point(1.0, 1.0), point(0.0, 2.0)];
2663
2664 let attributes = &[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0];
2665
2666 let mut cmds = PathCommands::builder();
2667 cmds.begin(EndpointId(0));
2668 cmds.line_to(EndpointId(1));
2669 cmds.line_to(EndpointId(2));
2670 cmds.end(true);
2671
2672 let cmds = cmds.build();
2673
2674 let mut tess = FillTessellator::new();
2675 tess.tessellate_with_ids(
2676 cmds.iter(),
2677 &(endpoints, endpoints),
2678 Some(&AttributeSlice::new(attributes, 3)),
2679 &FillOptions::default(),
2680 &mut CheckVertexSources { next_vertex: 0 },
2681 )
2682 .unwrap();
2683
2684 struct CheckVertexSources {
2685 next_vertex: u32,
2686 }
2687
2688 impl GeometryBuilder for CheckVertexSources {
2689 fn add_triangle(&mut self, _: VertexId, _: VertexId, _: VertexId) {}
2690 fn abort_geometry(&mut self) {}
2691 }
2692
2693 impl FillGeometryBuilder for CheckVertexSources {
2694 fn add_fill_vertex(
2695 &mut self,
2696 mut vertex: FillVertex,
2697 ) -> Result<VertexId, GeometryBuilderError> {
2698 let pos = vertex.position();
2699 for src in vertex.sources() {
2700 if eq(pos, point(0.0, 0.0)) {
2701 assert!(at_endpoint(&src, EndpointId(0)))
2702 } else if eq(pos, point(1.0, 1.0)) {
2703 assert!(at_endpoint(&src, EndpointId(1)))
2704 } else if eq(pos, point(0.0, 2.0)) {
2705 assert!(at_endpoint(&src, EndpointId(2)))
2706 } else {
2707 panic!()
2708 }
2709 }
2710
2711 if eq(pos, point(0.0, 0.0)) {
2712 assert_eq!(vertex.interpolated_attributes(), &[1.0, 0.0, 0.0])
2713 } else if eq(pos, point(1.0, 1.0)) {
2714 assert_eq!(vertex.interpolated_attributes(), &[0.0, 1.0, 0.0])
2715 } else if eq(pos, point(0.0, 2.0)) {
2716 assert_eq!(vertex.interpolated_attributes(), &[0.0, 0.0, 1.0])
2717 }
2718
2719 let id = self.next_vertex;
2720 self.next_vertex += 1;
2721
2722 Ok(VertexId(id))
2723 }
2724 }
2725}
2726
2727#[test]
2728fn fill_vertex_source_02() {
2729 let mut path = crate::path::Path::builder_with_attributes(3);
2738 let a = path.begin(point(1.0, 0.0), &[1.0, 0.0, 1.0]);
2739 let b = path.line_to(point(2.0, 0.0), &[2.0, 0.0, 1.0]);
2740 let c = path.line_to(point(2.0, 4.0), &[3.0, 0.0, 1.0]);
2741 let d = path.line_to(point(1.0, 4.0), &[4.0, 0.0, 1.0]);
2742 path.end(true);
2743 let e = path.begin(point(0.0, 1.0), &[0.0, 1.0, 2.0]);
2744 let f = path.line_to(point(0.0, 3.0), &[0.0, 2.0, 2.0]);
2745 let g = path.line_to(point(3.0, 3.0), &[0.0, 3.0, 2.0]);
2746 let h = path.line_to(point(3.0, 1.0), &[0.0, 4.0, 2.0]);
2747 path.end(true);
2748
2749 let path = path.build();
2750
2751 let mut tess = FillTessellator::new();
2752 tess.tessellate_with_ids(
2753 path.id_iter(),
2754 &path,
2755 Some(&path),
2756 &FillOptions::default(),
2757 &mut CheckVertexSources {
2758 next_vertex: 0,
2759 a,
2760 b,
2761 c,
2762 d,
2763 e,
2764 f,
2765 g,
2766 h,
2767 },
2768 )
2769 .unwrap();
2770
2771 struct CheckVertexSources {
2772 next_vertex: u32,
2773 a: EndpointId,
2774 b: EndpointId,
2775 c: EndpointId,
2776 d: EndpointId,
2777 e: EndpointId,
2778 f: EndpointId,
2779 g: EndpointId,
2780 h: EndpointId,
2781 }
2782
2783 impl GeometryBuilder for CheckVertexSources {
2784 fn add_triangle(&mut self, _: VertexId, _: VertexId, _: VertexId) {}
2785 }
2786
2787 impl FillGeometryBuilder for CheckVertexSources {
2788 fn add_fill_vertex(
2789 &mut self,
2790 mut vertex: FillVertex,
2791 ) -> Result<VertexId, GeometryBuilderError> {
2792 let pos = vertex.position();
2793 for src in vertex.sources() {
2794 if eq(pos, point(1.0, 0.0)) {
2795 assert!(at_endpoint(&src, self.a));
2796 } else if eq(pos, point(2.0, 0.0)) {
2797 assert!(at_endpoint(&src, self.b));
2798 } else if eq(pos, point(2.0, 4.0)) {
2799 assert!(at_endpoint(&src, self.c));
2800 } else if eq(pos, point(1.0, 4.0)) {
2801 assert!(at_endpoint(&src, self.d));
2802 } else if eq(pos, point(0.0, 1.0)) {
2803 assert!(at_endpoint(&src, self.e));
2804 } else if eq(pos, point(0.0, 3.0)) {
2805 assert!(at_endpoint(&src, self.f));
2806 } else if eq(pos, point(3.0, 3.0)) {
2807 assert!(at_endpoint(&src, self.g));
2808 } else if eq(pos, point(3.0, 1.0)) {
2809 assert!(at_endpoint(&src, self.h));
2810 } else if eq(pos, point(1.0, 1.0)) {
2811 assert!(
2812 on_edge(&src, self.h, self.e, 2.0 / 3.0)
2813 || on_edge(&src, self.d, self.a, 3.0 / 4.0)
2814 );
2815 } else if eq(pos, point(2.0, 1.0)) {
2816 assert!(
2817 on_edge(&src, self.h, self.e, 1.0 / 3.0)
2818 || on_edge(&src, self.b, self.c, 1.0 / 4.0)
2819 );
2820 } else if eq(pos, point(1.0, 3.0)) {
2821 assert!(
2822 on_edge(&src, self.f, self.g, 1.0 / 3.0)
2823 || on_edge(&src, self.d, self.a, 1.0 / 4.0)
2824 );
2825 } else if eq(pos, point(2.0, 3.0)) {
2826 assert!(
2827 on_edge(&src, self.f, self.g, 2.0 / 3.0)
2828 || on_edge(&src, self.b, self.c, 3.0 / 4.0)
2829 );
2830 } else {
2831 panic!()
2832 }
2833 }
2834
2835 fn assert_attr(a: Attributes, b: Attributes) {
2836 for i in 0..a.len() {
2837 let are_equal = (a[i] - b[i]).abs() < 0.001;
2838 #[cfg(feature = "std")]
2839 if !are_equal {
2840 std::println!("{a:?} != {b:?}");
2841 }
2842 assert!(are_equal);
2843 }
2844
2845 assert_eq!(a.len(), b.len());
2846 }
2847
2848 let pos = vertex.position();
2849 let attribs = vertex.interpolated_attributes();
2850 if eq(pos, point(1.0, 0.0)) {
2851 assert_attr(attribs, &[1.0, 0.0, 1.0]);
2852 } else if eq(pos, point(2.0, 0.0)) {
2853 assert_attr(attribs, &[2.0, 0.0, 1.0]);
2854 } else if eq(pos, point(2.0, 4.0)) {
2855 assert_attr(attribs, &[3.0, 0.0, 1.0]);
2856 } else if eq(pos, point(1.0, 4.0)) {
2857 assert_attr(attribs, &[4.0, 0.0, 1.0]);
2858 } else if eq(pos, point(0.0, 1.0)) {
2859 assert_attr(attribs, &[0.0, 1.0, 2.0]);
2860 } else if eq(pos, point(0.0, 3.0)) {
2861 assert_attr(attribs, &[0.0, 2.0, 2.0]);
2862 } else if eq(pos, point(3.0, 3.0)) {
2863 assert_attr(attribs, &[0.0, 3.0, 2.0]);
2864 } else if eq(pos, point(3.0, 1.0)) {
2865 assert_attr(attribs, &[0.0, 4.0, 2.0]);
2866 } else if eq(pos, point(1.0, 1.0)) {
2867 assert_attr(attribs, &[0.875, 1.0, 1.5]);
2868 } else if eq(pos, point(2.0, 1.0)) {
2869 assert_attr(attribs, &[1.125, 1.5, 1.5]);
2870 } else if eq(pos, point(1.0, 3.0)) {
2871 assert_attr(attribs, &[1.625, 1.16666, 1.5]);
2872 } else if eq(pos, point(2.0, 3.0)) {
2873 assert_attr(attribs, &[1.375, 1.33333, 1.5]);
2874 }
2875
2876 let id = self.next_vertex;
2877 self.next_vertex += 1;
2878
2879 Ok(VertexId(id))
2880 }
2881 }
2882}
2883
2884#[test]
2885fn fill_vertex_source_03() {
2886 use crate::path::commands::PathCommands;
2887 use crate::path::AttributeSlice;
2888
2889 let endpoints: &[Point] = &[
2899 point(0.0, 0.0),
2900 point(2.0, 0.0),
2901 point(1.0, 1.0),
2902 point(0.0, 2.0),
2903 point(2.0, 2.0),
2904 point(1.0, 1.0),
2905 ];
2906
2907 let attributes = &[0.0, 0.0, 1.0, 0.0, 0.0, 2.0];
2908
2909 let mut cmds = PathCommands::builder();
2910 cmds.begin(EndpointId(0));
2911 cmds.line_to(EndpointId(1));
2912 cmds.line_to(EndpointId(2));
2913 cmds.end(true);
2914 cmds.begin(EndpointId(3));
2915 cmds.line_to(EndpointId(4));
2916 cmds.line_to(EndpointId(5));
2917 cmds.end(true);
2918
2919 let cmds = cmds.build();
2920
2921 let mut tess = FillTessellator::new();
2922 tess.tessellate_with_ids(
2923 cmds.iter(),
2924 &(endpoints, endpoints),
2925 Some(&AttributeSlice::new(attributes, 1)),
2926 &FillOptions::default(),
2927 &mut CheckVertexSources { next_vertex: 0 },
2928 )
2929 .unwrap();
2930
2931 struct CheckVertexSources {
2932 next_vertex: u32,
2933 }
2934
2935 impl GeometryBuilder for CheckVertexSources {
2936 fn add_triangle(&mut self, _: VertexId, _: VertexId, _: VertexId) {}
2937 }
2938
2939 impl FillGeometryBuilder for CheckVertexSources {
2940 fn add_fill_vertex(
2941 &mut self,
2942 mut vertex: FillVertex,
2943 ) -> Result<VertexId, GeometryBuilderError> {
2944 if eq(vertex.position(), point(1.0, 1.0)) {
2945 assert_eq!(vertex.interpolated_attributes(), &[1.5]);
2946 assert_eq!(vertex.sources().count(), 2);
2947 } else {
2948 assert_eq!(vertex.interpolated_attributes(), &[0.0]);
2949 assert_eq!(vertex.sources().count(), 1);
2950 }
2951
2952 let id = self.next_vertex;
2953 self.next_vertex += 1;
2954
2955 Ok(VertexId(id))
2956 }
2957 }
2958}
2959
2960#[test]
2961fn fill_builder_vertex_source() {
2962 let mut tess = FillTessellator::new();
2963 let options = FillOptions::default();
2964
2965 let mut check = CheckVertexSources { next_vertex: 0 };
2966 let mut builder = tess.builder(&options, &mut check);
2967
2968 assert_eq!(builder.begin(point(0.0, 0.0)), EndpointId(0));
2969 assert_eq!(builder.line_to(point(1.0, 1.0)), EndpointId(1));
2970 assert_eq!(builder.line_to(point(0.0, 2.0)), EndpointId(2));
2971 builder.end(true);
2972
2973 builder.build().unwrap();
2974
2975 struct CheckVertexSources {
2976 next_vertex: u32,
2977 }
2978
2979 impl GeometryBuilder for CheckVertexSources {
2980 fn add_triangle(&mut self, _: VertexId, _: VertexId, _: VertexId) {}
2981 }
2982
2983 impl FillGeometryBuilder for CheckVertexSources {
2984 fn add_fill_vertex(
2985 &mut self,
2986 vertex: FillVertex,
2987 ) -> Result<VertexId, GeometryBuilderError> {
2988 let pos = vertex.position();
2989 for src in vertex.sources() {
2990 if eq(pos, point(0.0, 0.0)) {
2991 assert!(at_endpoint(&src, EndpointId(0)))
2992 } else if eq(pos, point(1.0, 1.0)) {
2993 assert!(at_endpoint(&src, EndpointId(1)))
2994 } else if eq(pos, point(0.0, 2.0)) {
2995 assert!(at_endpoint(&src, EndpointId(2)))
2996 } else {
2997 panic!()
2998 }
2999 }
3000
3001 let id = self.next_vertex;
3002 self.next_vertex += 1;
3003
3004 Ok(VertexId(id))
3005 }
3006 }
3007}