diff options
author | RazrFalcon <razrfalcon@gmail.com> | 2018-11-07 20:03:06 +0200 |
---|---|---|
committer | RazrFalcon <razrfalcon@gmail.com> | 2018-11-07 20:03:06 +0200 |
commit | f5c28ec82fe7d762ac4538808da4cc7862b61248 (patch) | |
tree | 413cfef37075def5813328960be9dfd9eb29162a /src/utils.rs | |
parent | 244f30fec7c1233e063616fc436b8125c074029e (diff) |
(cairo-backend) Fixed rendering of a zero length subpath with a square cap.
Diffstat (limited to 'src/utils.rs')
-rw-r--r-- | src/utils.rs | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/utils.rs b/src/utils.rs index d27e243..d9bc440 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -160,6 +160,69 @@ pub fn path_bbox( (minx as f64, miny as f64, width as f64, height as f64).into() } +/// Calculates path's length. +/// +/// Length from the first segment to the first MoveTo, ClosePath or slice end. +pub fn path_length(segments: &[usvg::PathSegment]) -> f64 { + debug_assert!(!segments.is_empty()); + + use lyon_geom; + + let (mut prev_x, mut prev_y) = { + if let usvg::PathSegment::MoveTo { x, y } = segments[0] { + (x as f32, y as f32) + } else { + panic!("first segment must be MoveTo"); + } + }; + + let start_x = prev_x; + let start_y = prev_y; + + let mut is_first_seg = true; + let mut length = 0.0f64; + for seg in segments { + match *seg { + usvg::PathSegment::MoveTo { .. } => { + if !is_first_seg { + break; + } + } + usvg::PathSegment::LineTo { x, y } => { + length += Line::new(prev_x as f64, prev_y as f64, x, y).length(); + + prev_x = x as f32; + prev_y = y as f32; + } + usvg::PathSegment::CurveTo { x1, y1, x2, y2, x, y } => { + let x = x as f32; + let y = y as f32; + + let curve = lyon_geom::CubicBezierSegment { + from: lyon_geom::math::Point::new(prev_x, prev_y), + ctrl1: lyon_geom::math::Point::new(x1 as f32, y1 as f32), + ctrl2: lyon_geom::math::Point::new(x2 as f32, y2 as f32), + to: lyon_geom::math::Point::new(x, y), + }; + + length += curve.approximate_length(1.0) as f64; + + prev_x = x; + prev_y = y; + } + usvg::PathSegment::ClosePath => { + length += Line::new(prev_x as f64, prev_y as f64, + start_x as f64, start_y as f64).length(); + break; + } + } + + is_first_seg = false; + } + + length +} + /// Applies the transform to the path segments. pub fn transform_path(segments: &mut [usvg::PathSegment], ts: &usvg::Transform) { for seg in segments { |