From 354472510ac00a8c392e5063222feb5a3cac73ea Mon Sep 17 00:00:00 2001 From: Luis Wirth Date: Sun, 18 Apr 2021 11:51:40 +0200 Subject: [PATCH 1/2] `#[rustfmt::skip] tessellation/src/earcut_tests.rs` Stop rustfmt from automatically formatting `tessellation/src/earcut_tests.rs`. This is done by putting `#[rustfmt::skip]` on the module declaration: `#[rustfmt::skip] mod earcut_tests;` This will not work with rustfmt 2.0 anymore. --- tessellation/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tessellation/src/lib.rs b/tessellation/src/lib.rs index 5225274a..6428e89b 100644 --- a/tessellation/src/lib.rs +++ b/tessellation/src/lib.rs @@ -196,6 +196,7 @@ mod monotone; mod stroke; #[cfg(test)] +#[rustfmt::skip] mod earcut_tests; #[cfg(test)] mod fill_tests; From 138152b50027fe217bb3b9267e65b2a0fb0b3afa Mon Sep 17 00:00:00 2001 From: Luis Wirth Date: Sun, 18 Apr 2021 11:56:20 +0200 Subject: [PATCH 2/2] `cargo fmt` --- algorithms/src/advanced_path.rs | 2 +- algorithms/src/hatching.rs | 6 +- algorithms/src/hit_test.rs | 57 +++++-- algorithms/src/splitter.rs | 5 +- algorithms/src/walk.rs | 4 +- bench/path/src/main.rs | 3 +- bench/tess/src/main.rs | 16 +- cli/src/fuzzing.rs | 41 +++-- cli/src/main.rs | 145 ++++++++++-------- cli/src/reduce.rs | 18 +-- cli/src/show.rs | 65 ++++---- examples/wgpu/src/main.rs | 59 ++++---- extra/src/triangle_rasterizer.rs | 2 +- geom/src/cubic_bezier.rs | 8 +- geom/src/cubic_bezier_intersections.rs | 7 +- geom/src/cubic_to_quadratic.rs | 9 +- geom/src/flatten_cubic.rs | 45 +++--- geom/src/line.rs | 3 +- geom/src/monotonic.rs | 6 +- geom/src/quadratic_bezier.rs | 49 +++--- geom/src/segment.rs | 58 +++++-- geom/src/triangle.rs | 2 +- geom/src/utils.rs | 2 +- path/src/builder.rs | 70 +++++---- path/src/commands.rs | 13 +- path/src/lib.rs | 20 +-- path/src/path.rs | 36 +++-- path/src/path_buffer.rs | 162 ++++++++++++++------ path/src/polygon.rs | 6 +- path/src/private.rs | 25 +-- svg/src/path_utils.rs | 5 +- tess2/src/flattened_path.rs | 11 +- tess2/src/lib.rs | 4 +- tess2/src/tessellator.rs | 2 +- tessellation/src/event_queue.rs | 17 ++- tessellation/src/fill.rs | 201 ++++++++++++++----------- tessellation/src/fill_tests.rs | 27 ++-- tessellation/src/fuzz_tests.rs | 5 +- tessellation/src/geometry_builder.rs | 24 +-- tessellation/src/lib.rs | 27 ++-- tessellation/src/monotone.rs | 48 +++--- tessellation/src/stroke.rs | 184 +++++++++++----------- 42 files changed, 860 insertions(+), 639 deletions(-) diff --git a/algorithms/src/advanced_path.rs b/algorithms/src/advanced_path.rs index 0c5d58be..7a2ba232 100644 --- a/algorithms/src/advanced_path.rs +++ b/algorithms/src/advanced_path.rs @@ -4,8 +4,8 @@ // - simplify/remove it. use crate::math::*; -use crate::path::{Path, PathEvent}; use crate::path::polygon::Polygon; +use crate::path::{Path, PathEvent}; use sid::{Id, IdRange, IdSlice, IdVec}; use std::ops; use std::u16; diff --git a/algorithms/src/hatching.rs b/algorithms/src/hatching.rs index b8962507..fc61fc18 100644 --- a/algorithms/src/hatching.rs +++ b/algorithms/src/hatching.rs @@ -26,11 +26,11 @@ //! let hatched_path = hatches.build(); //! ``` -use crate::math::{point, vector, Angle, Point, Rotation, Vector}; use crate::geom::LineSegment; +use crate::math::{point, vector, Angle, Point, Rotation, Vector}; use crate::path::builder::{Build, PathBuilder}; use crate::path::private::DebugValidator; -use crate::path::{self, PathEvent, EndpointId}; +use crate::path::{self, EndpointId, PathEvent}; use std::marker::PhantomData; use std::cmp::Ordering; @@ -705,7 +705,7 @@ fn simple_hatching() { &HatchingOptions::DEFAULT, &mut RegularHatchingPattern { interval: 1.0, - callback: &mut|segment: &HatchSegment| { + callback: &mut |segment: &HatchSegment| { hatches.add_line_segment(&LineSegment { from: segment.a.position, to: segment.b.position, diff --git a/algorithms/src/hit_test.rs b/algorithms/src/hit_test.rs index 4e5e216c..89ad3e7e 100644 --- a/algorithms/src/hit_test.rs +++ b/algorithms/src/hit_test.rs @@ -35,7 +35,12 @@ where prev_winding = None; } PathEvent::Line { from, to } => { - test_segment(*point, &LineSegment { from, to }, &mut winding, &mut prev_winding); + test_segment( + *point, + &LineSegment { from, to }, + &mut winding, + &mut prev_winding, + ); } PathEvent::End { last, first, .. } => { test_segment( @@ -56,7 +61,12 @@ where } let mut prev = segment.from; segment.for_each_flattened(tolerance, &mut |p| { - test_segment(*point, &LineSegment { from: prev, to: p }, &mut winding, &mut prev_winding); + test_segment( + *point, + &LineSegment { from: prev, to: p }, + &mut winding, + &mut prev_winding, + ); prev = p; }); } @@ -78,7 +88,12 @@ where } let mut prev = segment.from; segment.for_each_flattened(tolerance, &mut |p| { - test_segment(*point, &LineSegment { from: prev, to: p }, &mut winding, &mut prev_winding); + test_segment( + *point, + &LineSegment { from: prev, to: p }, + &mut winding, + &mut prev_winding, + ); prev = p; }); } @@ -88,14 +103,19 @@ where winding } -fn test_segment(point: Point, segment: &LineSegment, winding: &mut i32, prev_winding: &mut Option) { - let y0 = segment.from.y; - let y1 = segment.to.y; +fn test_segment( + point: Point, + segment: &LineSegment, + winding: &mut i32, + prev_winding: &mut Option, +) { + let y0 = segment.from.y; + let y1 = segment.to.y; if f32::min(y0, y1) > point.y || f32::max(y0, y1) < point.y || f32::min(segment.from.x, segment.to.x) > point.x - || y0 == y1 { - + || y0 == y1 + { return; } @@ -142,7 +162,7 @@ fn test_segment(point: Point, segment: &LineSegment, winding: &mut i32, pre // // The main idea is that within a sub-path we can't have consecutive affecting edges // of the same winding sign, so if we find some it means we are double-counting. - if *prev_winding != Some(w) { + if *prev_winding != Some(w) { *winding += w; } @@ -180,7 +200,10 @@ fn test_hit_test() { FillRule::EvenOdd, 0.1 )); - println!("winding {:?}", path_winding_number_at_position(&point(2.0, 0.0), path.iter(), 0.1)); + println!( + "winding {:?}", + path_winding_number_at_position(&point(2.0, 0.0), path.iter(), 0.1) + ); assert!(!hit_test_path( &point(2.0, 0.0), path.iter(), @@ -242,6 +265,16 @@ fn hit_test_point_aligned() { closed: true, }; - assert!(hit_test_path(&point(0.0, 5.0), poly.path_events(), FillRule::NonZero, 0.1)); - assert!(!hit_test_path(&point(15.0, 5.0), poly.path_events(), FillRule::NonZero, 0.1)); + assert!(hit_test_path( + &point(0.0, 5.0), + poly.path_events(), + FillRule::NonZero, + 0.1 + )); + assert!(!hit_test_path( + &point(15.0, 5.0), + poly.path_events(), + FillRule::NonZero, + 0.1 + )); } diff --git a/algorithms/src/splitter.rs b/algorithms/src/splitter.rs index 7bef6f21..313d6a74 100644 --- a/algorithms/src/splitter.rs +++ b/algorithms/src/splitter.rs @@ -2,9 +2,9 @@ use crate::advanced_path::*; use crate::geom::{Line, LineSegment}; /// Split paths with a line or line segment. use crate::math::*; -use crate::path::*; -use crate::path::polygon::Polygon; use crate::path::iterator::PathIterator; +use crate::path::polygon::Polygon; +use crate::path::*; use std::cmp::PartialOrd; use std::mem; @@ -749,7 +749,6 @@ fn split_with_segment_3() { #[test] fn split_with_segment_4() { - // ________ // | | //-+--+-----+- diff --git a/algorithms/src/walk.rs b/algorithms/src/walk.rs index 9e124633..37efe256 100644 --- a/algorithms/src/walk.rs +++ b/algorithms/src/walk.rs @@ -42,7 +42,7 @@ use crate::geom::{CubicBezierSegment, QuadraticBezierSegment}; use crate::math::*; use crate::path::builder::*; -use crate::path::{PathEvent, EndpointId}; +use crate::path::{EndpointId, PathEvent}; use std::f32; @@ -171,7 +171,7 @@ impl<'l> PathBuilder for PathWalker<'l> { if close { let first = self.first; self.line_to(first); - self.need_moveto = true; + self.need_moveto = true; } } diff --git a/bench/path/src/main.rs b/bench/path/src/main.rs index 5d1f9ad1..a94578f9 100644 --- a/bench/path/src/main.rs +++ b/bench/path/src/main.rs @@ -5,8 +5,8 @@ extern crate bencher; use lyon::extra::rust_logo::build_logo_path; use lyon::math::point; use lyon::path::commands; -use lyon::path::PathBuffer; use lyon::path::traits::*; +use lyon::path::PathBuffer; use lyon::path::{ControlPointId, EndpointId, Event, IdEvent, Path, PathEvent}; use bencher::Bencher; @@ -24,7 +24,6 @@ fn path_buffer_logo(bench: &mut Bencher) { }); } - fn simple_path_build_empty(bench: &mut Bencher) { bench.iter(|| { let mut path = Path::builder(); diff --git a/bench/tess/src/main.rs b/bench/tess/src/main.rs index c4fee74b..73a0e7a3 100644 --- a/bench/tess/src/main.rs +++ b/bench/tess/src/main.rs @@ -118,12 +118,8 @@ fn fill_tess_03_logo_no_intersections(bench: &mut Bencher) { bench.iter(|| { for _ in 0..N { let mut buffers: VertexBuffers = VertexBuffers::new(); - tess.tessellate_path( - &path, - &options, - &mut simple_builder(&mut buffers), - ) - .unwrap(); + tess.tessellate_path(&path, &options, &mut simple_builder(&mut buffers)) + .unwrap(); } }) } @@ -139,12 +135,8 @@ fn fill_tess_05_logo_no_curve(bench: &mut Bencher) { bench.iter(|| { for _ in 0..N { let mut buffers: VertexBuffers = VertexBuffers::new(); - tess.tessellate_path( - &path, - &options, - &mut simple_builder(&mut buffers), - ) - .unwrap(); + tess.tessellate_path(&path, &options, &mut simple_builder(&mut buffers)) + .unwrap(); } }) } diff --git a/cli/src/fuzzing.rs b/cli/src/fuzzing.rs index 76fe047b..c1264646 100644 --- a/cli/src/fuzzing.rs +++ b/cli/src/fuzzing.rs @@ -1,13 +1,13 @@ use crate::commands::{FuzzCmd, Tessellator}; +use lyon::algorithms::hatching::*; use lyon::extra::debugging::find_reduced_test_case; +use lyon::geom::LineSegment; use lyon::math::*; -use lyon::path::Path; use lyon::path::traits::PathBuilder; +use lyon::path::Path; use lyon::tess2; use lyon::tessellation::geometry_builder::NoOutput; use lyon::tessellation::{FillTessellator, StrokeTessellator}; -use lyon::algorithms::hatching::*; -use lyon::geom::LineSegment; use rand; use std::cmp::{max, min}; @@ -67,27 +67,22 @@ pub fn run(cmd: FuzzCmd) -> bool { loop { let path = generate_path(&cmd, i); if let Some(options) = cmd.tess.fill { - let status = ::std::panic::catch_unwind(|| { - match cmd.tess.tessellator { - Tessellator::Default => { - let result = FillTessellator::new().tessellate( - &path, - &options, - &mut NoOutput::new(), - ); - if !cmd.ignore_errors { - result.unwrap(); - } + let status = ::std::panic::catch_unwind(|| match cmd.tess.tessellator { + Tessellator::Default => { + let result = + FillTessellator::new().tessellate(&path, &options, &mut NoOutput::new()); + if !cmd.ignore_errors { + result.unwrap(); } - Tessellator::Tess2 => { - let result = tess2::FillTessellator::new().tessellate( - &path, - &options, - &mut NoOutput::new(), - ); - if !cmd.ignore_errors { - result.unwrap(); - } + } + Tessellator::Tess2 => { + let result = tess2::FillTessellator::new().tessellate( + &path, + &options, + &mut NoOutput::new(), + ); + if !cmd.ignore_errors { + result.unwrap(); } } }); diff --git a/cli/src/main.rs b/cli/src/main.rs index 4aca90e5..15a0bd2b 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,15 +1,15 @@ extern crate clap; +extern crate itertools; extern crate lyon; extern crate rand; -extern crate itertools; extern crate regex; mod commands; mod flatten; mod fuzzing; +mod reduce; mod show; mod tessellate; -mod reduce; use clap::*; use commands::*; @@ -154,7 +154,7 @@ fn main() { ) .subcommand( declare_tess_params(SubCommand::with_name("reduce"), true) - .about("Find a reduced testcase") + .about("Find a reduced testcase"), ) .get_matches(); @@ -257,80 +257,95 @@ fn declare_tess_params<'a, 'b>(app: App<'a, 'b>, need_path: bool) -> App<'a, 'b> } else { app } - .arg(Arg::with_name("FILL") - .short("f") - .long("fill") - .help("Fills the path") + .arg( + Arg::with_name("FILL") + .short("f") + .long("fill") + .help("Fills the path"), ) - .arg(Arg::with_name("STROKE") - .short("s") - .long("stroke") - .help("Strokes the path") + .arg( + Arg::with_name("STROKE") + .short("s") + .long("stroke") + .help("Strokes the path"), ) - .arg(Arg::with_name("HATCH") - .long("hatch") - .help("Fill the path with a regular hatching pattern using the provided value as spacing") - .takes_value(true) + .arg( + Arg::with_name("HATCH") + .long("hatch") + .help( + "Fill the path with a regular hatching pattern using the provided value as spacing", + ) + .takes_value(true), ) - .arg(Arg::with_name("DOT") - .long("dot") - .help("Fill the path with a regular dot pattern using the provided value as spacing") - .takes_value(true) + .arg( + Arg::with_name("DOT") + .long("dot") + .help("Fill the path with a regular dot pattern using the provided value as spacing") + .takes_value(true), ) - .arg(Arg::with_name("TOLERANCE") - .short("t") - .long("tolerance") - .help("Sets the tolerance threshold for flattening (0.5 by default)") - .value_name("TOLERANCE") - .takes_value(true) + .arg( + Arg::with_name("TOLERANCE") + .short("t") + .long("tolerance") + .help("Sets the tolerance threshold for flattening (0.5 by default)") + .value_name("TOLERANCE") + .takes_value(true), ) - .arg(Arg::with_name("LINE_WIDTH") - .short("w") - .long("line-width") - .help("The line width for strokes") - .value_name("LINE_WIDTH") - .takes_value(true) + .arg( + Arg::with_name("LINE_WIDTH") + .short("w") + .long("line-width") + .help("The line width for strokes") + .value_name("LINE_WIDTH") + .takes_value(true), ) - .arg(Arg::with_name("LINE_JOIN") - .long("line-join") - .help("The line-join type for strokes") - .value_name("LINE_JOIN") - .takes_value(true) + .arg( + Arg::with_name("LINE_JOIN") + .long("line-join") + .help("The line-join type for strokes") + .value_name("LINE_JOIN") + .takes_value(true), ) - .arg(Arg::with_name("LINE_CAP") - .long("line-cap") - .help("The line-cap type for strokes") - .value_name("LINE_CAP") - .takes_value(true) + .arg( + Arg::with_name("LINE_CAP") + .long("line-cap") + .help("The line-cap type for strokes") + .value_name("LINE_CAP") + .takes_value(true), ) - .arg(Arg::with_name("MITER_LIMIT") - .long("miter-limit") - .help("The miter limit for strokes") - .value_name("MITER_LIMIT") - .takes_value(true) + .arg( + Arg::with_name("MITER_LIMIT") + .long("miter-limit") + .help("The miter limit for strokes") + .value_name("MITER_LIMIT") + .takes_value(true), ) - .arg(Arg::with_name("FILL_RULE") - .long("fill-rule") - .help("Fill rule") - .value_name("FILL_RULE") - .takes_value(true) + .arg( + Arg::with_name("FILL_RULE") + .long("fill-rule") + .help("Fill rule") + .value_name("FILL_RULE") + .takes_value(true), ) - .arg(Arg::with_name("SWEEP_ORIENTATION") - .long("sweep-orientation") - .help("Traverse the geometry vertically or horizontally.") - .value_name("SWEEP_ORIENTATION") - .takes_value(true) + .arg( + Arg::with_name("SWEEP_ORIENTATION") + .long("sweep-orientation") + .help("Traverse the geometry vertically or horizontally.") + .value_name("SWEEP_ORIENTATION") + .takes_value(true), ) - .arg(Arg::with_name("TESSELLATOR") - .long("tessellator") - .help("Select the tessellator to use") - .value_name("TESSELLATOR") - .takes_value(true) + .arg( + Arg::with_name("TESSELLATOR") + .long("tessellator") + .help("Select the tessellator to use") + .value_name("TESSELLATOR") + .takes_value(true), ) - .arg(Arg::with_name("HATCHING_ANGLE") - .long("angle") - .help("Angle between the hatching and the x axis") - .takes_value(true) + .arg( + Arg::with_name("HATCHING_ANGLE") + .long("angle") + .help("Angle between the hatching and the x axis") + .takes_value(true), ) } diff --git a/cli/src/reduce.rs b/cli/src/reduce.rs index a4da4b54..78336a88 100644 --- a/cli/src/reduce.rs +++ b/cli/src/reduce.rs @@ -1,6 +1,6 @@ use crate::commands::{TessellateCmd, Tessellator}; -use lyon::path::Path; use lyon::path::traits::*; +use lyon::path::Path; use lyon::tessellation::geometry_builder::*; use lyon::tessellation::{FillTessellator, StrokeTessellator}; @@ -11,11 +11,9 @@ pub fn reduce_testcase(cmd: TessellateCmd) { let path = flattener.build(); lyon::extra::debugging::find_reduced_test_case(path.as_slice(), &|path: Path| { - StrokeTessellator::new().tessellate_path( - &path, - &options, - &mut NoOutput::new(), - ).is_err() + StrokeTessellator::new() + .tessellate_path(&path, &options, &mut NoOutput::new()) + .is_err() }); } @@ -35,11 +33,9 @@ pub fn reduce_testcase(cmd: TessellateCmd) { match cmd.tessellator { Tessellator::Default => { lyon::extra::debugging::find_reduced_test_case(path.as_slice(), &|path: Path| { - FillTessellator::new().tessellate_path( - &path, - &options, - &mut NoOutput::new(), - ).is_err() + FillTessellator::new() + .tessellate_path(&path, &options, &mut NoOutput::new()) + .is_err() }); } Tessellator::Tess2 => { diff --git a/cli/src/show.rs b/cli/src/show.rs index 900c5b46..19ff1241 100644 --- a/cli/src/show.rs +++ b/cli/src/show.rs @@ -14,8 +14,8 @@ use lyon::algorithms::aabb::bounding_rect; use lyon::algorithms::hatching::*; use lyon::geom::LineSegment; use lyon::math::*; -use lyon::path::Path; use lyon::path::builder::PathBuilder; +use lyon::path::Path; use lyon::tess2; use lyon::tessellation; use lyon::tessellation::geometry_builder::*; @@ -105,7 +105,6 @@ pub fn show_path(cmd: TessellateCmd, render_options: RenderCmd) { if let Some(options) = cmd.fill { match cmd.tessellator { Tessellator::Default => { - fill.tessellate( &cmd.path, &options, @@ -126,24 +125,25 @@ pub fn show_path(cmd: TessellateCmd, render_options: RenderCmd) { //} } Tessellator::Tess2 => { - tess2::FillTessellator::new().tessellate( - cmd.path.iter(), - &options, - &mut tess2::geometry_builder::BuffersBuilder::new( - &mut geometry, - WithId(0), - ), - ).unwrap(); + tess2::FillTessellator::new() + .tessellate( + cmd.path.iter(), + &options, + &mut tess2::geometry_builder::BuffersBuilder::new(&mut geometry, WithId(0)), + ) + .unwrap(); } } } if let Some(options) = cmd.stroke { - stroke.tessellate( - cmd.path.iter(), - &options, - &mut BuffersBuilder::new(&mut geometry, WithId(1)), - ).unwrap(); + stroke + .tessellate( + cmd.path.iter(), + &options, + &mut BuffersBuilder::new(&mut geometry, WithId(1)), + ) + .unwrap(); } if let Some(hatch) = cmd.hatch { @@ -164,11 +164,13 @@ pub fn show_path(cmd: TessellateCmd, render_options: RenderCmd) { ); let hatched_path = path.build(); - stroke.tessellate( - hatched_path.iter(), - &hatch.stroke, - &mut BuffersBuilder::new(&mut geometry, WithId(stroke_prim_id)), - ).unwrap(); + stroke + .tessellate( + hatched_path.iter(), + &hatch.stroke, + &mut BuffersBuilder::new(&mut geometry, WithId(stroke_prim_id)), + ) + .unwrap(); } if let Some(dots) = cmd.dots { @@ -187,11 +189,13 @@ pub fn show_path(cmd: TessellateCmd, render_options: RenderCmd) { ); let dotted_path = path.build(); - stroke.tessellate( - dotted_path.iter(), - &dots.stroke, - &mut BuffersBuilder::new(&mut geometry, WithId(stroke_prim_id)), - ).unwrap(); + stroke + .tessellate( + dotted_path.iter(), + &dots.stroke, + &mut BuffersBuilder::new(&mut geometry, WithId(stroke_prim_id)), + ) + .unwrap(); } let (bg_color, vignette_color) = match render_options.background { @@ -211,8 +215,8 @@ pub fn show_path(cmd: TessellateCmd, render_options: RenderCmd) { &Rect::new(point(-1.0, -1.0), size(2.0, 2.0)), &FillOptions::DEFAULT, &mut BuffersBuilder::new(&mut bg_geometry, BgVertexCtor), - ).unwrap(); - + ) + .unwrap(); let sample_count = match render_options.aa { AntiAliasing::Msaa(samples) => samples as u32, @@ -683,17 +687,12 @@ pub fn show_path(cmd: TessellateCmd, render_options: RenderCmd) { frame_count += 1.0; }); - } fn build_wireframe_indices(indices: &[u32]) -> Vec { let mut set = std::collections::HashSet::new(); let check = &mut |a: u32, b: u32| { - let (i1, i2) = if a < b { - (a, b) - } else { - (b, a) - }; + let (i1, i2) = if a < b { (a, b) } else { (b, a) }; set.insert((i1, i2)) }; diff --git a/examples/wgpu/src/main.rs b/examples/wgpu/src/main.rs index aa00ad08..d697d311 100644 --- a/examples/wgpu/src/main.rs +++ b/examples/wgpu/src/main.rs @@ -1,7 +1,7 @@ use lyon::extra::rust_logo::build_logo_path; use lyon::math::*; -use lyon::path::Path; use lyon::path::iterator::PathIterator; +use lyon::path::Path; use lyon::tessellation; use lyon::tessellation::geometry_builder::*; use lyon::tessellation::{FillOptions, FillTessellator}; @@ -152,38 +152,45 @@ fn main() { builder.close(); let arrow_path = builder.build(); - fill_tess.tessellate_path( - &path, - &FillOptions::tolerance(tolerance).with_fill_rule(tessellation::FillRule::NonZero), - &mut BuffersBuilder::new(&mut geometry, WithId(fill_prim_id as i32)), - ).unwrap(); + fill_tess + .tessellate_path( + &path, + &FillOptions::tolerance(tolerance).with_fill_rule(tessellation::FillRule::NonZero), + &mut BuffersBuilder::new(&mut geometry, WithId(fill_prim_id as i32)), + ) + .unwrap(); let fill_range = 0..(geometry.indices.len() as u32); - stroke_tess.tessellate_path( - &path, - &StrokeOptions::tolerance(tolerance), - &mut BuffersBuilder::new(&mut geometry, WithId(stroke_prim_id as i32)), - ).unwrap(); + stroke_tess + .tessellate_path( + &path, + &StrokeOptions::tolerance(tolerance), + &mut BuffersBuilder::new(&mut geometry, WithId(stroke_prim_id as i32)), + ) + .unwrap(); let stroke_range = fill_range.end..(geometry.indices.len() as u32); - fill_tess.tessellate_path( - &arrow_path, - &FillOptions::tolerance(tolerance), - &mut BuffersBuilder::new(&mut geometry, WithId(arrows_prim_id as i32)), - ).unwrap(); - + fill_tess + .tessellate_path( + &arrow_path, + &FillOptions::tolerance(tolerance), + &mut BuffersBuilder::new(&mut geometry, WithId(arrows_prim_id as i32)), + ) + .unwrap(); let arrow_range = stroke_range.end..(geometry.indices.len() as u32); let mut bg_geometry: VertexBuffers = VertexBuffers::new(); - fill_tess.tessellate_rectangle( - &Rect::new(point(-1.0, -1.0), size(2.0, 2.0)), - &FillOptions::DEFAULT, - &mut BuffersBuilder::new(&mut bg_geometry, Custom), - ).unwrap(); + fill_tess + .tessellate_rectangle( + &Rect::new(point(-1.0, -1.0), size(2.0, 2.0)), + &FillOptions::DEFAULT, + &mut BuffersBuilder::new(&mut bg_geometry, Custom), + ) + .unwrap(); let mut cpu_primitives = Vec::with_capacity(PRIM_BUFFER_LEN); for _ in 0..PRIM_BUFFER_LEN { @@ -193,7 +200,7 @@ fn main() { width: 0.0, translate: [0.0, 0.0], angle: 0.0, - .. Primitive::DEFAULT + ..Primitive::DEFAULT }); } @@ -202,13 +209,13 @@ fn main() { color: [0.0, 0.0, 0.0, 1.0], z_index: num_instances as i32 + 2, width: 1.0, - .. Primitive::DEFAULT + ..Primitive::DEFAULT }; // Main fill primitive cpu_primitives[fill_prim_id] = Primitive { color: [1.0, 1.0, 1.0, 1.0], z_index: num_instances as i32 + 1, - .. Primitive::DEFAULT + ..Primitive::DEFAULT }; // Instance primitives for idx in (fill_prim_id + 1)..(fill_prim_id + num_instances as usize) { @@ -570,7 +577,7 @@ fn main() { angle: tangent.angle_from_x_axis().get(), scale: 2.0, z_index: arrows_prim_id as i32, - .. Primitive::DEFAULT + ..Primitive::DEFAULT }; arrow_count += 1; true diff --git a/extra/src/triangle_rasterizer.rs b/extra/src/triangle_rasterizer.rs index a5f58a3f..13b92e15 100644 --- a/extra/src/triangle_rasterizer.rs +++ b/extra/src/triangle_rasterizer.rs @@ -2,9 +2,9 @@ use std::cmp::{max, min}; use std::ops::Add; use euclid; +use euclid::vec2; use image::MutableImageSlice; use math::*; -use euclid::vec2; type IntVector = euclid::default::Vector2D; diff --git a/geom/src/cubic_bezier.rs b/geom/src/cubic_bezier.rs index 17d64025..e73b90a2 100644 --- a/geom/src/cubic_bezier.rs +++ b/geom/src/cubic_bezier.rs @@ -2,12 +2,12 @@ use crate::cubic_bezier_intersections::cubic_bezier_intersections_t; use crate::cubic_to_quadratic::*; pub use crate::flatten_cubic::Flattened; use crate::flatten_cubic::{find_cubic_bezier_inflection_points, flatten_cubic_bezier_with_t}; -use crate::{rect, Point, Rect, Vector}; use crate::monotonic::Monotonic; use crate::scalar::Scalar; use crate::segment::{BoundingRect, Segment}; use crate::traits::Transformation; use crate::utils::{cubic_polynomial_roots, min_max}; +use crate::{rect, Point, Rect, Vector}; use crate::{Line, LineEquation, LineSegment, QuadraticBezierSegment}; use arrayvec::ArrayVec; @@ -420,11 +420,7 @@ impl CubicBezierSegment { } /// Iterates through the curve invoking a callback at each point. - pub fn for_each_flattened_with_t, S)>( - &self, - tolerance: S, - callback: &mut F, - ) { + pub fn for_each_flattened_with_t, S)>(&self, tolerance: S, callback: &mut F) { flatten_cubic_bezier_with_t(self, tolerance, callback); } diff --git a/geom/src/cubic_bezier_intersections.rs b/geom/src/cubic_bezier_intersections.rs index f4cc4e3b..63bf753e 100644 --- a/geom/src/cubic_bezier_intersections.rs +++ b/geom/src/cubic_bezier_intersections.rs @@ -1,3 +1,5 @@ +use crate::scalar::Scalar; +use crate::CubicBezierSegment; ///! Computes intersection parameters for two cubic bézier curves using bézier clipping, also known ///! as fat line clipping. ///! @@ -7,8 +9,6 @@ ///! https://scholarsarchive.byu.edu/facpub/1/ ///! for motivation and details of how the process works. use crate::{point, Point, Rect}; -use crate::scalar::Scalar; -use crate::CubicBezierSegment; use arrayvec::ArrayVec; use std::ops::Range; @@ -717,7 +717,8 @@ fn walk_convex_hull_edges_to_fat_line( for i in 0..hull_vertices.len() - 1 { let p = hull_vertices[i]; let q = hull_vertices[i + 1]; - if (vertices_are_for_top && q.y >= threshold) || (!vertices_are_for_top && q.y <= threshold) { + if (vertices_are_for_top && q.y >= threshold) || (!vertices_are_for_top && q.y <= threshold) + { return if q.y == threshold { Some(q.x) } else { diff --git a/geom/src/cubic_to_quadratic.rs b/geom/src/cubic_to_quadratic.rs index 1f8b0e18..9e5b5a90 100644 --- a/geom/src/cubic_to_quadratic.rs +++ b/geom/src/cubic_to_quadratic.rs @@ -1,5 +1,5 @@ -use crate::point; use crate::monotonic::Monotonic; +use crate::point; use crate::scalar::Scalar; use crate::{CubicBezierSegment, QuadraticBezierSegment}; @@ -28,8 +28,11 @@ where } /// Approximates a cubic bézier segment with a sequence of quadratic béziers. -pub fn cubic_to_quadratics_with_t(curve: &CubicBezierSegment, tolerance: S, cb: &mut F) -where +pub fn cubic_to_quadratics_with_t( + curve: &CubicBezierSegment, + tolerance: S, + cb: &mut F, +) where F: FnMut(&QuadraticBezierSegment, std::ops::Range), { debug_assert!(tolerance >= S::EPSILON); diff --git a/geom/src/flatten_cubic.rs b/geom/src/flatten_cubic.rs index 4df8f8b4..bef0045a 100644 --- a/geom/src/flatten_cubic.rs +++ b/geom/src/flatten_cubic.rs @@ -1,11 +1,10 @@ +use crate::cubic_to_quadratic::single_curve_approximation; +use crate::quadratic_bezier::FlattenedT as FlattenedQuadraticSegment; +use crate::scalar::Scalar; +use crate::CubicBezierSegment; ///! Utilities to flatten cubic bézier curve segments, implemented both with callback and ///! iterator based APIs. - use crate::Point; -use crate::scalar::Scalar; -use crate::CubicBezierSegment; -use crate::cubic_to_quadratic::single_curve_approximation; -use crate::quadratic_bezier::FlattenedT as FlattenedQuadraticSegment; // Computes the number of quadratic bézier segments to approximate a cubic one. // Derived by Raph Levien from section 10.6 of Sedeberg's CAGD notes @@ -19,11 +18,17 @@ fn num_quadratics(curve: &CubicBezierSegment, tolerance: S) -> S { let err = x * x + y * y; - (err / (S::value(432.0) * tolerance * tolerance)).powf(S::ONE / S::SIX).ceil().max(S::ONE) + (err / (S::value(432.0) * tolerance * tolerance)) + .powf(S::ONE / S::SIX) + .ceil() + .max(S::ONE) } -pub fn flatten_cubic_bezier_with_t(curve: &CubicBezierSegment, tolerance: S, callback: &mut F) -where +pub fn flatten_cubic_bezier_with_t( + curve: &CubicBezierSegment, + tolerance: S, + callback: &mut F, +) where F: FnMut(Point, S), { debug_assert!(tolerance >= S::EPSILON); @@ -64,7 +69,6 @@ pub struct Flattened { } impl Flattened { - pub(crate) fn new(curve: &CubicBezierSegment, tolerance: S) -> Self { debug_assert!(tolerance >= S::EPSILON); @@ -75,13 +79,8 @@ impl Flattened { let range_step = S::ONE / num_quadratics; - let quadratic = single_curve_approximation( - &curve.split_range(S::ZERO..range_step), - ); - let current_curve = FlattenedQuadraticSegment::new( - &quadratic, - flattening_tolerance, - ); + let quadratic = single_curve_approximation(&curve.split_range(S::ZERO..range_step)); + let current_curve = FlattenedQuadraticSegment::new(&quadratic, flattening_tolerance); Flattened { curve: *curve, @@ -112,13 +111,8 @@ impl Iterator for Flattened { let t1 = self.range_start + self.range_step; self.remaining_sub_curves -= 1; - let quadratic = single_curve_approximation( - &self.curve.split_range(t0..t1), - ); - self.current_curve = FlattenedQuadraticSegment::new( - &quadratic, - self.tolerance, - ); + let quadratic = single_curve_approximation(&self.curve.split_range(t0..t1)); + self.current_curve = FlattenedQuadraticSegment::new(&quadratic, self.tolerance); let t_inner = self.current_curve.next().unwrap(); let t = t0 + t_inner * self.range_step; @@ -127,7 +121,10 @@ impl Iterator for Flattened { } fn size_hint(&self) -> (usize, Option) { - (self.remaining_sub_curves as usize * self.current_curve.size_hint().0, None) + ( + self.remaining_sub_curves as usize * self.current_curve.size_hint().0, + None, + ) } } diff --git a/geom/src/line.rs b/geom/src/line.rs index 4c8fca99..816769af 100644 --- a/geom/src/line.rs +++ b/geom/src/line.rs @@ -1,9 +1,9 @@ -use crate::{point, vector, Point, Rect, Size, Vector}; use crate::monotonic::MonotonicSegment; use crate::scalar::Scalar; use crate::segment::{BoundingRect, Segment}; use crate::traits::Transformation; use crate::utils::min_max; +use crate::{point, vector, Point, Rect, Size, Vector}; use std::mem::swap; use std::ops::Range; @@ -202,7 +202,6 @@ impl LineSegment { /// segment. To get the intersection point, sample one of the segments /// at the corresponding value. pub fn intersection_t(&self, other: &Self) -> Option<(S, S)> { - if self.to == other.to || self.from == other.from || self.from == other.to diff --git a/geom/src/monotonic.rs b/geom/src/monotonic.rs index c296a4a8..c0a76348 100644 --- a/geom/src/monotonic.rs +++ b/geom/src/monotonic.rs @@ -1,7 +1,7 @@ -use crate::{Point, Rect, Vector}; use crate::scalar::{NumCast, Scalar}; use crate::segment::{BoundingRect, Segment}; use crate::{CubicBezierSegment, QuadraticBezierSegment}; +use crate::{Point, Rect, Vector}; use arrayvec::ArrayVec; use std::ops::Range; @@ -399,7 +399,9 @@ where let mut result = ArrayVec::new(); result.push((t1, t2)); - if let Some(intersection) = first_monotonic_segment_intersecion(a, t1..a_t_range.end, b, t2..b_t_range.end, tolerance) { + if let Some(intersection) = + first_monotonic_segment_intersecion(a, t1..a_t_range.end, b, t2..b_t_range.end, tolerance) + { result.push(intersection); } diff --git a/geom/src/quadratic_bezier.rs b/geom/src/quadratic_bezier.rs index ac653f69..1dbf8145 100644 --- a/geom/src/quadratic_bezier.rs +++ b/geom/src/quadratic_bezier.rs @@ -1,8 +1,8 @@ -use crate::{rect, Point, Rect, Vector}; use crate::monotonic::Monotonic; use crate::scalar::Scalar; use crate::segment::{BoundingRect, Segment}; use crate::traits::Transformation; +use crate::{rect, Point, Rect, Vector}; use crate::{CubicBezierSegment, Line, LineEquation, LineSegment, Triangle}; use arrayvec::ArrayVec; @@ -29,9 +29,7 @@ impl QuadraticBezierSegment { let one_t = S::ONE - t; let one_t2 = one_t * one_t; - self.from * one_t2 - + self.ctrl.to_vector() * S::TWO * one_t * t - + self.to.to_vector() * t2 + self.from * one_t2 + self.ctrl.to_vector() * S::TWO * one_t * t + self.to.to_vector() * t2 } /// Sample the x coordinate of the curve at t (expecting t between 0 and 1). @@ -95,7 +93,11 @@ impl QuadraticBezierSegment { } } - if self.from.y > self.to.y { S::ZERO } else { S::ONE } + if self.from.y > self.to.y { + S::ZERO + } else { + S::ONE + } } /// Find the advancement of the y-least position in the curve. @@ -109,7 +111,11 @@ impl QuadraticBezierSegment { } } - if self.from.y < self.to.y { S::ZERO } else { S::ONE } + if self.from.y < self.to.y { + S::ZERO + } else { + S::ONE + } } /// Return the y inflection point or None if this curve is y-monotonic. @@ -137,7 +143,11 @@ impl QuadraticBezierSegment { } } - if self.from.x > self.to.x { S::ZERO } else { S::ONE } + if self.from.x > self.to.x { + S::ZERO + } else { + S::ONE + } } /// Find the advancement of the x-least position in the curve. @@ -151,7 +161,11 @@ impl QuadraticBezierSegment { } } - if self.from.x < self.to.x { S::ZERO } else { S::ONE } + if self.from.x < self.to.x { + S::ZERO + } else { + S::ONE + } } /// Return the x inflection point or None if this curve is x-monotonic. @@ -306,9 +320,7 @@ impl QuadraticBezierSegment { where F: FnMut(Point), { - self.for_each_flattened_t(tolerance, &mut|t| { - callback(self.sample(t)) - }); + self.for_each_flattened_t(tolerance, &mut |t| callback(self.sample(t))); } /// Compute a flattened approximation of the curve, invoking a callback at @@ -349,9 +361,7 @@ impl QuadraticBezierSegment { where F: FnMut(Point, S), { - self.for_each_flattened_t(tolerance, &mut|t| { - callback(self.sample(t), t) - }); + self.for_each_flattened_t(tolerance, &mut |t| callback(self.sample(t), t)); } /// Returns the flattened representation of the curve as an iterator, starting *after* the @@ -598,8 +608,10 @@ impl FlatteningParameters { let ddx = S::TWO * curve.ctrl.x - curve.from.x - curve.to.x; let ddy = S::TWO * curve.ctrl.y - curve.from.y - curve.to.y; let cross = (curve.to.x - curve.from.x) * ddy - (curve.to.y - curve.from.y) * ddx; - let parabola_from = ((curve.ctrl.x - curve.from.x) * ddx + (curve.ctrl.y - curve.from.y) * ddy) / cross; - let parabola_to = ((curve.to.x - curve.ctrl.x) * ddx + (curve.to.y - curve.ctrl.y) * ddy) / cross; + let parabola_from = + ((curve.ctrl.x - curve.from.x) * ddx + (curve.ctrl.y - curve.from.y) * ddy) / cross; + let parabola_to = + ((curve.to.x - curve.ctrl.x) * ddx + (curve.to.y - curve.ctrl.y) * ddy) / cross; // Note, scale can be NaN, for example with straight lines. When it happens the NaN will // propagate to other parameters. We catch it all by setting the iteration count to zero // and leave the rest as garbage. @@ -657,7 +669,6 @@ fn approx_parabola_inv_integral(x: S) -> S { x * (S::ONE - b + (b * b + quarter * x * x).sqrt()) } - /// A flattening iterator for quadratic bézier segments. /// /// Yields points at each iteration. @@ -1095,7 +1106,7 @@ fn test_flattening_empty_curve() { assert!(iter.next().is_none()); let mut count: u32 = 0; - curve.for_each_flattened(0.1, &mut |_| { count += 1 }); + curve.for_each_flattened(0.1, &mut |_| count += 1); assert_eq!(count, 0); } @@ -1115,6 +1126,6 @@ fn test_flattening_straight_line() { assert!(iter.next().is_none()); let mut count: u32 = 0; - curve.for_each_flattened(0.1, &mut |_| { count += 1 }); + curve.for_each_flattened(0.1, &mut |_| count += 1); assert_eq!(count, 1); } diff --git a/geom/src/segment.rs b/geom/src/segment.rs index 49f1a1f6..a9cf338a 100644 --- a/geom/src/segment.rs +++ b/geom/src/segment.rs @@ -1,6 +1,6 @@ -use crate::{Point, Rect, Vector}; use crate::scalar::Scalar; use crate::{CubicBezierSegment, LineSegment, QuadraticBezierSegment}; +use crate::{Point, Rect, Vector}; use std::ops::Range; @@ -88,25 +88,51 @@ pub trait BoundingRect { } macro_rules! impl_segment { - ($S:ty) => ( + ($S:ty) => { type Scalar = $S; - fn from(&self) -> Point<$S> { self.from() } - fn to(&self) -> Point<$S> { self.to() } - fn sample(&self, t: $S) -> Point<$S> { self.sample(t) } - fn x(&self, t: $S) -> $S { self.x(t) } - fn y(&self, t: $S) -> $S { self.y(t) } - fn derivative(&self, t: $S) -> Vector<$S> { self.derivative(t) } - fn dx(&self, t: $S) -> $S { self.dx(t) } - fn dy(&self, t: $S) -> $S { self.dy(t) } - fn split(&self, t: $S) -> (Self, Self) { self.split(t) } - fn before_split(&self, t: $S) -> Self { self.before_split(t) } - fn after_split(&self, t: $S) -> Self { self.after_split(t) } - fn split_range(&self, t_range: Range<$S>) -> Self { self.split_range(t_range) } - fn flip(&self) -> Self { self.flip() } + fn from(&self) -> Point<$S> { + self.from() + } + fn to(&self) -> Point<$S> { + self.to() + } + fn sample(&self, t: $S) -> Point<$S> { + self.sample(t) + } + fn x(&self, t: $S) -> $S { + self.x(t) + } + fn y(&self, t: $S) -> $S { + self.y(t) + } + fn derivative(&self, t: $S) -> Vector<$S> { + self.derivative(t) + } + fn dx(&self, t: $S) -> $S { + self.dx(t) + } + fn dy(&self, t: $S) -> $S { + self.dy(t) + } + fn split(&self, t: $S) -> (Self, Self) { + self.split(t) + } + fn before_split(&self, t: $S) -> Self { + self.before_split(t) + } + fn after_split(&self, t: $S) -> Self { + self.after_split(t) + } + fn split_range(&self, t_range: Range<$S>) -> Self { + self.split_range(t_range) + } + fn flip(&self) -> Self { + self.flip() + } fn approximate_length(&self, tolerance: $S) -> $S { self.approximate_length(tolerance) } - ) + }; } /// Either a cubic, quadratic or linear bézier segment. diff --git a/geom/src/triangle.rs b/geom/src/triangle.rs index 4ce367b3..a930940b 100644 --- a/geom/src/triangle.rs +++ b/geom/src/triangle.rs @@ -1,7 +1,7 @@ -use crate::{Point, Rect, Size}; use crate::scalar::Scalar; use crate::traits::Transformation; use crate::LineSegment; +use crate::{Point, Rect, Size}; /// A 2D triangle defined by three points `a`, `b` and `c`. #[derive(Copy, Clone, Debug, PartialEq)] diff --git a/geom/src/utils.rs b/geom/src/utils.rs index d1e9c358..df7afb4a 100644 --- a/geom/src/utils.rs +++ b/geom/src/utils.rs @@ -1,5 +1,5 @@ -use crate::{vector, Point, Vector}; use crate::scalar::{Float, Scalar}; +use crate::{vector, Point, Vector}; use arrayvec::ArrayVec; #[inline] diff --git a/path/src/builder.rs b/path/src/builder.rs index 646122c9..022a79e3 100644 --- a/path/src/builder.rs +++ b/path/src/builder.rs @@ -80,14 +80,14 @@ //! use crate::events::PathEvent; -use crate::geom::{Arc, ArcFlags, SvgArc, LineSegment, traits::Transformation}; +use crate::geom::{traits::Transformation, Arc, ArcFlags, LineSegment, SvgArc}; use crate::math::*; -use crate::polygon::Polygon; use crate::path::Verb; +use crate::polygon::Polygon; use crate::{EndpointId, Winding}; -use std::marker::Sized; use std::iter::IntoIterator; +use std::marker::Sized; /// The radius of each corner of a rounded rectangle. #[derive(Copy, Clone, PartialEq, PartialOrd, Debug, Default)] @@ -193,7 +193,9 @@ pub trait PathBuilder { PathEvent::Quadratic { ctrl, to, .. } => { self.quadratic_bezier_to(ctrl, to); } - PathEvent::Cubic { ctrl1, ctrl2, to, .. } => { + PathEvent::Cubic { + ctrl1, ctrl2, to, .. + } => { self.cubic_bezier_to(ctrl1, ctrl2, to); } PathEvent::End { close, .. } => { @@ -205,7 +207,7 @@ pub trait PathBuilder { /// Adds events from an iterator. fn extend(&mut self, events: Evts) where - Evts: IntoIterator + Evts: IntoIterator, { for evt in events.into_iter() { self.path_event(evt) @@ -286,7 +288,7 @@ pub trait PathBuilder { /// No sub-path is in progress after the method is called. fn add_circle(&mut self, center: Point, radius: f32, winding: Winding) where - Self: Sized + Self: Sized, { add_circle(self, center, radius, winding); } @@ -324,7 +326,7 @@ pub trait PathBuilder { /// No sub-path is in progress after the method is called. fn add_rounded_rectangle(&mut self, rect: &Rect, radii: &BorderRadii, winding: Winding) where - Self: Sized + Self: Sized, { add_rounded_rectangle(self, rect, radii, winding); } @@ -341,7 +343,7 @@ pub trait PathBuilder { fn transformed(self, transform: Transform) -> Transformed where Self: Sized, - Transform: Transformation + Transform: Transformation, { Transformed::new(self, transform) } @@ -573,7 +575,6 @@ pub trait Build { fn build(self) -> Self::PathType; } - /// A Builder that approximates curves with successions of line segments. pub struct Flattened { builder: Builder, @@ -590,7 +591,6 @@ impl Build for Flattened { } impl PathBuilder for Flattened { - fn begin(&mut self, at: Point) -> EndpointId { self.current_position = at; self.builder.begin(at) @@ -608,14 +608,27 @@ impl PathBuilder for Flattened { } fn quadratic_bezier_to(&mut self, ctrl: Point, to: Point) -> EndpointId { - let id = crate::private::flatten_quadratic_bezier(self.tolerance, self.current_position, ctrl, to, self); + let id = crate::private::flatten_quadratic_bezier( + self.tolerance, + self.current_position, + ctrl, + to, + self, + ); self.current_position = to; id } fn cubic_bezier_to(&mut self, ctrl1: Point, ctrl2: Point, to: Point) -> EndpointId { - let id = crate::private::flatten_cubic_bezier(self.tolerance, self.current_position, ctrl1, ctrl2, to, self); + let id = crate::private::flatten_cubic_bezier( + self.tolerance, + self.current_position, + ctrl1, + ctrl2, + to, + self, + ); self.current_position = to; id @@ -635,7 +648,10 @@ impl Flattened { } } - pub fn build(self) -> Builder::PathType where Builder: Build { + pub fn build(self) -> Builder::PathType + where + Builder: Build, + { self.builder.build() } @@ -653,10 +669,7 @@ pub struct Transformed { impl Transformed { #[inline] pub fn new(builder: Builder, transform: Transform) -> Self { - Transformed { - builder, - transform, - } + Transformed { builder, transform } } #[inline] @@ -730,7 +743,6 @@ pub struct WithSvg { } impl WithSvg { - pub fn new(builder: Builder) -> Self { WithSvg { builder, @@ -743,7 +755,10 @@ impl WithSvg { } } - pub fn build(mut self) -> Builder::PathType where Builder: Build { + pub fn build(mut self) -> Builder::PathType + where + Builder: Build, + { self.end_if_needed(); self.builder.build() } @@ -752,9 +767,12 @@ impl WithSvg { WithSvg::new(Flattened::new(self.builder, tolerance)) } - pub fn transformed(self, transform: Transform) -> WithSvg> + pub fn transformed( + self, + transform: Transform, + ) -> WithSvg> where - Transform: Transformation + Transform: Transformation, { WithSvg::new(Transformed::new(self.builder, transform)) } @@ -873,7 +891,7 @@ impl WithSvg { #[inline(always)] fn begin_if_needed(&mut self, default: &Point) -> Option { if self.need_moveto { - return self.insert_move_to(default) + return self.insert_move_to(default); } None @@ -882,7 +900,7 @@ impl WithSvg { #[inline(never)] fn insert_move_to(&mut self, default: &Point) -> Option { if self.is_empty { - return Some(self.move_to(*default)) + return Some(self.move_to(*default)); } self.move_to(self.first_position); @@ -934,7 +952,6 @@ where } } - impl Build for WithSvg { type PathType = Builder::PathType; @@ -1041,7 +1058,8 @@ impl SvgPathBuilder for WithSvg { large_arc: flags.large_arc, sweep: flags.sweep, }, - }.to_arc(); + } + .to_arc(); self.arc(arc.center, arc.radii, arc.sweep_angle, arc.x_rotation); } @@ -1275,7 +1293,7 @@ fn svg_builder_relative_curves() { let mut p = Path::svg_builder(); p.move_to(point(0.0, 0.0)); - p.relative_quadratic_bezier_to( vector(0., 100.), vector(-100., 100.)); + p.relative_quadratic_bezier_to(vector(0., 100.), vector(-100., 100.)); p.relative_line_to(vector(-50., 0.)); let path = p.build(); diff --git a/path/src/commands.rs b/path/src/commands.rs index 35885f01..a3c76d58 100644 --- a/path/src/commands.rs +++ b/path/src/commands.rs @@ -459,18 +459,13 @@ impl PathCommandsBuilder { self.in_subpath = false; let id = EventId(self.cmds.len() as u32); - let cmd = if close { - verb::CLOSE - } else { - verb::END - }; + let cmd = if close { verb::CLOSE } else { verb::END }; self.cmds.push(cmd); self.cmds.push(self.first_event_index); Some(id) } - pub fn line_to(&mut self, to: EndpointId) -> EventId { debug_assert!(self.in_subpath); @@ -665,11 +660,7 @@ impl<'l> Iterator for Iter<'l> { let from = self.prev_endpoint; self.prev_endpoint = to; self.idx += 3; - Some(IdEvent::Quadratic { - from, - ctrl, - to, - }) + Some(IdEvent::Quadratic { from, ctrl, to }) } Some(verb::CUBIC) => { let ctrl1 = ControlPointId(self.cmds.next().unwrap()); diff --git a/path/src/lib.rs b/path/src/lib.rs index 9dd00af7..4d27a176 100644 --- a/path/src/lib.rs +++ b/path/src/lib.rs @@ -47,15 +47,17 @@ pub extern crate serde; pub mod builder; pub mod commands; +mod events; pub mod iterator; -pub mod polygon; -pub mod path_buffer; pub mod path; -mod events; +pub mod path_buffer; +pub mod polygon; #[doc(hidden)] pub mod private; +#[doc(inline)] +pub use crate::commands::{PathCommands, PathCommandsSlice}; pub use crate::events::*; pub use crate::geom::ArcFlags; #[doc(inline)] @@ -63,9 +65,7 @@ pub use crate::path::{Path, PathSlice}; #[doc(inline)] pub use crate::path_buffer::{PathBuffer, PathBufferSlice}; #[doc(inline)] -pub use crate::polygon::{Polygon, IdPolygon}; -#[doc(inline)] -pub use crate::commands::{PathCommands, PathCommandsSlice}; +pub use crate::polygon::{IdPolygon, Polygon}; use math::Point; use std::fmt; @@ -74,9 +74,9 @@ use std::u32; pub mod traits { //! `lyon_path` traits reexported here for convenience. + pub use crate::builder::Build; pub use crate::builder::PathBuilder; pub use crate::builder::SvgPathBuilder; - pub use crate::builder::Build; pub use crate::iterator::PathIterator; } @@ -116,7 +116,10 @@ pub mod math { /// Shorthand for `Rect::new(Point::new(x, y), Size::new(w, h))`. #[inline] pub fn rect(x: f32, y: f32, w: f32, h: f32) -> Rect { - Rect { origin: point(x, y), size: size(w, h) } + Rect { + origin: point(x, y), + size: size(w, h), + } } /// Shorthand for `Vector::new(x, y)`. @@ -138,7 +141,6 @@ pub mod math { } } - /// The fill rule defines how to determine what is inside and what is outside of the shape. /// /// See the SVG specification. diff --git a/path/src/path.rs b/path/src/path.rs index 686c99e0..a9c0e9c8 100644 --- a/path/src/path.rs +++ b/path/src/path.rs @@ -4,12 +4,12 @@ use crate::builder::*; use crate::geom::traits::Transformation; use crate::math::*; -use crate::{AttributeStore, ControlPointId, EndpointId, Event, IdEvent, PathEvent, PositionStore}; use crate::private::DebugValidator; +use crate::{AttributeStore, ControlPointId, EndpointId, Event, IdEvent, PathEvent, PositionStore}; +use std::fmt; use std::iter::IntoIterator; use std::u32; -use std::fmt; /// Enumeration corresponding to the [Event](https://docs.rs/lyon_core/*/lyon_core/events/enum.Event.html) enum /// without the parameters. @@ -293,7 +293,9 @@ impl<'l> fmt::Debug for PathSlice<'l> { write_point(formatter, ctrl)?; write_point(formatter, to)?; } - PathEvent::Cubic { ctrl1, ctrl2, to, .. } => { + PathEvent::Cubic { + ctrl1, ctrl2, to, .. + } => { write!(formatter, " C")?; write_point(formatter, ctrl1)?; write_point(formatter, ctrl2)?; @@ -474,7 +476,9 @@ impl Builder { PathEvent::Quadratic { ctrl, to, .. } => { self.quadratic_bezier_to(ctrl, to); } - PathEvent::Cubic { ctrl1, ctrl2, to, .. } => { + PathEvent::Cubic { + ctrl1, ctrl2, to, .. + } => { self.cubic_bezier_to(ctrl1, ctrl2, to); } PathEvent::End { close: true, .. } => { @@ -541,7 +545,6 @@ pub struct BuilderWithAttributes { } impl BuilderWithAttributes { - pub fn new(num_attributes: usize) -> Self { BuilderWithAttributes { builder: Builder::new(), @@ -583,7 +586,12 @@ impl BuilderWithAttributes { } #[inline] - pub fn quadratic_bezier_to(&mut self, ctrl: Point, to: Point, attributes: &[f32]) -> EndpointId { + pub fn quadratic_bezier_to( + &mut self, + ctrl: Point, + to: Point, + attributes: &[f32], + ) -> EndpointId { let id = self.builder.quadratic_bezier_to(ctrl, to); self.push_attributes(attributes); @@ -591,7 +599,13 @@ impl BuilderWithAttributes { } #[inline] - pub fn cubic_bezier_to(&mut self, ctrl1: Point, ctrl2: Point, to: Point, attributes: &[f32]) -> EndpointId { + pub fn cubic_bezier_to( + &mut self, + ctrl1: Point, + ctrl2: Point, + to: Point, + attributes: &[f32], + ) -> EndpointId { let id = self.builder.cubic_bezier_to(ctrl1, ctrl2, to); self.push_attributes(attributes); @@ -827,7 +841,7 @@ impl<'l> IterWithAttributes<'l> { fn pop_endpoint(&mut self) -> (Point, &'l [f32]) { let position = self.points.next(); let attributes_ptr = self.points.ptr as *const f32; - self.points.advance_n(self.attrib_stride); + self.points.advance_n(self.attrib_stride); let attributes = unsafe { // SAFETY: advance_n would have panicked if the slice is out of bounds std::slice::from_raw_parts(attributes_ptr, self.num_attributes) @@ -1640,7 +1654,6 @@ fn test_path_builder_empty_begin() { assert_eq!(it.next(), None); } - #[test] fn test_concatenate() { let mut builder = Path::builder(); @@ -1660,10 +1673,7 @@ fn test_concatenate() { let path2 = builder.build(); let mut builder = Path::builder(); - builder.concatenate(&[ - path1.as_slice(), - path2.as_slice(), - ]); + builder.concatenate(&[path1.as_slice(), path2.as_slice()]); let path = builder.build(); let mut it = path.iter(); diff --git a/path/src/path_buffer.rs b/path/src/path_buffer.rs index 2180bfc4..f7df7a31 100644 --- a/path/src/path_buffer.rs +++ b/path/src/path_buffer.rs @@ -1,7 +1,7 @@ //! A container to store multiple paths contiguously. -use crate::math::*; use crate::builder::*; +use crate::math::*; use crate::path; use crate::{EndpointId, PathSlice}; @@ -128,7 +128,9 @@ impl<'l> PathBufferSlice<'l> { impl<'l> fmt::Debug for PathBufferSlice<'l> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "PathBuffer {{ paths: {:?}, points: {:?}, verbs: {:?}, ", + write!( + formatter, + "PathBuffer {{ paths: {:?}, points: {:?}, verbs: {:?}, ", self.paths.len(), self.points.len(), self.verbs.len(), @@ -281,7 +283,6 @@ impl<'l> Build for Builder<'l> { } } - /// A Builder that appends a path to an existing PathBuffer, with custom attributes. pub struct BuilderWithAttributes<'l> { buffer: &'l mut PathBuffer, @@ -351,13 +352,24 @@ impl<'l> BuilderWithAttributes<'l> { } #[inline] - pub fn quadratic_bezier_to(&mut self, ctrl: Point, to: Point, attributes: &[f32]) -> EndpointId { + pub fn quadratic_bezier_to( + &mut self, + ctrl: Point, + to: Point, + attributes: &[f32], + ) -> EndpointId { let id = self.builder.quadratic_bezier_to(ctrl, to, attributes); self.adjust_id(id) } #[inline] - pub fn cubic_bezier_to(&mut self, ctrl1: Point, ctrl2: Point, to: Point, attributes: &[f32]) -> EndpointId { + pub fn cubic_bezier_to( + &mut self, + ctrl1: Point, + ctrl2: Point, + to: Point, + attributes: &[f32], + ) -> EndpointId { let id = self.builder.cubic_bezier_to(ctrl1, ctrl2, to, attributes); self.adjust_id(id) } @@ -370,44 +382,104 @@ impl<'l> BuilderWithAttributes<'l> { #[test] fn simple() { - use crate::PathEvent; - - let mut buffer = PathBuffer::new(); - - let mut builder = buffer.builder(); - builder.begin(point(0.0, 0.0)); - builder.line_to(point(10.0, 0.0)); - builder.line_to(point(10.0, 10.0)); - let a = builder.line_to(point(0.0, 10.0)); - builder.end(true); - - let p1 = builder.build(); - - let mut builder = buffer.builder(); - builder.begin(point(0.0, 0.0)); - builder.line_to(point(20.0, 0.0)); - builder.line_to(point(20.0, 20.0)); - let b = builder.line_to(point(0.0, 20.0)); - builder.end(false); - - let p2 = builder.build(); - - let mut iter = buffer.get(p1).iter(); - assert_eq!(iter.next(), Some(PathEvent::Begin { at: point(0.0, 0.0) })); - assert_eq!(iter.next(), Some(PathEvent::Line { from: point(0.0, 0.0), to: point(10.0, 0.0) })); - assert_eq!(iter.next(), Some(PathEvent::Line { from: point(10.0, 0.0), to: point(10.0, 10.0) })); - assert_eq!(iter.next(), Some(PathEvent::Line { from: point(10.0, 10.0), to: point(0.0, 10.0) })); - assert_eq!(iter.next(), Some(PathEvent::End { last: point(0.0, 10.0), first: point(0.0, 0.0), close: true })); - assert_eq!(iter.next(), None); - - let mut iter = buffer.get(p2).iter(); - assert_eq!(iter.next(), Some(PathEvent::Begin { at: point(0.0, 0.0) })); - assert_eq!(iter.next(), Some(PathEvent::Line { from: point(0.0, 0.0), to: point(20.0, 0.0) })); - assert_eq!(iter.next(), Some(PathEvent::Line { from: point(20.0, 0.0), to: point(20.0, 20.0) })); - assert_eq!(iter.next(), Some(PathEvent::Line { from: point(20.0, 20.0), to: point(0.0, 20.0) })); - assert_eq!(iter.next(), Some(PathEvent::End { last: point(0.0, 20.0), first: point(0.0, 0.0), close: false })); - assert_eq!(iter.next(), None); - - assert_eq!(buffer.get(p1)[a], point(0.0, 10.0)); - assert_eq!(buffer.get(p2)[b], point(0.0, 20.0)); + use crate::PathEvent; + + let mut buffer = PathBuffer::new(); + + let mut builder = buffer.builder(); + builder.begin(point(0.0, 0.0)); + builder.line_to(point(10.0, 0.0)); + builder.line_to(point(10.0, 10.0)); + let a = builder.line_to(point(0.0, 10.0)); + builder.end(true); + + let p1 = builder.build(); + + let mut builder = buffer.builder(); + builder.begin(point(0.0, 0.0)); + builder.line_to(point(20.0, 0.0)); + builder.line_to(point(20.0, 20.0)); + let b = builder.line_to(point(0.0, 20.0)); + builder.end(false); + + let p2 = builder.build(); + + let mut iter = buffer.get(p1).iter(); + assert_eq!( + iter.next(), + Some(PathEvent::Begin { + at: point(0.0, 0.0) + }) + ); + assert_eq!( + iter.next(), + Some(PathEvent::Line { + from: point(0.0, 0.0), + to: point(10.0, 0.0) + }) + ); + assert_eq!( + iter.next(), + Some(PathEvent::Line { + from: point(10.0, 0.0), + to: point(10.0, 10.0) + }) + ); + assert_eq!( + iter.next(), + Some(PathEvent::Line { + from: point(10.0, 10.0), + to: point(0.0, 10.0) + }) + ); + assert_eq!( + iter.next(), + Some(PathEvent::End { + last: point(0.0, 10.0), + first: point(0.0, 0.0), + close: true + }) + ); + assert_eq!(iter.next(), None); + + let mut iter = buffer.get(p2).iter(); + assert_eq!( + iter.next(), + Some(PathEvent::Begin { + at: point(0.0, 0.0) + }) + ); + assert_eq!( + iter.next(), + Some(PathEvent::Line { + from: point(0.0, 0.0), + to: point(20.0, 0.0) + }) + ); + assert_eq!( + iter.next(), + Some(PathEvent::Line { + from: point(20.0, 0.0), + to: point(20.0, 20.0) + }) + ); + assert_eq!( + iter.next(), + Some(PathEvent::Line { + from: point(20.0, 20.0), + to: point(0.0, 20.0) + }) + ); + assert_eq!( + iter.next(), + Some(PathEvent::End { + last: point(0.0, 20.0), + first: point(0.0, 0.0), + close: false + }) + ); + assert_eq!(iter.next(), None); + + assert_eq!(buffer.get(p1)[a], point(0.0, 10.0)); + assert_eq!(buffer.get(p2)[b], point(0.0, 20.0)); } diff --git a/path/src/polygon.rs b/path/src/polygon.rs index 0b3fed25..c9795077 100644 --- a/path/src/polygon.rs +++ b/path/src/polygon.rs @@ -1,8 +1,9 @@ //! Specific path types for polygons. use crate::math::Point; -use crate::{ControlPointId, EndpointId, Event, EventId, IdEvent, PathEvent, Position, PositionStore}; - +use crate::{ + ControlPointId, EndpointId, Event, EventId, IdEvent, PathEvent, Position, PositionStore, +}; /// A view over a sequence of endpoints forming a polygon. /// @@ -88,7 +89,6 @@ impl<'l, T> std::ops::Index for Polygon<'l, T> { } } - /// A view over a sequence of endpoint IDs forming a polygon. pub struct IdPolygon<'l> { pub points: &'l [EndpointId], diff --git a/path/src/private.rs b/path/src/private.rs index 32349ac4..3efcba8d 100644 --- a/path/src/private.rs +++ b/path/src/private.rs @@ -2,8 +2,8 @@ // but are exposed for use by other lyon crates. // Changing them doesn't necessarily imply semver breaking bumps. -pub use crate::math::Point; pub use crate::geom::{CubicBezierSegment, QuadraticBezierSegment}; +pub use crate::math::Point; pub use crate::traits::PathBuilder; pub use crate::EndpointId; @@ -24,7 +24,8 @@ impl DebugValidator { #[inline(always)] pub fn begin(&mut self) { - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { assert!(!self.in_subpath); self.in_subpath = true; } @@ -32,7 +33,8 @@ impl DebugValidator { #[inline(always)] pub fn end(&mut self) { - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { assert!(self.in_subpath); self.in_subpath = false; } @@ -40,20 +42,21 @@ impl DebugValidator { #[inline(always)] pub fn edge(&self) { - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { assert!(self.in_subpath); } } #[inline(always)] pub fn build(&self) { - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { assert!(!self.in_subpath); } } } - pub fn flatten_quadratic_bezier( tolerance: f32, from: Point, @@ -61,7 +64,7 @@ pub fn flatten_quadratic_bezier( to: Point, builder: &mut impl PathBuilder, ) -> EndpointId { - let curve = QuadraticBezierSegment { from, ctrl, to, }; + let curve = QuadraticBezierSegment { from, ctrl, to }; let mut id = EndpointId::INVALID; curve.for_each_flattened(tolerance, &mut |point| { id = builder.line_to(point); @@ -78,7 +81,12 @@ pub fn flatten_cubic_bezier( to: Point, builder: &mut impl PathBuilder, ) -> EndpointId { - let curve = CubicBezierSegment { from, ctrl1, ctrl2, to }; + let curve = CubicBezierSegment { + from, + ctrl1, + ctrl2, + to, + }; let mut id = EndpointId::INVALID; curve.for_each_flattened(tolerance, &mut |point| { id = builder.line_to(point); @@ -86,4 +94,3 @@ pub fn flatten_cubic_bezier( id } - diff --git a/svg/src/path_utils.rs b/svg/src/path_utils.rs index 42bba4fd..2ecc34e5 100644 --- a/svg/src/path_utils.rs +++ b/svg/src/path_utils.rs @@ -1,4 +1,4 @@ -use crate::parser::{PathSegment, PathParser}; +use crate::parser::{PathParser, PathSegment}; use crate::path::builder::*; use crate::path::geom::Arc; @@ -214,7 +214,8 @@ impl PathSerializer { start_angle, sweep_angle, x_rotation, - }.to_svg_arc(); + } + .to_svg_arc(); self.path += &format!( "A {} {} {} {} {} {} {}", diff --git a/tess2/src/flattened_path.rs b/tess2/src/flattened_path.rs index 0330bd15..b3bab508 100644 --- a/tess2/src/flattened_path.rs +++ b/tess2/src/flattened_path.rs @@ -1,7 +1,7 @@ use crate::math::*; use crate::path::builder::*; +use crate::path::private::{flatten_cubic_bezier, flatten_quadratic_bezier}; use crate::path::EndpointId; -use crate::path::private::{flatten_quadratic_bezier, flatten_cubic_bezier}; use std::ops::Range; @@ -210,7 +210,14 @@ impl PathBuilder for Builder { } fn cubic_bezier_to(&mut self, ctrl1: Point, ctrl2: Point, to: Point) -> EndpointId { - flatten_cubic_bezier(self.tolerance, self.current_position(), ctrl1, ctrl2, to, self) + flatten_cubic_bezier( + self.tolerance, + self.current_position(), + ctrl1, + ctrl2, + to, + self, + ) } } diff --git a/tess2/src/lib.rs b/tess2/src/lib.rs index 31548b60..40fab881 100644 --- a/tess2/src/lib.rs +++ b/tess2/src/lib.rs @@ -93,9 +93,9 @@ pub use crate::tessellation::FillOptions; pub use crate::tessellator::FillTessellator; pub mod geometry_builder { - pub use crate::tessellation::geometry_builder::{Positions, NoOutput, VertexBuffers}; - pub use crate::tessellation::VertexId; use crate::math::Point; + pub use crate::tessellation::geometry_builder::{NoOutput, Positions, VertexBuffers}; + pub use crate::tessellation::VertexId; /// An interface with similar goals to `GeometryBuilder` for algorithms that pre-build /// the vertex and index buffers. diff --git a/tess2/src/tessellator.rs b/tess2/src/tessellator.rs index 6072a927..ab3b7594 100644 --- a/tess2/src/tessellator.rs +++ b/tess2/src/tessellator.rs @@ -1,10 +1,10 @@ use crate::flattened_path::FlattenedPath; +use crate::geometry_builder::GeometryReceiver; use crate::math::*; use crate::path::builder::*; use crate::path::PathEvent; use crate::path::PathSlice; use crate::tessellation::{Count, FillOptions, FillRule}; -use crate::geometry_builder::GeometryReceiver; use std::os::raw::c_void; use std::ptr; diff --git a/tessellation/src/event_queue.rs b/tessellation/src/event_queue.rs index bf95147c..4692d6cc 100644 --- a/tessellation/src/event_queue.rs +++ b/tessellation/src/event_queue.rs @@ -1,8 +1,8 @@ use crate::fill::{compare_positions, is_after}; use crate::geom::{CubicBezierSegment, QuadraticBezierSegment}; use crate::math::{point, Point}; -use crate::path::{EndpointId, IdEvent, PathEvent, PositionStore}; use crate::path::private::DebugValidator; +use crate::path::{EndpointId, IdEvent, PathEvent, PositionStore}; use crate::Orientation; use std::cmp::Ordering; @@ -185,7 +185,12 @@ impl EventQueue { after: TessEventId, ) -> TessEventId { debug_assert!(self.sorted); - debug_assert!(is_after(data.to, position), "{:?} should be after {:?}", data.to, position); + debug_assert!( + is_after(data.to, position), + "{:?} should be after {:?}", + data.to, + position + ); let idx = self.events.len() as TessEventId; self.events.push(Event { @@ -816,7 +821,13 @@ impl EventQueueBuilder { } } - pub fn cubic_bezier_segment(&mut self, ctrl1: Point, ctrl2: Point, to: Point, to_id: EndpointId) { + pub fn cubic_bezier_segment( + &mut self, + ctrl1: Point, + ctrl2: Point, + to: Point, + to_id: EndpointId, + ) { self.validator.edge(); // Swap the curve so that it always goes downwards. This way if two // paths share the same edge with different windings, the flattening will diff --git a/tessellation/src/fill.rs b/tessellation/src/fill.rs index d885cf78..589865d6 100644 --- a/tessellation/src/fill.rs +++ b/tessellation/src/fill.rs @@ -1,20 +1,20 @@ use crate::event_queue::*; -use crate::math::*; use crate::geom::LineSegment; +use crate::math::*; use crate::monotone::*; use crate::path::polygon::Polygon; +use crate::path::traits::{Build, PathBuilder}; use crate::path::{ - AttributeStore, EndpointId, FillRule, IdEvent, PathEvent, PathSlice, PositionStore, Winding + AttributeStore, EndpointId, FillRule, IdEvent, PathEvent, PathSlice, PositionStore, Winding, }; -use crate::path::traits::{PathBuilder, Build}; use crate::{FillGeometryBuilder, Orientation, VertexId}; use crate::{ FillOptions, InternalError, Side, TessellationError, TessellationResult, VertexSource, }; use std::cmp::Ordering; use std::f32; -use std::ops::Range; use std::mem; +use std::ops::Range; #[cfg(debug_assertions)] use std::env; @@ -26,7 +26,11 @@ type ActiveEdgeIdx = usize; // because the latter deals with NaN. #[inline(always)] fn fmax(a: f32, b: f32) -> f32 { - if a > b { a } else { b } + if a > b { + a + } else { + b + } } fn slope(v: Vector) -> f32 { @@ -180,8 +184,8 @@ impl Span { None => { debug_assert!(false); unreachable!(); - }, - Some(tess) => tess + } + Some(tess) => tess, } } } @@ -193,14 +197,14 @@ struct Spans { impl Spans { fn begin_span(&mut self, span_idx: SpanIdx, position: &Point, vertex: VertexId) { - let mut tess = self.pool.pop() + let mut tess = self + .pool + .pop() .unwrap_or_else(|| Box::new(MonotoneTessellator::new())); tess.begin(*position, vertex); - self.spans.insert( - span_idx as usize, - Span { tess: Some(tess), } - ); + self.spans + .insert(span_idx as usize, Span { tess: Some(tess) }); } fn end_span( @@ -240,13 +244,17 @@ impl Spans { let right_span_idx = left_span_idx + 1; - self.spans[left_span_idx as usize] - .tess() - .vertex(*merge_position, merge_vertex, Side::Right); + self.spans[left_span_idx as usize].tess().vertex( + *merge_position, + merge_vertex, + Side::Right, + ); - self.spans[right_span_idx as usize] - .tess() - .vertex(*merge_position, merge_vertex, Side::Left); + self.spans[right_span_idx as usize].tess().vertex( + *merge_position, + merge_vertex, + Side::Left, + ); self.end_span(left_span_idx, current_position, current_vertex, output); } @@ -513,7 +521,10 @@ impl FillTessellator { fill_rule: FillRule::EvenOdd, orientation: Orientation::Vertical, tolerance: FillOptions::DEFAULT_TOLERANCE, - fill: Spans { spans: Vec::new(), pool: Vec::new() }, + fill: Spans { + spans: Vec::new(), + pool: Vec::new(), + }, log, assume_no_intersection: false, attrib_buffer: Vec::new(), @@ -596,11 +607,7 @@ impl FillTessellator { options: &FillOptions, output: &mut dyn FillGeometryBuilder, ) -> TessellationResult { - self.tessellate( - polygon.path_events(), - options, - output, - ) + self.tessellate(polygon.path_events(), options, output) } /// Tessellate an axis-aligned rectangle. @@ -818,15 +825,13 @@ impl FillTessellator { Orientation::Horizontal => reorient(self.current_position), }; - self.current_vertex = output.add_fill_vertex( - FillVertex { - position, - events: &self.events, - current_event, - attrib_store, - attrib_buffer: &mut self.attrib_buffer, - }, - )?; + self.current_vertex = output.add_fill_vertex(FillVertex { + position, + events: &self.events, + current_event, + attrib_store, + attrib_buffer: &mut self.attrib_buffer, + })?; let mut current_sibling = current_event; while self.events.valid_id(current_sibling) { @@ -934,7 +939,12 @@ impl FillTessellator { if edge.is_merge { assert!(self.fill_rule.is_in(winding.number)); } else { - assert!(!is_after(self.current_position, edge.to), "error at edge {}, position {:?}", idx, edge.to); + assert!( + !is_after(self.current_position, edge.to), + "error at edge {}, position {:?}", + idx, + edge.to + ); } } assert_eq!(winding.number, 0); @@ -1207,7 +1217,11 @@ impl FillTessellator { #[cfg_attr(feature = "profiling", inline(never))] #[cfg_attr(not(feature = "profiling"), inline(always))] - fn check_remaining_edges(&self, active_edge_idx: usize, current_x: f32) -> Result<(), InternalError> { + fn check_remaining_edges( + &self, + active_edge_idx: usize, + current_x: f32, + ) -> Result<(), InternalError> { // This function typically takes about 2.5% ~ 3% of the profile, so not necessarily the best // target for optimization. That said all of the work done here is only robustness checks // so we could add an option to skip it. @@ -1452,25 +1466,21 @@ impl FillTessellator { #[cfg(debug_assertions)] for active_edge in &self.active.edges[above.clone()] { - debug_assert!( - active_edge.is_merge || !is_after(self.current_position, active_edge.to) - ); + debug_assert!(active_edge.is_merge || !is_after(self.current_position, active_edge.to)); } let from = self.current_position; let from_id = self.current_vertex; self.active.edges.splice( above, - self.edges_below.iter().map(|edge| { - ActiveEdge { - from, - to: edge.to, - winding: edge.winding, - is_merge: false, - from_id, - src_edge: edge.src_edge, - range_end: edge.range_end, - } + self.edges_below.iter().map(|edge| ActiveEdge { + from, + to: edge.to, + winding: edge.winding, + is_merge: false, + from_id, + src_edge: edge.src_edge, + range_end: edge.range_end, }), ); @@ -1509,7 +1519,8 @@ impl FillTessellator { ) }; - self.fill.begin_span(new_span_idx, &upper_position, upper_id); + self.fill + .begin_span(new_span_idx, &upper_position, upper_id); self.fill.spans[left_span_idx as usize].tess().vertex( self.current_position, @@ -1608,10 +1619,16 @@ impl FillTessellator { tb: f64, active_edge_idx: usize, edge_below: &mut PendingEdge, - below_segment: &LineSegment + below_segment: &LineSegment, ) { let mut intersection_position = below_segment.sample(tb).to_f32(); - tess_log!(self, "-> intersection at: {:?} t={:?}|{:?}", intersection_position, ta, tb); + tess_log!( + self, + "-> intersection at: {:?} t={:?}|{:?}", + intersection_position, + ta, + tb + ); tess_log!( self, " from {:?}->{:?} and {:?}->{:?}", @@ -1626,8 +1643,7 @@ impl FillTessellator { if self.current_position == intersection_position { active_edge.from = intersection_position; let src_range = &mut self.events.edge_data[active_edge.src_edge as usize].range; - let remapped_ta = - remap_t_in_range(ta as f32, src_range.start..active_edge.range_end); + let remapped_ta = remap_t_in_range(ta as f32, src_range.start..active_edge.range_end); src_range.start = remapped_ta; return; @@ -1657,9 +1673,7 @@ impl FillTessellator { let mut inserted_evt = None; let mut flipped_active = false; - if active_edge.to != intersection_position - && active_edge.from != intersection_position - { + if active_edge.to != intersection_position && active_edge.from != intersection_position { let remapped_ta = remap_t_in_range( ta as f32, a_src_edge_data.range.start..active_edge.range_end, @@ -1698,13 +1712,10 @@ impl FillTessellator { active_edge.range_end = remapped_ta; } - if edge_below.to != intersection_position - && self.current_position != intersection_position + if edge_below.to != intersection_position && self.current_position != intersection_position { - let remapped_tb = remap_t_in_range( - tb as f32, - b_src_edge_data.range.start..edge_below.range_end, - ); + let remapped_tb = + remap_t_in_range(tb as f32, b_src_edge_data.range.start..edge_below.range_end); if is_after(edge_below.to, intersection_position) { let edge_data = EdgeData { @@ -1821,7 +1832,7 @@ impl FillTessellator { (false, true) => Ordering::Less, (true, true) => Ordering::Equal, } - }, + } }); let mut new_active_edges = Vec::with_capacity(self.active.edges.len()); @@ -1920,9 +1931,8 @@ impl FillTessellator { #[cfg_attr(feature = "profiling", inline(never))] fn sort_edges_below(&mut self) { - self.edges_below.sort_unstable_by( - |a, b| a.sort_key.partial_cmp(&b.sort_key).unwrap() - ); + self.edges_below + .sort_unstable_by(|a, b| a.sort_key.partial_cmp(&b.sort_key).unwrap()); } #[cfg_attr(feature = "profiling", inline(never))] @@ -1966,13 +1976,29 @@ impl FillTessellator { Ordering::Equal => (a_idx, b_idx, false), }; - tess_log!(self, "coincident edges {:?} -> {:?} / {:?}", self.current_position, a_to, b_to); + tess_log!( + self, + "coincident edges {:?} -> {:?} / {:?}", + self.current_position, + a_to, + b_to + ); - tess_log!(self, "update winding: {:?} -> {:?}", self.edges_below[upper_idx].winding, self.edges_below[upper_idx].winding + self.edges_below[lower_idx].winding); + tess_log!( + self, + "update winding: {:?} -> {:?}", + self.edges_below[upper_idx].winding, + self.edges_below[upper_idx].winding + self.edges_below[lower_idx].winding + ); self.edges_below[upper_idx].winding += self.edges_below[lower_idx].winding; let split_point = self.edges_below[upper_idx].to; - tess_log!(self, "remove coincident edge {:?}, split:{:?}", a_idx, split); + tess_log!( + self, + "remove coincident edge {:?}, split:{:?}", + a_idx, + split + ); let edge = self.edges_below.remove(lower_idx); if !split { @@ -1984,7 +2010,8 @@ impl FillTessellator { let t = LineSegment { from: self.current_position, to: edge.to, - }.solve_t_for_y(split_point.y); + } + .solve_t_for_y(split_point.y); let src_range = src_edge_data.range.start..edge.range_end; let t_remapped = remap_t_in_range(t, src_range); @@ -1997,14 +2024,10 @@ impl FillTessellator { ..src_edge_data }; - self.events.insert_sorted( - split_point, - edge_data, - self.current_event_id, - ); + self.events + .insert_sorted(split_point, edge_data, self.current_event_id); } - fn reset(&mut self) { self.current_position = point(f32::MIN, f32::MIN); self.current_vertex = VertexId::INVALID; @@ -2265,8 +2288,8 @@ impl<'l> FillBuilder<'l> { options: &'l FillOptions, output: &'l mut dyn FillGeometryBuilder, ) -> Self { - let mut events = std::mem::replace(&mut tessellator.events, EventQueue::new()) - .into_builder(); + let mut events = + std::mem::replace(&mut tessellator.events, EventQueue::new()).into_builder(); events.set_tolerance(options.tolerance); FillBuilder { @@ -2277,7 +2300,7 @@ impl<'l> FillBuilder<'l> { first_position: point(0.0, 0.0), tessellator, options, - output + output, } } @@ -2294,7 +2317,8 @@ impl<'l> FillBuilder<'l> { let mut event_queue = self.events.build(); std::mem::swap(&mut self.tessellator.events, &mut event_queue); - self.tessellator.tessellate_impl(self.options, None, self.output) + self.tessellator + .tessellate_impl(self.options, None, self.output) } } @@ -2349,12 +2373,7 @@ impl<'l> PathBuilder for FillBuilder<'l> { } /// Tessellate the stroke for an axis-aligned rounded rectangle. - fn add_circle( - &mut self, - center: Point, - radius: f32, - winding: Winding, - ) { + fn add_circle(&mut self, center: Point, radius: f32, winding: Winding) { // This specialized routine extracts the curves into separate sub-paths // to nudge the tessellator towards putting them in their own monotonic // spans. This avoids generating thin triangles from one side of the circle @@ -2820,7 +2839,10 @@ fn fill_vertex_source_03() { } impl FillGeometryBuilder for CheckVertexSources { - fn add_fill_vertex(&mut self, mut vertex: FillVertex) -> Result { + fn add_fill_vertex( + &mut self, + mut vertex: FillVertex, + ) -> Result { if eq(vertex.position(), point(1.0, 1.0)) { assert_eq!(vertex.interpolated_attributes(), &[1.5]); assert_eq!(vertex.sources().count(), 2); @@ -2869,7 +2891,10 @@ fn fill_builder_vertex_source() { } impl FillGeometryBuilder for CheckVertexSources { - fn add_fill_vertex(&mut self, vertex: FillVertex) -> Result { + fn add_fill_vertex( + &mut self, + vertex: FillVertex, + ) -> Result { let pos = vertex.position(); for src in vertex.sources() { if eq(pos, point(0.0, 0.0)) { diff --git a/tessellation/src/fill_tests.rs b/tessellation/src/fill_tests.rs index 118b16e5..29b3e39c 100644 --- a/tessellation/src/fill_tests.rs +++ b/tessellation/src/fill_tests.rs @@ -1,17 +1,16 @@ use crate::extra::rust_logo::build_logo_path; -use crate::math::*; use crate::geometry_builder::*; +use crate::math::*; use crate::path::builder::PathBuilder; use crate::path::{Path, PathSlice}; -use crate::{FillVertex, FillOptions, FillRule, FillTessellator, TessellationError, VertexId}; +use crate::{FillOptions, FillRule, FillTessellator, FillVertex, TessellationError, VertexId}; use std::env; fn tessellate(path: PathSlice, fill_rule: FillRule, log: bool) -> Result { let mut buffers: VertexBuffers = VertexBuffers::new(); { - let options = FillOptions::tolerance(0.05) - .with_fill_rule(fill_rule); + let options = FillOptions::tolerance(0.05).with_fill_rule(fill_rule); use crate::path::iterator::*; @@ -49,10 +48,7 @@ fn test_too_many_vertices() { } impl FillGeometryBuilder for Builder { - fn add_fill_vertex( - &mut self, - _: FillVertex, - ) -> Result { + fn add_fill_vertex(&mut self, _: FillVertex) -> Result { if self.max_vertices == 0 { return Err(GeometryBuilderError::TooManyVertices); } @@ -93,7 +89,11 @@ fn test_path_and_count_triangles(path: PathSlice, expected_triangle_count: usize test_path_internal(path, FillRule::NonZero, None); } -fn test_path_internal(path: PathSlice, fill_rule: FillRule, expected_triangle_count: Option) { +fn test_path_internal( + path: PathSlice, + fill_rule: FillRule, + expected_triangle_count: Option, +) { let add_logging = env::var("LYON_ENABLE_LOGGING").is_ok(); let find_test_case = env::var("LYON_REDUCED_TESTCASE").is_ok(); @@ -138,7 +138,11 @@ fn test_path_with_rotations(path: Path, step: f32, expected_triangle_count: Opti let tranformed_path = path.clone().transformed(&Rotation::new(angle)); - test_path_internal(tranformed_path.as_slice(), FillRule::EvenOdd, expected_triangle_count); + test_path_internal( + tranformed_path.as_slice(), + FillRule::EvenOdd, + expected_triangle_count, + ); test_path_internal(tranformed_path.as_slice(), FillRule::NonZero, None); angle.radians += step; @@ -2402,5 +2406,6 @@ fn low_tolerance_01() { &path, &FillOptions::tolerance(0.00001), &mut simple_builder(&mut buffers), - ).unwrap(); + ) + .unwrap(); } diff --git a/tessellation/src/fuzz_tests.rs b/tessellation/src/fuzz_tests.rs index 1d87f81c..95747558 100644 --- a/tessellation/src/fuzz_tests.rs +++ b/tessellation/src/fuzz_tests.rs @@ -1,5 +1,5 @@ -use crate::math::*; use crate::geometry_builder::{simple_builder, VertexBuffers}; +use crate::math::*; use crate::path::iterator::*; use crate::path::{Path, PathSlice}; use crate::{FillOptions, FillRule, FillTessellator, TessellationError}; @@ -7,8 +7,7 @@ use crate::{FillOptions, FillRule, FillTessellator, TessellationError}; fn tessellate(path: PathSlice, fill_rule: FillRule, log: bool) -> Result { let mut buffers: VertexBuffers = VertexBuffers::new(); { - let options = FillOptions::tolerance(0.05) - .with_fill_rule(fill_rule); + let options = FillOptions::tolerance(0.05).with_fill_rule(fill_rule); let mut builder = Path::builder(); for e in path.iter().flattened(0.05) { diff --git a/tessellation/src/geometry_builder.rs b/tessellation/src/geometry_builder.rs index 91d44e47..676e93db 100644 --- a/tessellation/src/geometry_builder.rs +++ b/tessellation/src/geometry_builder.rs @@ -264,7 +264,8 @@ pub trait StrokeGeometryBuilder: GeometryBuilder { /// Returns a vertex id that is only valid between begin_geometry and end_geometry. /// /// This method can only be called between begin_geometry and end_geometry. - fn add_stroke_vertex(&mut self, vertex: StrokeVertex) -> Result; + fn add_stroke_vertex(&mut self, vertex: StrokeVertex) + -> Result; } /// Structure that holds the vertex and index data. @@ -453,9 +454,9 @@ where Ctor: FillVertexConstructor, { fn add_fill_vertex(&mut self, vertex: FillVertex) -> Result { - self.buffers.vertices.push( - self.vertex_constructor.new_vertex(vertex) - ); + self.buffers + .vertices + .push(self.vertex_constructor.new_vertex(vertex)); let len = self.buffers.vertices.len(); if len > OutputIndex::MAX { return Err(GeometryBuilderError::TooManyVertices); @@ -471,10 +472,7 @@ where OutputIndex: Add + From + MaxIndex, Ctor: StrokeVertexConstructor, { - fn add_stroke_vertex( - &mut self, - v: StrokeVertex, - ) -> Result { + fn add_stroke_vertex(&mut self, v: StrokeVertex) -> Result { self.buffers .vertices .push(self.vertex_constructor.new_vertex(v)); @@ -525,10 +523,7 @@ impl GeometryBuilder for NoOutput { } impl FillGeometryBuilder for NoOutput { - fn add_fill_vertex( - &mut self, - _vertex: FillVertex, - ) -> Result { + fn add_fill_vertex(&mut self, _vertex: FillVertex) -> Result { if self.count.vertices >= std::u32::MAX { return Err(GeometryBuilderError::TooManyVertices); } @@ -538,10 +533,7 @@ impl FillGeometryBuilder for NoOutput { } impl StrokeGeometryBuilder for NoOutput { - fn add_stroke_vertex( - &mut self, - _: StrokeVertex, - ) -> Result { + fn add_stroke_vertex(&mut self, _: StrokeVertex) -> Result { if self.count.vertices >= std::u32::MAX { return Err(GeometryBuilderError::TooManyVertices); } diff --git a/tessellation/src/lib.rs b/tessellation/src/lib.rs index 6428e89b..44948518 100644 --- a/tessellation/src/lib.rs +++ b/tessellation/src/lib.rs @@ -218,9 +218,8 @@ pub use crate::stroke::*; #[doc(inline)] pub use crate::geometry_builder::{ - BuffersBuilder, Count, FillGeometryBuilder, - FillVertexConstructor, GeometryBuilder, GeometryBuilderError, - StrokeGeometryBuilder, StrokeVertexConstructor, VertexBuffers, + BuffersBuilder, Count, FillGeometryBuilder, FillVertexConstructor, GeometryBuilder, + GeometryBuilderError, StrokeGeometryBuilder, StrokeVertexConstructor, VertexBuffers, }; pub use crate::path::FillRule; @@ -738,7 +737,7 @@ fn test_with_invalid_miter_limit() { #[test] fn test_line_width() { - use crate::math::{Point, point}; + use crate::math::{point, Point}; let mut builder = crate::path::Path::builder(); builder.begin(point(0.0, 1.0)); builder.line_to(point(2.0, 1.0)); @@ -747,20 +746,20 @@ fn test_line_width() { let options = StrokeOptions::DEFAULT.with_line_width(2.0); let mut geometry: VertexBuffers = VertexBuffers::new(); - StrokeTessellator::new().tessellate( - path.iter(), - &options, - &mut crate::geometry_builder::simple_builder(&mut geometry), - ).unwrap(); - + StrokeTessellator::new() + .tessellate( + path.iter(), + &options, + &mut crate::geometry_builder::simple_builder(&mut geometry), + ) + .unwrap(); for p in &geometry.vertices { assert!( *p == point(0.0, 0.0) - || *p == point(0.0, 2.0) - || *p == point(2.0, 0.0) - || *p == point(2.0, 2.0) + || *p == point(0.0, 2.0) + || *p == point(2.0, 0.0) + || *p == point(2.0, 2.0) ); } } - diff --git a/tessellation/src/monotone.rs b/tessellation/src/monotone.rs index 84bb394f..6fd87430 100644 --- a/tessellation/src/monotone.rs +++ b/tessellation/src/monotone.rs @@ -1,7 +1,7 @@ -use crate::math::{Point, point}; +use crate::fill::is_after; +use crate::math::{point, Point}; use crate::Side; use crate::{FillGeometryBuilder, VertexId}; -use crate::fill::is_after; /// Helper class that generates a triangulation from a sequence of vertices describing a monotone /// polygon (used internally by the `FillTessellator`). @@ -187,7 +187,6 @@ fn test_monotone_tess() { println!(" ------------ "); } - struct SideEvents { // We decide whether we have to flush a convex vertex chain based on // whether the two sides are far apart. reference_point.x contains the @@ -261,19 +260,33 @@ impl AdvancedMonotoneTessellator { self.left.events.clear(); self.right.events.clear(); - self.left.push(MonotoneVertex { pos, id, side: Side::Left }); - self.right.push(MonotoneVertex { pos, id, side: Side::Right }); + self.left.push(MonotoneVertex { + pos, + id, + side: Side::Left, + }); + self.right.push(MonotoneVertex { + pos, + id, + side: Side::Right, + }); } pub fn vertex(&mut self, pos: Point, id: VertexId, side: Side) { match side { Side::Left => { self.left.reference_point.x = self.left.reference_point.x.max(pos.x); - self.left.conservative_reference_x = self.left.conservative_reference_x.max(self.left.reference_point.x); + self.left.conservative_reference_x = self + .left + .conservative_reference_x + .max(self.left.reference_point.x); } Side::Right => { self.right.reference_point.x = self.right.reference_point.x.min(pos.x); - self.right.conservative_reference_x = self.right.conservative_reference_x.min(self.right.reference_point.x); + self.right.conservative_reference_x = self + .right + .conservative_reference_x + .min(self.right.reference_point.x); } } @@ -347,7 +360,11 @@ impl AdvancedMonotoneTessellator { } #[inline(never)] -fn flush_side(side: &mut SideEvents, s: Side, tess: &mut BasicMonotoneTessellator) -> Option { +fn flush_side( + side: &mut SideEvents, + s: Side, + tess: &mut BasicMonotoneTessellator, +) -> Option { let len = side.events.len(); if len < 2 { return None; @@ -357,18 +374,14 @@ fn flush_side(side: &mut SideEvents, s: Side, tess: &mut BasicMonotoneTessellato while step * 2 < len { let mut last_index = 0; let imax = (len - 1) / (2 * step); - for i in 0 .. imax { + for i in 0..imax { let mut a = i * 2 * step; let mut b = a + step; last_index = b + step; if s == Side::Right { std::mem::swap(&mut a, &mut b); } - tess.push_triangle_ids( - side.events[a], - side.events[b], - side.events[last_index], - ); + tess.push_triangle_ids(side.events[a], side.events[b], side.events[last_index]); } if last_index + step < len { @@ -378,11 +391,7 @@ fn flush_side(side: &mut SideEvents, s: Side, tess: &mut BasicMonotoneTessellato std::mem::swap(&mut b, &mut c); } - tess.push_triangle_ids( - side.events[0], - side.events[b], - side.events[c], - ); + tess.push_triangle_ids(side.events[0], side.events[b], side.events[c]); } step *= 2; @@ -395,5 +404,4 @@ fn flush_side(side: &mut SideEvents, s: Side, tess: &mut BasicMonotoneTessellato Some(side.last) } - pub type MonotoneTessellator = AdvancedMonotoneTessellator; diff --git a/tessellation/src/stroke.rs b/tessellation/src/stroke.rs index 94e869bd..a4ddf354 100644 --- a/tessellation/src/stroke.rs +++ b/tessellation/src/stroke.rs @@ -1,16 +1,17 @@ -use crate::math::*; use crate::geom::utils::{directed_angle, normalized_tangent, tangent}; -use crate::geom::{CubicBezierSegment, QuadraticBezierSegment, Line, LineSegment}; +use crate::geom::{CubicBezierSegment, Line, LineSegment, QuadraticBezierSegment}; +use crate::math::*; use crate::math_utils::compute_normal; use crate::path::builder::{Build, PathBuilder}; -use crate::path::private::DebugValidator; -use crate::path::{AttributeStore, EndpointId, IdEvent, PathEvent, PathSlice, PositionStore, Winding}; use crate::path::polygon::Polygon; -use crate::{StrokeGeometryBuilder, VertexId}; +use crate::path::private::DebugValidator; +use crate::path::{ + AttributeStore, EndpointId, IdEvent, PathEvent, PathSlice, PositionStore, Winding, +}; use crate::{ - LineCap, LineJoin, Side, StrokeOptions, TessellationError, TessellationResult, - VertexSource, + LineCap, LineJoin, Side, StrokeOptions, TessellationError, TessellationResult, VertexSource, }; +use crate::{StrokeGeometryBuilder, VertexId}; use std::f32::consts::PI; const EPSILON: f32 = 1e-4; @@ -127,12 +128,8 @@ impl StrokeTessellator { builder: &mut dyn StrokeGeometryBuilder, ) -> TessellationResult { let custom_attributes = custom_attributes.unwrap_or(&()); - let mut stroker = StrokeBuilder::new( - options, - custom_attributes, - &mut self.attrib_buffer, - builder, - ); + let mut stroker = + StrokeBuilder::new(options, custom_attributes, &mut self.attrib_buffer, builder); stroker.tessellate_with_ids(path, positions); @@ -210,11 +207,7 @@ impl StrokeTessellator { options: &StrokeOptions, output: &mut dyn StrokeGeometryBuilder, ) -> TessellationResult { - self.tessellate( - polygon.path_events(), - options, - output, - ) + self.tessellate(polygon.path_events(), options, output) } /// Tessellate the stroke for an axis-aligned rectangle. @@ -616,28 +609,36 @@ impl<'l> StrokeBuilder<'l> { self.sub_path_start_length = self.length; } - fn tessellate_empty_square_cap(&mut self) -> Result<(), TessellationError> { + fn tessellate_empty_square_cap(&mut self) -> Result<(), TessellationError> { self.attributes.position_on_path = self.current; self.attributes.normal = vector(1.0, 1.0); self.attributes.side = Side::Right; - let a = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let a = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.attributes.normal = vector(1.0, -1.0); self.attributes.side = Side::Left; - let b = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let b = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.attributes.normal = vector(-1.0, -1.0); self.attributes.side = Side::Left; - let c = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let c = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.attributes.normal = vector(-1.0, 1.0); self.attributes.side = Side::Right; - let d = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let d = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.output.add_triangle(a, b, c); self.output.add_triangle(a, c, d); @@ -652,12 +653,16 @@ impl<'l> StrokeBuilder<'l> { self.attributes.normal = vector(-1.0, 0.0); self.attributes.side = Side::Left; - let left_id = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let left_id = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.attributes.normal = vector(1.0, 0.0); self.attributes.side = Side::Right; - let right_id = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let right_id = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.tessellate_round_cap(center, vector(0.0, -1.0), left_id, right_id, true)?; self.tessellate_round_cap(center, vector(0.0, 1.0), left_id, right_id, false) @@ -737,12 +742,16 @@ impl<'l> StrokeBuilder<'l> { self.attributes.normal = n1; self.attributes.side = Side::Left; - let first_left_id = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let first_left_id = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.attributes.normal = n2; self.attributes.side = Side::Right; - let first_right_id = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let first_right_id = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; if self.options.start_cap == LineCap::Round { self.tessellate_round_cap(first, d, first_left_id, first_right_id, true)?; @@ -785,19 +794,14 @@ impl<'l> StrokeBuilder<'l> { LineJoin::Miter }; - let ( - start_left_id, - start_right_id, - end_left_id, - end_right_id, - front_side - ) = match self.tessellate_join(previous_edge, next_edge, join_type) { - Ok(value) => value, - Err(e) => { - self.error(e); - return; - } - }; + let (start_left_id, start_right_id, end_left_id, end_right_id, front_side) = + match self.tessellate_join(previous_edge, next_edge, join_type) { + Ok(value) => value, + Err(e) => { + self.error(e); + return; + } + }; debug_assert!(end_left_id != end_right_id); @@ -810,11 +814,8 @@ impl<'l> StrokeBuilder<'l> { self.previous_left_id, start_right_id, ); - self.output.add_triangle( - self.previous_left_id, - start_left_id, - start_right_id, - ); + self.output + .add_triangle(self.previous_left_id, start_left_id, start_right_id); } Side::Right => { self.output.add_triangle( @@ -822,11 +823,8 @@ impl<'l> StrokeBuilder<'l> { self.previous_left_id, start_left_id, ); - self.output.add_triangle( - self.previous_right_id, - start_left_id, - start_right_id, - ); + self.output + .add_triangle(self.previous_right_id, start_left_id, start_right_id); } } } @@ -880,7 +878,9 @@ impl<'l> StrokeBuilder<'l> { self.attributes.normal = dir; self.attributes.side = Side::Left; - let mid_vertex = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let mid_vertex = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; let (v1, v2, v3) = if is_start { (left, right, mid_vertex) @@ -901,7 +901,7 @@ impl<'l> StrokeBuilder<'l> { &mut self.attributes, self.output, )?; - + tess_round_cap( center, (mid_angle, right_angle), @@ -949,8 +949,10 @@ impl<'l> StrokeBuilder<'l> { self.attributes.normal = -front_normal; self.attributes.side = front_side.opposite(); - let back_vertex = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; - + let back_vertex = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + Ok(Some(back_vertex)) } @@ -1008,27 +1010,26 @@ impl<'l> StrokeBuilder<'l> { // TODO: the 0.95 threshold above is completely arbitrary and needs // adjustments. join_type = LineJoin::Miter; - } else if join_type == LineJoin::Miter && (self.miter_limit_is_exceeded(normal) || back_vertex.is_none()) { + } else if join_type == LineJoin::Miter + && (self.miter_limit_is_exceeded(normal) || back_vertex.is_none()) + { // Per SVG spec: If the stroke-miterlimit is exceeded, the line join // falls back to bevel. join_type = LineJoin::Bevel; - } else if join_type == LineJoin::MiterClip && back_vertex.is_some() && !self.miter_limit_is_exceeded(normal) { + } else if join_type == LineJoin::MiterClip + && back_vertex.is_some() + && !self.miter_limit_is_exceeded(normal) + { join_type = LineJoin::Miter; } let (front_start_vertex, front_end_vertex) = match join_type { - LineJoin::Round => self.tessellate_round_join( - prev_tangent, - next_tangent, - front_side, - back_vertex, - )?, - LineJoin::Bevel => self.tessellate_bevel_join( - prev_tangent, - next_tangent, - front_side, - back_vertex, - )?, + LineJoin::Round => { + self.tessellate_round_join(prev_tangent, next_tangent, front_side, back_vertex)? + } + LineJoin::Bevel => { + self.tessellate_bevel_join(prev_tangent, next_tangent, front_side, back_vertex)? + } LineJoin::MiterClip => self.tessellate_miter_clip_join( prev_tangent, next_tangent, @@ -1039,7 +1040,9 @@ impl<'l> StrokeBuilder<'l> { LineJoin::Miter => { self.attributes.normal = front_normal; self.attributes.side = front_side; - let front_vertex = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let front_vertex = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.previous_normal = normal; debug_assert!(back_vertex.is_some()); @@ -1057,13 +1060,7 @@ impl<'l> StrokeBuilder<'l> { std::mem::swap(&mut end_0, &mut end_1); } - Ok(( - start_0, - start_1, - end_0, - end_1, - front_side, - )) + Ok((start_0, start_1, end_0, end_1, front_side)) } fn tessellate_bevel_join( @@ -1080,12 +1077,16 @@ impl<'l> StrokeBuilder<'l> { self.attributes.normal = previous_normal * neg_if_right; self.attributes.side = front_side; - let front_start_vertex = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let front_start_vertex = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.attributes.normal = next_normal * neg_if_right; self.attributes.side = front_side; - let front_end_vertex = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let front_end_vertex = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.previous_normal = next_normal; @@ -1130,10 +1131,14 @@ impl<'l> StrokeBuilder<'l> { self.attributes.side = front_side; self.attributes.normal = start_normal; - let front_start_vertex = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let front_start_vertex = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.attributes.normal = end_normal; - let front_end_vertex = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let front_end_vertex = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; // Add the triangle joining the back vertex and the start/end front vertices. if let Some(back_vertex) = back_vertex { @@ -1179,12 +1184,16 @@ impl<'l> StrokeBuilder<'l> { self.attributes.normal = v1 * neg_if_right; self.attributes.side = front_side; - let front_start_vertex = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let front_start_vertex = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.attributes.normal = v2 * neg_if_right; self.attributes.side = front_side; - let front_end_vertex = self.output.add_stroke_vertex(StrokeVertex(&mut self.attributes))?; + let front_end_vertex = self + .output + .add_stroke_vertex(StrokeVertex(&mut self.attributes))?; self.previous_normal = normal; @@ -1211,7 +1220,7 @@ impl<'l> StrokeBuilder<'l> { normal: Vector, ) -> (Vector, Vector) { let clip_line = Line { - point: normal.normalize().to_point() * self.options.miter_limit * 0.5, + point: normal.normalize().to_point() * self.options.miter_limit * 0.5, vector: tangent(normal), }; @@ -1261,8 +1270,7 @@ fn tess_round_cap( attributes.normal = normal; attributes.side = side; - let vertex = - output.add_stroke_vertex(StrokeVertex(attributes))?; + let vertex = output.add_stroke_vertex(StrokeVertex(attributes))?; let (v1, v2, v3) = if invert_winding { (vertex, vb, va) @@ -1302,7 +1310,6 @@ fn tess_round_cap( // line width in any dimension. #[inline(never)] fn approximate_thin_rectangle(builder: &mut StrokeBuilder, rect: &Rect) { - let (from, to, d) = if rect.size.width > rect.size.height { let d = rect.size.height * 0.5; let min_x = rect.min_x() + d; @@ -1629,10 +1636,7 @@ fn test_too_many_vertices() { } impl StrokeGeometryBuilder for Builder { - fn add_stroke_vertex( - &mut self, - _: StrokeVertex, - ) -> Result { + fn add_stroke_vertex(&mut self, _: StrokeVertex) -> Result { if self.max_vertices == 0 { return Err(GeometryBuilderError::TooManyVertices); }