From c8bbb71dd4e01434a183af7bf07ee1409e7da3d2 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 11 Jan 2019 14:21:02 -0800 Subject: [PATCH] Migrate the monotonic conversion iterator away from Euclid types --- utils/tile-svg/src/main.rs | 118 +++++++++---------------------------- 1 file changed, 29 insertions(+), 89 deletions(-) diff --git a/utils/tile-svg/src/main.rs b/utils/tile-svg/src/main.rs index 73197ad2..097d671f 100644 --- a/utils/tile-svg/src/main.rs +++ b/utils/tile-svg/src/main.rs @@ -235,8 +235,8 @@ impl Scene { let path = UsvgPathToSegments::new(path.segments.iter().cloned()); let path = PathTransformingIter::new(path, &transform); - let path = SegmentsToPathEvents::new(path); let path = MonotonicConversionIter::new(path); + let path = SegmentsToPathEvents::new(path); let outline = Outline::from_path_events(path); scene.bounds = scene.bounds.union(&outline.bounds); @@ -257,8 +257,8 @@ impl Scene { let path = StrokeToFillIter::new(path, StrokeStyle::new(stroke_width)); let path = PathEventsToSegments::new(path); let path = PathTransformingIter::new(path, &transform); - let path = SegmentsToPathEvents::new(path); let path = MonotonicConversionIter::new(path); + let path = SegmentsToPathEvents::new(path); let outline = Outline::from_path_events(path); scene.bounds = scene.bounds.union(&outline.bounds); @@ -838,12 +838,12 @@ impl<'s> CubicSegment<'s> { baseline: LineSegmentF32(baseline0), ctrl: LineSegmentF32(ctrl0), kind: SegmentKind::Cubic, - flags: SegmentFlags::empty(), + flags: self.0.flags & SegmentFlags::FIRST_IN_SUBPATH, }, Segment { baseline: LineSegmentF32(baseline1), ctrl: LineSegmentF32(ctrl1), kind: SegmentKind::Cubic, - flags: SegmentFlags::empty(), + flags: self.0.flags & SegmentFlags::CLOSES_SUBPATH, }) } @@ -1971,112 +1971,52 @@ impl PathTransformingIter where I: Iterator { // Monotonic conversion utilities // TODO(pcwalton): I think we only need to be monotonic in Y, maybe? -struct MonotonicConversionIter where I: Iterator { - inner: I, - buffer: ArrayVec<[PathEvent; 2]>, - last_point: Point2D, +struct MonotonicConversionIter where I: Iterator { + iter: I, + buffer: ArrayVec<[Segment; 2]>, } -impl Iterator for MonotonicConversionIter where I: Iterator { - type Item = PathEvent; +impl Iterator for MonotonicConversionIter where I: Iterator { + type Item = Segment; - fn next(&mut self) -> Option { - if let Some(event) = self.buffer.pop() { - match event { - PathEvent::MoveTo(to) | - PathEvent::LineTo(to) | - PathEvent::QuadraticTo(_, to) | - PathEvent::CubicTo(_, _, to) => { - self.last_point = to; - } - PathEvent::Arc(..) | PathEvent::Close => {} - } - return Some(event); + fn next(&mut self) -> Option { + if let Some(segment) = self.buffer.pop() { + return Some(segment); } - let event = match self.inner.next() { - None => return None, - Some(event) => event, - }; - - match event { - PathEvent::MoveTo(to) => { - self.last_point = to; - Some(PathEvent::MoveTo(to)) - } - PathEvent::LineTo(to) => { - self.last_point = to; - Some(PathEvent::LineTo(to)) - } - PathEvent::CubicTo(ctrl0, ctrl1, to) => { - let mut segment = Segment::none(); - segment.baseline = LineSegmentF32::new(&Point2DF32::from_euclid(self.last_point), - &Point2DF32::from_euclid(to)); - segment.ctrl = LineSegmentF32::new(&Point2DF32::from_euclid(ctrl0), - &Point2DF32::from_euclid(ctrl1)); - segment.kind = SegmentKind::Cubic; - return self.handle_cubic(&segment); - } - PathEvent::QuadraticTo(ctrl, to) => { + let segment = self.iter.next()?; + match segment.kind { + SegmentKind::None => self.next(), + SegmentKind::Line => Some(segment), + SegmentKind::Cubic => self.handle_cubic(&segment), + SegmentKind::Quadratic => { // TODO(pcwalton): Don't degree elevate! - let mut segment = Segment::none(); - segment.baseline = LineSegmentF32::new(&Point2DF32::from_euclid(self.last_point), - &Point2DF32::from_euclid(to)); - segment.ctrl = LineSegmentF32::new(&Point2DF32::from_euclid(ctrl), - &Point2DF32::default()); - segment.kind = SegmentKind::Quadratic; - return self.handle_cubic(&segment.to_cubic()); - } - PathEvent::Close => Some(PathEvent::Close), - PathEvent::Arc(a, b, c, d) => { - // FIXME(pcwalton): Make these monotonic too. - Some(PathEvent::Arc(a, b, c, d)) + self.handle_cubic(&segment.to_cubic()) } } } } -impl MonotonicConversionIter where I: Iterator { - fn new(inner: I) -> MonotonicConversionIter { - MonotonicConversionIter { - inner, - buffer: ArrayVec::new(), - last_point: Point2D::zero(), - } +impl MonotonicConversionIter where I: Iterator { + fn new(iter: I) -> MonotonicConversionIter { + MonotonicConversionIter { iter, buffer: ArrayVec::new() } } - fn handle_cubic(&mut self, segment: &Segment) -> Option { + fn handle_cubic(&mut self, segment: &Segment) -> Option { match segment.as_cubic_segment().y_extrema() { (Some(t0), Some(t1)) => { let (segments_01, segment_2) = segment.as_cubic_segment().split(t1); - self.buffer.push(PathEvent::CubicTo(segment_2.ctrl.from().as_euclid(), - segment_2.ctrl.to().as_euclid(), - segment_2.baseline.to().as_euclid())); + self.buffer.push(segment_2); let (segment_0, segment_1) = segments_01.as_cubic_segment().split(t0 / t1); - self.buffer.push(PathEvent::CubicTo(segment_1.ctrl.from().as_euclid(), - segment_1.ctrl.to().as_euclid(), - segment_1.baseline.to().as_euclid())); - self.last_point = segment_0.baseline.to().as_euclid(); - return Some(PathEvent::CubicTo(segment_0.ctrl.from().as_euclid(), - segment_0.ctrl.to().as_euclid(), - segment_0.baseline.to().as_euclid())); + self.buffer.push(segment_1); + Some(segment_0) } (Some(t0), None) | (None, Some(t0)) => { let (segment_0, segment_1) = segment.as_cubic_segment().split(t0); - self.buffer.push(PathEvent::CubicTo(segment_1.ctrl.from().as_euclid(), - segment_1.ctrl.to().as_euclid(), - segment_1.baseline.to().as_euclid())); - self.last_point = segment_0.baseline.to().as_euclid(); - return Some(PathEvent::CubicTo(segment_0.ctrl.from().as_euclid(), - segment_0.ctrl.to().as_euclid(), - segment_0.baseline.to().as_euclid())); - } - (None, None) => { - self.last_point = segment.baseline.to().as_euclid(); - return Some(PathEvent::CubicTo(segment.ctrl.from().as_euclid(), - segment.ctrl.to().as_euclid(), - segment.baseline.to().as_euclid())); + self.buffer.push(segment_1); + Some(segment_0) } + (None, None) => Some(*segment), } } }