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_POSITIVE))
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::take(&mut self.events);
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,
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::take(&mut self.events);
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,
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.assume_no_intersection = !options.handle_intersections;
772 self.tolerance = if true || options.handle_intersections {
773 options.tolerance * 0.5
774 } else {
775 f32::EPSILON
778 };
779
780 builder.begin_geometry();
781
782 let mut scan = mem::replace(&mut self.scan, ActiveEdgeScan::new());
783
784 let result = self.tessellator_loop(attrib_store, &mut scan, builder);
785
786 mem::swap(&mut self.scan, &mut scan);
787
788 if let Err(e) = result {
789 tess_log!(self, "Tessellation failed with error: {}.", e);
790 builder.abort_geometry();
791
792 return Err(e);
793 }
794
795 if !self.assume_no_intersection {
796 debug_assert!(self.active.edges.is_empty());
797 debug_assert!(self.fill.spans.is_empty());
798 }
799
800 if self.assume_no_intersection && (!self.active.edges.is_empty() | !self.fill.spans.is_empty()) {
801 tess_log!(self, "Tessellation failed with TessellatorOptions::handle_intersections = false. ");
802 builder.abort_geometry();
803
804 return Err(InternalError::intersections_disabled().into());
805 }
806
807 for span in &mut self.fill.spans {
811 if let Some(tess) = span.tess.as_mut() {
812 tess.flush(builder);
813 }
814 }
815
816 self.fill.spans.clear();
817
818 builder.end_geometry();
819
820 Ok(())
821 }
822
823 pub fn set_logging(&mut self, is_enabled: bool) {
826 #[cfg(all(debug_assertions, feature = "std"))]
827 let forced = std::env::var("LYON_FORCE_LOGGING").is_ok();
828
829 #[cfg(not(all(debug_assertions, feature = "std")))]
830 let forced = false;
831
832 self.log = is_enabled || forced;
833 }
834
835 #[cfg_attr(feature = "profiling", inline(never))]
836 fn tessellator_loop(
837 &mut self,
838 attrib_store: Option<&dyn AttributeStore>,
839 scan: &mut ActiveEdgeScan,
840 output: &mut dyn FillGeometryBuilder,
841 ) -> Result<(), TessellationError> {
842 log_svg_preamble(self);
843
844 let mut _prev_position = point(f32::MIN, f32::MIN);
845 self.current_event_id = self.events.first_id();
846 while self.events.valid_id(self.current_event_id) {
847 self.initialize_events(attrib_store, output)?;
848
849 debug_assert!(is_after(self.current_position, _prev_position));
850 _prev_position = self.current_position;
851
852 if let Err(e) = self.process_events(scan, output) {
853 self.recover_from_error(e, output);
856 self.process_events(scan, output)?
858 }
859
860 #[cfg(debug_assertions)]
861 self.check_active_edges();
862
863 self.current_event_id = self.events.next_id(self.current_event_id);
864 }
865
866 Ok(())
867 }
868
869 fn initialize_events(
870 &mut self,
871 attrib_store: Option<&dyn AttributeStore>,
872 output: &mut dyn FillGeometryBuilder,
873 ) -> Result<(), TessellationError> {
874 let current_event = self.current_event_id;
875
876 tess_log!(
877 self,
878 "\n\n<!-- event #{} -->",
879 current_event
880 );
881
882 self.current_position = self.events.position(current_event);
883
884 if self.current_position.x.is_nan() || self.current_position.y.is_nan() {
885 return Err(TessellationError::UnsupportedParamater(
886 UnsupportedParamater::PositionIsNaN,
887 ));
888 }
889
890 let position = match self.orientation {
891 Orientation::Vertical => self.current_position,
892 Orientation::Horizontal => reorient(self.current_position),
893 };
894
895 self.current_vertex = output.add_fill_vertex(FillVertex {
896 position,
897 events: &self.events,
898 current_event,
899 attrib_store,
900 attrib_buffer: &mut self.attrib_buffer,
901 })?;
902
903 let mut current_sibling = current_event;
904 while self.events.valid_id(current_sibling) {
905 let edge = &self.events.edge_data[current_sibling as usize];
906 if edge.is_edge {
910 let to = edge.to;
911 debug_assert!(is_after(to, self.current_position));
912 self.edges_below.push(PendingEdge {
913 to,
914 sort_key: slope(to - self.current_position), src_edge: current_sibling,
916 winding: edge.winding,
917 range_end: edge.range.end,
918 });
919 }
920
921 current_sibling = self.events.next_sibling_id(current_sibling);
922 }
923
924 Ok(())
925 }
926
927 #[cfg_attr(feature = "profiling", inline(never))]
929 fn process_events(
930 &mut self,
931 scan: &mut ActiveEdgeScan,
932 output: &mut dyn FillGeometryBuilder,
933 ) -> Result<(), InternalError> {
934 tess_log!(self, "<!--");
935 tess_log!(
936 self,
937 " events at {:?} {:?} {} edges below",
938 self.current_position,
939 self.current_vertex,
940 self.edges_below.len(),
941 );
942
943 tess_log!(self, "edges below (initially): {:#?}", self.edges_below);
944
945 self.scan_active_edges(scan)?;
948
949 self.process_edges_above(scan, output);
951
952 self.process_edges_below(scan);
954
955 self.update_active_edges(scan);
958
959 tess_log!(self, "-->");
960
961 #[cfg(debug_assertions)]
962 self.log_active_edges();
963
964 Ok(())
965 }
966
967 #[cfg(debug_assertions)]
968 fn log_active_edges(&self) {
969 tess_log!(self, r#"<g class="active-edges">"#);
970 tess_log!(
971 self,
972 r#"<path d="M 0 {} L 1000 {}" class="sweep-line"/>"#,
973 self.current_position.y,
974 self.current_position.y
975 );
976 tess_log!(self, "<!-- active edges: -->");
977 for e in &self.active.edges {
978 if e.is_merge {
979 tess_log!(
980 self,
981 r#" <circle cx="{}" cy="{}" r="3px" class="merge"/>"#,
982 e.from.x,
983 e.from.y
984 );
985 } else {
986 tess_log!(
987 self,
988 r#" <path d="M {:.5?} {:.5?} L {:.5?} {:.5?}" class="edge", winding="{:>2}"/>"#,
989 e.from.x,
990 e.from.y,
991 e.to.x,
992 e.to.y,
993 e.winding,
994 );
995 }
996 }
997 tess_log!(self, "<!-- spans: {}-->", self.fill.spans.len());
998 tess_log!(self, "</g>");
999 }
1000
1001 #[cfg(debug_assertions)]
1002 fn check_active_edges(&self) {
1003 if self.assume_no_intersection {
1004 return;
1008 }
1009
1010 let mut winding = WindingState::new();
1011 for (idx, edge) in self.active.edges.iter().enumerate() {
1012 winding.update(self.fill_rule, edge.winding);
1013 if edge.is_merge {
1014 assert!(self.fill_rule.is_in(winding.number));
1015 } else {
1016 assert!(
1017 !is_after(self.current_position, edge.to),
1018 "error at edge {}, position {:.6?} (current: {:.6?}",
1019 idx,
1020 edge.to,
1021 self.current_position,
1022 );
1023 }
1024 }
1025 assert_eq!(winding.number, 0);
1026 let expected_span_count = (winding.span_index + 1) as usize;
1027 assert_eq!(self.fill.spans.len(), expected_span_count);
1028 }
1029
1030 #[cfg_attr(feature = "profiling", inline(never))]
1045 fn scan_active_edges(&self, scan: &mut ActiveEdgeScan) -> Result<(), InternalError> {
1046 scan.reset();
1047
1048 let current_x = self.current_position.x;
1049 let mut connecting_edges = false;
1050 let mut active_edge_idx = 0;
1051 let mut winding = WindingState::new();
1052 let mut previous_was_merge = false;
1053
1054 for active_edge in &self.active.edges {
1056 if active_edge.is_merge {
1057 winding.span_index += 1;
1067 active_edge_idx += 1;
1068 previous_was_merge = true;
1069
1070 continue;
1071 }
1072
1073 let edge_is_before_current_point =
1074 if points_are_equal(self.current_position, active_edge.to) {
1075 connecting_edges = true;
1078 false
1079 } else if active_edge.max_x() < current_x {
1080 true
1081 } else if active_edge.min_x() > current_x {
1082 tess_log!(
1083 self,
1084 "min_x({:?}) > current_x({:?})",
1085 active_edge.min_x(),
1086 current_x
1087 );
1088 false
1089 } else if active_edge.from.y == active_edge.to.y {
1090 connecting_edges = true;
1091 false
1092 } else {
1093 let ex = active_edge.solve_x_for_y(self.current_position.y);
1094
1095 if (ex - current_x).abs() <= self.tolerance {
1096 connecting_edges = true;
1097 false
1098 } else if ex > current_x {
1099 tess_log!(self, "ex({:?}) > current_x({:?})", ex, current_x);
1100 false
1101 } else {
1102 true
1103 }
1104 };
1105
1106 if !edge_is_before_current_point {
1107 break;
1108 }
1109
1110 winding.update(self.fill_rule, active_edge.winding);
1111 previous_was_merge = false;
1112 active_edge_idx += 1;
1113
1114 tess_log!(
1115 self,
1116 " > span: {}, in: {}",
1117 winding.span_index,
1118 winding.is_in
1119 );
1120 }
1121
1122 scan.above.start = active_edge_idx;
1123 scan.winding_before_point = winding;
1124
1125 if previous_was_merge {
1126 scan.winding_before_point.span_index -= 1;
1127 scan.above.start -= 1;
1128
1129 if !connecting_edges {
1141 scan.vertex_events
1154 .push((winding.span_index - 1, Side::Right));
1155 scan.vertex_events.push((winding.span_index, Side::Left));
1156 scan.merge_split_event = true;
1157 tess_log!(self, "split+merge");
1158 }
1159 }
1160
1161 scan.split_event = !connecting_edges && winding.is_in && !scan.merge_split_event;
1165
1166 tess_log!(
1169 self,
1170 "connecting_edges {} | edge {} | span {}",
1171 connecting_edges,
1172 active_edge_idx,
1173 winding.span_index
1174 );
1175 if connecting_edges {
1176 let in_before_vertex = winding.is_in;
1177 let mut first_connecting_edge = !previous_was_merge;
1178
1179 for active_edge in &self.active.edges[active_edge_idx..] {
1180 if active_edge.is_merge {
1181 if !winding.is_in {
1182 return Err(InternalError::MergeVertexOutside);
1183 }
1184
1185 scan.spans_to_end.push(winding.span_index);
1202
1203 winding.span_index += 1;
1216 active_edge_idx += 1;
1217 first_connecting_edge = false;
1218
1219 continue;
1220 }
1221
1222 if !self.is_edge_connecting(active_edge, active_edge_idx, scan)? {
1223 break;
1224 }
1225
1226 if !first_connecting_edge && winding.is_in {
1227 scan.spans_to_end.push(winding.span_index);
1234 }
1235
1236 winding.update(self.fill_rule, active_edge.winding);
1237
1238 tess_log!(
1239 self,
1240 " x span: {} in: {}",
1241 winding.span_index,
1242 winding.is_in
1243 );
1244
1245 if winding.is_in && winding.span_index >= self.fill.spans.len() as i32 {
1246 return Err(InternalError::InsufficientNumberOfSpans);
1247 }
1248
1249 active_edge_idx += 1;
1250 first_connecting_edge = false;
1251 }
1252
1253 let in_after_vertex = winding.is_in;
1254
1255 let vertex_is_merge_event = in_before_vertex
1256 && in_after_vertex
1257 && self.edges_below.is_empty()
1258 && scan.edges_to_split.is_empty();
1259
1260 if vertex_is_merge_event {
1261 scan.merge_event = true;
1266 }
1267
1268 if in_before_vertex {
1269 let first_span_index = scan.winding_before_point.span_index;
1273 scan.vertex_events.push((first_span_index, Side::Right));
1274 }
1275
1276 if in_after_vertex {
1277 scan.vertex_events.push((winding.span_index, Side::Left));
1281 }
1282 }
1283
1284 tess_log!(self, "edges after | {}", active_edge_idx);
1285
1286 scan.above.end = active_edge_idx;
1287
1288 self.check_remaining_edges(active_edge_idx, current_x)
1291 }
1292
1293 #[cfg_attr(feature = "profiling", inline(never))]
1294 #[cfg_attr(not(feature = "profiling"), inline(always))]
1295 fn check_remaining_edges(
1296 &self,
1297 active_edge_idx: usize,
1298 current_x: f32,
1299 ) -> Result<(), InternalError> {
1300 for active_edge in &self.active.edges[active_edge_idx..] {
1304 if active_edge.is_merge {
1305 continue;
1306 }
1307
1308 if active_edge.max_x() < current_x {
1309 return Err(InternalError::IncorrectActiveEdgeOrder(1));
1310 }
1311
1312 if points_are_equal(self.current_position, active_edge.to) {
1313 return Err(InternalError::IncorrectActiveEdgeOrder(2));
1314 }
1315
1316 if active_edge.min_x() < current_x
1317 && active_edge.solve_x_for_y(self.current_position.y) < current_x
1318 {
1319 return Err(InternalError::IncorrectActiveEdgeOrder(3));
1320 }
1321 }
1322
1323 Ok(())
1324 }
1325
1326 fn is_edge_connecting(
1329 &self,
1330 active_edge: &ActiveEdge,
1331 active_edge_idx: usize,
1332 scan: &mut ActiveEdgeScan,
1333 ) -> Result<bool, InternalError> {
1334 if points_are_equal(self.current_position, active_edge.to) {
1335 return Ok(true);
1336 }
1337
1338 let current_x = self.current_position.x;
1339 let threshold = self.tolerance;
1340
1341 let min_x = active_edge.min_x();
1342 let max_x = active_edge.max_x();
1343
1344 if max_x + threshold < current_x || active_edge.to.y < self.current_position.y {
1345 return Err(InternalError::IncorrectActiveEdgeOrder(4));
1346 }
1347
1348 if min_x > current_x {
1349 return Ok(false);
1350 }
1351
1352 let ex = if active_edge.from.y != active_edge.to.y {
1353 active_edge.solve_x_for_y(self.current_position.y)
1354 } else if max_x >= current_x && min_x <= current_x {
1355 current_x
1356 } else {
1357 active_edge.to.x
1358 };
1359
1360 if (ex - current_x).abs() <= threshold {
1361 tess_log!(
1362 self,
1363 "vertex on an edge! {:?} -> {:?}",
1364 active_edge.from,
1365 active_edge.to
1366 );
1367 scan.edges_to_split.push(active_edge_idx);
1368 return Ok(true);
1369 }
1370
1371 if ex < current_x {
1372 return Err(InternalError::IncorrectActiveEdgeOrder(5));
1373 }
1374
1375 tess_log!(self, "ex = {:?} (diff={})", ex, ex - current_x);
1376
1377 Ok(false)
1378 }
1379
1380 #[cfg_attr(feature = "profiling", inline(never))]
1381 fn process_edges_above(
1382 &mut self,
1383 scan: &mut ActiveEdgeScan,
1384 output: &mut dyn FillGeometryBuilder,
1385 ) {
1386 for &(span_index, side) in &scan.vertex_events {
1387 tess_log!(
1388 self,
1389 " -> Vertex event, span: {:?} / {:?} / id: {:?}",
1390 span_index,
1391 side,
1392 self.current_vertex
1393 );
1394 self.fill.spans[span_index as usize].tess().vertex(
1395 self.current_position,
1396 self.current_vertex,
1397 side,
1398 );
1399 }
1400
1401 for &span_index in &scan.spans_to_end {
1402 tess_log!(self, " -> End span {:?}", span_index);
1403 self.fill.end_span(
1404 span_index,
1405 &self.current_position,
1406 self.current_vertex,
1407 output,
1408 );
1409 }
1410
1411 self.fill.cleanup_spans();
1412
1413 for &edge_idx in &scan.edges_to_split {
1414 let active_edge = &mut self.active.edges[edge_idx];
1415 let to = active_edge.to;
1416
1417 self.edges_below.push(PendingEdge {
1418 to,
1419 sort_key: slope(to - self.current_position),
1420 src_edge: active_edge.src_edge,
1421 winding: active_edge.winding,
1422 range_end: active_edge.range_end,
1423 });
1424 tess_log!(
1425 self,
1426 "split {:?}, add edge below {:?} -> {:?} ({:?})",
1427 edge_idx,
1428 self.current_position,
1429 self.edges_below.last().unwrap().to,
1430 active_edge.winding,
1431 );
1432
1433 active_edge.to = self.current_position;
1434 }
1435
1436 if scan.merge_event {
1437 let edge = &mut self.active.edges[scan.above.start];
1444 edge.is_merge = true;
1445 edge.from = edge.to;
1446 edge.winding = 0;
1447 edge.from_id = self.current_vertex;
1448
1449 scan.above.start += 1;
1451 }
1452 }
1453
1454 #[cfg_attr(feature = "profiling", inline(never))]
1455 fn process_edges_below(&mut self, scan: &mut ActiveEdgeScan) {
1456 let mut winding = scan.winding_before_point;
1457
1458 tess_log!(
1459 self,
1460 "connecting edges: {}..{} in: {:?}",
1461 scan.above.start,
1462 scan.above.end,
1463 winding.is_in
1464 );
1465 tess_log!(self, "winding state before point: {:?}", winding);
1466 tess_log!(self, "edges below: {:#?}", self.edges_below);
1467
1468 self.sort_edges_below();
1469
1470 self.handle_coincident_edges_below();
1471
1472 if scan.split_event {
1473 tess_log!(self, "split event");
1482
1483 let left_enclosing_edge_idx = scan.above.start - 1;
1484 self.split_event(left_enclosing_edge_idx, winding.span_index);
1485 }
1486
1487 let mut first_pending_edge = true;
1491 for pending_edge in &self.edges_below {
1492 if !first_pending_edge && winding.is_in {
1493 tess_log!(
1501 self,
1502 " begin span {} ({})",
1503 winding.span_index,
1504 self.fill.spans.len()
1505 );
1506
1507 self.fill.begin_span(
1508 winding.span_index,
1509 &self.current_position,
1510 self.current_vertex,
1511 );
1512 }
1513 winding.update(self.fill_rule, pending_edge.winding);
1514
1515 tess_log!(
1516 self,
1517 "edge below: span: {}, in: {}",
1518 winding.span_index,
1519 winding.is_in
1520 );
1521
1522 first_pending_edge = false;
1523 }
1524 }
1525
1526 #[cfg_attr(feature = "profiling", inline(never))]
1527 fn update_active_edges(&mut self, scan: &ActiveEdgeScan) {
1528 let above = scan.above.start..scan.above.end;
1529
1530 tess_log!(
1531 self,
1532 " remove {} edges ({}..{})",
1533 above.end - above.start,
1534 above.start,
1535 above.end
1536 );
1537
1538 if !self.assume_no_intersection {
1539 self.handle_intersections(above.clone());
1540 }
1541
1542 #[cfg(debug_assertions)]
1543 for active_edge in &self.active.edges[above.clone()] {
1544 debug_assert!(active_edge.is_merge || !is_after(self.current_position, active_edge.to));
1545 }
1546
1547 let from = self.current_position;
1548 let from_id = self.current_vertex;
1549 self.active.edges.splice(
1550 above,
1551 self.edges_below.drain(..).map(|edge| ActiveEdge {
1552 from,
1553 to: edge.to,
1554 winding: edge.winding,
1555 is_merge: false,
1556 from_id,
1557 src_edge: edge.src_edge,
1558 range_end: edge.range_end,
1559 }),
1560 );
1561 }
1562
1563 fn split_event(&mut self, left_enclosing_edge_idx: ActiveEdgeIdx, left_span_idx: SpanIdx) {
1564 let right_enclosing_edge_idx = left_enclosing_edge_idx + 1;
1565
1566 let upper_left = self.active.edges[left_enclosing_edge_idx].from;
1567 let upper_right = self.active.edges[right_enclosing_edge_idx].from;
1568
1569 let right_span_idx = left_span_idx + 1;
1570
1571 let (upper_position, upper_id, new_span_idx) = if is_after(upper_left, upper_right) {
1572 (
1578 upper_left,
1579 self.active.edges[left_enclosing_edge_idx].from_id,
1580 left_span_idx,
1581 )
1582 } else {
1583 (
1589 upper_right,
1590 self.active.edges[right_enclosing_edge_idx].from_id,
1591 right_span_idx,
1592 )
1593 };
1594
1595 self.fill
1596 .begin_span(new_span_idx, &upper_position, upper_id);
1597
1598 self.fill.spans[left_span_idx as usize].tess().vertex(
1599 self.current_position,
1600 self.current_vertex,
1601 Side::Right,
1602 );
1603 self.fill.spans[right_span_idx as usize].tess().vertex(
1604 self.current_position,
1605 self.current_vertex,
1606 Side::Left,
1607 );
1608 }
1609
1610 #[cfg_attr(feature = "profiling", inline(never))]
1611 fn handle_intersections(&mut self, skip_range: Range<usize>) {
1612 let mut edges_below = mem::take(&mut self.edges_below);
1630 for edge_below in &mut edges_below {
1631 let below_min_x = self.current_position.x.min(edge_below.to.x);
1632 let below_max_x = fmax(self.current_position.x, edge_below.to.x);
1633
1634 let below_segment = LineSegment {
1635 from: self.current_position.to_f64(),
1636 to: edge_below.to.to_f64(),
1637 };
1638
1639 let mut tb_min = 1.0;
1640 let mut intersection = None;
1641 for (i, active_edge) in self.active.edges.iter().enumerate() {
1642 if skip_range.contains(&i) {
1643 continue;
1644 }
1645 if active_edge.is_merge || below_min_x > active_edge.max_x() {
1646 continue;
1647 }
1648
1649 if below_max_x < active_edge.min_x() {
1650 continue;
1663 }
1664
1665 let active_segment = LineSegment {
1666 from: active_edge.from.to_f64(),
1667 to: active_edge.to.to_f64(),
1668 };
1669
1670 if let Some((ta, tb)) = active_segment.intersection_t(&below_segment) {
1671 if tb < tb_min && tb > 0.0 && ta > 0.0 && ta <= 1.0 {
1672 tb_min = tb;
1674 intersection = Some((ta, tb, i));
1675 }
1676 }
1677 }
1678
1679 if let Some((ta, tb, active_edge_idx)) = intersection {
1680 self.process_intersection(ta, tb, active_edge_idx, edge_below, &below_segment);
1681 }
1682 }
1683 self.edges_below = edges_below;
1684
1685 }
1687
1688 #[inline(never)]
1689 fn process_intersection(
1690 &mut self,
1691 ta: f64,
1692 tb: f64,
1693 active_edge_idx: usize,
1694 edge_below: &mut PendingEdge,
1695 below_segment: &LineSegment<f64>,
1696 ) {
1697 let mut intersection_position = below_segment.sample(tb).to_f32();
1698 tess_log!(
1699 self,
1700 "-> intersection at: {:?} t={:?}|{:?}",
1701 intersection_position,
1702 ta,
1703 tb
1704 );
1705 tess_log!(
1706 self,
1707 " from {:?}->{:?} and {:?}->{:?}",
1708 self.active.edges[active_edge_idx].from,
1709 self.active.edges[active_edge_idx].to,
1710 self.current_position,
1711 edge_below.to,
1712 );
1713
1714 let active_edge = &mut self.active.edges[active_edge_idx];
1715
1716 if self.current_position == intersection_position {
1717 active_edge.from = intersection_position;
1718 let src_range = &mut self.events.edge_data[active_edge.src_edge as usize].range;
1719 let remapped_ta = remap_t_in_range(ta as f32, src_range.start..active_edge.range_end);
1720 src_range.start = remapped_ta;
1721
1722 return;
1723 }
1724
1725 if !is_after(intersection_position, self.current_position) {
1726 tess_log!(self, "fixup the intersection");
1727 intersection_position.y = self.current_position.y.next_after(f32::INFINITY);
1728 }
1729
1730 assert!(
1731 is_after(intersection_position, self.current_position),
1732 "!!! {:.9?} {:.9?}",
1733 intersection_position,
1734 self.current_position
1735 );
1736
1737 if is_near(intersection_position, edge_below.to) {
1738 tess_log!(self, "intersection near below.to");
1739 intersection_position = edge_below.to;
1740 } else if is_near(intersection_position, active_edge.to) {
1741 tess_log!(self, "intersection near active_edge.to");
1742 intersection_position = active_edge.to;
1743 }
1744
1745 let a_src_edge_data = self.events.edge_data[active_edge.src_edge as usize].clone();
1746 let b_src_edge_data = self.events.edge_data[edge_below.src_edge as usize].clone();
1747
1748 let mut inserted_evt = None;
1749 let mut flipped_active = false;
1750
1751 if active_edge.to != intersection_position && active_edge.from != intersection_position {
1752 let remapped_ta = remap_t_in_range(
1753 ta as f32,
1754 a_src_edge_data.range.start..active_edge.range_end,
1755 );
1756
1757 if is_after(active_edge.to, intersection_position) {
1758 inserted_evt = Some(self.events.insert_sorted(
1760 intersection_position,
1761 EdgeData {
1762 range: remapped_ta..active_edge.range_end,
1763 winding: active_edge.winding,
1764 to: active_edge.to,
1765 is_edge: true,
1766 ..a_src_edge_data
1767 },
1768 self.current_event_id,
1769 ));
1770 } else {
1771 tess_log!(self, "flip active edge after intersection");
1772 flipped_active = true;
1773 self.events.insert_sorted(
1774 active_edge.to,
1775 EdgeData {
1776 range: active_edge.range_end..remapped_ta,
1777 winding: -active_edge.winding,
1778 to: intersection_position,
1779 is_edge: true,
1780 ..a_src_edge_data
1781 },
1782 self.current_event_id,
1783 );
1784 }
1785
1786 active_edge.to = intersection_position;
1787 active_edge.range_end = remapped_ta;
1788 }
1789
1790 if edge_below.to != intersection_position && self.current_position != intersection_position
1791 {
1792 let remapped_tb =
1793 remap_t_in_range(tb as f32, b_src_edge_data.range.start..edge_below.range_end);
1794
1795 if is_after(edge_below.to, intersection_position) {
1796 let edge_data = EdgeData {
1797 range: remapped_tb..edge_below.range_end,
1798 winding: edge_below.winding,
1799 to: edge_below.to,
1800 is_edge: true,
1801 ..b_src_edge_data
1802 };
1803
1804 if let Some(idx) = inserted_evt {
1805 self.events
1807 .insert_sibling(idx, intersection_position, edge_data);
1808 } else {
1809 self.events.insert_sorted(
1810 intersection_position,
1811 edge_data,
1812 self.current_event_id,
1813 );
1814 }
1815 } else {
1816 tess_log!(self, "flip edge below after intersection");
1817 self.events.insert_sorted(
1818 edge_below.to,
1819 EdgeData {
1820 range: edge_below.range_end..remapped_tb,
1821 winding: -edge_below.winding,
1822 to: intersection_position,
1823 is_edge: true,
1824 ..b_src_edge_data
1825 },
1826 self.current_event_id,
1827 );
1828
1829 if flipped_active {
1830 self.events.vertex_event_sorted(
1836 intersection_position,
1837 b_src_edge_data.to_id,
1838 self.current_event_id,
1839 );
1840 }
1841 }
1842
1843 edge_below.to = intersection_position;
1844 edge_below.range_end = remapped_tb;
1845 }
1846 }
1847
1848 fn sort_active_edges(&mut self) {
1849 let y = self.current_position.y;
1858
1859 let mut keys = Vec::with_capacity(self.active.edges.len());
1860
1861 let mut has_merge_vertex = false;
1862 let mut prev_x = f32::NAN;
1863 for (i, edge) in self.active.edges.iter().enumerate() {
1864 if edge.is_merge {
1865 debug_assert!(!prev_x.is_nan());
1866 has_merge_vertex = true;
1867 keys.push((prev_x, i));
1868 } else {
1869 debug_assert!(!is_after(self.current_position, edge.to));
1870
1871 let eq_to = edge.to.y == y;
1872 let eq_from = edge.from.y == y;
1873
1874 let x = if eq_to && eq_from {
1875 let current_x = self.current_position.x;
1876 if edge.max_x() >= current_x && edge.min_x() <= current_x {
1877 self.current_position.x
1878 } else {
1879 edge.min_x()
1880 }
1881 } else if eq_from {
1882 edge.from.x
1883 } else if eq_to {
1884 edge.to.x
1885 } else {
1886 edge.solve_x_for_y(y)
1887 };
1888
1889 keys.push((fmax(x, edge.min_x()), i));
1890 prev_x = x;
1891 }
1892 }
1893
1894 keys.sort_by(|a, b| match a.0.partial_cmp(&b.0).unwrap() {
1895 Ordering::Less => Ordering::Less,
1896 Ordering::Greater => Ordering::Greater,
1897 Ordering::Equal => {
1898 let a = &self.active.edges[a.1];
1899 let b = &self.active.edges[b.1];
1900 match (a.is_merge, b.is_merge) {
1901 (false, false) => {
1902 let slope_a = slope(a.to - a.from);
1903 let slope_b = slope(b.to - b.from);
1904 slope_b.partial_cmp(&slope_a).unwrap_or(Ordering::Equal)
1905 }
1906 (true, false) => Ordering::Greater,
1907 (false, true) => Ordering::Less,
1908 (true, true) => Ordering::Equal,
1909 }
1910 }
1911 });
1912
1913 let mut new_active_edges = Vec::with_capacity(self.active.edges.len());
1914 for &(_, idx) in &keys {
1915 new_active_edges.push(self.active.edges[idx]);
1916 }
1917
1918 self.active.edges = new_active_edges;
1919
1920 if !has_merge_vertex {
1921 return;
1922 }
1923
1924 let mut winding_number = 0;
1925 for i in 0..self.active.edges.len() {
1926 let needs_swap = {
1927 let edge = &self.active.edges[i];
1928 if edge.is_merge {
1929 !self.fill_rule.is_in(winding_number)
1930 } else {
1931 winding_number += edge.winding;
1932 false
1933 }
1934 };
1935
1936 if needs_swap {
1937 let mut w = winding_number;
1938 tess_log!(self, "Fixing up merge vertex after sort.");
1939 let mut idx = i;
1940 while idx > 0 {
1941 w -= self.active.edges[idx - 1].winding;
1943 self.active.edges.swap(idx, idx - 1);
1944
1945 if self.fill_rule.is_in(w) {
1946 break;
1947 }
1948
1949 idx -= 1;
1950 }
1951 }
1952 }
1953 }
1954
1955 #[inline(never)]
1956 fn recover_from_error(&mut self, _error: InternalError, output: &mut dyn FillGeometryBuilder) {
1957 tess_log!(self, "Attempt to recover error {:?}", _error);
1958
1959 self.sort_active_edges();
1960
1961 if !self.assume_no_intersection {
1962 debug_assert!(self
1963 .active
1964 .edges
1965 .first()
1966 .map(|e| !e.is_merge)
1967 .unwrap_or(true));
1968 }
1969 let len = self.active.edges.len();
1979 if len > 1 && self.active.edges[len - 1].is_merge {
1980 self.active.edges.swap(len - 1, len - 2);
1981 }
1982
1983 let mut winding = WindingState::new();
1984
1985 for edge in &self.active.edges {
1986 if edge.is_merge {
1987 winding.span_index += 1;
1988 } else {
1989 winding.update(self.fill_rule, edge.winding);
1990 }
1991
1992 if winding.span_index >= self.fill.spans.len() as i32 {
1993 self.fill
1994 .begin_span(winding.span_index, &edge.from, edge.from_id);
1995 }
1996 }
1997
1998 while self.fill.spans.len() > (winding.span_index + 1) as usize {
1999 self.fill.spans.last_mut().unwrap().tess().flush(output);
2000 self.fill.spans.pop();
2001 }
2002
2003 tess_log!(self, "-->");
2004
2005 #[cfg(debug_assertions)]
2006 self.log_active_edges();
2007 }
2008
2009 #[cfg_attr(feature = "profiling", inline(never))]
2010 fn sort_edges_below(&mut self) {
2011 self.edges_below
2012 .sort_unstable_by(|a, b| a.sort_key.partial_cmp(&b.sort_key).unwrap_or(Ordering::Equal));
2013 }
2014
2015 #[cfg_attr(feature = "profiling", inline(never))]
2016 fn handle_coincident_edges_below(&mut self) {
2017 if self.edges_below.len() < 2 {
2018 return;
2019 }
2020
2021 for idx in (0..(self.edges_below.len() - 1)).rev() {
2022 let a_idx = idx;
2023 let b_idx = idx + 1;
2024
2025 let a_slope = self.edges_below[a_idx].sort_key;
2026 let b_slope = self.edges_below[b_idx].sort_key;
2027
2028 const THRESHOLD: f32 = 0.00005;
2029
2030 let angle_is_close = if a_slope.abs() <= 1.0 {
2034 (a_slope - b_slope).abs() < THRESHOLD
2035 } else {
2036 (1.0 / a_slope - 1.0 / b_slope).abs() < THRESHOLD
2037 };
2038
2039 if angle_is_close {
2040 self.merge_coincident_edges(a_idx, b_idx);
2041 }
2042 }
2043 }
2044
2045 #[cold]
2046 fn merge_coincident_edges(&mut self, a_idx: usize, b_idx: usize) {
2047 let a_to = self.edges_below[a_idx].to;
2048 let b_to = self.edges_below[b_idx].to;
2049
2050 let (lower_idx, upper_idx, split) = match compare_positions(a_to, b_to) {
2051 Ordering::Greater => (a_idx, b_idx, true),
2052 Ordering::Less => (b_idx, a_idx, true),
2053 Ordering::Equal => (a_idx, b_idx, false),
2054 };
2055
2056 tess_log!(
2057 self,
2058 "coincident edges {:?} -> {:?} / {:?}",
2059 self.current_position,
2060 a_to,
2061 b_to
2062 );
2063
2064 tess_log!(
2065 self,
2066 "update winding: {:?} -> {:?}",
2067 self.edges_below[upper_idx].winding,
2068 self.edges_below[upper_idx].winding + self.edges_below[lower_idx].winding
2069 );
2070 self.edges_below[upper_idx].winding += self.edges_below[lower_idx].winding;
2071 let split_point = self.edges_below[upper_idx].to;
2072
2073 tess_log!(
2074 self,
2075 "remove coincident edge {:?}, split:{:?}",
2076 a_idx,
2077 split
2078 );
2079 let edge = self.edges_below.remove(lower_idx);
2080
2081 if !split {
2082 return;
2083 }
2084
2085 let src_edge_data = self.events.edge_data[edge.src_edge as usize].clone();
2086
2087 let t = LineSegment {
2088 from: self.current_position,
2089 to: edge.to,
2090 }
2091 .solve_t_for_y(split_point.y);
2092
2093 let src_range = src_edge_data.range.start..edge.range_end;
2094 let t_remapped = remap_t_in_range(t, src_range);
2095
2096 let edge_data = EdgeData {
2097 range: t_remapped..edge.range_end,
2098 winding: edge.winding,
2099 to: edge.to,
2100 is_edge: true,
2101 ..src_edge_data
2102 };
2103
2104 self.events
2105 .insert_sorted(split_point, edge_data, self.current_event_id);
2106 }
2107
2108 fn reset(&mut self) {
2109 self.current_position = point(f32::MIN, f32::MIN);
2110 self.current_vertex = VertexId::INVALID;
2111 self.current_event_id = INVALID_EVENT_ID;
2112 self.active.edges.clear();
2113 self.edges_below.clear();
2114 self.fill.spans.clear();
2115 }
2116}
2117
2118pub(crate) fn points_are_equal(a: Point, b: Point) -> bool {
2119 a == b
2120}
2121
2122pub(crate) fn compare_positions(a: Point, b: Point) -> Ordering {
2123 if a.y > b.y {
2128 return Ordering::Greater;
2129 }
2130 if a.y < b.y {
2131 return Ordering::Less;
2132 }
2133 if a.x > b.x {
2134 return Ordering::Greater;
2135 }
2136 if a.x < b.x {
2137 return Ordering::Less;
2138 }
2139
2140 Ordering::Equal
2141}
2142
2143#[inline]
2144pub(crate) fn is_after(a: Point, b: Point) -> bool {
2145 a.y > b.y || (a.y == b.y && a.x > b.x)
2146}
2147
2148#[inline]
2149pub(crate) fn is_near(a: Point, b: Point) -> bool {
2150 (a - b).square_length() < 0.000000001
2151}
2152
2153#[inline]
2154fn reorient(p: Point) -> Point {
2155 point(p.y, -p.x)
2156}
2157
2158pub struct FillVertex<'l> {
2160 pub(crate) position: Point,
2161 pub(crate) events: &'l EventQueue,
2162 pub(crate) current_event: TessEventId,
2163 pub(crate) attrib_buffer: &'l mut [f32],
2164 pub(crate) attrib_store: Option<&'l dyn AttributeStore>,
2165}
2166
2167impl<'l> FillVertex<'l> {
2168 pub fn position(&self) -> Point {
2169 self.position
2170 }
2171
2172 pub fn sources(&self) -> VertexSourceIterator {
2174 VertexSourceIterator {
2175 events: self.events,
2176 id: self.current_event,
2177 prev: None,
2178 }
2179 }
2180
2181 pub fn as_endpoint_id(&self) -> Option<EndpointId> {
2191 let mut current = self.current_event;
2192 while self.events.valid_id(current) {
2193 let edge = &self.events.edge_data[current as usize];
2194 let t = edge.range.start;
2195 if t == 0.0 {
2196 return Some(edge.from_id);
2197 }
2198 if t == 1.0 {
2199 return Some(edge.to_id);
2200 }
2201
2202 current = self.events.next_sibling_id(current)
2203 }
2204
2205 None
2206 }
2207
2208 pub fn interpolated_attributes(&mut self) -> Attributes {
2210 if self.attrib_store.is_none() {
2211 return NO_ATTRIBUTES;
2212 }
2213
2214 let store = self.attrib_store.unwrap();
2215
2216 let mut sources = VertexSourceIterator {
2217 events: self.events,
2218 id: self.current_event,
2219 prev: None,
2220 };
2221
2222 let num_attributes = store.num_attributes();
2223
2224 let first = sources.next().unwrap();
2225 let mut next = sources.next();
2226
2227 if next.is_none() {
2229 if let VertexSource::Endpoint { id } = first {
2230 return store.get(id);
2231 }
2232 }
2233
2234 match first {
2236 VertexSource::Endpoint { id } => {
2237 let a = store.get(id);
2238 assert_eq!(a.len(), num_attributes);
2239 assert_eq!(self.attrib_buffer.len(), num_attributes);
2240 self.attrib_buffer[..num_attributes].clone_from_slice(&a[..num_attributes]);
2241 }
2242 VertexSource::Edge { from, to, t } => {
2243 let a = store.get(from);
2244 let b = store.get(to);
2245 assert_eq!(a.len(), num_attributes);
2246 assert_eq!(b.len(), num_attributes);
2247 assert_eq!(self.attrib_buffer.len(), num_attributes);
2248 for i in 0..num_attributes {
2249 self.attrib_buffer[i] = a[i] * (1.0 - t) + b[i] * t;
2250 }
2251 }
2252 }
2253
2254 let mut div = 1.0;
2255 loop {
2256 match next {
2257 Some(VertexSource::Endpoint { id }) => {
2258 let a = store.get(id);
2259 assert_eq!(a.len(), num_attributes);
2260 assert_eq!(self.attrib_buffer.len(), num_attributes);
2261 for (i, &att) in a.iter().enumerate() {
2262 self.attrib_buffer[i] += att;
2263 }
2264 }
2265 Some(VertexSource::Edge { from, to, t }) => {
2266 let a = store.get(from);
2267 let b = store.get(to);
2268 assert_eq!(a.len(), num_attributes);
2269 assert_eq!(b.len(), num_attributes);
2270 assert_eq!(self.attrib_buffer.len(), num_attributes);
2271 for i in 0..num_attributes {
2272 self.attrib_buffer[i] += a[i] * (1.0 - t) + b[i] * t;
2273 }
2274 }
2275 None => {
2276 break;
2277 }
2278 }
2279 div += 1.0;
2280 next = sources.next();
2281 }
2282
2283 if div > 1.0 {
2284 for attribute in self.attrib_buffer.iter_mut() {
2285 *attribute /= div;
2286 }
2287 }
2288
2289 self.attrib_buffer
2290 }
2291}
2292
2293#[derive(Clone)]
2295pub struct VertexSourceIterator<'l> {
2296 events: &'l EventQueue,
2297 id: TessEventId,
2298 prev: Option<VertexSource>,
2299}
2300
2301impl<'l> Iterator for VertexSourceIterator<'l> {
2302 type Item = VertexSource;
2303 #[inline]
2304 fn next(&mut self) -> Option<VertexSource> {
2305 let mut src;
2306 loop {
2307 if self.id == INVALID_EVENT_ID {
2308 return None;
2309 }
2310
2311 let edge = &self.events.edge_data[self.id as usize];
2312
2313 self.id = self.events.next_sibling_id(self.id);
2314
2315 let t = edge.range.start;
2316
2317 src = if t == 0.0 {
2318 Some(VertexSource::Endpoint { id: edge.from_id })
2319 } else if t == 1.0 {
2320 Some(VertexSource::Endpoint { id: edge.to_id })
2321 } else {
2322 Some(VertexSource::Edge {
2323 from: edge.from_id,
2324 to: edge.to_id,
2325 t,
2326 })
2327 };
2328
2329 if src != self.prev {
2330 break;
2331 }
2332 }
2333
2334 self.prev = src;
2335 src
2336 }
2337}
2338
2339fn remap_t_in_range(val: f32, range: Range<f32>) -> f32 {
2340 if range.end > range.start {
2341 let d = range.end - range.start;
2342 range.start + val * d
2343 } else {
2344 let d = range.start - range.end;
2345 range.end + (1.0 - val) * d
2346 }
2347}
2348
2349pub struct FillBuilder<'l> {
2350 events: EventQueueBuilder,
2351 next_id: EndpointId,
2352 first_id: EndpointId,
2353 first_position: Point,
2354 horizontal_sweep: bool,
2355 attrib_store: SimpleAttributeStore,
2356 tessellator: &'l mut FillTessellator,
2357 output: &'l mut dyn FillGeometryBuilder,
2358 options: &'l FillOptions,
2359}
2360
2361impl<'l> FillBuilder<'l> {
2362 fn new(
2363 num_attributes: usize,
2364 tessellator: &'l mut FillTessellator,
2365 options: &'l FillOptions,
2366 output: &'l mut dyn FillGeometryBuilder,
2367 ) -> Self {
2368 let events = core::mem::take(&mut tessellator.events)
2369 .into_builder(options.tolerance);
2370
2371 FillBuilder {
2372 events,
2373 next_id: EndpointId(0),
2374 first_id: EndpointId(0),
2375 horizontal_sweep: options.sweep_orientation == Orientation::Horizontal,
2376 first_position: point(0.0, 0.0),
2377 tessellator,
2378 options,
2379 output,
2380 attrib_store: SimpleAttributeStore::new(num_attributes),
2381 }
2382 }
2383
2384 #[inline]
2385 fn position(&self, p: Point) -> Point {
2386 if self.horizontal_sweep {
2387 point(-p.y, p.x)
2388 } else {
2389 p
2390 }
2391 }
2392
2393 pub fn num_attributes(&self) -> usize {
2394 self.attrib_store.num_attributes()
2395 }
2396
2397 pub fn begin(&mut self, at: Point, attributes: Attributes) -> EndpointId {
2398 let at = self.position(at);
2399 let id = self.attrib_store.add(attributes);
2400 self.first_id = id;
2401 self.first_position = at;
2402 self.events.begin(at, id);
2403
2404 id
2405 }
2406
2407 pub fn end(&mut self, _close: bool) {
2408 self.events.end(self.first_position, self.first_id);
2409 }
2410
2411 pub fn line_to(&mut self, to: Point, attributes: Attributes) -> EndpointId {
2412 let to = self.position(to);
2413 let id = self.attrib_store.add(attributes);
2414 self.events.line_segment(to, id, 0.0, 1.0);
2415
2416 id
2417 }
2418
2419 pub fn quadratic_bezier_to(
2420 &mut self,
2421 ctrl: Point,
2422 to: Point,
2423 attributes: Attributes,
2424 ) -> EndpointId {
2425 let ctrl = self.position(ctrl);
2426 let to = self.position(to);
2427 let id = self.attrib_store.add(attributes);
2428 self.events.quadratic_bezier_segment(ctrl, to, id);
2429
2430 id
2431 }
2432
2433 pub fn cubic_bezier_to(
2434 &mut self,
2435 ctrl1: Point,
2436 ctrl2: Point,
2437 to: Point,
2438 attributes: Attributes,
2439 ) -> EndpointId {
2440 let ctrl1 = self.position(ctrl1);
2441 let ctrl2 = self.position(ctrl2);
2442 let to = self.position(to);
2443 let id = self.attrib_store.add(attributes);
2444 self.events.cubic_bezier_segment(ctrl1, ctrl2, to, id);
2445
2446 id
2447 }
2448
2449 pub fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
2450 self.attrib_store.reserve(endpoints);
2451 self.events.reserve(endpoints + ctrl_points * 2);
2452 }
2453
2454 pub fn add_circle(
2455 &mut self,
2456 center: Point,
2457 radius: f32,
2458 winding: Winding,
2459 attributes: Attributes,
2460 ) {
2461 let radius = radius.abs();
2469 let dir = match winding {
2470 Winding::Positive => 1.0,
2471 Winding::Negative => -1.0,
2472 };
2473
2474 self.reserve(16, 8);
2475
2476 let tan_pi_over_8 = 0.41421357;
2477 let d = radius * tan_pi_over_8;
2478
2479 let start = center + vector(-radius, 0.0);
2480 self.begin(start, attributes);
2481 let ctrl_0 = center + vector(-radius, -d * dir);
2482 let mid_0 = center + vector(-1.0, -dir) * radius * FRAC_1_SQRT_2;
2483 let ctrl_1 = center + vector(-d, -radius * dir);
2484 let mid_1 = center + vector(0.0, -radius * dir);
2485 self.quadratic_bezier_to(ctrl_0, mid_0, attributes);
2486 self.end(false);
2487 self.begin(mid_0, attributes);
2488 self.quadratic_bezier_to(ctrl_1, mid_1, attributes);
2489 self.end(false);
2490
2491 self.begin(mid_1, attributes);
2492 let ctrl_0 = center + vector(d, -radius * dir);
2493 let mid_2 = center + vector(1.0, -dir) * radius * FRAC_1_SQRT_2;
2494 let ctrl_1 = center + vector(radius, -d * dir);
2495 let mid_3 = center + vector(radius, 0.0);
2496 self.quadratic_bezier_to(ctrl_0, mid_2, attributes);
2497 self.end(false);
2498 self.begin(mid_2, attributes);
2499 self.quadratic_bezier_to(ctrl_1, mid_3, attributes);
2500 self.end(false);
2501
2502 self.begin(mid_3, attributes);
2503 let ctrl_0 = center + vector(radius, d * dir);
2504 let mid_4 = center + vector(1.0, dir) * radius * FRAC_1_SQRT_2;
2505 let ctrl_1 = center + vector(d, radius * dir);
2506 let mid_5 = center + vector(0.0, radius * dir);
2507 self.quadratic_bezier_to(ctrl_0, mid_4, attributes);
2508 self.end(false);
2509 self.begin(mid_4, attributes);
2510 self.quadratic_bezier_to(ctrl_1, mid_5, attributes);
2511 self.end(false);
2512
2513 self.begin(mid_5, attributes);
2514 let ctrl_0 = center + vector(-d, radius * dir);
2515 let mid_6 = center + vector(-1.0, dir) * radius * FRAC_1_SQRT_2;
2516 let ctrl_1 = center + vector(-radius, d * dir);
2517 self.quadratic_bezier_to(ctrl_0, mid_6, attributes);
2518 self.end(false);
2519 self.begin(mid_6, attributes);
2520 self.quadratic_bezier_to(ctrl_1, start, attributes);
2521 self.end(false);
2522
2523 self.begin(start, attributes);
2524 self.line_to(mid_0, attributes);
2525 self.line_to(mid_1, attributes);
2526 self.line_to(mid_2, attributes);
2527 self.line_to(mid_3, attributes);
2528 self.line_to(mid_4, attributes);
2529 self.line_to(mid_5, attributes);
2530 self.line_to(mid_6, attributes);
2531 self.close();
2532 }
2533
2534 pub fn build(self) -> TessellationResult {
2535 let mut event_queue = self.events.build();
2536 core::mem::swap(&mut self.tessellator.events, &mut event_queue);
2537
2538 let attrib_store = if self.attrib_store.num_attributes > 0 {
2539 Some(&self.attrib_store as &dyn AttributeStore)
2540 } else {
2541 None
2542 };
2543
2544 self.tessellator
2545 .tessellate_impl(self.options, attrib_store, self.output)
2546 }
2547}
2548
2549impl<'l> PathBuilder for FillBuilder<'l> {
2550 fn num_attributes(&self) -> usize {
2551 self.attrib_store.num_attributes()
2552 }
2553
2554 fn begin(&mut self, at: Point, attributes: Attributes) -> EndpointId {
2555 self.begin(at, attributes)
2556 }
2557
2558 fn end(&mut self, close: bool) {
2559 self.end(close)
2560 }
2561
2562 fn line_to(&mut self, to: Point, attributes: Attributes) -> EndpointId {
2563 self.line_to(to, attributes)
2564 }
2565
2566 fn quadratic_bezier_to(
2567 &mut self,
2568 ctrl: Point,
2569 to: Point,
2570 attributes: Attributes,
2571 ) -> EndpointId {
2572 self.quadratic_bezier_to(ctrl, to, attributes)
2573 }
2574
2575 fn cubic_bezier_to(
2576 &mut self,
2577 ctrl1: Point,
2578 ctrl2: Point,
2579 to: Point,
2580 attributes: Attributes,
2581 ) -> EndpointId {
2582 self.cubic_bezier_to(ctrl1, ctrl2, to, attributes)
2583 }
2584
2585 fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
2586 self.reserve(endpoints, ctrl_points)
2587 }
2588
2589 fn add_circle(&mut self, center: Point, radius: f32, winding: Winding, attributes: Attributes) {
2590 self.add_circle(center, radius, winding, attributes)
2591 }
2592}
2593
2594impl<'l> Build for FillBuilder<'l> {
2595 type PathType = TessellationResult;
2596
2597 #[inline]
2598 fn build(self) -> TessellationResult {
2599 self.build()
2600 }
2601}
2602
2603fn log_svg_preamble(_tess: &FillTessellator) {
2604 tess_log!(
2605 _tess,
2606 r#"
2607<svg viewBox="0 0 1000 1000">
2608
2609<style type="text/css">
2610<![CDATA[
2611 path.sweep-line {{
2612 stroke: red;
2613 fill: none;
2614 }}
2615
2616 path.edge {{
2617 stroke: blue;
2618 fill: none;
2619 }}
2620
2621 path.edge.select {{
2622 stroke: green;
2623 fill: none;
2624 }}
2625
2626 circle.merge {{
2627 fill: yellow;
2628 stroke: orange;
2629 fill-opacity: 1;
2630 }}
2631
2632 circle.current {{
2633 fill: white;
2634 stroke: grey;
2635 fill-opacity: 1;
2636 }}
2637
2638 g.active-edges {{
2639 opacity: 0;
2640 }}
2641
2642 g.active-edges.select {{
2643 opacity: 1;
2644 }}
2645]]>
2646</style>
2647"#
2648 );
2649}
2650
2651#[cfg(test)]
2652use crate::geometry_builder::*;
2653
2654#[cfg(test)]
2655fn eq(a: Point, b: Point) -> bool {
2656 (a.x - b.x).abs() < 0.00001 && (a.y - b.y).abs() < 0.00001
2657}
2658
2659#[cfg(test)]
2660fn at_endpoint(src: &VertexSource, endpoint: EndpointId) -> bool {
2661 match src {
2662 VertexSource::Edge { .. } => false,
2663 VertexSource::Endpoint { id } => *id == endpoint,
2664 }
2665}
2666
2667#[cfg(test)]
2668fn on_edge(src: &VertexSource, from_id: EndpointId, to_id: EndpointId, d: f32) -> bool {
2669 match src {
2670 VertexSource::Edge { t, from, to, .. } => {
2671 *from == from_id
2672 && *to == to_id
2673 && ((d - *t).abs() < 0.00001 || (1.0 - d - *t).abs() <= 0.00001)
2674 }
2675 VertexSource::Endpoint { .. } => false,
2676 }
2677}
2678
2679#[test]
2680fn fill_vertex_source_01() {
2681 use crate::path::commands::PathCommands;
2682 use crate::path::AttributeSlice;
2683
2684 let endpoints: &[Point] = &[point(0.0, 0.0), point(1.0, 1.0), point(0.0, 2.0)];
2685
2686 let attributes = &[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0];
2687
2688 let mut cmds = PathCommands::builder();
2689 cmds.begin(EndpointId(0));
2690 cmds.line_to(EndpointId(1));
2691 cmds.line_to(EndpointId(2));
2692 cmds.end(true);
2693
2694 let cmds = cmds.build();
2695
2696 let mut tess = FillTessellator::new();
2697 tess.tessellate_with_ids(
2698 cmds.iter(),
2699 &(endpoints, endpoints),
2700 Some(&AttributeSlice::new(attributes, 3)),
2701 &FillOptions::default(),
2702 &mut CheckVertexSources { next_vertex: 0 },
2703 )
2704 .unwrap();
2705
2706 struct CheckVertexSources {
2707 next_vertex: u32,
2708 }
2709
2710 impl GeometryBuilder for CheckVertexSources {
2711 fn add_triangle(&mut self, _: VertexId, _: VertexId, _: VertexId) {}
2712 fn abort_geometry(&mut self) {}
2713 }
2714
2715 impl FillGeometryBuilder for CheckVertexSources {
2716 fn add_fill_vertex(
2717 &mut self,
2718 mut vertex: FillVertex,
2719 ) -> Result<VertexId, GeometryBuilderError> {
2720 let pos = vertex.position();
2721 for src in vertex.sources() {
2722 if eq(pos, point(0.0, 0.0)) {
2723 assert!(at_endpoint(&src, EndpointId(0)))
2724 } else if eq(pos, point(1.0, 1.0)) {
2725 assert!(at_endpoint(&src, EndpointId(1)))
2726 } else if eq(pos, point(0.0, 2.0)) {
2727 assert!(at_endpoint(&src, EndpointId(2)))
2728 } else {
2729 panic!()
2730 }
2731 }
2732
2733 if eq(pos, point(0.0, 0.0)) {
2734 assert_eq!(vertex.interpolated_attributes(), &[1.0, 0.0, 0.0])
2735 } else if eq(pos, point(1.0, 1.0)) {
2736 assert_eq!(vertex.interpolated_attributes(), &[0.0, 1.0, 0.0])
2737 } else if eq(pos, point(0.0, 2.0)) {
2738 assert_eq!(vertex.interpolated_attributes(), &[0.0, 0.0, 1.0])
2739 }
2740
2741 let id = self.next_vertex;
2742 self.next_vertex += 1;
2743
2744 Ok(VertexId(id))
2745 }
2746 }
2747}
2748
2749#[test]
2750fn fill_vertex_source_02() {
2751 let mut path = crate::path::Path::builder_with_attributes(3);
2760 let a = path.begin(point(1.0, 0.0), &[1.0, 0.0, 1.0]);
2761 let b = path.line_to(point(2.0, 0.0), &[2.0, 0.0, 1.0]);
2762 let c = path.line_to(point(2.0, 4.0), &[3.0, 0.0, 1.0]);
2763 let d = path.line_to(point(1.0, 4.0), &[4.0, 0.0, 1.0]);
2764 path.end(true);
2765 let e = path.begin(point(0.0, 1.0), &[0.0, 1.0, 2.0]);
2766 let f = path.line_to(point(0.0, 3.0), &[0.0, 2.0, 2.0]);
2767 let g = path.line_to(point(3.0, 3.0), &[0.0, 3.0, 2.0]);
2768 let h = path.line_to(point(3.0, 1.0), &[0.0, 4.0, 2.0]);
2769 path.end(true);
2770
2771 let path = path.build();
2772
2773 let mut tess = FillTessellator::new();
2774 tess.tessellate_with_ids(
2775 path.id_iter(),
2776 &path,
2777 Some(&path),
2778 &FillOptions::default(),
2779 &mut CheckVertexSources {
2780 next_vertex: 0,
2781 a,
2782 b,
2783 c,
2784 d,
2785 e,
2786 f,
2787 g,
2788 h,
2789 },
2790 )
2791 .unwrap();
2792
2793 struct CheckVertexSources {
2794 next_vertex: u32,
2795 a: EndpointId,
2796 b: EndpointId,
2797 c: EndpointId,
2798 d: EndpointId,
2799 e: EndpointId,
2800 f: EndpointId,
2801 g: EndpointId,
2802 h: EndpointId,
2803 }
2804
2805 impl GeometryBuilder for CheckVertexSources {
2806 fn add_triangle(&mut self, _: VertexId, _: VertexId, _: VertexId) {}
2807 }
2808
2809 impl FillGeometryBuilder for CheckVertexSources {
2810 fn add_fill_vertex(
2811 &mut self,
2812 mut vertex: FillVertex,
2813 ) -> Result<VertexId, GeometryBuilderError> {
2814 let pos = vertex.position();
2815 for src in vertex.sources() {
2816 if eq(pos, point(1.0, 0.0)) {
2817 assert!(at_endpoint(&src, self.a));
2818 } else if eq(pos, point(2.0, 0.0)) {
2819 assert!(at_endpoint(&src, self.b));
2820 } else if eq(pos, point(2.0, 4.0)) {
2821 assert!(at_endpoint(&src, self.c));
2822 } else if eq(pos, point(1.0, 4.0)) {
2823 assert!(at_endpoint(&src, self.d));
2824 } else if eq(pos, point(0.0, 1.0)) {
2825 assert!(at_endpoint(&src, self.e));
2826 } else if eq(pos, point(0.0, 3.0)) {
2827 assert!(at_endpoint(&src, self.f));
2828 } else if eq(pos, point(3.0, 3.0)) {
2829 assert!(at_endpoint(&src, self.g));
2830 } else if eq(pos, point(3.0, 1.0)) {
2831 assert!(at_endpoint(&src, self.h));
2832 } else if eq(pos, point(1.0, 1.0)) {
2833 assert!(
2834 on_edge(&src, self.h, self.e, 2.0 / 3.0)
2835 || on_edge(&src, self.d, self.a, 3.0 / 4.0)
2836 );
2837 } else if eq(pos, point(2.0, 1.0)) {
2838 assert!(
2839 on_edge(&src, self.h, self.e, 1.0 / 3.0)
2840 || on_edge(&src, self.b, self.c, 1.0 / 4.0)
2841 );
2842 } else if eq(pos, point(1.0, 3.0)) {
2843 assert!(
2844 on_edge(&src, self.f, self.g, 1.0 / 3.0)
2845 || on_edge(&src, self.d, self.a, 1.0 / 4.0)
2846 );
2847 } else if eq(pos, point(2.0, 3.0)) {
2848 assert!(
2849 on_edge(&src, self.f, self.g, 2.0 / 3.0)
2850 || on_edge(&src, self.b, self.c, 3.0 / 4.0)
2851 );
2852 } else {
2853 panic!()
2854 }
2855 }
2856
2857 fn assert_attr(a: Attributes, b: Attributes) {
2858 for i in 0..a.len() {
2859 let are_equal = (a[i] - b[i]).abs() < 0.001;
2860 #[cfg(feature = "std")]
2861 if !are_equal {
2862 std::println!("{a:?} != {b:?}");
2863 }
2864 assert!(are_equal);
2865 }
2866
2867 assert_eq!(a.len(), b.len());
2868 }
2869
2870 let pos = vertex.position();
2871 let attribs = vertex.interpolated_attributes();
2872 if eq(pos, point(1.0, 0.0)) {
2873 assert_attr(attribs, &[1.0, 0.0, 1.0]);
2874 } else if eq(pos, point(2.0, 0.0)) {
2875 assert_attr(attribs, &[2.0, 0.0, 1.0]);
2876 } else if eq(pos, point(2.0, 4.0)) {
2877 assert_attr(attribs, &[3.0, 0.0, 1.0]);
2878 } else if eq(pos, point(1.0, 4.0)) {
2879 assert_attr(attribs, &[4.0, 0.0, 1.0]);
2880 } else if eq(pos, point(0.0, 1.0)) {
2881 assert_attr(attribs, &[0.0, 1.0, 2.0]);
2882 } else if eq(pos, point(0.0, 3.0)) {
2883 assert_attr(attribs, &[0.0, 2.0, 2.0]);
2884 } else if eq(pos, point(3.0, 3.0)) {
2885 assert_attr(attribs, &[0.0, 3.0, 2.0]);
2886 } else if eq(pos, point(3.0, 1.0)) {
2887 assert_attr(attribs, &[0.0, 4.0, 2.0]);
2888 } else if eq(pos, point(1.0, 1.0)) {
2889 assert_attr(attribs, &[0.875, 1.0, 1.5]);
2890 } else if eq(pos, point(2.0, 1.0)) {
2891 assert_attr(attribs, &[1.125, 1.5, 1.5]);
2892 } else if eq(pos, point(1.0, 3.0)) {
2893 assert_attr(attribs, &[1.625, 1.16666, 1.5]);
2894 } else if eq(pos, point(2.0, 3.0)) {
2895 assert_attr(attribs, &[1.375, 1.33333, 1.5]);
2896 }
2897
2898 let id = self.next_vertex;
2899 self.next_vertex += 1;
2900
2901 Ok(VertexId(id))
2902 }
2903 }
2904}
2905
2906#[test]
2907fn fill_vertex_source_03() {
2908 use crate::path::commands::PathCommands;
2909 use crate::path::AttributeSlice;
2910
2911 let endpoints: &[Point] = &[
2921 point(0.0, 0.0),
2922 point(2.0, 0.0),
2923 point(1.0, 1.0),
2924 point(0.0, 2.0),
2925 point(2.0, 2.0),
2926 point(1.0, 1.0),
2927 ];
2928
2929 let attributes = &[0.0, 0.0, 1.0, 0.0, 0.0, 2.0];
2930
2931 let mut cmds = PathCommands::builder();
2932 cmds.begin(EndpointId(0));
2933 cmds.line_to(EndpointId(1));
2934 cmds.line_to(EndpointId(2));
2935 cmds.end(true);
2936 cmds.begin(EndpointId(3));
2937 cmds.line_to(EndpointId(4));
2938 cmds.line_to(EndpointId(5));
2939 cmds.end(true);
2940
2941 let cmds = cmds.build();
2942
2943 let mut tess = FillTessellator::new();
2944 tess.tessellate_with_ids(
2945 cmds.iter(),
2946 &(endpoints, endpoints),
2947 Some(&AttributeSlice::new(attributes, 1)),
2948 &FillOptions::default(),
2949 &mut CheckVertexSources { next_vertex: 0 },
2950 )
2951 .unwrap();
2952
2953 struct CheckVertexSources {
2954 next_vertex: u32,
2955 }
2956
2957 impl GeometryBuilder for CheckVertexSources {
2958 fn add_triangle(&mut self, _: VertexId, _: VertexId, _: VertexId) {}
2959 }
2960
2961 impl FillGeometryBuilder for CheckVertexSources {
2962 fn add_fill_vertex(
2963 &mut self,
2964 mut vertex: FillVertex,
2965 ) -> Result<VertexId, GeometryBuilderError> {
2966 if eq(vertex.position(), point(1.0, 1.0)) {
2967 assert_eq!(vertex.interpolated_attributes(), &[1.5]);
2968 assert_eq!(vertex.sources().count(), 2);
2969 } else {
2970 assert_eq!(vertex.interpolated_attributes(), &[0.0]);
2971 assert_eq!(vertex.sources().count(), 1);
2972 }
2973
2974 let id = self.next_vertex;
2975 self.next_vertex += 1;
2976
2977 Ok(VertexId(id))
2978 }
2979 }
2980}
2981
2982#[test]
2983fn fill_builder_vertex_source() {
2984 let mut tess = FillTessellator::new();
2985 let options = FillOptions::default();
2986
2987 let mut check = CheckVertexSources { next_vertex: 0 };
2988 let mut builder = tess.builder(&options, &mut check);
2989
2990 assert_eq!(builder.begin(point(0.0, 0.0)), EndpointId(0));
2991 assert_eq!(builder.line_to(point(1.0, 1.0)), EndpointId(1));
2992 assert_eq!(builder.line_to(point(0.0, 2.0)), EndpointId(2));
2993 builder.end(true);
2994
2995 builder.build().unwrap();
2996
2997 struct CheckVertexSources {
2998 next_vertex: u32,
2999 }
3000
3001 impl GeometryBuilder for CheckVertexSources {
3002 fn add_triangle(&mut self, _: VertexId, _: VertexId, _: VertexId) {}
3003 }
3004
3005 impl FillGeometryBuilder for CheckVertexSources {
3006 fn add_fill_vertex(
3007 &mut self,
3008 vertex: FillVertex,
3009 ) -> Result<VertexId, GeometryBuilderError> {
3010 let pos = vertex.position();
3011 for src in vertex.sources() {
3012 if eq(pos, point(0.0, 0.0)) {
3013 assert!(at_endpoint(&src, EndpointId(0)))
3014 } else if eq(pos, point(1.0, 1.0)) {
3015 assert!(at_endpoint(&src, EndpointId(1)))
3016 } else if eq(pos, point(0.0, 2.0)) {
3017 assert!(at_endpoint(&src, EndpointId(2)))
3018 } else {
3019 panic!()
3020 }
3021 }
3022
3023 let id = self.next_vertex;
3024 self.next_vertex += 1;
3025
3026 Ok(VertexId(id))
3027 }
3028 }
3029}