Skip to main content

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