From eabe1b239d75e95508cf470a57d0017ef3a9540f Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 23 Jun 2020 13:01:50 -0700 Subject: [PATCH] Update `pathfinder_content` --- content/src/outline.rs | 5 +++ content/src/segment.rs | 80 +----------------------------------------- 2 files changed, 6 insertions(+), 79 deletions(-) diff --git a/content/src/outline.rs b/content/src/outline.rs index 8cb4f229..f5bbd58c 100644 --- a/content/src/outline.rs +++ b/content/src/outline.rs @@ -333,6 +333,11 @@ impl Contour { self.points[self.points.len() - index as usize] } + #[inline] + pub fn flags_of(&self, index: u32) -> PointFlags { + self.flags[index as usize] + } + #[inline] pub fn push_endpoint(&mut self, point: Vector2F) { self.push_point(point, PointFlags::empty(), true); diff --git a/content/src/segment.rs b/content/src/segment.rs index 3c607f79..1c2b1c1b 100644 --- a/content/src/segment.rs +++ b/content/src/segment.rs @@ -12,13 +12,11 @@ use pathfinder_geometry::line_segment::LineSegment2F; use pathfinder_geometry::transform2d::Transform2F; -use pathfinder_geometry::util::{self, EPSILON}; +use pathfinder_geometry::util::EPSILON; use pathfinder_geometry::vector::{Vector2F, vec2f}; use pathfinder_simd::default::F32x4; use std::f32::consts::SQRT_2; -const MAX_NEWTON_ITERATIONS: u32 = 32; - #[derive(Clone, Copy, Debug, PartialEq)] pub struct Segment { pub baseline: LineSegment2F, @@ -155,16 +153,6 @@ impl Segment { new_segment } - #[inline] - pub fn is_monotonic(&self) -> bool { - // FIXME(pcwalton): Don't degree elevate! - match self.kind { - SegmentKind::None | SegmentKind::Line => true, - SegmentKind::Quadratic => self.to_cubic().as_cubic_segment().is_monotonic(), - SegmentKind::Cubic => self.as_cubic_segment().is_monotonic(), - } - } - #[inline] pub fn reversed(&self) -> Segment { Segment { @@ -341,72 +329,6 @@ impl<'s> CubicSegment<'s> { self.split(t).0.baseline.to() } - #[inline] - pub fn is_monotonic(self) -> bool { - // TODO(pcwalton): Optimize this. - let (p0, p3) = (self.0.baseline.from_y(), self.0.baseline.to_y()); - let (p1, p2) = (self.0.ctrl.from_y(), self.0.ctrl.to_y()); - (p0 <= p1 && p1 <= p2 && p2 <= p3) || (p0 >= p1 && p1 >= p2 && p2 >= p3) - } - - #[inline] - pub fn y_extrema(self) -> (Option, Option) { - if self.is_monotonic() { - return (None, None); - } - - let p0p1p2p3 = F32x4::new( - self.0.baseline.from_y(), - self.0.ctrl.from_y(), - self.0.ctrl.to_y(), - self.0.baseline.to_y(), - ); - - let pxp0p1p2 = p0p1p2p3.wxyz(); - let pxv0v1v2 = p0p1p2p3 - pxp0p1p2; - let (v0, v1, v2) = (pxv0v1v2[1], pxv0v1v2[2], pxv0v1v2[3]); - - let (t0, t1); - let (v0_to_v1, v2_to_v1) = (v0 - v1, v2 - v1); - let denom = v0_to_v1 + v2_to_v1; - - if util::approx_eq(denom, 0.0) { - // Let's not divide by zero (issue #146). Fall back to Newton's method. - // FIXME(pcwalton): Can we have two roots here? - let mut t = 0.5; - for _ in 0..MAX_NEWTON_ITERATIONS { - let dydt = 3.0 * ((denom * t - v0_to_v1 - v0_to_v1) * t + v0); - if f32::abs(dydt) <= EPSILON { - break - } - let d2ydt2 = 6.0 * (denom * t - v0_to_v1); - t -= dydt / d2ydt2; - } - t0 = t; - t1 = 0.0; - debug!("... t=(newton) {}", t); - } else { - // Algebraically compute the values for t. - let discrim = f32::sqrt(v1 * v1 - v0 * v2); - let denom_recip = 1.0 / denom; - - t0 = (v0_to_v1 + discrim) * denom_recip; - t1 = (v0_to_v1 - discrim) * denom_recip; - - debug!("... t=({} +/- {})/{} t0={} t1={}", v0_to_v1, discrim, denom, t0, t1); - } - - return match ( - t0 > EPSILON && t0 < 1.0 - EPSILON, - t1 > EPSILON && t1 < 1.0 - EPSILON, - ) { - (false, false) => (None, None), - (true, false) => (Some(t0), None), - (false, true) => (Some(t1), None), - (true, true) => (Some(f32::min(t0, t1)), Some(f32::max(t0, t1))), - }; - } - #[inline] pub fn min_x(&self) -> f32 { f32::min(self.0.baseline.min_x(), self.0.ctrl.min_x())