lyon_tessellation/
event_queue.rs

1use crate::fill::{compare_positions, is_after};
2use crate::geom::{CubicBezierSegment, LineSegment, QuadraticBezierSegment};
3use crate::math::{point, Point};
4use crate::path::private::DebugValidator;
5use crate::path::{EndpointId, IdEvent, PathEvent, PositionStore};
6use crate::Orientation;
7
8use core::cmp::Ordering;
9use core::mem::swap;
10use core::ops::Range;
11use alloc::vec::Vec;
12
13#[inline]
14fn reorient(p: Point) -> Point {
15    point(-p.y, p.x)
16}
17
18pub(crate) type TessEventId = u32;
19
20pub(crate) const INVALID_EVENT_ID: TessEventId = u32::MAX;
21
22pub(crate) struct Event {
23    pub next_sibling: TessEventId,
24    pub next_event: TessEventId,
25    pub position: Point,
26}
27
28#[derive(Clone, Debug)]
29pub(crate) struct EdgeData {
30    pub to: Point,
31    pub range: core::ops::Range<f32>,
32    pub winding: i16,
33    pub is_edge: bool,
34    pub from_id: EndpointId,
35    pub to_id: EndpointId,
36}
37
38#[doc(hidden)]
39/// A queue of sorted events for the fill tessellator's sweep-line algorithm.
40pub struct EventQueue {
41    pub(crate) events: Vec<Event>,
42    pub(crate) edge_data: Vec<EdgeData>,
43    first: TessEventId,
44    sorted: bool,
45}
46
47impl Default for EventQueue {
48    fn default() -> Self {
49        Self::new()
50    }
51}
52
53impl EventQueue {
54    pub fn new() -> Self {
55        EventQueue {
56            events: Vec::new(),
57            edge_data: Vec::new(),
58            first: INVALID_EVENT_ID,
59            sorted: false,
60        }
61    }
62
63    pub fn with_capacity(cap: usize) -> Self {
64        EventQueue {
65            events: Vec::with_capacity(cap),
66            edge_data: Vec::with_capacity(cap),
67            first: 0,
68            sorted: false,
69        }
70    }
71
72    pub fn reset(&mut self) {
73        self.events.clear();
74        self.edge_data.clear();
75        self.first = INVALID_EVENT_ID;
76        self.sorted = false;
77    }
78
79    /// Creates an `EventQueue` from an iterator of path event and a tolerance threshold.
80    ///
81    /// The tolerance threshold is used for curve flattening approximation. See the
82    /// [Flattening and tolerance](index.html#flattening-and-tolerance) section of the
83    /// crate documentation.
84    pub fn from_path(tolerance: f32, path: impl IntoIterator<Item = PathEvent>) -> Self {
85        let path = path.into_iter();
86        let (min, max) = path.size_hint();
87        let capacity = max.unwrap_or(min);
88        let mut builder = EventQueueBuilder::with_capacity(capacity, tolerance);
89        builder.set_path(tolerance, Orientation::Vertical, path);
90
91        builder.build()
92    }
93
94    /// Creates an `EventQueue` from an an iterator over endpoint and control
95    /// point ids, storage for the positions and, optionally, storage for
96    /// custom endpoint attributes.
97    ///
98    /// The tolerance threshold is used for curve flattening approximation. See the
99    /// [Flattening and tolerance](index.html#flattening-and-tolerance) section of the
100    /// crate documentation.
101    pub fn from_path_with_ids(
102        tolerance: f32,
103        sweep_orientation: Orientation,
104        path: impl IntoIterator<Item = IdEvent>,
105        positions: &impl PositionStore,
106    ) -> Self {
107        let path = path.into_iter();
108        let (min, max) = path.size_hint();
109        let capacity = max.unwrap_or(min);
110        let mut builder = EventQueueBuilder::with_capacity(capacity, tolerance);
111        builder.set_path_with_ids(tolerance, sweep_orientation, path, positions);
112
113        builder.build()
114    }
115
116    pub fn into_builder(mut self, tolerance: f32) -> EventQueueBuilder {
117        self.reset();
118        EventQueueBuilder {
119            queue: self,
120            current: point(f32::NAN, f32::NAN),
121            prev: point(f32::NAN, f32::NAN),
122            second: point(f32::NAN, f32::NAN),
123            nth: 0,
124            tolerance,
125            prev_endpoint_id: EndpointId(u32::MAX),
126            validator: DebugValidator::new(),
127        }
128    }
129
130    pub fn reserve(&mut self, n: usize) {
131        self.events.reserve(n);
132    }
133
134    fn push_unsorted(&mut self, position: Point) {
135        self.events.push(Event {
136            position,
137            next_sibling: INVALID_EVENT_ID,
138            next_event: INVALID_EVENT_ID,
139        });
140    }
141
142    fn push_sorted(&mut self, position: Point) {
143        self.events.push(Event {
144            position,
145            next_sibling: u32::MAX,
146            next_event: u32::MAX,
147        });
148
149        let id = (self.events.len() - 1) as u32;
150        let mut current = self.first_id();
151        let mut prev = current;
152        while self.valid_id(current) {
153            let evt_pos = self.events[current as usize].position;
154            match compare_positions(position, evt_pos) {
155                Ordering::Greater => {}
156                Ordering::Equal => {
157                    // Add to sibling list.
158                    let mut current_sibling = current;
159                    let mut next_sibling = self.next_sibling_id(current);
160                    while self.valid_id(next_sibling) {
161                        current_sibling = next_sibling;
162                        next_sibling = self.next_sibling_id(current_sibling);
163                    }
164                    self.events[current_sibling as usize].next_sibling = id;
165                    return;
166                }
167                Ordering::Less => {
168                    if prev != current {
169                        // Insert between `prev` and `current`.
170                        self.events[prev as usize].next_event = id;
171                    } else {
172                        // It's the first element.
173                        self.first = id;
174                    }
175                    self.events[id as usize].next_event = current;
176                    return;
177                }
178            }
179
180            prev = current;
181            current = self.next_id(current);
182        }
183
184        // Append at the end.
185        self.events[prev as usize].next_event = id;
186    }
187
188    pub(crate) fn insert_sorted(
189        &mut self,
190        position: Point,
191        data: EdgeData,
192        after: TessEventId,
193    ) -> TessEventId {
194        debug_assert!(self.sorted);
195        debug_assert!(
196            is_after(data.to, position),
197            "{:?} should be after {:?}",
198            data.to,
199            position
200        );
201
202        let idx = self.events.len() as TessEventId;
203        self.events.push(Event {
204            position,
205            next_sibling: INVALID_EVENT_ID,
206            next_event: INVALID_EVENT_ID,
207        });
208        self.edge_data.push(data);
209
210        self.insert_into_sorted_list(idx, position, after);
211
212        idx
213    }
214
215    pub(crate) fn insert_sibling(&mut self, sibling: TessEventId, position: Point, data: EdgeData) {
216        debug_assert!(is_after(data.to, position));
217        let idx = self.events.len() as TessEventId;
218        let next_sibling = self.events[sibling as usize].next_sibling;
219
220        self.events.push(Event {
221            position,
222            next_event: INVALID_EVENT_ID,
223            next_sibling,
224        });
225
226        self.edge_data.push(data);
227
228        self.events[sibling as usize].next_sibling = idx;
229    }
230
231    pub(crate) fn vertex_event_sorted(
232        &mut self,
233        position: Point,
234        endpoint_id: EndpointId,
235        after: TessEventId,
236    ) {
237        let idx = self.events.len() as TessEventId;
238
239        self.push_unsorted(position);
240        self.edge_data.push(EdgeData {
241            to: point(f32::NAN, f32::NAN),
242            range: 0.0..0.0,
243            winding: 0,
244            is_edge: false,
245            from_id: endpoint_id,
246            to_id: endpoint_id,
247        });
248
249        self.insert_into_sorted_list(idx, position, after);
250    }
251
252    fn insert_into_sorted_list(&mut self, idx: TessEventId, position: Point, after: TessEventId) {
253        let mut prev = after;
254        let mut current = after;
255        while self.valid_id(current) {
256            let pos = self.events[current as usize].position;
257
258            if pos == position {
259                debug_assert!(prev != current);
260                self.events[idx as usize].next_sibling = self.events[current as usize].next_sibling;
261                self.events[current as usize].next_sibling = idx;
262                return;
263            } else if is_after(pos, position) {
264                self.events[prev as usize].next_event = idx;
265                self.events[idx as usize].next_event = current;
266                return;
267            }
268
269            prev = current;
270            current = self.next_id(current);
271        }
272
273        self.events[prev as usize].next_event = idx;
274    }
275
276    pub(crate) fn clear(&mut self) {
277        self.events.clear();
278        self.first = INVALID_EVENT_ID;
279        self.sorted = false;
280    }
281
282    /// Returns the ID of the first event in the queue.
283    pub(crate) fn first_id(&self) -> TessEventId {
284        self.first
285    }
286
287    /// Returns the ID of the next (non-sibling) event after the provided one.
288    pub(crate) fn next_id(&self, id: TessEventId) -> TessEventId {
289        self.events[id as usize].next_event
290    }
291
292    /// Returns the ID of the next sibling event after the provided one.
293    pub(crate) fn next_sibling_id(&self, id: TessEventId) -> TessEventId {
294        self.events[id as usize].next_sibling
295    }
296
297    /// Returns whether or not the given event ID is valid.
298    pub(crate) fn valid_id(&self, id: TessEventId) -> bool {
299        id != INVALID_EVENT_ID
300    }
301
302    /// Returns the position of a given event in the queue.
303    pub(crate) fn position(&self, id: TessEventId) -> Point {
304        self.events[id as usize].position
305    }
306
307    fn sort(&mut self) {
308        self.sorted = true;
309
310        if self.events.is_empty() {
311            return;
312        }
313
314        let range = 0..self.events.len();
315        self.first = self.merge_sort(range);
316    }
317
318    /// Merge sort with two twists:
319    /// - Events at the same position are grouped into a "sibling" list.
320    /// - We take advantage of having events stored contiguously in a vector
321    ///   by recursively splitting ranges of the array instead of traversing
322    ///   the lists to find a split point.
323    fn merge_sort(&mut self, range: Range<usize>) -> TessEventId {
324        let split = (range.start + range.end) / 2;
325
326        if split == range.start {
327            return range.start as TessEventId;
328        }
329
330        let a_head = self.merge_sort(range.start..split);
331        let b_head = self.merge_sort(split..range.end);
332
333        self.merge(a_head, b_head)
334    }
335
336    fn merge(&mut self, mut a: TessEventId, mut b: TessEventId) -> TessEventId {
337        if a == INVALID_EVENT_ID {
338            return b;
339        }
340        if b == INVALID_EVENT_ID {
341            return a;
342        }
343
344        debug_assert!(a != b);
345        let mut first = true;
346        let mut sorted_head = INVALID_EVENT_ID;
347        let mut prev = INVALID_EVENT_ID;
348
349        loop {
350            if a == INVALID_EVENT_ID {
351                if !first {
352                    self.events[prev as usize].next_event = b;
353                }
354                break;
355            }
356
357            if b == INVALID_EVENT_ID {
358                if !first {
359                    self.events[prev as usize].next_event = a;
360                }
361                break;
362            }
363
364            let node;
365            match compare_positions(
366                self.events[a as usize].position,
367                self.events[b as usize].position,
368            ) {
369                Ordering::Less => {
370                    node = a;
371                    a = self.events[a as usize].next_event;
372                }
373                Ordering::Greater => {
374                    node = b;
375                    b = self.events[b as usize].next_event;
376                }
377                Ordering::Equal => {
378                    // Add b to a's sibling list.
379                    let a_sib = self.find_last_sibling(a) as usize;
380                    self.events[a_sib].next_sibling = b;
381
382                    b = self.events[b as usize].next_event;
383
384                    continue;
385                }
386            }
387
388            if first {
389                first = false;
390                sorted_head = node;
391            } else {
392                self.events[prev as usize].next_event = node;
393            }
394
395            prev = node;
396        }
397
398        if sorted_head == INVALID_EVENT_ID {
399            sorted_head = a;
400        }
401
402        sorted_head
403    }
404
405    fn find_last_sibling(&self, id: TessEventId) -> TessEventId {
406        let mut current_sibling = id;
407        let mut next_sibling = self.next_sibling_id(id);
408        while self.valid_id(next_sibling) {
409            current_sibling = next_sibling;
410            next_sibling = self.next_sibling_id(current_sibling);
411        }
412
413        current_sibling
414    }
415
416    #[cfg(all(debug_assertions, feature = "std"))]
417    fn log(&self) {
418        let mut iter_count = self.events.len() * self.events.len();
419
420        std::println!("--");
421        let mut current = self.first;
422        while (current as usize) < self.events.len() {
423            assert!(iter_count > 0);
424            iter_count -= 1;
425
426            std::print!("[");
427            let mut current_sibling = current;
428            while (current_sibling as usize) < self.events.len() {
429                std::print!("{:?},", self.events[current_sibling as usize].position);
430                current_sibling = self.events[current_sibling as usize].next_sibling;
431            }
432            std::print!("]  ");
433            current = self.events[current as usize].next_event;
434        }
435        std::println!("\n--");
436    }
437
438    fn assert_sorted(&self) {
439        let mut current = self.first;
440        let mut pos = point(f32::MIN, f32::MIN);
441        let mut n = 0;
442        while self.valid_id(current) {
443            assert!(is_after(self.events[current as usize].position, pos));
444            pos = self.events[current as usize].position;
445            let mut current_sibling = current;
446            while self.valid_id(current_sibling) {
447                n += 1;
448                assert_eq!(self.events[current_sibling as usize].position, pos);
449                current_sibling = self.next_sibling_id(current_sibling);
450            }
451            current = self.next_id(current);
452        }
453        assert_eq!(n, self.events.len());
454    }
455}
456
457pub struct EventQueueBuilder {
458    current: Point,
459    prev: Point,
460    second: Point,
461    nth: u32,
462    queue: EventQueue,
463    tolerance: f32,
464    prev_endpoint_id: EndpointId,
465    validator: DebugValidator,
466}
467
468impl EventQueueBuilder {
469    pub fn new(tolerance: f32) -> Self {
470        EventQueue::new().into_builder(tolerance)
471    }
472
473    pub fn with_capacity(cap: usize, tolerance: f32) -> Self {
474        EventQueue::with_capacity(cap).into_builder(tolerance)
475    }
476
477    pub fn set_tolerance(&mut self, tolerance: f32) {
478        self.tolerance = tolerance;
479    }
480
481    pub fn build(mut self) -> EventQueue {
482        self.validator.build();
483
484        self.queue.sort();
485
486        self.queue
487    }
488
489    pub fn set_path(
490        &mut self,
491        tolerance: f32,
492        sweep_orientation: Orientation,
493        path: impl IntoIterator<Item = PathEvent>,
494    ) {
495        self.reset();
496
497        self.tolerance = tolerance;
498        let endpoint_id = EndpointId(u32::MAX);
499        match sweep_orientation {
500            Orientation::Vertical => {
501                for evt in path {
502                    match evt {
503                        PathEvent::Begin { at } => {
504                            self.begin(at, endpoint_id);
505                        }
506                        PathEvent::Line { to, .. } => {
507                            self.line_segment(to, endpoint_id, 0.0, 1.0);
508                        }
509                        PathEvent::Quadratic { ctrl, to, .. } => {
510                            self.quadratic_bezier_segment(ctrl, to, endpoint_id);
511                        }
512                        PathEvent::Cubic {
513                            ctrl1, ctrl2, to, ..
514                        } => {
515                            self.cubic_bezier_segment(ctrl1, ctrl2, to, endpoint_id);
516                        }
517                        PathEvent::End { first, .. } => {
518                            self.end(first, endpoint_id);
519                        }
520                    }
521                }
522            }
523
524            Orientation::Horizontal => {
525                for evt in path {
526                    match evt {
527                        PathEvent::Begin { at } => {
528                            self.begin(reorient(at), endpoint_id);
529                        }
530                        PathEvent::Line { to, .. } => {
531                            self.line_segment(reorient(to), endpoint_id, 0.0, 1.0);
532                        }
533                        PathEvent::Quadratic { ctrl, to, .. } => {
534                            self.quadratic_bezier_segment(
535                                reorient(ctrl),
536                                reorient(to),
537                                endpoint_id,
538                            );
539                        }
540                        PathEvent::Cubic {
541                            ctrl1, ctrl2, to, ..
542                        } => {
543                            self.cubic_bezier_segment(
544                                reorient(ctrl1),
545                                reorient(ctrl2),
546                                reorient(to),
547                                endpoint_id,
548                            );
549                        }
550                        PathEvent::End { first, .. } => {
551                            self.end(reorient(first), endpoint_id);
552                        }
553                    }
554                }
555            }
556        }
557    }
558
559    pub fn set_path_with_ids(
560        &mut self,
561        tolerance: f32,
562        sweep_orientation: Orientation,
563        path_events: impl IntoIterator<Item = IdEvent>,
564        points: &impl PositionStore,
565    ) {
566        self.reset();
567
568        self.tolerance = tolerance;
569        match sweep_orientation {
570            Orientation::Vertical => {
571                for evt in path_events {
572                    match evt {
573                        IdEvent::Begin { at } => {
574                            self.begin(points.get_endpoint(at), at);
575                        }
576                        IdEvent::Line { to, .. } => {
577                            self.line_segment(points.get_endpoint(to), to, 0.0, 1.0);
578                        }
579                        IdEvent::Quadratic { ctrl, to, .. } => {
580                            self.quadratic_bezier_segment(
581                                points.get_control_point(ctrl),
582                                points.get_endpoint(to),
583                                to,
584                            );
585                        }
586                        IdEvent::Cubic {
587                            ctrl1, ctrl2, to, ..
588                        } => {
589                            self.cubic_bezier_segment(
590                                points.get_control_point(ctrl1),
591                                points.get_control_point(ctrl2),
592                                points.get_endpoint(to),
593                                to,
594                            );
595                        }
596                        IdEvent::End { first, .. } => {
597                            self.end(points.get_endpoint(first), first);
598                        }
599                    }
600                }
601            }
602
603            Orientation::Horizontal => {
604                for evt in path_events {
605                    match evt {
606                        IdEvent::Begin { at } => {
607                            self.begin(reorient(points.get_endpoint(at)), at);
608                        }
609                        IdEvent::Line { to, .. } => {
610                            self.line_segment(reorient(points.get_endpoint(to)), to, 0.0, 1.0);
611                        }
612                        IdEvent::Quadratic { ctrl, to, .. } => {
613                            self.quadratic_bezier_segment(
614                                reorient(points.get_control_point(ctrl)),
615                                reorient(points.get_endpoint(to)),
616                                to,
617                            );
618                        }
619                        IdEvent::Cubic {
620                            ctrl1, ctrl2, to, ..
621                        } => {
622                            self.cubic_bezier_segment(
623                                reorient(points.get_control_point(ctrl1)),
624                                reorient(points.get_control_point(ctrl2)),
625                                reorient(points.get_endpoint(to)),
626                                to,
627                            );
628                        }
629                        IdEvent::End { first, .. } => {
630                            self.end(reorient(points.get_endpoint(first)), first);
631                        }
632                    }
633                }
634            }
635        }
636    }
637
638    fn reset(&mut self) {
639        self.queue.reset();
640        self.nth = 0;
641    }
642
643    fn vertex_event(&mut self, at: Point, endpoint_id: EndpointId) {
644        self.queue.push_unsorted(at);
645        self.queue.edge_data.push(EdgeData {
646            to: point(f32::NAN, f32::NAN),
647            range: 0.0..0.0,
648            winding: 0,
649            is_edge: false,
650            from_id: endpoint_id,
651            to_id: endpoint_id,
652        });
653    }
654
655    fn vertex_event_on_curve(&mut self, at: Point, t: f32, from_id: EndpointId, to_id: EndpointId) {
656        self.queue.push_unsorted(at);
657        self.queue.edge_data.push(EdgeData {
658            to: point(f32::NAN, f32::NAN),
659            range: t..t,
660            winding: 0,
661            is_edge: false,
662            from_id,
663            to_id,
664        });
665    }
666
667    pub fn end(&mut self, first: Point, first_endpoint_id: EndpointId) {
668        if self.nth == 0 {
669            self.validator.end();
670            return;
671        }
672
673        // Unless we are already back to the first point, we need to
674        // to insert an edge.
675        self.line_segment(first, first_endpoint_id, 0.0, 1.0);
676
677        // Since we can only check for the need of a vertex event when
678        // we have a previous edge, we skipped it for the first edge
679        // and have to do it now.
680        if is_after(first, self.prev) && is_after(first, self.second) {
681            self.vertex_event(first, first_endpoint_id);
682        }
683
684        self.validator.end();
685
686        self.prev_endpoint_id = first_endpoint_id;
687        self.nth = 0;
688    }
689
690    pub fn begin(&mut self, to: Point, to_id: EndpointId) {
691        self.validator.begin();
692
693        self.nth = 0;
694        self.current = to;
695        self.prev_endpoint_id = to_id;
696    }
697
698    #[allow(clippy::too_many_arguments)]
699    fn add_edge(
700        &mut self,
701        edge: &LineSegment<f32>,
702        mut winding: i16,
703        from_id: EndpointId,
704        to_id: EndpointId,
705        mut t0: f32,
706        mut t1: f32,
707    ) {
708        if edge.from == edge.to {
709            return;
710        }
711
712        let mut evt_pos = edge.from;
713        let mut evt_to = edge.to;
714        if is_after(evt_pos, edge.to) {
715            evt_to = evt_pos;
716            evt_pos = edge.to;
717            swap(&mut t0, &mut t1);
718            winding *= -1;
719        }
720
721        self.queue.push_unsorted(evt_pos);
722        self.queue.edge_data.push(EdgeData {
723            to: evt_to,
724            range: t0..t1,
725            winding,
726            is_edge: true,
727            from_id,
728            to_id,
729        });
730
731        self.nth += 1;
732    }
733
734    pub fn line_segment(&mut self, to: Point, to_id: EndpointId, t0: f32, t1: f32) {
735        self.validator.edge();
736
737        let from = self.current;
738        if from == to {
739            return;
740        }
741
742        if is_after(from, to) && self.nth > 0 && is_after(from, self.prev) {
743            self.vertex_event(from, self.prev_endpoint_id);
744        }
745
746        if self.nth == 0 {
747            self.second = to;
748        }
749
750        self.add_edge(
751            &LineSegment { from, to },
752            1,
753            self.prev_endpoint_id,
754            to_id,
755            t0,
756            t1,
757        );
758
759        self.prev = self.current;
760        self.prev_endpoint_id = to_id;
761        self.current = to;
762    }
763
764    pub fn quadratic_bezier_segment(&mut self, ctrl: Point, to: Point, to_id: EndpointId) {
765        self.validator.edge();
766        // Swap the curve so that it always goes downwards. This way if two
767        // paths share the same edge with different windings, the flattening will
768        // play out the same way, which avoid cracks.
769
770        // We have to put special care into properly tracking the previous and second
771        // points as if we hadn't swapped.
772
773        let original = QuadraticBezierSegment {
774            from: self.current,
775            ctrl,
776            to,
777        };
778
779        let needs_swap = is_after(original.from, original.to);
780
781        let mut segment = original;
782        let mut winding = 1;
783        if needs_swap {
784            swap(&mut segment.from, &mut segment.to);
785            winding = -1;
786        }
787
788        let mut prev = segment.from;
789        let mut first = None;
790        let is_first_edge = self.nth == 0;
791        segment.for_each_flattened_with_t(self.tolerance, &mut |line, t| {
792            if line.from == line.to {
793                return;
794            }
795
796            if first.is_none() {
797                first = Some(line.to)
798            // We can't call vertex(prev, from, to) in the first iteration
799            // because if we flipped the curve, we don't have a proper value for
800            // the previous vertex yet.
801            // We'll handle it after the loop.
802            } else if is_after(line.from, line.to) && is_after(line.from, prev) {
803                self.vertex_event_on_curve(line.from, t.start, self.prev_endpoint_id, to_id);
804            }
805
806            self.add_edge(line, winding, self.prev_endpoint_id, to_id, t.start, t.end);
807
808            prev = line.from;
809        });
810
811        if let Some(first) = first {
812            let (second, previous) = if needs_swap {
813                (prev, first)
814            } else {
815                (first, prev)
816            };
817
818            if is_first_edge {
819                self.second = second;
820            } else if is_after(original.from, self.prev) && is_after(original.from, second) {
821                // Handle the first vertex we took out of the loop above.
822                // The missing vertex is always the origin of the edge (before the flip).
823                self.vertex_event(original.from, self.prev_endpoint_id);
824            }
825
826            self.prev = previous;
827            self.current = original.to;
828            self.prev_endpoint_id = to_id;
829        }
830    }
831
832    pub fn cubic_bezier_segment(
833        &mut self,
834        ctrl1: Point,
835        ctrl2: Point,
836        to: Point,
837        to_id: EndpointId,
838    ) {
839        self.validator.edge();
840        // Swap the curve so that it always goes downwards. This way if two
841        // paths share the same edge with different windings, the flattening will
842        // play out the same way, which avoid cracks.
843
844        // We have to put special care into properly tracking the previous and second
845        // points as if we hadn't swapped.
846
847        let original = CubicBezierSegment {
848            from: self.current,
849            ctrl1,
850            ctrl2,
851            to,
852        };
853
854        let needs_swap = is_after(original.from, original.to);
855
856        let mut segment = original;
857        let mut winding = 1;
858        if needs_swap {
859            swap(&mut segment.from, &mut segment.to);
860            swap(&mut segment.ctrl1, &mut segment.ctrl2);
861            winding = -1;
862        }
863
864        let mut prev = segment.from;
865        let mut first = None;
866        let is_first_edge = self.nth == 0;
867        segment.for_each_flattened_with_t(self.tolerance, &mut |line, t| {
868            if line.from == line.to {
869                return;
870            }
871
872            if first.is_none() {
873                first = Some(line.to)
874            // We can't call vertex(prev, from, to) in the first iteration
875            // because if we flipped the curve, we don't have a proper value for
876            // the previous vertex yet.
877            // We'll handle it after the loop.
878            } else if is_after(line.from, line.to) && is_after(line.from, prev) {
879                self.vertex_event_on_curve(line.from, t.start, self.prev_endpoint_id, to_id);
880            }
881
882            self.add_edge(line, winding, self.prev_endpoint_id, to_id, t.start, t.end);
883
884            prev = line.from;
885        });
886
887        if let Some(first) = first {
888            let (second, previous) = if needs_swap {
889                (prev, first)
890            } else {
891                (first, prev)
892            };
893
894            if is_first_edge {
895                self.second = second;
896            } else if is_after(original.from, self.prev) && is_after(original.from, second) {
897                // Handle the first vertex we took out of the loop above.
898                // The missing vertex is always the origin of the edge (before the flip).
899                self.vertex_event(original.from, self.prev_endpoint_id);
900            }
901
902            self.prev = previous;
903            self.current = original.to;
904            self.prev_endpoint_id = to_id;
905        }
906    }
907
908    pub fn reserve(&mut self, n: usize) {
909        self.queue.reserve(n);
910    }
911}
912
913#[test]
914fn test_event_queue_sort_1() {
915    let mut queue = EventQueue::new();
916    queue.push_unsorted(point(0.0, 0.0));
917    queue.push_unsorted(point(4.0, 0.0));
918    queue.push_unsorted(point(2.0, 0.0));
919    queue.push_unsorted(point(3.0, 0.0));
920    queue.push_unsorted(point(4.0, 0.0));
921    queue.push_unsorted(point(0.0, 0.0));
922    queue.push_unsorted(point(6.0, 0.0));
923
924    queue.sort();
925    queue.assert_sorted();
926}
927
928#[test]
929fn test_event_queue_sort_2() {
930    let mut queue = EventQueue::new();
931    queue.push_unsorted(point(0.0, 0.0));
932    queue.push_unsorted(point(0.0, 0.0));
933    queue.push_unsorted(point(0.0, 0.0));
934    queue.push_unsorted(point(0.0, 0.0));
935
936    queue.sort();
937    queue.assert_sorted();
938}
939
940#[test]
941fn test_event_queue_sort_3() {
942    let mut queue = EventQueue::new();
943    queue.push_unsorted(point(0.0, 0.0));
944    queue.push_unsorted(point(1.0, 0.0));
945    queue.push_unsorted(point(2.0, 0.0));
946    queue.push_unsorted(point(3.0, 0.0));
947    queue.push_unsorted(point(4.0, 0.0));
948    queue.push_unsorted(point(5.0, 0.0));
949
950    queue.sort();
951    queue.assert_sorted();
952}
953
954#[test]
955fn test_event_queue_sort_4() {
956    let mut queue = EventQueue::new();
957    queue.push_unsorted(point(5.0, 0.0));
958    queue.push_unsorted(point(4.0, 0.0));
959    queue.push_unsorted(point(3.0, 0.0));
960    queue.push_unsorted(point(2.0, 0.0));
961    queue.push_unsorted(point(1.0, 0.0));
962    queue.push_unsorted(point(0.0, 0.0));
963
964    queue.sort();
965    queue.assert_sorted();
966}
967
968#[test]
969fn test_event_queue_sort_5() {
970    let mut queue = EventQueue::new();
971    queue.push_unsorted(point(5.0, 0.0));
972    queue.push_unsorted(point(5.0, 0.0));
973    queue.push_unsorted(point(4.0, 0.0));
974    queue.push_unsorted(point(4.0, 0.0));
975    queue.push_unsorted(point(3.0, 0.0));
976    queue.push_unsorted(point(3.0, 0.0));
977    queue.push_unsorted(point(2.0, 0.0));
978    queue.push_unsorted(point(2.0, 0.0));
979    queue.push_unsorted(point(1.0, 0.0));
980    queue.push_unsorted(point(1.0, 0.0));
981    queue.push_unsorted(point(0.0, 0.0));
982    queue.push_unsorted(point(0.0, 0.0));
983
984    queue.sort();
985    queue.assert_sorted();
986}
987
988#[test]
989fn test_event_queue_push_sorted() {
990    let mut queue = EventQueue::new();
991    queue.push_unsorted(point(5.0, 0.0));
992    queue.push_unsorted(point(4.0, 0.0));
993    queue.push_unsorted(point(3.0, 0.0));
994    queue.push_unsorted(point(2.0, 0.0));
995    queue.push_unsorted(point(1.0, 0.0));
996    queue.push_unsorted(point(0.0, 0.0));
997
998    queue.sort();
999    queue.push_sorted(point(1.5, 0.0));
1000    queue.assert_sorted();
1001
1002    queue.push_sorted(point(2.5, 0.0));
1003    queue.assert_sorted();
1004
1005    queue.push_sorted(point(2.5, 0.0));
1006    queue.assert_sorted();
1007
1008    queue.push_sorted(point(6.5, 0.0));
1009    queue.assert_sorted();
1010}
1011
1012#[test]
1013fn test_logo() {
1014    use crate::path::Path;
1015
1016    let mut path = Path::builder().with_svg();
1017
1018    crate::extra::rust_logo::build_logo_path(&mut path);
1019    let path = path.build();
1020
1021    crate::extra::debugging::find_reduced_test_case(path.as_slice(), &|path: Path| {
1022        let _ = EventQueue::from_path(0.05, path.iter());
1023        true
1024    });
1025}