From dcee161f6aed8491b4f8cd8cb2703cb2375afb78 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 14 Jan 2019 11:13:43 -0800 Subject: [PATCH] Move the path transform iterator to the geometry crate --- geometry/src/transform.rs | 55 +++++++++++++++++++++++++++++++++++ utils/tile-svg/src/main.rs | 59 ++------------------------------------ 2 files changed, 58 insertions(+), 56 deletions(-) diff --git a/geometry/src/transform.rs b/geometry/src/transform.rs index 7f802f04..1f7cff0e 100644 --- a/geometry/src/transform.rs +++ b/geometry/src/transform.rs @@ -11,6 +11,7 @@ //! Applies a transform to paths. use crate::point::Point2DF32; +use crate::segment::Segment; use crate::simd::F32x4; use euclid::Transform2D; use lyon_path::PathEvent; @@ -69,6 +70,60 @@ impl Transform2DF32 { } } +/// Transforms a path with a SIMD 2D transform. +pub struct Transform2DF32PathIter +where + I: Iterator, +{ + iter: I, + transform: Transform2DF32, +} + +impl Iterator for Transform2DF32PathIter +where + I: Iterator, +{ + type Item = Segment; + + #[inline] + fn next(&mut self) -> Option { + // TODO(pcwalton): Can we go faster by transforming an entire line segment with SIMD? + let mut segment = self.iter.next()?; + if !segment.is_none() { + segment + .baseline + .set_from(&self.transform.transform_point(&segment.baseline.from())); + segment + .baseline + .set_to(&self.transform.transform_point(&segment.baseline.to())); + if !segment.is_line() { + segment + .ctrl + .set_from(&self.transform.transform_point(&segment.ctrl.from())); + if !segment.is_quadratic() { + segment + .ctrl + .set_to(&self.transform.transform_point(&segment.ctrl.to())); + } + } + } + Some(segment) + } +} + +impl Transform2DF32PathIter +where + I: Iterator, +{ + #[inline] + pub fn new(iter: I, transform: &Transform2DF32) -> Transform2DF32PathIter { + Transform2DF32PathIter { + iter, + transform: *transform, + } + } +} + /// Transforms a path with a Euclid 2D transform. pub struct Transform2DPathIter where I: Iterator { inner: I, diff --git a/utils/tile-svg/src/main.rs b/utils/tile-svg/src/main.rs index fd6ee3b7..8d70a4da 100644 --- a/utils/tile-svg/src/main.rs +++ b/utils/tile-svg/src/main.rs @@ -30,7 +30,7 @@ use pathfinder_geometry::segment::{PathEventsToSegments, Segment, SegmentFlags}; use pathfinder_geometry::segment::{SegmentKind, SegmentsToPathEvents}; use pathfinder_geometry::simd::{F32x4, I32x4}; use pathfinder_geometry::stroke::{StrokeStyle, StrokeToFillIter}; -use pathfinder_geometry::transform::Transform2DF32; +use pathfinder_geometry::transform::{Transform2DF32, Transform2DF32PathIter}; use pathfinder_geometry::util; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use rayon::ThreadPoolBuilder; @@ -257,7 +257,7 @@ impl Scene { let style = scene.push_paint(&Paint::from_svg_paint(&fill.paint)); let path = UsvgPathToSegments::new(path.segments.iter().cloned()); - let path = PathTransformingIter::new(path, &transform); + let path = Transform2DF32PathIter::new(path, &transform); let path = MonotonicConversionIter::new(path); let outline = Outline::from_segments(path); @@ -280,7 +280,7 @@ impl Scene { let path = PathIter::new(path); let path = StrokeToFillIter::new(path, StrokeStyle::new(stroke_width)); let path = PathEventsToSegments::new(path); - let path = PathTransformingIter::new(path, &transform); + let path = Transform2DF32PathIter::new(path, &transform); let path = MonotonicConversionIter::new(path); let outline = Outline::from_segments(path); @@ -1362,59 +1362,6 @@ where } } -// Path transformation utilities - -struct PathTransformingIter -where - I: Iterator, -{ - iter: I, - transform: Transform2DF32, -} - -impl Iterator for PathTransformingIter -where - I: Iterator, -{ - type Item = Segment; - - fn next(&mut self) -> Option { - // TODO(pcwalton): Can we go faster by transforming an entire line segment with SIMD? - let mut segment = self.iter.next()?; - if !segment.is_none() { - segment - .baseline - .set_from(&self.transform.transform_point(&segment.baseline.from())); - segment - .baseline - .set_to(&self.transform.transform_point(&segment.baseline.to())); - if !segment.is_line() { - segment - .ctrl - .set_from(&self.transform.transform_point(&segment.ctrl.from())); - if !segment.is_quadratic() { - segment - .ctrl - .set_to(&self.transform.transform_point(&segment.ctrl.to())); - } - } - } - Some(segment) - } -} - -impl PathTransformingIter -where - I: Iterator, -{ - fn new(iter: I, transform: &Transform2DF32) -> PathTransformingIter { - PathTransformingIter { - iter, - transform: *transform, - } - } -} - // Monotonic conversion utilities // TODO(pcwalton): I think we only need to be monotonic in Y, maybe?