lyon_tessellation/
fill.rs

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// It's a bit odd but this consistently performs a bit better than f32::max, probably
54// because the latter deals with NaN.
55#[inline(always)]
56fn fmax(a: f32, b: f32) -> f32 {
57    if a > b {
58        a
59    } else {
60        b
61    }
62}
63
64fn slope(v: Vector) -> f32 {
65    v.x / (v.y.max(f32::MIN))
66}
67
68#[cfg(all(debug_assertions, feature = "std"))]
69macro_rules! tess_log {
70    ($obj:ident, $fmt:expr) => (
71        if $obj.log {
72            std::println!($fmt);
73        }
74    );
75    ($obj:ident, $fmt:expr, $($arg:tt)*) => (
76        if $obj.log {
77            std::println!($fmt, $($arg)*);
78        }
79    );
80}
81
82#[cfg(not(all(debug_assertions, feature = "std")))]
83macro_rules! tess_log {
84    ($obj:ident, $fmt:expr) => {};
85    ($obj:ident, $fmt:expr, $($arg:tt)*) => {};
86}
87
88#[derive(Copy, Clone, Debug)]
89struct WindingState {
90    span_index: SpanIdx,
91    number: i16,
92    is_in: bool,
93}
94
95impl WindingState {
96    fn new() -> Self {
97        // The span index starts at -1 so that entering the first span (of index 0) increments
98        // it to zero.
99        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    // We want to be careful about the size of the struct.
169    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        // Because of float precision hazard, solve_x_for_y can
187        // return something slightly out of the min/max range which
188        // causes the ordering to be inconsistent with the way the
189        // scan phase uses the min/max range.
190        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    /// We store `MonotoneTessellator` behind a `Box` for performance purposes.
206    /// For more info, see [Issue #621](https://github.com/nical/lyon/pull/621).
207    tess: Option<Box<MonotoneTessellator>>,
208}
209
210impl Span {
211    fn tess(&mut self) -> &mut MonotoneTessellator {
212        // this should only ever be called on a "live" span.
213        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    /// We store `MonotoneTessellator` behind a `Box` for performance purposes.
227    /// For more info, see [Issue #621](https://github.com/nical/lyon/pull/621).
228    #[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            // Recycle the allocations for future use.
258            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        //  \...\ /.
275        //   \...x..  <-- merge vertex
276        //    \./...  <-- active_edge
277        //     x....  <-- current vertex
278
279        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        // Get rid of the spans that were marked for removal.
298        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    // Index in events.edge_data
307    src_edge: TessEventId,
308    winding: i16,
309    range_end: f32,
310}
311
312/// A Context object that can tessellate fill operations for complex paths.
313///
314/// <svg version="1.1" viewBox="0 0 400 200" height="200" width="400">
315///   <g transform="translate(0,-852.36216)">
316///     <path style="fill:#aad400;stroke:none;" transform="translate(0,852.36216)" d="M 20 20 L 20 180 L 180.30273 180 L 180.30273 20 L 20 20 z M 100 55 L 145 145 L 55 145 L 100 55 z "/>
317///     <path style="fill:#aad400;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-" d="m 219.75767,872.36216 0,160.00004 160.30273,0 0,-160.00004 -160.30273,0 z m 80,35 45,90 -90,0 45,-90 z"/>
318///     <path style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-" d="m 220,1032.3622 35,-35.00004 125,35.00004 -35,-35.00004 35,-125 -80,35 -80,-35 35,125"/>
319///     <circle r="5" cy="872.36218" cx="20" style="color:#000000;;fill:#ff6600;fill-;stroke:#000000;" />
320///     <circle r="5" cx="180.10918" cy="872.61475" style="fill:#ff6600;stroke:#000000;"/>
321///     <circle r="5" cy="1032.2189" cx="180.10918" style="fill:#ff6600;stroke:#000000;"/>
322///     <circle r="5" cx="20.505075" cy="1032.4714" style="fill:#ff6600;stroke:#000000;"/>
323///     <circle r="5" cy="907.21252" cx="99.802048" style="fill:#ff6600;stroke:#000000;"/>
324///     <circle r="5" cx="55.102798" cy="997.36865" style="fill:#ff6600;stroke:#000000;"/>
325///     <circle r="5" cy="997.62122" cx="145.25891" style="fill:#ff6600;stroke:#000000;"/>
326///   </g>
327/// </svg>
328///
329/// ## Overview
330///
331/// The most important structure is [`FillTessellator`](struct.FillTessellator.html).
332/// It implements the path fill tessellation algorithm which is by far the most advanced
333/// feature in all lyon crates.
334///
335/// The `FillTessellator` takes a description of the input path and
336/// [`FillOptions`](struct.FillOptions.html) as input. The description of the path can be an
337/// `PathEvent` iterator, or an iterator of `IdEvent` with an implementation of`PositionStore`
338/// to retrieve positions form endpoint and control point ids, and optionally an `AttributeStore`
339/// providing custom endpoint attributes that the tessellator can hand over to the geometry builder.
340///
341/// The output of the tessellator is produced by the
342/// [`FillGeometryBuilder`](geometry_builder/trait.FillGeometryBuilder.html) (see the
343/// [`geometry_builder` documentation](geometry_builder/index.html) for more details about
344/// how tessellators produce their output geometry, and how to generate custom vertex layouts).
345///
346/// The [tessellator's wiki page](https://github.com/nical/lyon/wiki/Tessellator) is a good place
347/// to learn more about how the tessellator's algorithm works. The source code also contains
348/// inline documentation for the adventurous who want to delve into more details.
349///
350/// The tessellator does not handle `NaN` values in any of its inputs.
351///
352/// ## Associating custom attributes with vertices.
353///
354/// It is sometimes useful to be able to link vertices generated by the tessellator back
355/// with the path's original data, for example to be able to add attributes that the tessellator
356/// does not know about (vertex color, texture coordinates, etc.).
357///
358/// The fill tessellator has two mechanisms to help with these advanced use cases. One is
359/// simple to use and one that, while more complicated to use, can cover advanced scenarios.
360///
361/// Before going delving into these mechanisms, it is important to understand that the
362/// vertices generated by the tessellator don't always correspond to the vertices existing
363/// in the original path.
364/// - Self-intersections, for example, introduce a new vertex where two edges meet.
365/// - When several vertices are at the same position, they are merged into a single vertex
366///   from the point of view of the tessellator.
367/// - The tessellator does not handle curves, and uses an approximation that introduces a
368///   number of line segments and therefore endpoints between the original endpoints of any
369///   quadratic or cubic bézier curve.
370///
371/// This complicates the task of adding extra data to vertices without loosing the association
372/// during tessellation.
373///
374/// ### Vertex sources
375///
376/// This is the complicated, but most powerful mechanism. The tessellator keeps track of where
377/// each vertex comes from in the original path, and provides access to this information via
378/// an iterator of [`VertexSource`](enum.VertexSource.html) in `FillVertex::sources`.
379///
380/// It is most common for the vertex source iterator to yield a single `VertexSource::Endpoint`
381/// source, which happens when the vertex directly corresponds to an endpoint of the original path.
382/// More complicated cases can be expressed.
383/// For example if a vertex is inserted at an intersection halfway in the edge AB and two thirds
384/// of the way through edge BC, the source for this new vertex is `VertexSource::Edge { from: A, to: B, t: 0.5 }`
385/// and `VertexSource::Edge { from: C, to: D, t: 0.666666 }` where A, B, C and D are endpoint IDs.
386///
387/// To use this feature, make sure to use `FillTessellator::tessellate_with_ids` instead of
388/// `FillTessellator::tessellate`.
389///
390/// ### Interpolated float attributes
391///
392/// Having to iterate over potentially several sources for each vertex can be cumbersome, in addition
393/// to having to deal with generating proper values for the attributes of vertices that were introduced
394/// at intersections or along curves.
395///
396/// In many scenarios, vertex attributes are made of floating point numbers and the most reasonable
397/// way to generate new attributes is to linearly interpolate these numbers between the endpoints
398/// of the edges they originate from.
399///
400/// Custom endpoint attributes are represented as `&[f32]` slices accessible via
401/// `FillVertex::interpolated_attributes`. All vertices, whether they originate from a single
402/// endpoint or some more complex source, have exactly the same number of attributes.
403/// Without having to know about the meaning of attributes, the tessellator can either
404/// forward the slice of attributes from a provided `AttributeStore` when possible or
405/// generate the values via linear interpolation.
406///
407/// To use this feature, make sure to use `FillTessellator::tessellate_path` or
408/// `FillTessellator::tessellate_with_ids` instead of `FillTessellator::tessellate`.
409///
410/// Attributes are lazily computed when calling `FillVertex::interpolated_attributes`.
411/// In other words they don't add overhead when not used, however it is best to avoid calling
412/// interpolated_attributes several times per vertex.
413///
414/// # Examples
415///
416/// ```
417/// # extern crate lyon_tessellation as tess;
418/// # use tess::path::Path;
419/// # use tess::path::builder::*;
420/// # use tess::path::iterator::*;
421/// # use tess::math::{Point, point};
422/// # use tess::geometry_builder::{VertexBuffers, simple_builder};
423/// # use tess::*;
424/// # fn main() {
425/// // Create a simple path.
426/// let mut path_builder = Path::builder();
427/// path_builder.begin(point(0.0, 0.0));
428/// path_builder.line_to(point(1.0, 2.0));
429/// path_builder.line_to(point(2.0, 0.0));
430/// path_builder.line_to(point(1.0, 1.0));
431/// path_builder.end(true);
432/// let path = path_builder.build();
433///
434/// // Create the destination vertex and index buffers.
435/// let mut buffers: VertexBuffers<Point, u16> = VertexBuffers::new();
436///
437/// {
438///     let mut vertex_builder = simple_builder(&mut buffers);
439///
440///     // Create the tessellator.
441///     let mut tessellator = FillTessellator::new();
442///
443///     // Compute the tessellation.
444///     let result = tessellator.tessellate_path(
445///         &path,
446///         &FillOptions::default(),
447///         &mut vertex_builder
448///     );
449///     assert!(result.is_ok());
450/// }
451///
452/// println!("The generated vertices are: {:?}.", &buffers.vertices[..]);
453/// println!("The generated indices are: {:?}.", &buffers.indices[..]);
454///
455/// # }
456/// ```
457///
458/// ```
459/// # extern crate lyon_tessellation as tess;
460/// # use tess::path::Path;
461/// # use tess::path::builder::*;
462/// # use tess::path::iterator::*;
463/// # use tess::math::{Point, point};
464/// # use tess::geometry_builder::{VertexBuffers, simple_builder};
465/// # use tess::*;
466/// # fn main() {
467/// // Create a path with three custom endpoint attributes.
468/// let mut path_builder = Path::builder_with_attributes(3);
469/// path_builder.begin(point(0.0, 0.0), &[0.0, 0.1, 0.5]);
470/// path_builder.line_to(point(1.0, 2.0), &[1.0, 1.0, 0.1]);
471/// path_builder.line_to(point(2.0, 0.0), &[1.0, 0.0, 0.8]);
472/// path_builder.line_to(point(1.0, 1.0), &[0.1, 0.3, 0.5]);
473/// path_builder.end(true);
474/// let path = path_builder.build();
475///
476/// struct MyVertex {
477///     x: f32, y: f32,
478///     r: f32, g: f32, b: f32, a: f32,
479/// }
480/// // A custom vertex constructor, see the geometry_builder module.
481/// struct Ctor;
482/// impl FillVertexConstructor<MyVertex> for Ctor {
483///     fn new_vertex(&mut self, mut vertex: FillVertex) -> MyVertex {
484///         let position = vertex.position();
485///         let attrs = vertex.interpolated_attributes();
486///         MyVertex {
487///             x: position.x,
488///             y: position.y,
489///             r: attrs[0],
490///             g: attrs[1],
491///             b: attrs[2],
492///             a: 1.0,
493///         }
494///     }
495/// }
496///
497/// // Create the destination vertex and index buffers.
498/// let mut buffers: VertexBuffers<MyVertex, u16> = VertexBuffers::new();
499///
500/// {
501///     // We use our custom vertex constructor here.
502///     let mut vertex_builder = BuffersBuilder::new(&mut buffers, Ctor);
503///
504///     // Create the tessellator.
505///     let mut tessellator = FillTessellator::new();
506///
507///     // Compute the tessellation. Here we use tessellate_with_ids
508///     // which has a slightly more complicated interface. The provides
509///     // the iterator as well as storage for positions and attributes at
510///     // the same time.
511///     let result = tessellator.tessellate_with_ids(
512///         path.id_iter(), // Iterator over ids in the path
513///         &path,          // PositionStore
514///         Some(&path),    // AttributeStore
515///         &FillOptions::default(),
516///         &mut vertex_builder
517///     );
518///     assert!(result.is_ok());
519/// }
520///
521/// # }
522/// ```
523pub 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    /// Constructor.
549    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    /// Compute the tessellation from a path iterator.
578    pub fn tessellate(
579        &mut self,
580        path: impl IntoIterator<Item = PathEvent>,
581        options: &FillOptions,
582        output: &mut dyn FillGeometryBuilder,
583    ) -> TessellationResult {
584        let event_queue = core::mem::replace(&mut self.events, EventQueue::new());
585        let mut queue_builder = event_queue.into_builder(options.tolerance);
586
587        queue_builder.set_path(
588            options.tolerance,
589            options.sweep_orientation,
590            path.into_iter(),
591        );
592
593        self.events = queue_builder.build();
594
595        self.tessellate_impl(options, None, output)
596    }
597
598    /// Compute the tessellation using an iterator over endpoint and control
599    /// point ids, storage for the positions and, optionally, storage for
600    /// custom endpoint attributes.
601    pub fn tessellate_with_ids(
602        &mut self,
603        path: impl IntoIterator<Item = IdEvent>,
604        positions: &impl PositionStore,
605        custom_attributes: Option<&dyn AttributeStore>,
606        options: &FillOptions,
607        output: &mut dyn FillGeometryBuilder,
608    ) -> TessellationResult {
609        let event_queue = core::mem::replace(&mut self.events, EventQueue::new());
610        let mut queue_builder = event_queue.into_builder(options.tolerance);
611
612        queue_builder.set_path_with_ids(
613            options.tolerance,
614            options.sweep_orientation,
615            path.into_iter(),
616            positions,
617        );
618
619        self.events = queue_builder.build();
620
621        self.tessellate_impl(options, custom_attributes, output)
622    }
623
624    /// Compute the tessellation from a path slice.
625    ///
626    /// The tessellator will internally only track vertex sources and interpolated
627    /// attributes if the path has interpolated attributes.
628    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    /// Tessellate a `Polygon`.
644    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    /// Tessellate an axis-aligned rectangle.
654    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    /// Tessellate a circle.
664    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    /// Tessellate an ellipse.
675    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    /// Tessellate directly from a sequence of `PathBuilder` commands, without
693    /// creating an intermediate path data structure.
694    ///
695    /// The returned builder implements the [`lyon_path::traits::PathBuilder`] trait,
696    /// is compatible with the all `PathBuilder` adapters.
697    /// It also has all requirements documented in `PathBuilder` (All sub-paths must be
698    /// wrapped in a `begin`/`end` pair).
699    ///
700    /// # Example
701    ///
702    /// ```rust
703    /// use lyon_tessellation::{FillTessellator, FillOptions};
704    /// use lyon_tessellation::geometry_builder::{simple_builder, VertexBuffers};
705    /// use lyon_tessellation::math::{Point, point};
706    ///
707    /// let mut buffers: VertexBuffers<Point, u16> = VertexBuffers::new();
708    /// let mut vertex_builder = simple_builder(&mut buffers);
709    /// let mut tessellator = FillTessellator::new();
710    /// let options = FillOptions::default();
711    ///
712    /// // Create a temporary builder (borrows the tessellator).
713    /// let mut builder = tessellator.builder(&options, &mut vertex_builder);
714    ///
715    /// // Build the path directly in the tessellator, skipping an intermediate data
716    /// // structure.
717    /// builder.begin(point(0.0, 0.0));
718    /// builder.line_to(point(10.0, 0.0));
719    /// builder.line_to(point(10.0, 10.0));
720    /// builder.line_to(point(0.0, 10.0));
721    /// builder.end(true);
722    ///
723    /// // Finish the tessellation and get the result.
724    /// let result = builder.build();
725    /// ```
726    ///
727    /// [`lyon_path::traits::PathBuilder`]: https://docs.rs/lyon_path/*/lyon_path/traits/trait.PathBuilder.html
728    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    /// Tessellate directly from a sequence of `PathBuilder` commands, without
737    /// creating an intermediate path data structure.
738    ///
739    /// Similar to `FillTessellator::builder` with custom attributes.
740    pub fn builder_with_attributes<'l>(
741        &'l mut self,
742        num_attributes: usize,
743        options: &'l FillOptions,
744        output: &'l mut dyn FillGeometryBuilder,
745    ) -> FillBuilder<'l> {
746        FillBuilder::new(num_attributes, self, options, output)
747    }
748
749    fn tessellate_impl(
750        &mut self,
751        options: &FillOptions,
752        attrib_store: Option<&dyn AttributeStore>,
753        builder: &mut dyn FillGeometryBuilder,
754    ) -> TessellationResult {
755        if options.tolerance.is_nan() || options.tolerance <= 0.0 {
756            return Err(TessellationError::UnsupportedParamater(
757                UnsupportedParamater::ToleranceIsNaN,
758            ));
759        }
760
761        self.reset();
762
763        if let Some(store) = attrib_store {
764            self.attrib_buffer.resize(store.num_attributes(), 0.0);
765        } else {
766            self.attrib_buffer.clear();
767        }
768
769        self.fill_rule = options.fill_rule;
770        self.orientation = options.sweep_orientation;
771        self.tolerance = options.tolerance * 0.5;
772        self.assume_no_intersection = !options.handle_intersections;
773
774        builder.begin_geometry();
775
776        let mut scan = mem::replace(&mut self.scan, ActiveEdgeScan::new());
777
778        let result = self.tessellator_loop(attrib_store, &mut scan, builder);
779
780        mem::swap(&mut self.scan, &mut scan);
781
782        if let Err(e) = result {
783            tess_log!(self, "Tessellation failed with error: {}.", e);
784            builder.abort_geometry();
785
786            return Err(e);
787        }
788
789        if !self.assume_no_intersection {
790            debug_assert!(self.active.edges.is_empty());
791            debug_assert!(self.fill.spans.is_empty());
792        }
793
794        // There shouldn't be any span left after the tessellation ends.
795        // If for whatever reason (bug) there are, flush them so that we don't
796        // miss the triangles they contain.
797        for span in &mut self.fill.spans {
798            if let Some(tess) = span.tess.as_mut() {
799                tess.flush(builder);
800            }
801        }
802
803        self.fill.spans.clear();
804
805        builder.end_geometry();
806
807        Ok(())
808    }
809
810    /// Enable/disable some verbose logging during the tessellation, for
811    /// debugging purposes.
812    pub fn set_logging(&mut self, is_enabled: bool) {
813        #[cfg(all(debug_assertions, feature = "std"))]
814        let forced = std::env::var("LYON_FORCE_LOGGING").is_ok();
815
816        #[cfg(not(all(debug_assertions, feature = "std")))]
817        let forced = false;
818
819        self.log = is_enabled || forced;
820    }
821
822    #[cfg_attr(feature = "profiling", inline(never))]
823    fn tessellator_loop(
824        &mut self,
825        attrib_store: Option<&dyn AttributeStore>,
826        scan: &mut ActiveEdgeScan,
827        output: &mut dyn FillGeometryBuilder,
828    ) -> Result<(), TessellationError> {
829        log_svg_preamble(self);
830
831        let mut _prev_position = point(f32::MIN, f32::MIN);
832        self.current_event_id = self.events.first_id();
833        while self.events.valid_id(self.current_event_id) {
834            self.initialize_events(attrib_store, output)?;
835
836            debug_assert!(is_after(self.current_position, _prev_position));
837            _prev_position = self.current_position;
838
839            if let Err(e) = self.process_events(scan, output) {
840                // Something went wrong, attempt to salvage the state of the sweep
841                // line
842                self.recover_from_error(e, output);
843                // ... and try again.
844                self.process_events(scan, output)?
845            }
846
847            #[cfg(debug_assertions)]
848            self.check_active_edges();
849
850            self.current_event_id = self.events.next_id(self.current_event_id);
851        }
852
853        Ok(())
854    }
855
856    fn initialize_events(
857        &mut self,
858        attrib_store: Option<&dyn AttributeStore>,
859        output: &mut dyn FillGeometryBuilder,
860    ) -> Result<(), TessellationError> {
861        let current_event = self.current_event_id;
862
863        tess_log!(
864            self,
865            "\n\n<!--         event #{}          -->",
866            current_event
867        );
868
869        self.current_position = self.events.position(current_event);
870
871        if self.current_position.x.is_nan() || self.current_position.y.is_nan() {
872            return Err(TessellationError::UnsupportedParamater(
873                UnsupportedParamater::PositionIsNaN,
874            ));
875        }
876
877        let position = match self.orientation {
878            Orientation::Vertical => self.current_position,
879            Orientation::Horizontal => reorient(self.current_position),
880        };
881
882        self.current_vertex = output.add_fill_vertex(FillVertex {
883            position,
884            events: &self.events,
885            current_event,
886            attrib_store,
887            attrib_buffer: &mut self.attrib_buffer,
888        })?;
889
890        let mut current_sibling = current_event;
891        while self.events.valid_id(current_sibling) {
892            let edge = &self.events.edge_data[current_sibling as usize];
893            // We insert "fake" edges when there are end events
894            // to make sure we process that vertex even if it has
895            // no edge below.
896            if edge.is_edge {
897                let to = edge.to;
898                debug_assert!(is_after(to, self.current_position));
899                self.edges_below.push(PendingEdge {
900                    to,
901                    sort_key: slope(to - self.current_position), //.angle_from_x_axis().radians,
902                    src_edge: current_sibling,
903                    winding: edge.winding,
904                    range_end: edge.range.end,
905                });
906            }
907
908            current_sibling = self.events.next_sibling_id(current_sibling);
909        }
910
911        Ok(())
912    }
913
914    /// An iteration of the sweep line algorithm.
915    #[cfg_attr(feature = "profiling", inline(never))]
916    fn process_events(
917        &mut self,
918        scan: &mut ActiveEdgeScan,
919        output: &mut dyn FillGeometryBuilder,
920    ) -> Result<(), InternalError> {
921        tess_log!(self, "<!--");
922        tess_log!(
923            self,
924            "     events at {:?} {:?}         {} edges below",
925            self.current_position,
926            self.current_vertex,
927            self.edges_below.len(),
928        );
929
930        tess_log!(self, "edges below (initially): {:#?}", self.edges_below);
931
932        // Step 1 - Scan the active edge list, deferring processing and detecting potential
933        // ordering issues in the active edges.
934        self.scan_active_edges(scan)?;
935
936        // Step 2 - Do the necessary processing on edges that end at the current point.
937        self.process_edges_above(scan, output);
938
939        // Step 3 - Do the necessary processing on edges that start at the current point.
940        self.process_edges_below(scan);
941
942        // Step 4 - Insert/remove edges to the active edge as necessary and handle
943        // potential self-intersections.
944        self.update_active_edges(scan);
945
946        tess_log!(self, "-->");
947
948        #[cfg(debug_assertions)]
949        self.log_active_edges();
950
951        Ok(())
952    }
953
954    #[cfg(debug_assertions)]
955    fn log_active_edges(&self) {
956        tess_log!(self, r#"<g class="active-edges">"#);
957        tess_log!(
958            self,
959            r#"<path d="M 0 {} L 1000 {}" class="sweep-line"/>"#,
960            self.current_position.y,
961            self.current_position.y
962        );
963        tess_log!(self, "<!-- active edges: -->");
964        for e in &self.active.edges {
965            if e.is_merge {
966                tess_log!(
967                    self,
968                    r#"  <circle cx="{}" cy="{}" r="3px" class="merge"/>"#,
969                    e.from.x,
970                    e.from.y
971                );
972            } else {
973                tess_log!(
974                    self,
975                    r#"  <path d="M {:.5?} {:.5?} L {:.5?} {:.5?}" class="edge", winding="{:>2}"/>"#,
976                    e.from.x,
977                    e.from.y,
978                    e.to.x,
979                    e.to.y,
980                    e.winding,
981                );
982            }
983        }
984        tess_log!(self, "<!-- spans: {}-->", self.fill.spans.len());
985        tess_log!(self, "</g>");
986    }
987
988    #[cfg(debug_assertions)]
989    fn check_active_edges(&self) {
990        let mut winding = WindingState::new();
991        for (idx, edge) in self.active.edges.iter().enumerate() {
992            winding.update(self.fill_rule, edge.winding);
993            if edge.is_merge {
994                assert!(self.fill_rule.is_in(winding.number));
995            } else {
996                assert!(
997                    !is_after(self.current_position, edge.to),
998                    "error at edge {}, position {:.6?} (current: {:.6?}",
999                    idx,
1000                    edge.to,
1001                    self.current_position,
1002                );
1003            }
1004        }
1005        assert_eq!(winding.number, 0);
1006        let expected_span_count = (winding.span_index + 1) as usize;
1007        assert_eq!(self.fill.spans.len(), expected_span_count);
1008    }
1009
1010    /// Scan the active edges to find the information we will need for the tessellation, without
1011    /// modifying the state of the sweep line and active spans.
1012    ///
1013    /// During this scan we also check that the ordering of the active edges is correct.
1014    /// If an error is detected we bail out of the scan which will cause us to sort the active
1015    /// edge list and try to scan again (this is why have to defer any modification to after
1016    /// the scan).
1017    ///
1018    /// The scan happens in three steps:
1019    /// - 1) Loop over the edges on the left of the current point to compute the winding number.
1020    /// - 2) Loop over the edges that connect with the current point to determine what processing
1021    ///      is needed (for example end events or right events).
1022    /// - 3) Loop over the edges on the right of the current point to detect potential edges that should
1023    ///      have been handled in the previous phases.
1024    #[cfg_attr(feature = "profiling", inline(never))]
1025    fn scan_active_edges(&self, scan: &mut ActiveEdgeScan) -> Result<(), InternalError> {
1026        scan.reset();
1027
1028        let current_x = self.current_position.x;
1029        let mut connecting_edges = false;
1030        let mut active_edge_idx = 0;
1031        let mut winding = WindingState::new();
1032        let mut previous_was_merge = false;
1033
1034        // Step 1 - Iterate over edges *before* the current point.
1035        for active_edge in &self.active.edges {
1036            if active_edge.is_merge {
1037                // \.....\ /...../
1038                //  \.....x...../   <--- merge vertex
1039                //   \....:..../
1040                // ---\---:---/----  <-- sweep line
1041                //     \..:../
1042
1043                // An unresolved merge vertex implies the left and right spans are
1044                // adjacent and there is no transition between the two which means
1045                // we need to bump the span index manually.
1046                winding.span_index += 1;
1047                active_edge_idx += 1;
1048                previous_was_merge = true;
1049
1050                continue;
1051            }
1052
1053            let edge_is_before_current_point =
1054                if points_are_equal(self.current_position, active_edge.to) {
1055                    // We just found our first edge that connects with the current point.
1056                    // We might find other ones in the next iterations.
1057                    connecting_edges = true;
1058                    false
1059                } else if active_edge.max_x() < current_x {
1060                    true
1061                } else if active_edge.min_x() > current_x {
1062                    tess_log!(
1063                        self,
1064                        "min_x({:?}) > current_x({:?})",
1065                        active_edge.min_x(),
1066                        current_x
1067                    );
1068                    false
1069                } else if active_edge.from.y == active_edge.to.y {
1070                    connecting_edges = true;
1071                    false
1072                } else {
1073                    let ex = active_edge.solve_x_for_y(self.current_position.y);
1074
1075                    if (ex - current_x).abs() <= self.tolerance {
1076                        connecting_edges = true;
1077                        false
1078                    } else if ex > current_x {
1079                        tess_log!(self, "ex({:?}) > current_x({:?})", ex, current_x);
1080                        false
1081                    } else {
1082                        true
1083                    }
1084                };
1085
1086            if !edge_is_before_current_point {
1087                break;
1088            }
1089
1090            winding.update(self.fill_rule, active_edge.winding);
1091            previous_was_merge = false;
1092            active_edge_idx += 1;
1093
1094            tess_log!(
1095                self,
1096                " > span: {}, in: {}",
1097                winding.span_index,
1098                winding.is_in
1099            );
1100        }
1101
1102        scan.above.start = active_edge_idx;
1103        scan.winding_before_point = winding;
1104
1105        if previous_was_merge {
1106            scan.winding_before_point.span_index -= 1;
1107            scan.above.start -= 1;
1108
1109            // First connecting edge is a merge.
1110            //  ...:./.      ...:...
1111            //  ...:/..  or  ...:...
1112            //  ...X...      ...X...
1113            //
1114            // The span on the left does not end here but it has a vertex
1115            // on its right side.
1116            //
1117            // The next loop can now assume that merge edges can't make the first
1118            // transition connecting with the current vertex,
1119
1120            if !connecting_edges {
1121                // There are no edges left and right of the merge that connect with
1122                // the current vertex. In other words the merge is the only edge
1123                // connecting and there must be a split event formed by two edges
1124                // below the current vertex.
1125                //
1126                // In this case we don't end any span and we skip splitting. The merge
1127                // and the split cancel each-other out.
1128                //
1129                //  ...:...
1130                //  ...:...
1131                //  ...x...
1132                //  ../ \..
1133                scan.vertex_events
1134                    .push((winding.span_index - 1, Side::Right));
1135                scan.vertex_events.push((winding.span_index, Side::Left));
1136                scan.merge_split_event = true;
1137                tess_log!(self, "split+merge");
1138            }
1139        }
1140
1141        //  .......
1142        //  ...x...
1143        //  ../ \..
1144        scan.split_event = !connecting_edges && winding.is_in && !scan.merge_split_event;
1145
1146        // Step 2 - Iterate over edges connecting with the current point.
1147
1148        tess_log!(
1149            self,
1150            "connecting_edges {} | edge {} | span {}",
1151            connecting_edges,
1152            active_edge_idx,
1153            winding.span_index
1154        );
1155        if connecting_edges {
1156            let in_before_vertex = winding.is_in;
1157            let mut first_connecting_edge = !previous_was_merge;
1158
1159            for active_edge in &self.active.edges[active_edge_idx..] {
1160                if active_edge.is_merge {
1161                    if !winding.is_in {
1162                        return Err(InternalError::MergeVertexOutside);
1163                    }
1164
1165                    // Merge above the current vertex to resolve.
1166                    //
1167                    // Resolving a merge usually leads to a span adjacent to the merge
1168                    // ending.
1169                    //
1170                    // If there was already an edge connecting with the current vertex
1171                    // just left of the merge edge, we can end the span between that edge
1172                    // and the merge.
1173                    //
1174                    //    |
1175                    //    v
1176                    //  \...:...
1177                    //  .\..:...
1178                    //  ..\.:...
1179                    //  ...\:...
1180                    //  ....X...
1181                    scan.spans_to_end.push(winding.span_index);
1182
1183                    // To deal with the right side of the merge, we simply pretend it
1184                    // transitioned into the shape. Next edge that transitions out (if any)
1185                    // will close out the span as if it was surrounded be regular edges.
1186                    //
1187                    //       |
1188                    //       v
1189                    //  ...:.../
1190                    //  ...:../
1191                    //  ...:./
1192                    //  ...:/
1193                    //  ...X
1194
1195                    winding.span_index += 1;
1196                    active_edge_idx += 1;
1197                    first_connecting_edge = false;
1198
1199                    continue;
1200                }
1201
1202                if !self.is_edge_connecting(active_edge, active_edge_idx, scan)? {
1203                    break;
1204                }
1205
1206                if !first_connecting_edge && winding.is_in {
1207                    // End event.
1208                    //
1209                    //  \.../
1210                    //   \./
1211                    //    x
1212                    //
1213                    scan.spans_to_end.push(winding.span_index);
1214                }
1215
1216                winding.update(self.fill_rule, active_edge.winding);
1217
1218                tess_log!(
1219                    self,
1220                    " x span: {} in: {}",
1221                    winding.span_index,
1222                    winding.is_in
1223                );
1224
1225                if winding.is_in && winding.span_index >= self.fill.spans.len() as i32 {
1226                    return Err(InternalError::InsufficientNumberOfSpans);
1227                }
1228
1229                active_edge_idx += 1;
1230                first_connecting_edge = false;
1231            }
1232
1233            let in_after_vertex = winding.is_in;
1234
1235            let vertex_is_merge_event = in_before_vertex
1236                && in_after_vertex
1237                && self.edges_below.is_empty()
1238                && scan.edges_to_split.is_empty();
1239
1240            if vertex_is_merge_event {
1241                //  .\   /.      .\ |./ /.
1242                //  ..\ /..      ..\|//...
1243                //  ...x...  or  ...x.....  (etc.)
1244                //  .......      .........
1245                scan.merge_event = true;
1246            }
1247
1248            if in_before_vertex {
1249                //   ...|         ..\ /..
1250                //   ...x    or   ...x...  (etc.)
1251                //   ...|         ...:...
1252                let first_span_index = scan.winding_before_point.span_index;
1253                scan.vertex_events.push((first_span_index, Side::Right));
1254            }
1255
1256            if in_after_vertex {
1257                //    |...        ..\ /..
1258                //    x...   or   ...x...  (etc.)
1259                //    |...        ...:...
1260                scan.vertex_events.push((winding.span_index, Side::Left));
1261            }
1262        }
1263
1264        tess_log!(self, "edges after | {}", active_edge_idx);
1265
1266        scan.above.end = active_edge_idx;
1267
1268        // Step 3 - Now Iterate over edges after the current point.
1269        // We only do this to detect errors.
1270        self.check_remaining_edges(active_edge_idx, current_x)
1271    }
1272
1273    #[cfg_attr(feature = "profiling", inline(never))]
1274    #[cfg_attr(not(feature = "profiling"), inline(always))]
1275    fn check_remaining_edges(
1276        &self,
1277        active_edge_idx: usize,
1278        current_x: f32,
1279    ) -> Result<(), InternalError> {
1280        // This function typically takes about 2.5% ~ 3% of the profile, so not necessarily the best
1281        // target for optimization. That said all of the work done here is only robustness checks
1282        // so we could add an option to skip it.
1283        for active_edge in &self.active.edges[active_edge_idx..] {
1284            if active_edge.is_merge {
1285                continue;
1286            }
1287
1288            if active_edge.max_x() < current_x {
1289                return Err(InternalError::IncorrectActiveEdgeOrder(1));
1290            }
1291
1292            if points_are_equal(self.current_position, active_edge.to) {
1293                return Err(InternalError::IncorrectActiveEdgeOrder(2));
1294            }
1295
1296            if active_edge.min_x() < current_x
1297                && active_edge.solve_x_for_y(self.current_position.y) < current_x
1298            {
1299                return Err(InternalError::IncorrectActiveEdgeOrder(3));
1300            }
1301        }
1302
1303        Ok(())
1304    }
1305
1306    // Returns Ok(true) if the edge connects with the current vertex, Ok(false) otherwise.
1307    // Returns Err if the active edge order is wrong.
1308    fn is_edge_connecting(
1309        &self,
1310        active_edge: &ActiveEdge,
1311        active_edge_idx: usize,
1312        scan: &mut ActiveEdgeScan,
1313    ) -> Result<bool, InternalError> {
1314        if points_are_equal(self.current_position, active_edge.to) {
1315            return Ok(true);
1316        }
1317
1318        let current_x = self.current_position.x;
1319        let threshold = self.tolerance;
1320
1321        let min_x = active_edge.min_x();
1322        let max_x = active_edge.max_x();
1323
1324        if max_x + threshold < current_x || active_edge.to.y < self.current_position.y {
1325            return Err(InternalError::IncorrectActiveEdgeOrder(4));
1326        }
1327
1328        if min_x > current_x {
1329            return Ok(false);
1330        }
1331
1332        let ex = if active_edge.from.y != active_edge.to.y {
1333            active_edge.solve_x_for_y(self.current_position.y)
1334        } else if max_x >= current_x && min_x <= current_x {
1335            current_x
1336        } else {
1337            active_edge.to.x
1338        };
1339
1340        if (ex - current_x).abs() <= threshold {
1341            tess_log!(
1342                self,
1343                "vertex on an edge! {:?} -> {:?}",
1344                active_edge.from,
1345                active_edge.to
1346            );
1347            scan.edges_to_split.push(active_edge_idx);
1348            return Ok(true);
1349        }
1350
1351        if ex < current_x {
1352            return Err(InternalError::IncorrectActiveEdgeOrder(5));
1353        }
1354
1355        tess_log!(self, "ex = {:?} (diff={})", ex, ex - current_x);
1356
1357        Ok(false)
1358    }
1359
1360    #[cfg_attr(feature = "profiling", inline(never))]
1361    fn process_edges_above(
1362        &mut self,
1363        scan: &mut ActiveEdgeScan,
1364        output: &mut dyn FillGeometryBuilder,
1365    ) {
1366        for &(span_index, side) in &scan.vertex_events {
1367            tess_log!(
1368                self,
1369                "   -> Vertex event, span: {:?} / {:?} / id: {:?}",
1370                span_index,
1371                side,
1372                self.current_vertex
1373            );
1374            self.fill.spans[span_index as usize].tess().vertex(
1375                self.current_position,
1376                self.current_vertex,
1377                side,
1378            );
1379        }
1380
1381        for &span_index in &scan.spans_to_end {
1382            tess_log!(self, "   -> End span {:?}", span_index);
1383            self.fill.end_span(
1384                span_index,
1385                &self.current_position,
1386                self.current_vertex,
1387                output,
1388            );
1389        }
1390
1391        self.fill.cleanup_spans();
1392
1393        for &edge_idx in &scan.edges_to_split {
1394            let active_edge = &mut self.active.edges[edge_idx];
1395            let to = active_edge.to;
1396
1397            self.edges_below.push(PendingEdge {
1398                to,
1399                sort_key: slope(to - self.current_position),
1400                src_edge: active_edge.src_edge,
1401                winding: active_edge.winding,
1402                range_end: active_edge.range_end,
1403            });
1404            tess_log!(
1405                self,
1406                "split {:?}, add edge below {:?} -> {:?} ({:?})",
1407                edge_idx,
1408                self.current_position,
1409                self.edges_below.last().unwrap().to,
1410                active_edge.winding,
1411            );
1412
1413            active_edge.to = self.current_position;
1414        }
1415
1416        if scan.merge_event {
1417            // Merge event.
1418            //
1419            //  ...\   /...
1420            //  ....\ /....
1421            //  .....x.....
1422            //
1423            let edge = &mut self.active.edges[scan.above.start];
1424            edge.is_merge = true;
1425            edge.from = edge.to;
1426            edge.winding = 0;
1427            edge.from_id = self.current_vertex;
1428
1429            // take the merge edge out of the range so that it isn't removed later.
1430            scan.above.start += 1;
1431        }
1432    }
1433
1434    #[cfg_attr(feature = "profiling", inline(never))]
1435    fn process_edges_below(&mut self, scan: &mut ActiveEdgeScan) {
1436        let mut winding = scan.winding_before_point;
1437
1438        tess_log!(
1439            self,
1440            "connecting edges: {}..{} in: {:?}",
1441            scan.above.start,
1442            scan.above.end,
1443            winding.is_in
1444        );
1445        tess_log!(self, "winding state before point: {:?}", winding);
1446        tess_log!(self, "edges below: {:#?}", self.edges_below);
1447
1448        self.sort_edges_below();
1449
1450        self.handle_coincident_edges_below();
1451
1452        if scan.split_event {
1453            // Split event.
1454            //
1455            //  ...........
1456            //  .....x.....
1457            //  ..../ \....
1458            //  .../   \...
1459            //
1460
1461            tess_log!(self, "split event");
1462
1463            let left_enclosing_edge_idx = scan.above.start - 1;
1464            self.split_event(left_enclosing_edge_idx, winding.span_index);
1465        }
1466
1467        // Go through the edges that start at the current point and emit
1468        // start events for each time an in-out pair is found.
1469
1470        let mut first_pending_edge = true;
1471        for pending_edge in &self.edges_below {
1472            if !first_pending_edge && winding.is_in {
1473                // Start event.
1474                //
1475                //      x
1476                //     /.\
1477                //    /...\
1478                //
1479
1480                tess_log!(
1481                    self,
1482                    " begin span {} ({})",
1483                    winding.span_index,
1484                    self.fill.spans.len()
1485                );
1486
1487                self.fill.begin_span(
1488                    winding.span_index,
1489                    &self.current_position,
1490                    self.current_vertex,
1491                );
1492            }
1493            winding.update(self.fill_rule, pending_edge.winding);
1494
1495            tess_log!(
1496                self,
1497                "edge below: span: {}, in: {}",
1498                winding.span_index,
1499                winding.is_in
1500            );
1501
1502            first_pending_edge = false;
1503        }
1504    }
1505
1506    #[cfg_attr(feature = "profiling", inline(never))]
1507    fn update_active_edges(&mut self, scan: &ActiveEdgeScan) {
1508        let above = scan.above.start..scan.above.end;
1509
1510        tess_log!(
1511            self,
1512            " remove {} edges ({}..{})",
1513            above.end - above.start,
1514            above.start,
1515            above.end
1516        );
1517
1518        if !self.assume_no_intersection {
1519            self.handle_intersections(above.clone());
1520        }
1521
1522        #[cfg(debug_assertions)]
1523        for active_edge in &self.active.edges[above.clone()] {
1524            debug_assert!(active_edge.is_merge || !is_after(self.current_position, active_edge.to));
1525        }
1526
1527        let from = self.current_position;
1528        let from_id = self.current_vertex;
1529        self.active.edges.splice(
1530            above,
1531            self.edges_below.drain(..).map(|edge| ActiveEdge {
1532                from,
1533                to: edge.to,
1534                winding: edge.winding,
1535                is_merge: false,
1536                from_id,
1537                src_edge: edge.src_edge,
1538                range_end: edge.range_end,
1539            }),
1540        );
1541    }
1542
1543    fn split_event(&mut self, left_enclosing_edge_idx: ActiveEdgeIdx, left_span_idx: SpanIdx) {
1544        let right_enclosing_edge_idx = left_enclosing_edge_idx + 1;
1545
1546        let upper_left = self.active.edges[left_enclosing_edge_idx].from;
1547        let upper_right = self.active.edges[right_enclosing_edge_idx].from;
1548
1549        let right_span_idx = left_span_idx + 1;
1550
1551        let (upper_position, upper_id, new_span_idx) = if is_after(upper_left, upper_right) {
1552            //                |.....
1553            // upper_left --> x.....
1554            //               /.:....
1555            //              /...x... <-- current split vertex
1556            //             /.../ \..
1557            (
1558                upper_left,
1559                self.active.edges[left_enclosing_edge_idx].from_id,
1560                left_span_idx,
1561            )
1562        } else {
1563            //                          .....|
1564            //                          .....x <-- upper_right
1565            //                          ....:.\
1566            // current split vertex --> ...x...\
1567            //                          ../ \...\
1568            (
1569                upper_right,
1570                self.active.edges[right_enclosing_edge_idx].from_id,
1571                right_span_idx,
1572            )
1573        };
1574
1575        self.fill
1576            .begin_span(new_span_idx, &upper_position, upper_id);
1577
1578        self.fill.spans[left_span_idx as usize].tess().vertex(
1579            self.current_position,
1580            self.current_vertex,
1581            Side::Right,
1582        );
1583        self.fill.spans[right_span_idx as usize].tess().vertex(
1584            self.current_position,
1585            self.current_vertex,
1586            Side::Left,
1587        );
1588    }
1589
1590    #[cfg_attr(feature = "profiling", inline(never))]
1591    fn handle_intersections(&mut self, skip_range: Range<usize>) {
1592        // Do intersection checks for all of the new edges against already active edges.
1593        //
1594        // If several intersections are found on the same edges we only keep the top-most.
1595        // the active and new edges are then truncated at the intersection position and the
1596        // lower parts are added to the event queue.
1597        //
1598        // In order to not break invariants of the sweep line we need to ensure that:
1599        // - the intersection position is never ordered before the current position,
1600        // - after truncation, edges continue being oriented downwards,
1601        //
1602        // Floating-point precision (or the lack thereof) prevent us from taking the
1603        // above properties from granted even though they make sense from a purely
1604        // geometrical perspective. Therefore we have to take great care in checking
1605        // whether these invariants aren't broken by the insertion of the intersection,
1606        // manually fixing things up if need be and making sure to not break more
1607        // invariants in doing so.
1608
1609        let mut edges_below = mem::take(&mut self.edges_below);
1610        for edge_below in &mut edges_below {
1611            let below_min_x = self.current_position.x.min(edge_below.to.x);
1612            let below_max_x = fmax(self.current_position.x, edge_below.to.x);
1613
1614            let below_segment = LineSegment {
1615                from: self.current_position.to_f64(),
1616                to: edge_below.to.to_f64(),
1617            };
1618
1619            let mut tb_min = 1.0;
1620            let mut intersection = None;
1621            for (i, active_edge) in self.active.edges.iter().enumerate() {
1622                if skip_range.contains(&i) {
1623                    continue;
1624                }
1625                if active_edge.is_merge || below_min_x > active_edge.max_x() {
1626                    continue;
1627                }
1628
1629                if below_max_x < active_edge.min_x() {
1630                    // We can't early out because there might be edges further on the right
1631                    // that extend further on the left which would be missed.
1632                    //
1633                    // sweep line -> =o===/==/==
1634                    //                |\ /  /
1635                    //                | o  /
1636                    //  edge below -> |   /
1637                    //                |  /
1638                    //                | / <- missed active edge
1639                    //                |/
1640                    //                x <- missed intersection
1641                    //               /|
1642                    continue;
1643                }
1644
1645                let active_segment = LineSegment {
1646                    from: active_edge.from.to_f64(),
1647                    to: active_edge.to.to_f64(),
1648                };
1649
1650                if let Some((ta, tb)) = active_segment.intersection_t(&below_segment) {
1651                    if tb < tb_min && tb > 0.0 && ta > 0.0 && ta <= 1.0 {
1652                        // we only want the closest intersection;
1653                        tb_min = tb;
1654                        intersection = Some((ta, tb, i));
1655                    }
1656                }
1657            }
1658
1659            if let Some((ta, tb, active_edge_idx)) = intersection {
1660                self.process_intersection(ta, tb, active_edge_idx, edge_below, &below_segment);
1661            }
1662        }
1663        self.edges_below = edges_below;
1664
1665        //self.log_active_edges();
1666    }
1667
1668    #[inline(never)]
1669    fn process_intersection(
1670        &mut self,
1671        ta: f64,
1672        tb: f64,
1673        active_edge_idx: usize,
1674        edge_below: &mut PendingEdge,
1675        below_segment: &LineSegment<f64>,
1676    ) {
1677        let mut intersection_position = below_segment.sample(tb).to_f32();
1678        tess_log!(
1679            self,
1680            "-> intersection at: {:?} t={:?}|{:?}",
1681            intersection_position,
1682            ta,
1683            tb
1684        );
1685        tess_log!(
1686            self,
1687            "   from {:?}->{:?} and {:?}->{:?}",
1688            self.active.edges[active_edge_idx].from,
1689            self.active.edges[active_edge_idx].to,
1690            self.current_position,
1691            edge_below.to,
1692        );
1693
1694        let active_edge = &mut self.active.edges[active_edge_idx];
1695
1696        if self.current_position == intersection_position {
1697            active_edge.from = intersection_position;
1698            let src_range = &mut self.events.edge_data[active_edge.src_edge as usize].range;
1699            let remapped_ta = remap_t_in_range(ta as f32, src_range.start..active_edge.range_end);
1700            src_range.start = remapped_ta;
1701
1702            return;
1703        }
1704
1705        if !is_after(intersection_position, self.current_position) {
1706            tess_log!(self, "fixup the intersection");
1707            intersection_position.y = self.current_position.y.next_after(f32::INFINITY);
1708        }
1709
1710        assert!(
1711            is_after(intersection_position, self.current_position),
1712            "!!! {:.9?} {:.9?}",
1713            intersection_position,
1714            self.current_position
1715        );
1716
1717        if is_near(intersection_position, edge_below.to) {
1718            tess_log!(self, "intersection near below.to");
1719            intersection_position = edge_below.to;
1720        } else if is_near(intersection_position, active_edge.to) {
1721            tess_log!(self, "intersection near active_edge.to");
1722            intersection_position = active_edge.to;
1723        }
1724
1725        let a_src_edge_data = self.events.edge_data[active_edge.src_edge as usize].clone();
1726        let b_src_edge_data = self.events.edge_data[edge_below.src_edge as usize].clone();
1727
1728        let mut inserted_evt = None;
1729        let mut flipped_active = false;
1730
1731        if active_edge.to != intersection_position && active_edge.from != intersection_position {
1732            let remapped_ta = remap_t_in_range(
1733                ta as f32,
1734                a_src_edge_data.range.start..active_edge.range_end,
1735            );
1736
1737            if is_after(active_edge.to, intersection_position) {
1738                // Should take this branch most of the time.
1739                inserted_evt = Some(self.events.insert_sorted(
1740                    intersection_position,
1741                    EdgeData {
1742                        range: remapped_ta..active_edge.range_end,
1743                        winding: active_edge.winding,
1744                        to: active_edge.to,
1745                        is_edge: true,
1746                        ..a_src_edge_data
1747                    },
1748                    self.current_event_id,
1749                ));
1750            } else {
1751                tess_log!(self, "flip active edge after intersection");
1752                flipped_active = true;
1753                self.events.insert_sorted(
1754                    active_edge.to,
1755                    EdgeData {
1756                        range: active_edge.range_end..remapped_ta,
1757                        winding: -active_edge.winding,
1758                        to: intersection_position,
1759                        is_edge: true,
1760                        ..a_src_edge_data
1761                    },
1762                    self.current_event_id,
1763                );
1764            }
1765
1766            active_edge.to = intersection_position;
1767            active_edge.range_end = remapped_ta;
1768        }
1769
1770        if edge_below.to != intersection_position && self.current_position != intersection_position
1771        {
1772            let remapped_tb =
1773                remap_t_in_range(tb as f32, b_src_edge_data.range.start..edge_below.range_end);
1774
1775            if is_after(edge_below.to, intersection_position) {
1776                let edge_data = EdgeData {
1777                    range: remapped_tb..edge_below.range_end,
1778                    winding: edge_below.winding,
1779                    to: edge_below.to,
1780                    is_edge: true,
1781                    ..b_src_edge_data
1782                };
1783
1784                if let Some(idx) = inserted_evt {
1785                    // Should take this branch most of the time.
1786                    self.events
1787                        .insert_sibling(idx, intersection_position, edge_data);
1788                } else {
1789                    self.events.insert_sorted(
1790                        intersection_position,
1791                        edge_data,
1792                        self.current_event_id,
1793                    );
1794                }
1795            } else {
1796                tess_log!(self, "flip edge below after intersection");
1797                self.events.insert_sorted(
1798                    edge_below.to,
1799                    EdgeData {
1800                        range: edge_below.range_end..remapped_tb,
1801                        winding: -edge_below.winding,
1802                        to: intersection_position,
1803                        is_edge: true,
1804                        ..b_src_edge_data
1805                    },
1806                    self.current_event_id,
1807                );
1808
1809                if flipped_active {
1810                    // It is extremely rare but if we end up flipping both of the
1811                    // edges that are inserted in the event queue, then we created a
1812                    // merge event which means we have to insert a vertex event into
1813                    // the queue, otherwise the tessellator will skip over the end of
1814                    // these two edges.
1815                    self.events.vertex_event_sorted(
1816                        intersection_position,
1817                        b_src_edge_data.to_id,
1818                        self.current_event_id,
1819                    );
1820                }
1821            }
1822
1823            edge_below.to = intersection_position;
1824            edge_below.range_end = remapped_tb;
1825        }
1826    }
1827
1828    fn sort_active_edges(&mut self) {
1829        // Merge edges are a little subtle when it comes to sorting.
1830        // They are points rather than edges and the best we can do is
1831        // keep their relative ordering with their previous or next edge.
1832        // Unfortunately this can cause merge vertices to end up outside of
1833        // the shape.
1834        // After sorting we go through the active edges and rearrange merge
1835        // vertices to prevent that.
1836
1837        let y = self.current_position.y;
1838
1839        let mut keys = Vec::with_capacity(self.active.edges.len());
1840
1841        let mut has_merge_vertex = false;
1842        let mut prev_x = f32::NAN;
1843        for (i, edge) in self.active.edges.iter().enumerate() {
1844            if edge.is_merge {
1845                debug_assert!(!prev_x.is_nan());
1846                has_merge_vertex = true;
1847                keys.push((prev_x, i));
1848            } else {
1849                debug_assert!(!is_after(self.current_position, edge.to));
1850
1851                let eq_to = edge.to.y == y;
1852                let eq_from = edge.from.y == y;
1853
1854                let x = if eq_to && eq_from {
1855                    let current_x = self.current_position.x;
1856                    if edge.max_x() >= current_x && edge.min_x() <= current_x {
1857                        self.current_position.x
1858                    } else {
1859                        edge.min_x()
1860                    }
1861                } else if eq_from {
1862                    edge.from.x
1863                } else if eq_to {
1864                    edge.to.x
1865                } else {
1866                    edge.solve_x_for_y(y)
1867                };
1868
1869                keys.push((fmax(x, edge.min_x()), i));
1870                prev_x = x;
1871            }
1872        }
1873
1874        keys.sort_by(|a, b| match a.0.partial_cmp(&b.0).unwrap() {
1875            Ordering::Less => Ordering::Less,
1876            Ordering::Greater => Ordering::Greater,
1877            Ordering::Equal => {
1878                let a = &self.active.edges[a.1];
1879                let b = &self.active.edges[b.1];
1880                match (a.is_merge, b.is_merge) {
1881                    (false, false) => {
1882                        let slope_a = slope(a.to - a.from);
1883                        let slope_b = slope(b.to - b.from);
1884                        slope_b.partial_cmp(&slope_a).unwrap_or(Ordering::Equal)
1885                    }
1886                    (true, false) => Ordering::Greater,
1887                    (false, true) => Ordering::Less,
1888                    (true, true) => Ordering::Equal,
1889                }
1890            }
1891        });
1892
1893        let mut new_active_edges = Vec::with_capacity(self.active.edges.len());
1894        for &(_, idx) in &keys {
1895            new_active_edges.push(self.active.edges[idx]);
1896        }
1897
1898        self.active.edges = new_active_edges;
1899
1900        if !has_merge_vertex {
1901            return;
1902        }
1903
1904        let mut winding_number = 0;
1905        for i in 0..self.active.edges.len() {
1906            let needs_swap = {
1907                let edge = &self.active.edges[i];
1908                if edge.is_merge {
1909                    !self.fill_rule.is_in(winding_number)
1910                } else {
1911                    winding_number += edge.winding;
1912                    false
1913                }
1914            };
1915
1916            if needs_swap {
1917                let mut w = winding_number;
1918                tess_log!(self, "Fixing up merge vertex after sort.");
1919                let mut idx = i;
1920                loop {
1921                    // Roll back previous edge winding and swap.
1922                    w -= self.active.edges[idx - 1].winding;
1923                    self.active.edges.swap(idx, idx - 1);
1924
1925                    if self.fill_rule.is_in(w) {
1926                        break;
1927                    }
1928
1929                    idx -= 1;
1930                }
1931            }
1932        }
1933    }
1934
1935    #[inline(never)]
1936    fn recover_from_error(&mut self, _error: InternalError, output: &mut dyn FillGeometryBuilder) {
1937        tess_log!(self, "Attempt to recover error {:?}", _error);
1938
1939        self.sort_active_edges();
1940
1941        debug_assert!(self
1942            .active
1943            .edges
1944            .first()
1945            .map(|e| !e.is_merge)
1946            .unwrap_or(true));
1947        // This can only happen if we ignore self-intersections,
1948        // so we are in a pretty broken state already.
1949        // There isn't a fully correct solution for this (other
1950        // than properly detecting self intersections and not
1951        // getting into this situation), but the rest of the code
1952        // doesn't deal with merge edges being at the last position
1953        // so we artificially move them to avoid that.
1954        // TODO: with self-intersections properly handled it may make more sense
1955        // to turn this into an assertion.
1956        let len = self.active.edges.len();
1957        if len > 1 && self.active.edges[len - 1].is_merge {
1958            self.active.edges.swap(len - 1, len - 2);
1959        }
1960
1961        let mut winding = WindingState::new();
1962
1963        for edge in &self.active.edges {
1964            if edge.is_merge {
1965                winding.span_index += 1;
1966            } else {
1967                winding.update(self.fill_rule, edge.winding);
1968            }
1969
1970            if winding.span_index >= self.fill.spans.len() as i32 {
1971                self.fill
1972                    .begin_span(winding.span_index, &edge.from, edge.from_id);
1973            }
1974        }
1975
1976        while self.fill.spans.len() > (winding.span_index + 1) as usize {
1977            self.fill.spans.last_mut().unwrap().tess().flush(output);
1978            self.fill.spans.pop();
1979        }
1980
1981        tess_log!(self, "-->");
1982
1983        #[cfg(debug_assertions)]
1984        self.log_active_edges();
1985    }
1986
1987    #[cfg_attr(feature = "profiling", inline(never))]
1988    fn sort_edges_below(&mut self) {
1989        self.edges_below
1990            .sort_unstable_by(|a, b| a.sort_key.partial_cmp(&b.sort_key).unwrap_or(Ordering::Equal));
1991    }
1992
1993    #[cfg_attr(feature = "profiling", inline(never))]
1994    fn handle_coincident_edges_below(&mut self) {
1995        if self.edges_below.len() < 2 {
1996            return;
1997        }
1998
1999        for idx in (0..(self.edges_below.len() - 1)).rev() {
2000            let a_idx = idx;
2001            let b_idx = idx + 1;
2002
2003            let a_slope = self.edges_below[a_idx].sort_key;
2004            let b_slope = self.edges_below[b_idx].sort_key;
2005
2006            const THRESHOLD: f32 = 0.00005;
2007
2008            // The slope function preserves the ordering for sorting but isn't a very good approximation
2009            // of the angle as edges get closer to horizontal.
2010            // When edges are larger in x than y, comparing the inverse is a better approximation.
2011            let angle_is_close = if a_slope.abs() <= 1.0 {
2012                (a_slope - b_slope).abs() < THRESHOLD
2013            } else {
2014                (1.0 / a_slope - 1.0 / b_slope).abs() < THRESHOLD
2015            };
2016
2017            if angle_is_close {
2018                self.merge_coincident_edges(a_idx, b_idx);
2019            }
2020        }
2021    }
2022
2023    #[cold]
2024    fn merge_coincident_edges(&mut self, a_idx: usize, b_idx: usize) {
2025        let a_to = self.edges_below[a_idx].to;
2026        let b_to = self.edges_below[b_idx].to;
2027
2028        let (lower_idx, upper_idx, split) = match compare_positions(a_to, b_to) {
2029            Ordering::Greater => (a_idx, b_idx, true),
2030            Ordering::Less => (b_idx, a_idx, true),
2031            Ordering::Equal => (a_idx, b_idx, false),
2032        };
2033
2034        tess_log!(
2035            self,
2036            "coincident edges {:?} -> {:?} / {:?}",
2037            self.current_position,
2038            a_to,
2039            b_to
2040        );
2041
2042        tess_log!(
2043            self,
2044            "update winding: {:?} -> {:?}",
2045            self.edges_below[upper_idx].winding,
2046            self.edges_below[upper_idx].winding + self.edges_below[lower_idx].winding
2047        );
2048        self.edges_below[upper_idx].winding += self.edges_below[lower_idx].winding;
2049        let split_point = self.edges_below[upper_idx].to;
2050
2051        tess_log!(
2052            self,
2053            "remove coincident edge {:?}, split:{:?}",
2054            a_idx,
2055            split
2056        );
2057        let edge = self.edges_below.remove(lower_idx);
2058
2059        if !split {
2060            return;
2061        }
2062
2063        let src_edge_data = self.events.edge_data[edge.src_edge as usize].clone();
2064
2065        let t = LineSegment {
2066            from: self.current_position,
2067            to: edge.to,
2068        }
2069        .solve_t_for_y(split_point.y);
2070
2071        let src_range = src_edge_data.range.start..edge.range_end;
2072        let t_remapped = remap_t_in_range(t, src_range);
2073
2074        let edge_data = EdgeData {
2075            range: t_remapped..edge.range_end,
2076            winding: edge.winding,
2077            to: edge.to,
2078            is_edge: true,
2079            ..src_edge_data
2080        };
2081
2082        self.events
2083            .insert_sorted(split_point, edge_data, self.current_event_id);
2084    }
2085
2086    fn reset(&mut self) {
2087        self.current_position = point(f32::MIN, f32::MIN);
2088        self.current_vertex = VertexId::INVALID;
2089        self.current_event_id = INVALID_EVENT_ID;
2090        self.active.edges.clear();
2091        self.edges_below.clear();
2092        self.fill.spans.clear();
2093    }
2094}
2095
2096pub(crate) fn points_are_equal(a: Point, b: Point) -> bool {
2097    a == b
2098}
2099
2100pub(crate) fn compare_positions(a: Point, b: Point) -> Ordering {
2101    // This function is somewhat hot during the sorting phase but it might be that inlining
2102    // moves the cost of fetching the positions here.
2103    // The y coordinates are rarely equal (typically less than 7% of the time) but it's
2104    // unclear whether moving the x comparison out into a cold function helps in practice.
2105    if a.y > b.y {
2106        return Ordering::Greater;
2107    }
2108    if a.y < b.y {
2109        return Ordering::Less;
2110    }
2111    if a.x > b.x {
2112        return Ordering::Greater;
2113    }
2114    if a.x < b.x {
2115        return Ordering::Less;
2116    }
2117
2118    Ordering::Equal
2119}
2120
2121#[inline]
2122pub(crate) fn is_after(a: Point, b: Point) -> bool {
2123    a.y > b.y || (a.y == b.y && a.x > b.x)
2124}
2125
2126#[inline]
2127pub(crate) fn is_near(a: Point, b: Point) -> bool {
2128    (a - b).square_length() < 0.000000001
2129}
2130
2131#[inline]
2132fn reorient(p: Point) -> Point {
2133    point(p.y, -p.x)
2134}
2135
2136/// Extra vertex information from the `FillTessellator`, accessible when building vertices.
2137pub struct FillVertex<'l> {
2138    pub(crate) position: Point,
2139    pub(crate) events: &'l EventQueue,
2140    pub(crate) current_event: TessEventId,
2141    pub(crate) attrib_buffer: &'l mut [f32],
2142    pub(crate) attrib_store: Option<&'l dyn AttributeStore>,
2143}
2144
2145impl<'l> FillVertex<'l> {
2146    pub fn position(&self) -> Point {
2147        self.position
2148    }
2149
2150    /// Return an iterator over the sources of the vertex.
2151    pub fn sources(&self) -> VertexSourceIterator {
2152        VertexSourceIterator {
2153            events: self.events,
2154            id: self.current_event,
2155            prev: None,
2156        }
2157    }
2158
2159    /// Returns the first endpoint that this vertex is on, if any.
2160    ///
2161    /// This is meant to be used only in very simple cases where self-intersections,
2162    /// overlapping vertices and curves are unexpected.
2163    /// This will return `None` at self-intersections and between the endpoints of
2164    /// a flattened curve. If two endpoints are at the same position only one of
2165    /// them is returned.
2166    ///
2167    /// See also: `FillVertex::sources`.
2168    pub fn as_endpoint_id(&self) -> Option<EndpointId> {
2169        let mut current = self.current_event;
2170        while self.events.valid_id(current) {
2171            let edge = &self.events.edge_data[current as usize];
2172            let t = edge.range.start;
2173            if t == 0.0 {
2174                return Some(edge.from_id);
2175            }
2176            if t == 1.0 {
2177                return Some(edge.to_id);
2178            }
2179
2180            current = self.events.next_sibling_id(current)
2181        }
2182
2183        None
2184    }
2185
2186    /// Fetch or interpolate the custom attribute values at this vertex.
2187    pub fn interpolated_attributes(&mut self) -> Attributes {
2188        if self.attrib_store.is_none() {
2189            return NO_ATTRIBUTES;
2190        }
2191
2192        let store = self.attrib_store.unwrap();
2193
2194        let mut sources = VertexSourceIterator {
2195            events: self.events,
2196            id: self.current_event,
2197            prev: None,
2198        };
2199
2200        let num_attributes = store.num_attributes();
2201
2202        let first = sources.next().unwrap();
2203        let mut next = sources.next();
2204
2205        // Fast path for the single-source-single-endpoint common case.
2206        if next.is_none() {
2207            if let VertexSource::Endpoint { id } = first {
2208                return store.get(id);
2209            }
2210        }
2211
2212        // First source taken out of the loop to avoid initializing the buffer.
2213        match first {
2214            VertexSource::Endpoint { id } => {
2215                let a = store.get(id);
2216                assert_eq!(a.len(), num_attributes);
2217                assert_eq!(self.attrib_buffer.len(), num_attributes);
2218                self.attrib_buffer[..num_attributes].clone_from_slice(&a[..num_attributes]);
2219            }
2220            VertexSource::Edge { from, to, t } => {
2221                let a = store.get(from);
2222                let b = store.get(to);
2223                assert_eq!(a.len(), num_attributes);
2224                assert_eq!(b.len(), num_attributes);
2225                assert_eq!(self.attrib_buffer.len(), num_attributes);
2226                for i in 0..num_attributes {
2227                    self.attrib_buffer[i] = a[i] * (1.0 - t) + b[i] * t;
2228                }
2229            }
2230        }
2231
2232        let mut div = 1.0;
2233        loop {
2234            match next {
2235                Some(VertexSource::Endpoint { id }) => {
2236                    let a = store.get(id);
2237                    assert_eq!(a.len(), num_attributes);
2238                    assert_eq!(self.attrib_buffer.len(), num_attributes);
2239                    for (i, &att) in a.iter().enumerate() {
2240                        self.attrib_buffer[i] += att;
2241                    }
2242                }
2243                Some(VertexSource::Edge { from, to, t }) => {
2244                    let a = store.get(from);
2245                    let b = store.get(to);
2246                    assert_eq!(a.len(), num_attributes);
2247                    assert_eq!(b.len(), num_attributes);
2248                    assert_eq!(self.attrib_buffer.len(), num_attributes);
2249                    for i in 0..num_attributes {
2250                        self.attrib_buffer[i] += a[i] * (1.0 - t) + b[i] * t;
2251                    }
2252                }
2253                None => {
2254                    break;
2255                }
2256            }
2257            div += 1.0;
2258            next = sources.next();
2259        }
2260
2261        if div > 1.0 {
2262            for attribute in self.attrib_buffer.iter_mut() {
2263                *attribute /= div;
2264            }
2265        }
2266
2267        self.attrib_buffer
2268    }
2269}
2270
2271/// An iterator over the sources of a given vertex.
2272#[derive(Clone)]
2273pub struct VertexSourceIterator<'l> {
2274    events: &'l EventQueue,
2275    id: TessEventId,
2276    prev: Option<VertexSource>,
2277}
2278
2279impl<'l> Iterator for VertexSourceIterator<'l> {
2280    type Item = VertexSource;
2281    #[inline]
2282    fn next(&mut self) -> Option<VertexSource> {
2283        let mut src;
2284        loop {
2285            if self.id == INVALID_EVENT_ID {
2286                return None;
2287            }
2288
2289            let edge = &self.events.edge_data[self.id as usize];
2290
2291            self.id = self.events.next_sibling_id(self.id);
2292
2293            let t = edge.range.start;
2294
2295            src = if t == 0.0 {
2296                Some(VertexSource::Endpoint { id: edge.from_id })
2297            } else if t == 1.0 {
2298                Some(VertexSource::Endpoint { id: edge.to_id })
2299            } else {
2300                Some(VertexSource::Edge {
2301                    from: edge.from_id,
2302                    to: edge.to_id,
2303                    t,
2304                })
2305            };
2306
2307            if src != self.prev {
2308                break;
2309            }
2310        }
2311
2312        self.prev = src;
2313        src
2314    }
2315}
2316
2317fn remap_t_in_range(val: f32, range: Range<f32>) -> f32 {
2318    if range.end > range.start {
2319        let d = range.end - range.start;
2320        range.start + val * d
2321    } else {
2322        let d = range.start - range.end;
2323        range.end + (1.0 - val) * d
2324    }
2325}
2326
2327pub struct FillBuilder<'l> {
2328    events: EventQueueBuilder,
2329    next_id: EndpointId,
2330    first_id: EndpointId,
2331    first_position: Point,
2332    horizontal_sweep: bool,
2333    attrib_store: SimpleAttributeStore,
2334    tessellator: &'l mut FillTessellator,
2335    output: &'l mut dyn FillGeometryBuilder,
2336    options: &'l FillOptions,
2337}
2338
2339impl<'l> FillBuilder<'l> {
2340    fn new(
2341        num_attributes: usize,
2342        tessellator: &'l mut FillTessellator,
2343        options: &'l FillOptions,
2344        output: &'l mut dyn FillGeometryBuilder,
2345    ) -> Self {
2346        let events = core::mem::replace(&mut tessellator.events, EventQueue::new())
2347            .into_builder(options.tolerance);
2348
2349        FillBuilder {
2350            events,
2351            next_id: EndpointId(0),
2352            first_id: EndpointId(0),
2353            horizontal_sweep: options.sweep_orientation == Orientation::Horizontal,
2354            first_position: point(0.0, 0.0),
2355            tessellator,
2356            options,
2357            output,
2358            attrib_store: SimpleAttributeStore::new(num_attributes),
2359        }
2360    }
2361
2362    #[inline]
2363    fn position(&self, p: Point) -> Point {
2364        if self.horizontal_sweep {
2365            point(-p.y, p.x)
2366        } else {
2367            p
2368        }
2369    }
2370
2371    pub fn num_attributes(&self) -> usize {
2372        self.attrib_store.num_attributes()
2373    }
2374
2375    pub fn begin(&mut self, at: Point, attributes: Attributes) -> EndpointId {
2376        let at = self.position(at);
2377        let id = self.attrib_store.add(attributes);
2378        self.first_id = id;
2379        self.first_position = at;
2380        self.events.begin(at, id);
2381
2382        id
2383    }
2384
2385    pub fn end(&mut self, _close: bool) {
2386        self.events.end(self.first_position, self.first_id);
2387    }
2388
2389    pub fn line_to(&mut self, to: Point, attributes: Attributes) -> EndpointId {
2390        let to = self.position(to);
2391        let id = self.attrib_store.add(attributes);
2392        self.events.line_segment(to, id, 0.0, 1.0);
2393
2394        id
2395    }
2396
2397    pub fn quadratic_bezier_to(
2398        &mut self,
2399        ctrl: Point,
2400        to: Point,
2401        attributes: Attributes,
2402    ) -> EndpointId {
2403        let ctrl = self.position(ctrl);
2404        let to = self.position(to);
2405        let id = self.attrib_store.add(attributes);
2406        self.events.quadratic_bezier_segment(ctrl, to, id);
2407
2408        id
2409    }
2410
2411    pub fn cubic_bezier_to(
2412        &mut self,
2413        ctrl1: Point,
2414        ctrl2: Point,
2415        to: Point,
2416        attributes: Attributes,
2417    ) -> EndpointId {
2418        let ctrl1 = self.position(ctrl1);
2419        let ctrl2 = self.position(ctrl2);
2420        let to = self.position(to);
2421        let id = self.attrib_store.add(attributes);
2422        self.events.cubic_bezier_segment(ctrl1, ctrl2, to, id);
2423
2424        id
2425    }
2426
2427    pub fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
2428        self.attrib_store.reserve(endpoints);
2429        self.events.reserve(endpoints + ctrl_points * 2);
2430    }
2431
2432    pub fn add_circle(
2433        &mut self,
2434        center: Point,
2435        radius: f32,
2436        winding: Winding,
2437        attributes: Attributes,
2438    ) {
2439        // This specialized routine extracts the curves into separate sub-paths
2440        // to nudge the tessellator towards putting them in their own monotonic
2441        // spans. This avoids generating thin triangles from one side of the circle
2442        // to the other.
2443        // We can do this because we know shape is convex and we don't need to trace
2444        // the outline.
2445
2446        let radius = radius.abs();
2447        let dir = match winding {
2448            Winding::Positive => 1.0,
2449            Winding::Negative => -1.0,
2450        };
2451
2452        self.reserve(16, 8);
2453
2454        let tan_pi_over_8 = 0.41421357;
2455        let d = radius * tan_pi_over_8;
2456
2457        let start = center + vector(-radius, 0.0);
2458        self.begin(start, attributes);
2459        let ctrl_0 = center + vector(-radius, -d * dir);
2460        let mid_0 = center + vector(-1.0, -dir) * radius * FRAC_1_SQRT_2;
2461        let ctrl_1 = center + vector(-d, -radius * dir);
2462        let mid_1 = center + vector(0.0, -radius * dir);
2463        self.quadratic_bezier_to(ctrl_0, mid_0, attributes);
2464        self.end(false);
2465        self.begin(mid_0, attributes);
2466        self.quadratic_bezier_to(ctrl_1, mid_1, attributes);
2467        self.end(false);
2468
2469        self.begin(mid_1, attributes);
2470        let ctrl_0 = center + vector(d, -radius * dir);
2471        let mid_2 = center + vector(1.0, -dir) * radius * FRAC_1_SQRT_2;
2472        let ctrl_1 = center + vector(radius, -d * dir);
2473        let mid_3 = center + vector(radius, 0.0);
2474        self.quadratic_bezier_to(ctrl_0, mid_2, attributes);
2475        self.end(false);
2476        self.begin(mid_2, attributes);
2477        self.quadratic_bezier_to(ctrl_1, mid_3, attributes);
2478        self.end(false);
2479
2480        self.begin(mid_3, attributes);
2481        let ctrl_0 = center + vector(radius, d * dir);
2482        let mid_4 = center + vector(1.0, dir) * radius * FRAC_1_SQRT_2;
2483        let ctrl_1 = center + vector(d, radius * dir);
2484        let mid_5 = center + vector(0.0, radius * dir);
2485        self.quadratic_bezier_to(ctrl_0, mid_4, attributes);
2486        self.end(false);
2487        self.begin(mid_4, attributes);
2488        self.quadratic_bezier_to(ctrl_1, mid_5, attributes);
2489        self.end(false);
2490
2491        self.begin(mid_5, attributes);
2492        let ctrl_0 = center + vector(-d, radius * dir);
2493        let mid_6 = center + vector(-1.0, dir) * radius * FRAC_1_SQRT_2;
2494        let ctrl_1 = center + vector(-radius, d * dir);
2495        self.quadratic_bezier_to(ctrl_0, mid_6, attributes);
2496        self.end(false);
2497        self.begin(mid_6, attributes);
2498        self.quadratic_bezier_to(ctrl_1, start, attributes);
2499        self.end(false);
2500
2501        self.begin(start, attributes);
2502        self.line_to(mid_0, attributes);
2503        self.line_to(mid_1, attributes);
2504        self.line_to(mid_2, attributes);
2505        self.line_to(mid_3, attributes);
2506        self.line_to(mid_4, attributes);
2507        self.line_to(mid_5, attributes);
2508        self.line_to(mid_6, attributes);
2509        self.close();
2510    }
2511
2512    pub fn build(self) -> TessellationResult {
2513        let mut event_queue = self.events.build();
2514        core::mem::swap(&mut self.tessellator.events, &mut event_queue);
2515
2516        let attrib_store = if self.attrib_store.num_attributes > 0 {
2517            Some(&self.attrib_store as &dyn AttributeStore)
2518        } else {
2519            None
2520        };
2521
2522        self.tessellator
2523            .tessellate_impl(self.options, attrib_store, self.output)
2524    }
2525}
2526
2527impl<'l> PathBuilder for FillBuilder<'l> {
2528    fn num_attributes(&self) -> usize {
2529        self.attrib_store.num_attributes()
2530    }
2531
2532    fn begin(&mut self, at: Point, attributes: Attributes) -> EndpointId {
2533        self.begin(at, attributes)
2534    }
2535
2536    fn end(&mut self, close: bool) {
2537        self.end(close)
2538    }
2539
2540    fn line_to(&mut self, to: Point, attributes: Attributes) -> EndpointId {
2541        self.line_to(to, attributes)
2542    }
2543
2544    fn quadratic_bezier_to(
2545        &mut self,
2546        ctrl: Point,
2547        to: Point,
2548        attributes: Attributes,
2549    ) -> EndpointId {
2550        self.quadratic_bezier_to(ctrl, to, attributes)
2551    }
2552
2553    fn cubic_bezier_to(
2554        &mut self,
2555        ctrl1: Point,
2556        ctrl2: Point,
2557        to: Point,
2558        attributes: Attributes,
2559    ) -> EndpointId {
2560        self.cubic_bezier_to(ctrl1, ctrl2, to, attributes)
2561    }
2562
2563    fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
2564        self.reserve(endpoints, ctrl_points)
2565    }
2566
2567    fn add_circle(&mut self, center: Point, radius: f32, winding: Winding, attributes: Attributes) {
2568        self.add_circle(center, radius, winding, attributes)
2569    }
2570}
2571
2572impl<'l> Build for FillBuilder<'l> {
2573    type PathType = TessellationResult;
2574
2575    #[inline]
2576    fn build(self) -> TessellationResult {
2577        self.build()
2578    }
2579}
2580
2581fn log_svg_preamble(_tess: &FillTessellator) {
2582    tess_log!(
2583        _tess,
2584        r#"
2585<svg viewBox="0 0 1000 1000">
2586
2587<style type="text/css">
2588<![CDATA[
2589  path.sweep-line {{
2590    stroke: red;
2591    fill: none;
2592  }}
2593
2594  path.edge {{
2595    stroke: blue;
2596    fill: none;
2597  }}
2598
2599  path.edge.select {{
2600    stroke: green;
2601    fill: none;
2602  }}
2603
2604  circle.merge {{
2605    fill: yellow;
2606    stroke: orange;
2607    fill-opacity: 1;
2608  }}
2609
2610  circle.current {{
2611    fill: white;
2612    stroke: grey;
2613    fill-opacity: 1;
2614  }}
2615
2616  g.active-edges {{
2617    opacity: 0;
2618  }}
2619
2620  g.active-edges.select {{
2621    opacity: 1;
2622  }}
2623]]>
2624</style>
2625"#
2626    );
2627}
2628
2629#[cfg(test)]
2630use crate::geometry_builder::*;
2631
2632#[cfg(test)]
2633fn eq(a: Point, b: Point) -> bool {
2634    (a.x - b.x).abs() < 0.00001 && (a.y - b.y).abs() < 0.00001
2635}
2636
2637#[cfg(test)]
2638fn at_endpoint(src: &VertexSource, endpoint: EndpointId) -> bool {
2639    match src {
2640        VertexSource::Edge { .. } => false,
2641        VertexSource::Endpoint { id } => *id == endpoint,
2642    }
2643}
2644
2645#[cfg(test)]
2646fn on_edge(src: &VertexSource, from_id: EndpointId, to_id: EndpointId, d: f32) -> bool {
2647    match src {
2648        VertexSource::Edge { t, from, to, .. } => {
2649            *from == from_id
2650                && *to == to_id
2651                && ((d - *t).abs() < 0.00001 || (1.0 - d - *t).abs() <= 0.00001)
2652        }
2653        VertexSource::Endpoint { .. } => false,
2654    }
2655}
2656
2657#[test]
2658fn fill_vertex_source_01() {
2659    use crate::path::commands::PathCommands;
2660    use crate::path::AttributeSlice;
2661
2662    let endpoints: &[Point] = &[point(0.0, 0.0), point(1.0, 1.0), point(0.0, 2.0)];
2663
2664    let attributes = &[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0];
2665
2666    let mut cmds = PathCommands::builder();
2667    cmds.begin(EndpointId(0));
2668    cmds.line_to(EndpointId(1));
2669    cmds.line_to(EndpointId(2));
2670    cmds.end(true);
2671
2672    let cmds = cmds.build();
2673
2674    let mut tess = FillTessellator::new();
2675    tess.tessellate_with_ids(
2676        cmds.iter(),
2677        &(endpoints, endpoints),
2678        Some(&AttributeSlice::new(attributes, 3)),
2679        &FillOptions::default(),
2680        &mut CheckVertexSources { next_vertex: 0 },
2681    )
2682    .unwrap();
2683
2684    struct CheckVertexSources {
2685        next_vertex: u32,
2686    }
2687
2688    impl GeometryBuilder for CheckVertexSources {
2689        fn add_triangle(&mut self, _: VertexId, _: VertexId, _: VertexId) {}
2690        fn abort_geometry(&mut self) {}
2691    }
2692
2693    impl FillGeometryBuilder for CheckVertexSources {
2694        fn add_fill_vertex(
2695            &mut self,
2696            mut vertex: FillVertex,
2697        ) -> Result<VertexId, GeometryBuilderError> {
2698            let pos = vertex.position();
2699            for src in vertex.sources() {
2700                if eq(pos, point(0.0, 0.0)) {
2701                    assert!(at_endpoint(&src, EndpointId(0)))
2702                } else if eq(pos, point(1.0, 1.0)) {
2703                    assert!(at_endpoint(&src, EndpointId(1)))
2704                } else if eq(pos, point(0.0, 2.0)) {
2705                    assert!(at_endpoint(&src, EndpointId(2)))
2706                } else {
2707                    panic!()
2708                }
2709            }
2710
2711            if eq(pos, point(0.0, 0.0)) {
2712                assert_eq!(vertex.interpolated_attributes(), &[1.0, 0.0, 0.0])
2713            } else if eq(pos, point(1.0, 1.0)) {
2714                assert_eq!(vertex.interpolated_attributes(), &[0.0, 1.0, 0.0])
2715            } else if eq(pos, point(0.0, 2.0)) {
2716                assert_eq!(vertex.interpolated_attributes(), &[0.0, 0.0, 1.0])
2717            }
2718
2719            let id = self.next_vertex;
2720            self.next_vertex += 1;
2721
2722            Ok(VertexId(id))
2723        }
2724    }
2725}
2726
2727#[test]
2728fn fill_vertex_source_02() {
2729    // Check the vertex sources of a simple self-intersecting shape.
2730    //    _
2731    //  _|_|_
2732    // | | | |
2733    // |_|_|_|
2734    //   |_|
2735    //
2736
2737    let mut path = crate::path::Path::builder_with_attributes(3);
2738    let a = path.begin(point(1.0, 0.0), &[1.0, 0.0, 1.0]);
2739    let b = path.line_to(point(2.0, 0.0), &[2.0, 0.0, 1.0]);
2740    let c = path.line_to(point(2.0, 4.0), &[3.0, 0.0, 1.0]);
2741    let d = path.line_to(point(1.0, 4.0), &[4.0, 0.0, 1.0]);
2742    path.end(true);
2743    let e = path.begin(point(0.0, 1.0), &[0.0, 1.0, 2.0]);
2744    let f = path.line_to(point(0.0, 3.0), &[0.0, 2.0, 2.0]);
2745    let g = path.line_to(point(3.0, 3.0), &[0.0, 3.0, 2.0]);
2746    let h = path.line_to(point(3.0, 1.0), &[0.0, 4.0, 2.0]);
2747    path.end(true);
2748
2749    let path = path.build();
2750
2751    let mut tess = FillTessellator::new();
2752    tess.tessellate_with_ids(
2753        path.id_iter(),
2754        &path,
2755        Some(&path),
2756        &FillOptions::default(),
2757        &mut CheckVertexSources {
2758            next_vertex: 0,
2759            a,
2760            b,
2761            c,
2762            d,
2763            e,
2764            f,
2765            g,
2766            h,
2767        },
2768    )
2769    .unwrap();
2770
2771    struct CheckVertexSources {
2772        next_vertex: u32,
2773        a: EndpointId,
2774        b: EndpointId,
2775        c: EndpointId,
2776        d: EndpointId,
2777        e: EndpointId,
2778        f: EndpointId,
2779        g: EndpointId,
2780        h: EndpointId,
2781    }
2782
2783    impl GeometryBuilder for CheckVertexSources {
2784        fn add_triangle(&mut self, _: VertexId, _: VertexId, _: VertexId) {}
2785    }
2786
2787    impl FillGeometryBuilder for CheckVertexSources {
2788        fn add_fill_vertex(
2789            &mut self,
2790            mut vertex: FillVertex,
2791        ) -> Result<VertexId, GeometryBuilderError> {
2792            let pos = vertex.position();
2793            for src in vertex.sources() {
2794                if eq(pos, point(1.0, 0.0)) {
2795                    assert!(at_endpoint(&src, self.a));
2796                } else if eq(pos, point(2.0, 0.0)) {
2797                    assert!(at_endpoint(&src, self.b));
2798                } else if eq(pos, point(2.0, 4.0)) {
2799                    assert!(at_endpoint(&src, self.c));
2800                } else if eq(pos, point(1.0, 4.0)) {
2801                    assert!(at_endpoint(&src, self.d));
2802                } else if eq(pos, point(0.0, 1.0)) {
2803                    assert!(at_endpoint(&src, self.e));
2804                } else if eq(pos, point(0.0, 3.0)) {
2805                    assert!(at_endpoint(&src, self.f));
2806                } else if eq(pos, point(3.0, 3.0)) {
2807                    assert!(at_endpoint(&src, self.g));
2808                } else if eq(pos, point(3.0, 1.0)) {
2809                    assert!(at_endpoint(&src, self.h));
2810                } else if eq(pos, point(1.0, 1.0)) {
2811                    assert!(
2812                        on_edge(&src, self.h, self.e, 2.0 / 3.0)
2813                            || on_edge(&src, self.d, self.a, 3.0 / 4.0)
2814                    );
2815                } else if eq(pos, point(2.0, 1.0)) {
2816                    assert!(
2817                        on_edge(&src, self.h, self.e, 1.0 / 3.0)
2818                            || on_edge(&src, self.b, self.c, 1.0 / 4.0)
2819                    );
2820                } else if eq(pos, point(1.0, 3.0)) {
2821                    assert!(
2822                        on_edge(&src, self.f, self.g, 1.0 / 3.0)
2823                            || on_edge(&src, self.d, self.a, 1.0 / 4.0)
2824                    );
2825                } else if eq(pos, point(2.0, 3.0)) {
2826                    assert!(
2827                        on_edge(&src, self.f, self.g, 2.0 / 3.0)
2828                            || on_edge(&src, self.b, self.c, 3.0 / 4.0)
2829                    );
2830                } else {
2831                    panic!()
2832                }
2833            }
2834
2835            fn assert_attr(a: Attributes, b: Attributes) {
2836                for i in 0..a.len() {
2837                    let are_equal = (a[i] - b[i]).abs() < 0.001;
2838                    #[cfg(feature = "std")]
2839                    if !are_equal {
2840                        std::println!("{a:?} != {b:?}");
2841                    }
2842                    assert!(are_equal);
2843                }
2844
2845                assert_eq!(a.len(), b.len());
2846            }
2847
2848            let pos = vertex.position();
2849            let attribs = vertex.interpolated_attributes();
2850            if eq(pos, point(1.0, 0.0)) {
2851                assert_attr(attribs, &[1.0, 0.0, 1.0]);
2852            } else if eq(pos, point(2.0, 0.0)) {
2853                assert_attr(attribs, &[2.0, 0.0, 1.0]);
2854            } else if eq(pos, point(2.0, 4.0)) {
2855                assert_attr(attribs, &[3.0, 0.0, 1.0]);
2856            } else if eq(pos, point(1.0, 4.0)) {
2857                assert_attr(attribs, &[4.0, 0.0, 1.0]);
2858            } else if eq(pos, point(0.0, 1.0)) {
2859                assert_attr(attribs, &[0.0, 1.0, 2.0]);
2860            } else if eq(pos, point(0.0, 3.0)) {
2861                assert_attr(attribs, &[0.0, 2.0, 2.0]);
2862            } else if eq(pos, point(3.0, 3.0)) {
2863                assert_attr(attribs, &[0.0, 3.0, 2.0]);
2864            } else if eq(pos, point(3.0, 1.0)) {
2865                assert_attr(attribs, &[0.0, 4.0, 2.0]);
2866            } else if eq(pos, point(1.0, 1.0)) {
2867                assert_attr(attribs, &[0.875, 1.0, 1.5]);
2868            } else if eq(pos, point(2.0, 1.0)) {
2869                assert_attr(attribs, &[1.125, 1.5, 1.5]);
2870            } else if eq(pos, point(1.0, 3.0)) {
2871                assert_attr(attribs, &[1.625, 1.16666, 1.5]);
2872            } else if eq(pos, point(2.0, 3.0)) {
2873                assert_attr(attribs, &[1.375, 1.33333, 1.5]);
2874            }
2875
2876            let id = self.next_vertex;
2877            self.next_vertex += 1;
2878
2879            Ok(VertexId(id))
2880        }
2881    }
2882}
2883
2884#[test]
2885fn fill_vertex_source_03() {
2886    use crate::path::commands::PathCommands;
2887    use crate::path::AttributeSlice;
2888
2889    // x---x
2890    //  \ /
2891    //   x  <---
2892    //  / \
2893    // x---x
2894    //
2895    // check that the attribute interpolation is weighted correctly at
2896    // start events.
2897
2898    let endpoints: &[Point] = &[
2899        point(0.0, 0.0),
2900        point(2.0, 0.0),
2901        point(1.0, 1.0),
2902        point(0.0, 2.0),
2903        point(2.0, 2.0),
2904        point(1.0, 1.0),
2905    ];
2906
2907    let attributes = &[0.0, 0.0, 1.0, 0.0, 0.0, 2.0];
2908
2909    let mut cmds = PathCommands::builder();
2910    cmds.begin(EndpointId(0));
2911    cmds.line_to(EndpointId(1));
2912    cmds.line_to(EndpointId(2));
2913    cmds.end(true);
2914    cmds.begin(EndpointId(3));
2915    cmds.line_to(EndpointId(4));
2916    cmds.line_to(EndpointId(5));
2917    cmds.end(true);
2918
2919    let cmds = cmds.build();
2920
2921    let mut tess = FillTessellator::new();
2922    tess.tessellate_with_ids(
2923        cmds.iter(),
2924        &(endpoints, endpoints),
2925        Some(&AttributeSlice::new(attributes, 1)),
2926        &FillOptions::default(),
2927        &mut CheckVertexSources { next_vertex: 0 },
2928    )
2929    .unwrap();
2930
2931    struct CheckVertexSources {
2932        next_vertex: u32,
2933    }
2934
2935    impl GeometryBuilder for CheckVertexSources {
2936        fn add_triangle(&mut self, _: VertexId, _: VertexId, _: VertexId) {}
2937    }
2938
2939    impl FillGeometryBuilder for CheckVertexSources {
2940        fn add_fill_vertex(
2941            &mut self,
2942            mut vertex: FillVertex,
2943        ) -> Result<VertexId, GeometryBuilderError> {
2944            if eq(vertex.position(), point(1.0, 1.0)) {
2945                assert_eq!(vertex.interpolated_attributes(), &[1.5]);
2946                assert_eq!(vertex.sources().count(), 2);
2947            } else {
2948                assert_eq!(vertex.interpolated_attributes(), &[0.0]);
2949                assert_eq!(vertex.sources().count(), 1);
2950            }
2951
2952            let id = self.next_vertex;
2953            self.next_vertex += 1;
2954
2955            Ok(VertexId(id))
2956        }
2957    }
2958}
2959
2960#[test]
2961fn fill_builder_vertex_source() {
2962    let mut tess = FillTessellator::new();
2963    let options = FillOptions::default();
2964
2965    let mut check = CheckVertexSources { next_vertex: 0 };
2966    let mut builder = tess.builder(&options, &mut check);
2967
2968    assert_eq!(builder.begin(point(0.0, 0.0)), EndpointId(0));
2969    assert_eq!(builder.line_to(point(1.0, 1.0)), EndpointId(1));
2970    assert_eq!(builder.line_to(point(0.0, 2.0)), EndpointId(2));
2971    builder.end(true);
2972
2973    builder.build().unwrap();
2974
2975    struct CheckVertexSources {
2976        next_vertex: u32,
2977    }
2978
2979    impl GeometryBuilder for CheckVertexSources {
2980        fn add_triangle(&mut self, _: VertexId, _: VertexId, _: VertexId) {}
2981    }
2982
2983    impl FillGeometryBuilder for CheckVertexSources {
2984        fn add_fill_vertex(
2985            &mut self,
2986            vertex: FillVertex,
2987        ) -> Result<VertexId, GeometryBuilderError> {
2988            let pos = vertex.position();
2989            for src in vertex.sources() {
2990                if eq(pos, point(0.0, 0.0)) {
2991                    assert!(at_endpoint(&src, EndpointId(0)))
2992                } else if eq(pos, point(1.0, 1.0)) {
2993                    assert!(at_endpoint(&src, EndpointId(1)))
2994                } else if eq(pos, point(0.0, 2.0)) {
2995                    assert!(at_endpoint(&src, EndpointId(2)))
2996                } else {
2997                    panic!()
2998                }
2999            }
3000
3001            let id = self.next_vertex;
3002            self.next_vertex += 1;
3003
3004            Ok(VertexId(id))
3005        }
3006    }
3007}