Skip to main content

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: INVALID_EVENT_ID,
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    /// Returns the ID of the first event in the queue.
277    pub(crate) fn first_id(&self) -> TessEventId {
278        self.first
279    }
280
281    /// Returns the ID of the next (non-sibling) event after the provided one.
282    pub(crate) fn next_id(&self, id: TessEventId) -> TessEventId {
283        self.events[id as usize].next_event
284    }
285
286    /// Returns the ID of the next sibling event after the provided one.
287    pub(crate) fn next_sibling_id(&self, id: TessEventId) -> TessEventId {
288        self.events[id as usize].next_sibling
289    }
290
291    /// Returns whether or not the given event ID is valid.
292    pub(crate) fn valid_id(&self, id: TessEventId) -> bool {
293        id != INVALID_EVENT_ID
294    }
295
296    /// Returns the position of a given event in the queue.
297    pub(crate) fn position(&self, id: TessEventId) -> Point {
298        self.events[id as usize].position
299    }
300
301    fn sort(&mut self) {
302        self.sorted = true;
303
304        if self.events.is_empty() {
305            return;
306        }
307
308        let range = 0..self.events.len();
309        self.first = self.merge_sort(range);
310    }
311
312    /// Merge sort with two twists:
313    /// - Events at the same position are grouped into a "sibling" list.
314    /// - We take advantage of having events stored contiguously in a vector
315    ///   by recursively splitting ranges of the array instead of traversing
316    ///   the lists to find a split point.
317    fn merge_sort(&mut self, range: Range<usize>) -> TessEventId {
318        let split = (range.start + range.end) / 2;
319
320        if split == range.start {
321            return range.start as TessEventId;
322        }
323
324        let a_head = self.merge_sort(range.start..split);
325        let b_head = self.merge_sort(split..range.end);
326
327        self.merge(a_head, b_head)
328    }
329
330    fn merge(&mut self, mut a: TessEventId, mut b: TessEventId) -> TessEventId {
331        if a == INVALID_EVENT_ID {
332            return b;
333        }
334        if b == INVALID_EVENT_ID {
335            return a;
336        }
337
338        debug_assert!(a != b);
339        let mut first = true;
340        let mut sorted_head = INVALID_EVENT_ID;
341        let mut prev = INVALID_EVENT_ID;
342
343        loop {
344            if a == INVALID_EVENT_ID {
345                if !first {
346                    self.events[prev as usize].next_event = b;
347                }
348                break;
349            }
350
351            if b == INVALID_EVENT_ID {
352                if !first {
353                    self.events[prev as usize].next_event = a;
354                }
355                break;
356            }
357
358            let node;
359            match compare_positions(
360                self.events[a as usize].position,
361                self.events[b as usize].position,
362            ) {
363                Ordering::Less => {
364                    node = a;
365                    a = self.events[a as usize].next_event;
366                }
367                Ordering::Greater => {
368                    node = b;
369                    b = self.events[b as usize].next_event;
370                }
371                Ordering::Equal => {
372                    // Add b to a's sibling list.
373                    let a_sib = self.find_last_sibling(a) as usize;
374                    self.events[a_sib].next_sibling = b;
375
376                    b = self.events[b as usize].next_event;
377
378                    continue;
379                }
380            }
381
382            if first {
383                first = false;
384                sorted_head = node;
385            } else {
386                self.events[prev as usize].next_event = node;
387            }
388
389            prev = node;
390        }
391
392        if sorted_head == INVALID_EVENT_ID {
393            sorted_head = a;
394        }
395
396        sorted_head
397    }
398
399    fn find_last_sibling(&self, id: TessEventId) -> TessEventId {
400        let mut current_sibling = id;
401        let mut next_sibling = self.next_sibling_id(id);
402        while self.valid_id(next_sibling) {
403            current_sibling = next_sibling;
404            next_sibling = self.next_sibling_id(current_sibling);
405        }
406
407        current_sibling
408    }
409
410    #[cfg(all(debug_assertions, feature = "std"))]
411    fn log(&self) {
412        let mut iter_count = self.events.len() * self.events.len();
413
414        std::println!("--");
415        let mut current = self.first;
416        while (current as usize) < self.events.len() {
417            assert!(iter_count > 0);
418            iter_count -= 1;
419
420            std::print!("[");
421            let mut current_sibling = current;
422            while (current_sibling as usize) < self.events.len() {
423                std::print!("{:?},", self.events[current_sibling as usize].position);
424                current_sibling = self.events[current_sibling as usize].next_sibling;
425            }
426            std::print!("]  ");
427            current = self.events[current as usize].next_event;
428        }
429        std::println!("\n--");
430    }
431
432    fn assert_sorted(&self) {
433        let mut current = self.first;
434        let mut pos = point(f32::MIN, f32::MIN);
435        let mut n = 0;
436        while self.valid_id(current) {
437            assert!(is_after(self.events[current as usize].position, pos));
438            pos = self.events[current as usize].position;
439            let mut current_sibling = current;
440            while self.valid_id(current_sibling) {
441                n += 1;
442                assert_eq!(self.events[current_sibling as usize].position, pos);
443                current_sibling = self.next_sibling_id(current_sibling);
444            }
445            current = self.next_id(current);
446        }
447        assert_eq!(n, self.events.len());
448    }
449}
450
451pub struct EventQueueBuilder {
452    current: Point,
453    prev: Point,
454    second: Point,
455    nth: u32,
456    queue: EventQueue,
457    tolerance: f32,
458    prev_endpoint_id: EndpointId,
459    validator: DebugValidator,
460}
461
462impl EventQueueBuilder {
463    pub fn new(tolerance: f32) -> Self {
464        EventQueue::new().into_builder(tolerance)
465    }
466
467    pub fn with_capacity(cap: usize, tolerance: f32) -> Self {
468        EventQueue::with_capacity(cap).into_builder(tolerance)
469    }
470
471    pub fn set_tolerance(&mut self, tolerance: f32) {
472        self.tolerance = tolerance;
473    }
474
475    pub fn build(mut self) -> EventQueue {
476        self.validator.build();
477
478        self.queue.sort();
479
480        self.queue
481    }
482
483    pub fn set_path(
484        &mut self,
485        tolerance: f32,
486        sweep_orientation: Orientation,
487        path: impl IntoIterator<Item = PathEvent>,
488    ) {
489        self.reset();
490
491        self.tolerance = tolerance;
492        let endpoint_id = EndpointId(u32::MAX);
493        match sweep_orientation {
494            Orientation::Vertical => {
495                for evt in path {
496                    match evt {
497                        PathEvent::Begin { at } => {
498                            self.begin(at, endpoint_id);
499                        }
500                        PathEvent::Line { to, .. } => {
501                            self.line_segment(to, endpoint_id, 0.0, 1.0);
502                        }
503                        PathEvent::Quadratic { ctrl, to, .. } => {
504                            self.quadratic_bezier_segment(ctrl, to, endpoint_id);
505                        }
506                        PathEvent::Cubic {
507                            ctrl1, ctrl2, to, ..
508                        } => {
509                            self.cubic_bezier_segment(ctrl1, ctrl2, to, endpoint_id);
510                        }
511                        PathEvent::End { first, .. } => {
512                            self.end(first, endpoint_id);
513                        }
514                    }
515                }
516            }
517
518            Orientation::Horizontal => {
519                for evt in path {
520                    match evt {
521                        PathEvent::Begin { at } => {
522                            self.begin(reorient(at), endpoint_id);
523                        }
524                        PathEvent::Line { to, .. } => {
525                            self.line_segment(reorient(to), endpoint_id, 0.0, 1.0);
526                        }
527                        PathEvent::Quadratic { ctrl, to, .. } => {
528                            self.quadratic_bezier_segment(
529                                reorient(ctrl),
530                                reorient(to),
531                                endpoint_id,
532                            );
533                        }
534                        PathEvent::Cubic {
535                            ctrl1, ctrl2, to, ..
536                        } => {
537                            self.cubic_bezier_segment(
538                                reorient(ctrl1),
539                                reorient(ctrl2),
540                                reorient(to),
541                                endpoint_id,
542                            );
543                        }
544                        PathEvent::End { first, .. } => {
545                            self.end(reorient(first), endpoint_id);
546                        }
547                    }
548                }
549            }
550        }
551    }
552
553    pub fn set_path_with_ids(
554        &mut self,
555        tolerance: f32,
556        sweep_orientation: Orientation,
557        path_events: impl IntoIterator<Item = IdEvent>,
558        points: &impl PositionStore,
559    ) {
560        self.reset();
561
562        self.tolerance = tolerance;
563        match sweep_orientation {
564            Orientation::Vertical => {
565                for evt in path_events {
566                    match evt {
567                        IdEvent::Begin { at } => {
568                            self.begin(points.get_endpoint(at), at);
569                        }
570                        IdEvent::Line { to, .. } => {
571                            self.line_segment(points.get_endpoint(to), to, 0.0, 1.0);
572                        }
573                        IdEvent::Quadratic { ctrl, to, .. } => {
574                            self.quadratic_bezier_segment(
575                                points.get_control_point(ctrl),
576                                points.get_endpoint(to),
577                                to,
578                            );
579                        }
580                        IdEvent::Cubic {
581                            ctrl1, ctrl2, to, ..
582                        } => {
583                            self.cubic_bezier_segment(
584                                points.get_control_point(ctrl1),
585                                points.get_control_point(ctrl2),
586                                points.get_endpoint(to),
587                                to,
588                            );
589                        }
590                        IdEvent::End { first, .. } => {
591                            self.end(points.get_endpoint(first), first);
592                        }
593                    }
594                }
595            }
596
597            Orientation::Horizontal => {
598                for evt in path_events {
599                    match evt {
600                        IdEvent::Begin { at } => {
601                            self.begin(reorient(points.get_endpoint(at)), at);
602                        }
603                        IdEvent::Line { to, .. } => {
604                            self.line_segment(reorient(points.get_endpoint(to)), to, 0.0, 1.0);
605                        }
606                        IdEvent::Quadratic { ctrl, to, .. } => {
607                            self.quadratic_bezier_segment(
608                                reorient(points.get_control_point(ctrl)),
609                                reorient(points.get_endpoint(to)),
610                                to,
611                            );
612                        }
613                        IdEvent::Cubic {
614                            ctrl1, ctrl2, to, ..
615                        } => {
616                            self.cubic_bezier_segment(
617                                reorient(points.get_control_point(ctrl1)),
618                                reorient(points.get_control_point(ctrl2)),
619                                reorient(points.get_endpoint(to)),
620                                to,
621                            );
622                        }
623                        IdEvent::End { first, .. } => {
624                            self.end(reorient(points.get_endpoint(first)), first);
625                        }
626                    }
627                }
628            }
629        }
630    }
631
632    fn reset(&mut self) {
633        self.queue.reset();
634        self.nth = 0;
635    }
636
637    fn vertex_event(&mut self, at: Point, endpoint_id: EndpointId) {
638        self.queue.push_unsorted(at);
639        self.queue.edge_data.push(EdgeData {
640            to: point(f32::NAN, f32::NAN),
641            range: 0.0..0.0,
642            winding: 0,
643            is_edge: false,
644            from_id: endpoint_id,
645            to_id: endpoint_id,
646        });
647    }
648
649    fn vertex_event_on_curve(&mut self, at: Point, t: f32, from_id: EndpointId, to_id: EndpointId) {
650        self.queue.push_unsorted(at);
651        self.queue.edge_data.push(EdgeData {
652            to: point(f32::NAN, f32::NAN),
653            range: t..t,
654            winding: 0,
655            is_edge: false,
656            from_id,
657            to_id,
658        });
659    }
660
661    pub fn end(&mut self, first: Point, first_endpoint_id: EndpointId) {
662        if self.nth == 0 {
663            self.validator.end();
664            return;
665        }
666
667        // Unless we are already back to the first point, we need to
668        // to insert an edge.
669        self.line_segment(first, first_endpoint_id, 0.0, 1.0);
670
671        // Since we can only check for the need of a vertex event when
672        // we have a previous edge, we skipped it for the first edge
673        // and have to do it now.
674        if is_after(first, self.prev) && is_after(first, self.second) {
675            self.vertex_event(first, first_endpoint_id);
676        }
677
678        self.validator.end();
679
680        self.prev_endpoint_id = first_endpoint_id;
681        self.nth = 0;
682    }
683
684    pub fn begin(&mut self, to: Point, to_id: EndpointId) {
685        self.validator.begin();
686
687        self.nth = 0;
688        self.current = to;
689        self.prev_endpoint_id = to_id;
690    }
691
692    #[allow(clippy::too_many_arguments)]
693    fn add_edge(
694        &mut self,
695        edge: &LineSegment<f32>,
696        mut winding: i16,
697        from_id: EndpointId,
698        to_id: EndpointId,
699        mut t0: f32,
700        mut t1: f32,
701    ) {
702        if edge.from == edge.to {
703            return;
704        }
705
706        let mut evt_pos = edge.from;
707        let mut evt_to = edge.to;
708        if is_after(evt_pos, edge.to) {
709            evt_to = evt_pos;
710            evt_pos = edge.to;
711            swap(&mut t0, &mut t1);
712            winding *= -1;
713        }
714
715        self.queue.push_unsorted(evt_pos);
716        self.queue.edge_data.push(EdgeData {
717            to: evt_to,
718            range: t0..t1,
719            winding,
720            is_edge: true,
721            from_id,
722            to_id,
723        });
724
725        self.nth += 1;
726    }
727
728    pub fn line_segment(&mut self, to: Point, to_id: EndpointId, t0: f32, t1: f32) {
729        self.validator.edge();
730
731        let from = self.current;
732        if from == to {
733            return;
734        }
735
736        if is_after(from, to) && self.nth > 0 && is_after(from, self.prev) {
737            self.vertex_event(from, self.prev_endpoint_id);
738        }
739
740        if self.nth == 0 {
741            self.second = to;
742        }
743
744        self.add_edge(
745            &LineSegment { from, to },
746            1,
747            self.prev_endpoint_id,
748            to_id,
749            t0,
750            t1,
751        );
752
753        self.prev = self.current;
754        self.prev_endpoint_id = to_id;
755        self.current = to;
756    }
757
758    pub fn quadratic_bezier_segment(&mut self, ctrl: Point, to: Point, to_id: EndpointId) {
759        self.validator.edge();
760        // Swap the curve so that it always goes downwards. This way if two
761        // paths share the same edge with different windings, the flattening will
762        // play out the same way, which avoid cracks.
763
764        // We have to put special care into properly tracking the previous and second
765        // points as if we hadn't swapped.
766
767        let original = QuadraticBezierSegment {
768            from: self.current,
769            ctrl,
770            to,
771        };
772
773        let needs_swap = is_after(original.from, original.to);
774
775        let mut segment = original;
776        let mut winding = 1;
777        if needs_swap {
778            swap(&mut segment.from, &mut segment.to);
779            winding = -1;
780        }
781
782        let mut prev = segment.from;
783        let mut first = None;
784        let is_first_edge = self.nth == 0;
785        segment.for_each_flattened_with_t(self.tolerance, &mut |line, t| {
786            if line.from == line.to {
787                return;
788            }
789
790            if first.is_none() {
791                first = Some(line.to)
792            // We can't call vertex(prev, from, to) in the first iteration
793            // because if we flipped the curve, we don't have a proper value for
794            // the previous vertex yet.
795            // We'll handle it after the loop.
796            } else if is_after(line.from, line.to) && is_after(line.from, prev) {
797                self.vertex_event_on_curve(line.from, t.start, self.prev_endpoint_id, to_id);
798            }
799
800            self.add_edge(line, winding, self.prev_endpoint_id, to_id, t.start, t.end);
801
802            prev = line.from;
803        });
804
805        if let Some(first) = first {
806            let (second, previous) = if needs_swap {
807                (prev, first)
808            } else {
809                (first, prev)
810            };
811
812            if is_first_edge {
813                self.second = second;
814            } else if is_after(original.from, self.prev) && is_after(original.from, second) {
815                // Handle the first vertex we took out of the loop above.
816                // The missing vertex is always the origin of the edge (before the flip).
817                self.vertex_event(original.from, self.prev_endpoint_id);
818            }
819
820            self.prev = previous;
821            self.current = original.to;
822            self.prev_endpoint_id = to_id;
823        }
824    }
825
826    pub fn cubic_bezier_segment(
827        &mut self,
828        ctrl1: Point,
829        ctrl2: Point,
830        to: Point,
831        to_id: EndpointId,
832    ) {
833        self.validator.edge();
834        // Swap the curve so that it always goes downwards. This way if two
835        // paths share the same edge with different windings, the flattening will
836        // play out the same way, which avoid cracks.
837
838        // We have to put special care into properly tracking the previous and second
839        // points as if we hadn't swapped.
840
841        let original = CubicBezierSegment {
842            from: self.current,
843            ctrl1,
844            ctrl2,
845            to,
846        };
847
848        let needs_swap = is_after(original.from, original.to);
849
850        let mut segment = original;
851        let mut winding = 1;
852        if needs_swap {
853            swap(&mut segment.from, &mut segment.to);
854            swap(&mut segment.ctrl1, &mut segment.ctrl2);
855            winding = -1;
856        }
857
858        let mut prev = segment.from;
859        let mut first = None;
860        let is_first_edge = self.nth == 0;
861        segment.for_each_flattened_with_t(self.tolerance, &mut |line, t| {
862            if line.from == line.to {
863                return;
864            }
865
866            if first.is_none() {
867                first = Some(line.to)
868            // We can't call vertex(prev, from, to) in the first iteration
869            // because if we flipped the curve, we don't have a proper value for
870            // the previous vertex yet.
871            // We'll handle it after the loop.
872            } else if is_after(line.from, line.to) && is_after(line.from, prev) {
873                self.vertex_event_on_curve(line.from, t.start, self.prev_endpoint_id, to_id);
874            }
875
876            self.add_edge(line, winding, self.prev_endpoint_id, to_id, t.start, t.end);
877
878            prev = line.from;
879        });
880
881        if let Some(first) = first {
882            let (second, previous) = if needs_swap {
883                (prev, first)
884            } else {
885                (first, prev)
886            };
887
888            if is_first_edge {
889                self.second = second;
890            } else if is_after(original.from, self.prev) && is_after(original.from, second) {
891                // Handle the first vertex we took out of the loop above.
892                // The missing vertex is always the origin of the edge (before the flip).
893                self.vertex_event(original.from, self.prev_endpoint_id);
894            }
895
896            self.prev = previous;
897            self.current = original.to;
898            self.prev_endpoint_id = to_id;
899        }
900    }
901
902    pub fn reserve(&mut self, n: usize) {
903        self.queue.reserve(n);
904    }
905}
906
907#[test]
908fn test_event_queue_sort_1() {
909    let mut queue = EventQueue::new();
910    queue.push_unsorted(point(0.0, 0.0));
911    queue.push_unsorted(point(4.0, 0.0));
912    queue.push_unsorted(point(2.0, 0.0));
913    queue.push_unsorted(point(3.0, 0.0));
914    queue.push_unsorted(point(4.0, 0.0));
915    queue.push_unsorted(point(0.0, 0.0));
916    queue.push_unsorted(point(6.0, 0.0));
917
918    queue.sort();
919    queue.assert_sorted();
920}
921
922#[test]
923fn test_event_queue_sort_2() {
924    let mut queue = EventQueue::new();
925    queue.push_unsorted(point(0.0, 0.0));
926    queue.push_unsorted(point(0.0, 0.0));
927    queue.push_unsorted(point(0.0, 0.0));
928    queue.push_unsorted(point(0.0, 0.0));
929
930    queue.sort();
931    queue.assert_sorted();
932}
933
934#[test]
935fn test_event_queue_sort_3() {
936    let mut queue = EventQueue::new();
937    queue.push_unsorted(point(0.0, 0.0));
938    queue.push_unsorted(point(1.0, 0.0));
939    queue.push_unsorted(point(2.0, 0.0));
940    queue.push_unsorted(point(3.0, 0.0));
941    queue.push_unsorted(point(4.0, 0.0));
942    queue.push_unsorted(point(5.0, 0.0));
943
944    queue.sort();
945    queue.assert_sorted();
946}
947
948#[test]
949fn test_event_queue_sort_4() {
950    let mut queue = EventQueue::new();
951    queue.push_unsorted(point(5.0, 0.0));
952    queue.push_unsorted(point(4.0, 0.0));
953    queue.push_unsorted(point(3.0, 0.0));
954    queue.push_unsorted(point(2.0, 0.0));
955    queue.push_unsorted(point(1.0, 0.0));
956    queue.push_unsorted(point(0.0, 0.0));
957
958    queue.sort();
959    queue.assert_sorted();
960}
961
962#[test]
963fn test_event_queue_sort_5() {
964    let mut queue = EventQueue::new();
965    queue.push_unsorted(point(5.0, 0.0));
966    queue.push_unsorted(point(5.0, 0.0));
967    queue.push_unsorted(point(4.0, 0.0));
968    queue.push_unsorted(point(4.0, 0.0));
969    queue.push_unsorted(point(3.0, 0.0));
970    queue.push_unsorted(point(3.0, 0.0));
971    queue.push_unsorted(point(2.0, 0.0));
972    queue.push_unsorted(point(2.0, 0.0));
973    queue.push_unsorted(point(1.0, 0.0));
974    queue.push_unsorted(point(1.0, 0.0));
975    queue.push_unsorted(point(0.0, 0.0));
976    queue.push_unsorted(point(0.0, 0.0));
977
978    queue.sort();
979    queue.assert_sorted();
980}
981
982#[test]
983fn test_event_queue_push_sorted() {
984    let mut queue = EventQueue::new();
985    queue.push_unsorted(point(5.0, 0.0));
986    queue.push_unsorted(point(4.0, 0.0));
987    queue.push_unsorted(point(3.0, 0.0));
988    queue.push_unsorted(point(2.0, 0.0));
989    queue.push_unsorted(point(1.0, 0.0));
990    queue.push_unsorted(point(0.0, 0.0));
991
992    queue.sort();
993    queue.push_sorted(point(1.5, 0.0));
994    queue.assert_sorted();
995
996    queue.push_sorted(point(2.5, 0.0));
997    queue.assert_sorted();
998
999    queue.push_sorted(point(2.5, 0.0));
1000    queue.assert_sorted();
1001
1002    queue.push_sorted(point(6.5, 0.0));
1003    queue.assert_sorted();
1004}
1005
1006#[test]
1007fn test_logo() {
1008    use crate::path::Path;
1009
1010    let mut path = Path::builder().with_svg();
1011
1012    crate::extra::rust_logo::build_logo_path(&mut path);
1013    let path = path.build();
1014
1015    crate::extra::debugging::find_reduced_test_case(path.as_slice(), &|path: Path| {
1016        let _ = EventQueue::from_path(0.05, path.iter());
1017        true
1018    });
1019}