diff options
author | Evgeniy Reizner <razrfalcon@gmail.com> | 2019-05-26 23:45:22 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-26 23:45:22 +0300 |
commit | 01582324f464890976cacb1e4703c4a513f9f283 (patch) | |
tree | 88ba1d0399d96511ce3df78b1a2e69d6f9271be4 /src/utils.rs | |
parent | d6c1553384964510c1e8225fb328762c35f2b89d (diff) |
New text layout.
Closes #89, Closes #90, Closes #92, Closes #95, Closes #96, Closes #103, Closes #109, Closes #122
Diffstat (limited to 'src/utils.rs')
-rw-r--r-- | src/utils.rs | 230 |
1 files changed, 0 insertions, 230 deletions
diff --git a/src/utils.rs b/src/utils.rs index bbc5d3c..46303d6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -69,233 +69,3 @@ pub fn abs_transform( root_ts } - -/// Calculates path's bounding box. -/// -/// Width and/or height can be zero. -pub fn path_bbox( - segments: &[usvg::PathSegment], - stroke: Option<&usvg::Stroke>, - ts: Option<usvg::Transform>, -) -> Option<Rect> { - debug_assert!(!segments.is_empty()); - - let ts = match ts { - Some(ts) => ts, - None => usvg::Transform::default(), - }; - - use crate::lyon_geom; - - let mut prev_x = 0.0; - let mut prev_y = 0.0; - let mut minx = 0.0; - let mut miny = 0.0; - let mut maxx = 0.0; - let mut maxy = 0.0; - - if let Some(usvg::PathSegment::MoveTo { x, y }) = TransformedPath::new(segments, ts).next() { - let x = x as f32; - let y = y as f32; - - prev_x = x; - prev_y = y; - minx = x; - miny = y; - maxx = x; - maxy = y; - } - - for seg in TransformedPath::new(segments, ts) { - match seg { - usvg::PathSegment::MoveTo { x, y } - | usvg::PathSegment::LineTo { x, y } => { - let x = x as f32; - let y = y as f32; - prev_x = x; - prev_y = y; - - if x > maxx { maxx = x; } - else if x < minx { minx = x; } - - if y > maxy { maxy = y; } - else if y < miny { miny = y; } - } - 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), - }; - - prev_x = x; - prev_y = y; - - let r = curve.bounding_rect(); - - let right = r.max_x(); - let bottom = r.max_y(); - if r.min_x() < minx { minx = r.min_x(); } - if right > maxx { maxx = right; } - if r.min_y() < miny { miny = r.min_y(); } - if bottom > maxy { maxy = bottom; } - } - usvg::PathSegment::ClosePath => {} - } - } - - // TODO: find a better way - // It's an approximation, but it's better than nothing. - if let Some(ref stroke) = stroke { - let w = (stroke.width.value() / 2.0) as f32; - minx -= w; - miny -= w; - maxx += w; - maxy += w; - } - - let width = maxx - minx; - let height = maxy - miny; - - Rect::new(minx as f64, miny as f64, width as f64, height as f64) -} - -/// 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 crate::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 { - match *seg { - usvg::PathSegment::MoveTo { ref mut x, ref mut y } => { - ts.apply_to(x, y); - } - usvg::PathSegment::LineTo { ref mut x, ref mut y } => { - ts.apply_to(x, y); - } - usvg::PathSegment::CurveTo { ref mut x1, ref mut y1, ref mut x2, - ref mut y2, ref mut x, ref mut y } => { - ts.apply_to(x1, y1); - ts.apply_to(x2, y2); - ts.apply_to(x, y); - } - usvg::PathSegment::ClosePath => {} - } - } -} - - -/// An iterator over transformed path segments. -pub struct TransformedPath<'a> { - segments: &'a [usvg::PathSegment], - ts: usvg::Transform, - idx: usize, -} - -impl<'a> TransformedPath<'a> { - /// Creates a new `TransformedPath` iterator. - pub fn new(segments: &'a [usvg::PathSegment], ts: usvg::Transform) -> Self { - TransformedPath { segments, ts, idx: 0 } - } -} - -impl<'a> Iterator for TransformedPath<'a> { - type Item = usvg::PathSegment; - - fn next(&mut self) -> Option<Self::Item> { - if self.idx == self.segments.len() { - return None; - } - - if self.ts.is_default() { - self.idx += 1; - return self.segments.get(self.idx - 1).cloned(); - } - - let seg = match self.segments[self.idx] { - usvg::PathSegment::MoveTo { x, y } => { - let (x, y) = self.ts.apply(x, y); - usvg::PathSegment::MoveTo { x, y } - } - usvg::PathSegment::LineTo { x, y } => { - let (x, y) = self.ts.apply(x, y); - usvg::PathSegment::LineTo { x, y } - } - usvg::PathSegment::CurveTo { x1, y1, x2, y2, x, y } => { - let (x1, y1) = self.ts.apply(x1, y1); - let (x2, y2) = self.ts.apply(x2, y2); - let (x, y) = self.ts.apply(x, y); - usvg::PathSegment::CurveTo { x1, y1, x2, y2, x, y } - } - usvg::PathSegment::ClosePath => usvg::PathSegment::ClosePath, - }; - - self.idx += 1; - - Some(seg) - } -} |