diff --git a/partitionfinder/src/capi.rs b/partitionfinder/src/capi.rs index 73f63742..194e9109 100644 --- a/partitionfinder/src/capi.rs +++ b/partitionfinder/src/capi.rs @@ -7,7 +7,7 @@ use partitioner::Partitioner; use tessellator::{QuadTessLevels, Tessellator}; use std::mem; use std::slice; -use {AntialiasingMode, BQuad, ControlPoints, EdgeInstance, Endpoint, Subpath, Vertex}; +use {AntialiasingMode, BQuad, EdgeInstance, Endpoint, Subpath, Vertex}; #[derive(Clone, Copy)] #[repr(C)] @@ -61,12 +61,13 @@ pub unsafe extern fn pf_legalizer_endpoints(legalizer: *const Legalizer, #[no_mangle] pub unsafe extern fn pf_legalizer_control_points(legalizer: *const Legalizer, out_control_points_count: *mut u32) - -> *const ControlPoints { + -> *const Point2DF32 { let control_points = (*legalizer).control_points(); if !out_control_points_count.is_null() { *out_control_points_count = control_points.len() as u32 } - control_points.as_ptr() + // FIXME(pcwalton): This is unsafe! `Point2D` and `Point2DF32` may have different layouts! + control_points.as_ptr() as *const Point2DF32 } #[no_mangle] @@ -131,12 +132,14 @@ pub unsafe extern fn pf_partitioner_destroy<'a>(partitioner: *mut Partitioner<'a pub unsafe extern fn pf_partitioner_init<'a>(partitioner: *mut Partitioner<'a>, endpoints: *const Endpoint, endpoint_count: u32, - control_points: *const ControlPoints, + control_points: *const Point2DF32, control_points_count: u32, subpaths: *const Subpath, subpath_count: u32) { + // FIXME(pcwalton): This is unsafe! `Point2D` and `Point2DF32` may have different layouts! (*partitioner).init(slice::from_raw_parts(endpoints, endpoint_count as usize), - slice::from_raw_parts(control_points, control_points_count as usize), + slice::from_raw_parts(control_points as *const Point2D, + control_points_count as usize), slice::from_raw_parts(subpaths, subpath_count as usize)) } @@ -161,12 +164,13 @@ pub unsafe extern fn pf_partitioner_b_quads<'a>(partitioner: *mut Partitioner<'a #[no_mangle] pub unsafe extern fn pf_tessellator_new(endpoints: *const Endpoint, endpoint_count: u32, - control_points: *const ControlPoints, + control_points: *const Point2D, control_points_count: u32, b_quads: *const BQuad, b_quad_count: u32, antialiasing_mode: AntialiasingMode) -> *mut Tessellator<'static> { + // FIXME(pcwalton): This is unsafe! `Point2D` and `Point2DF32` may have different layouts! let mut tessellator = Box::new(Tessellator::new(slice::from_raw_parts(endpoints, endpoint_count as usize), slice::from_raw_parts(control_points, diff --git a/partitionfinder/src/geometry.rs b/partitionfinder/src/geometry.rs index b30c572f..edc6488b 100644 --- a/partitionfinder/src/geometry.rs +++ b/partitionfinder/src/geometry.rs @@ -59,61 +59,48 @@ pub fn line_line_crossing_point(a_p0: &Point2D, } // TODO(pcwalton): Implement this. -pub fn line_cubic_bezier_crossing_point(_a_p0: &Point2D, - _a_p1: &Point2D, - _b_p0: &Point2D, - _b_p1: &Point2D, - _b_p2: &Point2D, - _b_p3: &Point2D) +pub fn line_quadratic_bezier_crossing_point(_a_p0: &Point2D, + _a_p1: &Point2D, + _b_p0: &Point2D, + _b_p1: &Point2D, + _b_p2: &Point2D) -> Option> { None } // TODO(pcwalton): Implement this. -pub fn cubic_bezier_cubic_bezier_crossing_point(_a_p0: &Point2D, - _a_p1: &Point2D, - _a_p2: &Point2D, - _a_p3: &Point2D, - _b_p0: &Point2D, - _b_p1: &Point2D, - _b_p2: &Point2D, - _b_p3: &Point2D) - -> Option> { +pub fn quadratic_bezier_quadratic_bezier_crossing_point(_a_p0: &Point2D, + _a_p1: &Point2D, + _a_p2: &Point2D, + _b_p0: &Point2D, + _b_p1: &Point2D, + _b_p2: &Point2D) + -> Option> { None } -fn sample_cubic_bezier(t: f32, - p0: &Point2D, - p1: &Point2D, - p2: &Point2D, - p3: &Point2D) - -> Point2D { - let (p0p1, p1p2, p2p3) = (p0.lerp(*p1, t), p1.lerp(*p2, t), p2.lerp(*p3, t)); - let (p0p1p2, p1p2p3) = (p0p1.lerp(p1p2, t), p1p2.lerp(p2p3, t)); - p0p1p2.lerp(p1p2p3, t) +fn sample_quadratic_bezier(t: f32, p0: &Point2D, p1: &Point2D, p2: &Point2D) + -> Point2D { + p0.lerp(*p1, t).lerp(p1.lerp(*p2, t), t) } -pub fn sample_cubic_bezier_deriv(t: f32, - p0: &Point2D, - p1: &Point2D, - p2: &Point2D, - p3: &Point2D) - -> Vector2D { - // https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves +pub fn sample_quadratic_bezier_deriv(t: f32, + p0: &Point2D, + p1: &Point2D, + p2: &Point2D) + -> Vector2D { + // https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Quadratic_B.C3.A9zier_curves // FIXME(pcwalton): Can this be made faster? - let tt = 1.0 - t; - return (*p1 - *p0) * 3.0 * tt * tt + (*p2 - *p1) * 6.0 * tt * t + (*p3 - *p2) * 3.0 * t * t + return ((*p1 - *p0) * (1.0 - t) + (*p2 - *p1) * t) * 2.0 } -pub fn sample_cubic_bezier_deriv_deriv(t: f32, - p0: &Point2D, - p1: &Point2D, - p2: &Point2D, - p3: &Point2D) - -> Vector2D { - // https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves +pub fn sample_quadratic_bezier_deriv_deriv(p0: &Point2D, + p1: &Point2D, + p2: &Point2D) + -> Vector2D { + // https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Quadratic_B.C3.A9zier_curves // FIXME(pcwalton): Can this be made faster? - (*p2 - *p1 * 2.0 + p0.to_vector()).lerp(*p3 - *p2 * 2.0 + p1.to_vector(), t) * 6.0 + (*p2 - *p1 * 2.0 + p0.to_vector()) * 2.0 } pub fn solve_line_y_for_x(x: f32, a: &Point2D, b: &Point2D) -> f32 { @@ -133,51 +120,45 @@ pub(crate) fn newton_raphson(f: F, dfdx: DFDX, mut x_guess: f32) -> f32 x_guess } -pub fn solve_cubic_bezier_t_for_x(x: f32, - p0: &Point2D, - p1: &Point2D, - p2: &Point2D, - p3: &Point2D) - -> f32 { - newton_raphson(|t| sample_cubic_bezier(t, p0, p1, p2, p3).x - x, - |t| sample_cubic_bezier_deriv(t, p0, p1, p2, p3).x, +pub fn solve_quadratic_bezier_t_for_x(x: f32, + p0: &Point2D, + p1: &Point2D, + p2: &Point2D) + -> f32 { + // TODO(pcwalton): Use the quadratic equation instead. + newton_raphson(|t| sample_quadratic_bezier(t, p0, p1, p2).x - x, + |t| sample_quadratic_bezier_deriv(t, p0, p1, p2).x, 0.5) } -pub fn solve_cubic_bezier_y_for_x(x: f32, - p0: &Point2D, - p1: &Point2D, - p2: &Point2D, - p3: &Point2D) - -> f32 { - sample_cubic_bezier(solve_cubic_bezier_t_for_x(x, p0, p1, p2, p3), p0, p1, p2, p3).y +pub fn solve_quadratic_bezier_y_for_x(x: f32, + p0: &Point2D, + p1: &Point2D, + p2: &Point2D) + -> f32 { + sample_quadratic_bezier(solve_quadratic_bezier_t_for_x(x, p0, p1, p2), p0, p1, p2).y } #[derive(Clone, Copy, Debug)] -pub struct SubdividedCubicBezier { +pub struct SubdividedQuadraticBezier { pub ap0: Point2D, pub ap1: Point2D, - pub ap2: Point2D, - pub ap3bp0: Point2D, + pub ap2bp0: Point2D, pub bp1: Point2D, pub bp2: Point2D, - pub bp3: Point2D, } -impl SubdividedCubicBezier { - pub fn new(t: f32, p0: &Point2D, p1: &Point2D, p2: &Point2D, p3: &Point2D) - -> SubdividedCubicBezier { - let (ap1, p1p2, bp2) = (p0.lerp(*p1, t), p1.lerp(*p2, t), p2.lerp(*p3, t)); - let (ap2, bp1) = (ap1.lerp(p1p2, t), (p1p2.lerp(bp2, t))); - let ap3bp0 = ap2.lerp(bp1, t); - SubdividedCubicBezier { +impl SubdividedQuadraticBezier { + pub fn new(t: f32, p0: &Point2D, p1: &Point2D, p2: &Point2D) + -> SubdividedQuadraticBezier { + let (ap1, bp1) = (p0.lerp(*p1, t), p1.lerp(*p2, t)); + let ap2bp0 = ap1.lerp(bp1, t); + SubdividedQuadraticBezier { ap0: *p0, ap1: ap1, - ap2: ap2, - ap3bp0: ap3bp0, + ap2bp0: ap2bp0, bp1: bp1, - bp2: bp2, - bp3: *p3, + bp2: *p2, } } } diff --git a/partitionfinder/src/legalizer.rs b/partitionfinder/src/legalizer.rs index a0caf88b..b92a53ff 100644 --- a/partitionfinder/src/legalizer.rs +++ b/partitionfinder/src/legalizer.rs @@ -1,15 +1,12 @@ // partitionfinder/legalizer.rs use euclid::Point2D; -use geometry::{self, ApproxOrdered, SubdividedCubicBezier}; use std::u32; -use {ControlPoints, Endpoint, Subpath}; - -const MAX_SUBDIVISIONS: u8 = 16; +use {Endpoint, Subpath}; pub struct Legalizer { endpoints: Vec, - control_points: Vec, + control_points: Vec>, subpaths: Vec, } @@ -29,7 +26,7 @@ impl Legalizer { } #[inline] - pub fn control_points(&self) -> &[ControlPoints] { + pub fn control_points(&self) -> &[Point2D] { &self.control_points } @@ -45,7 +42,7 @@ impl Legalizer { }); self.endpoints.push(Endpoint { position: *position, - control_points_index: u32::MAX, + control_point_index: u32::MAX, subpath_index: (self.subpaths.len() - 1) as u32, }) } @@ -62,82 +59,39 @@ impl Legalizer { .last_endpoint_index += 1; self.endpoints.push(Endpoint { position: *endpoint, - control_points_index: u32::MAX, + control_point_index: u32::MAX, subpath_index: (self.subpaths.len() - 1) as u32, }) } #[inline] pub fn quadratic_curve_to(&mut self, control_point: &Point2D, endpoint: &Point2D) { - self.bezier_curve_to(control_point, control_point, endpoint) + self.subpaths + .last_mut() + .expect("`line_to()` called with no current subpath") + .last_endpoint_index += 1; + self.endpoints.push(Endpoint { + position: *endpoint, + control_point_index: self.control_points.len() as u32, + subpath_index: (self.subpaths.len() - 1) as u32, + }); + self.control_points.push(*control_point) } pub fn bezier_curve_to(&mut self, point1: &Point2D, point2: &Point2D, endpoint: &Point2D) { - self.bezier_curve_to_subdividing_if_necessary(point1, point2, endpoint, 0) - } - - fn bezier_curve_to_subdividing_if_necessary(&mut self, - point1: &Point2D, - point2: &Point2D, - endpoint: &Point2D, - iteration: u8) { + // https://stackoverflow.com/a/2029695 + // + // FIXME(pcwalton): Reimplement subdivision! let last_endpoint_index = self.subpaths .last() - .expect("`bezier_curve_to()` called with no current_subpath") + .expect("`bezier_curve_to()` called with no current subpath") .last_endpoint_index; let point0 = self.endpoints[last_endpoint_index as usize - 1].position; - if iteration >= MAX_SUBDIVISIONS || - [point0.x, point1.x, point2.x, endpoint.x].approx_ordered() { - return self.monotone_bezier_curve_to(point1, point2, endpoint) - } - - let t = geometry::newton_raphson(|t| { - geometry::sample_cubic_bezier_deriv(t, - &point0, - point1, - point2, - endpoint).x - }, - |t| { - geometry::sample_cubic_bezier_deriv_deriv(t, - &point0, - point1, - point2, - endpoint).x - }, - 0.5); - - let subdivision = SubdividedCubicBezier::new(t, &point0, point1, point2, endpoint); - - self.bezier_curve_to_subdividing_if_necessary(&subdivision.ap1, - &subdivision.ap2, - &subdivision.ap3bp0, - iteration + 1); - self.bezier_curve_to_subdividing_if_necessary(&subdivision.bp1, - &subdivision.bp2, - &subdivision.bp3, - iteration + 1); - } - - fn monotone_bezier_curve_to(&mut self, - point1: &Point2D, - point2: &Point2D, - endpoint: &Point2D) { - self.subpaths - .last_mut() - .expect("`bezier_curve_to()` called with no current subpath") - .last_endpoint_index += 1; - self.control_points.push(ControlPoints { - point1: *point1, - point2: *point2, - }); - self.endpoints.push(Endpoint { - position: *endpoint, - control_points_index: (self.control_points.len() - 1) as u32, - subpath_index: (self.subpaths.len() - 1) as u32, - }) + let control_point = ((point1.to_vector() + point2.to_vector()) * 0.75 - + (point0.to_vector() + endpoint.to_vector()) * 0.25).to_point(); + self.quadratic_curve_to(&control_point, endpoint) } } \ No newline at end of file diff --git a/partitionfinder/src/lib.rs b/partitionfinder/src/lib.rs index 3f103f5e..31b13d74 100644 --- a/partitionfinder/src/lib.rs +++ b/partitionfinder/src/lib.rs @@ -38,17 +38,10 @@ pub struct BQuad { pub struct Endpoint { pub position: Point2D, /// `u32::MAX` if not present. - pub control_points_index: u32, + pub control_point_index: u32, pub subpath_index: u32, } -#[repr(C)] -#[derive(Debug, Clone, Copy)] -pub struct ControlPoints { - pub point1: Point2D, - pub point2: Point2D, -} - #[repr(C)] #[derive(Debug, Clone, Copy)] pub struct Subpath { diff --git a/partitionfinder/src/partitioner.rs b/partitionfinder/src/partitioner.rs index f626b1a9..a715f9d1 100644 --- a/partitionfinder/src/partitioner.rs +++ b/partitionfinder/src/partitioner.rs @@ -7,11 +7,11 @@ use log::LogLevel; use std::collections::BinaryHeap; use std::cmp::{self, Ordering}; use std::u32; -use {BQuad, ControlPoints, Endpoint, Subpath}; +use {BQuad, Endpoint, Subpath}; pub struct Partitioner<'a> { endpoints: &'a [Endpoint], - control_points: &'a [ControlPoints], + control_points: &'a [Point2D], subpaths: &'a [Subpath], b_quads: Vec, @@ -39,7 +39,7 @@ impl<'a> Partitioner<'a> { pub fn init(&mut self, new_endpoints: &'a [Endpoint], - new_control_points: &'a [ControlPoints], + new_control_points: &'a [Point2D], new_subpaths: &'a [Subpath]) { self.endpoints = new_endpoints; self.control_points = new_control_points; @@ -374,18 +374,17 @@ impl<'a> Partitioner<'a> { let next_endpoint_index = active_edge.next_endpoint_index(); let prev_endpoint = &self.endpoints[prev_endpoint_index as usize]; let next_endpoint = &self.endpoints[next_endpoint_index as usize]; - match self.control_points_index(next_endpoint_index) { + match self.control_point_index(next_endpoint_index) { None => { let x_vector = next_endpoint.position.x - prev_endpoint.position.x; (x - prev_endpoint.position.x) / x_vector } - Some(control_points_index) => { - let control_points = &self.control_points[control_points_index as usize]; - geometry::solve_cubic_bezier_t_for_x(x, - &prev_endpoint.position, - &control_points.point1, - &control_points.point2, - &next_endpoint.position) + Some(control_point_index) => { + let control_point = &self.control_points[control_point_index as usize]; + geometry::solve_quadratic_bezier_t_for_x(x, + &prev_endpoint.position, + control_point, + &next_endpoint.position) } } } @@ -403,7 +402,7 @@ impl<'a> Partitioner<'a> { fn solve_active_edge_y_for_x(&self, x: f32, active_edge: &ActiveEdge) -> f32 { let prev_endpoint_index = active_edge.prev_endpoint_index(); let next_endpoint_index = active_edge.next_endpoint_index(); - if self.control_points_index(next_endpoint_index).is_none() { + if self.control_point_index(next_endpoint_index).is_none() { self.solve_line_y_for_x(x, prev_endpoint_index, next_endpoint_index) } else { self.solve_cubic_bezier_y_for_x(x, prev_endpoint_index, next_endpoint_index) @@ -421,20 +420,19 @@ impl<'a> Partitioner<'a> { -> f32 { let prev_endpoint = &self.endpoints[prev_endpoint_index as usize]; let next_endpoint = &self.endpoints[next_endpoint_index as usize]; - let control_points_index = self.control_points_index(next_endpoint_index) + let control_point_index = self.control_point_index(next_endpoint_index) .expect("Edge not a cubic bezier!"); - let control_points = &self.control_points[control_points_index as usize]; - geometry::solve_cubic_bezier_y_for_x(x, - &prev_endpoint.position, - &control_points.point1, - &control_points.point2, - &next_endpoint.position) + let control_point = &self.control_points[control_point_index as usize]; + geometry::solve_quadratic_bezier_y_for_x(x, + &prev_endpoint.position, + &control_point, + &next_endpoint.position) } - fn control_points_index(&self, next_endpoint_index: u32) -> Option { - match self.endpoints[next_endpoint_index as usize].control_points_index { + fn control_point_index(&self, next_endpoint_index: u32) -> Option { + match self.endpoints[next_endpoint_index as usize].control_point_index { u32::MAX => None, - control_points_index => Some(control_points_index), + control_point_index => Some(control_point_index), } } @@ -486,12 +484,12 @@ impl<'a> Partitioner<'a> { let next_upper_endpoint_index = upper_active_edge.next_endpoint_index(); let prev_lower_endpoint_index = lower_active_edge.prev_endpoint_index(); let next_lower_endpoint_index = lower_active_edge.next_endpoint_index(); - let upper_control_points_index = self.endpoints[next_upper_endpoint_index as usize] - .control_points_index; - let lower_control_points_index = self.endpoints[next_lower_endpoint_index as usize] - .control_points_index; + let upper_control_point_index = self.endpoints[next_upper_endpoint_index as usize] + .control_point_index; + let lower_control_point_index = self.endpoints[next_lower_endpoint_index as usize] + .control_point_index; - match (upper_control_points_index, lower_control_points_index) { + match (upper_control_point_index, lower_control_point_index) { (u32::MAX, u32::MAX) => { self.line_line_crossing_point(prev_upper_endpoint_index, next_upper_endpoint_index, @@ -499,22 +497,22 @@ impl<'a> Partitioner<'a> { next_lower_endpoint_index) } (u32::MAX, _) => { - self.line_cubic_bezier_crossing_point(prev_upper_endpoint_index, - next_upper_endpoint_index, - next_lower_endpoint_index, - next_lower_endpoint_index) + self.line_quadratic_bezier_crossing_point(prev_upper_endpoint_index, + next_upper_endpoint_index, + next_lower_endpoint_index, + next_lower_endpoint_index) } (_, u32::MAX) => { - self.line_cubic_bezier_crossing_point(prev_lower_endpoint_index, - next_lower_endpoint_index, - next_upper_endpoint_index, - next_upper_endpoint_index) + self.line_quadratic_bezier_crossing_point(prev_lower_endpoint_index, + next_lower_endpoint_index, + next_upper_endpoint_index, + next_upper_endpoint_index) } (_, _) => { - self.cubic_bezier_cubic_bezier_crossing_point(prev_upper_endpoint_index, - next_upper_endpoint_index, - prev_lower_endpoint_index, - next_lower_endpoint_index) + self.quadratic_bezier_quadratic_bezier_crossing_point(prev_upper_endpoint_index, + next_upper_endpoint_index, + prev_lower_endpoint_index, + next_lower_endpoint_index) } } } @@ -532,44 +530,41 @@ impl<'a> Partitioner<'a> { &endpoints[next_lower_endpoint_index as usize].position) } - fn line_cubic_bezier_crossing_point(&self, - prev_line_endpoint_index: u32, - next_line_endpoint_index: u32, - prev_bezier_endpoint_index: u32, - next_bezier_endpoint_index: u32) - -> Option> { - let control_points_index = self.control_points_index(next_bezier_endpoint_index) - .expect("Edge not a cubic Bezier!"); - let control_points = &self.control_points[control_points_index as usize]; - geometry::line_cubic_bezier_crossing_point( + fn line_quadratic_bezier_crossing_point(&self, + prev_line_endpoint_index: u32, + next_line_endpoint_index: u32, + prev_bezier_endpoint_index: u32, + next_bezier_endpoint_index: u32) + -> Option> { + let control_point_index = self.control_point_index(next_bezier_endpoint_index) + .expect("Edge not a quadratic Bezier!"); + let control_point = &self.control_points[control_point_index as usize]; + geometry::line_quadratic_bezier_crossing_point( &self.endpoints[prev_line_endpoint_index as usize].position, &self.endpoints[next_line_endpoint_index as usize].position, &self.endpoints[prev_bezier_endpoint_index as usize].position, - &control_points.point1, - &control_points.point2, + control_point, &self.endpoints[next_bezier_endpoint_index as usize].position) } - fn cubic_bezier_cubic_bezier_crossing_point(&self, - prev_upper_endpoint_index: u32, - next_upper_endpoint_index: u32, - prev_lower_endpoint_index: u32, - next_lower_endpoint_index: u32) - -> Option> { - let upper_control_points_index = self.control_points_index(next_upper_endpoint_index) - .expect("Upper edge not a cubic Bezier!"); - let upper_control_points = &self.control_points[upper_control_points_index as usize]; - let lower_control_points_index = self.control_points_index(next_lower_endpoint_index) - .expect("Lower edge not a cubic Bezier!"); - let lower_control_points = &self.control_points[lower_control_points_index as usize]; - geometry::cubic_bezier_cubic_bezier_crossing_point( + fn quadratic_bezier_quadratic_bezier_crossing_point(&self, + prev_upper_endpoint_index: u32, + next_upper_endpoint_index: u32, + prev_lower_endpoint_index: u32, + next_lower_endpoint_index: u32) + -> Option> { + let upper_control_point_index = self.control_point_index(next_upper_endpoint_index) + .expect("Upper edge not a quadratic Bezier!"); + let upper_control_point = &self.control_points[upper_control_point_index as usize]; + let lower_control_point_index = self.control_point_index(next_lower_endpoint_index) + .expect("Lower edge not a quadratic Bezier!"); + let lower_control_point = &self.control_points[lower_control_point_index as usize]; + geometry::quadratic_bezier_quadratic_bezier_crossing_point( &self.endpoints[prev_upper_endpoint_index as usize].position, - &upper_control_points.point1, - &upper_control_points.point2, + upper_control_point, &self.endpoints[next_upper_endpoint_index as usize].position, &self.endpoints[prev_lower_endpoint_index as usize].position, - &lower_control_points.point1, - &lower_control_points.point2, + lower_control_point, &self.endpoints[next_lower_endpoint_index as usize].position) } diff --git a/partitionfinder/src/partitionfinder.h b/partitionfinder/src/partitionfinder.h index e6f0d3c4..2718c7b8 100644 --- a/partitionfinder/src/partitionfinder.h +++ b/partitionfinder/src/partitionfinder.h @@ -71,12 +71,6 @@ struct pf_endpoint { typedef struct pf_endpoint pf_endpoint_t; -struct pf_control_points { - pf_point2d_f32_t point1, point2; -}; - -typedef struct pf_control_points pf_control_points_t; - struct pf_subpath { uint32_t first_endpoint_index; uint32_t last_endpoint_index; @@ -103,8 +97,8 @@ void pf_legalizer_destroy(pf_legalizer_t *legalizer); const pf_endpoint_t *pf_legalizer_endpoints(const pf_legalizer_t *legalizer, uint32_t *out_endpoint_count); -const pf_control_points_t *pf_legalizer_control_points(const pf_legalizer_t *legalizer, - uint32_t *out_control_points_count); +const pf_point2d_f32_t *pf_legalizer_control_points(const pf_legalizer_t *legalizer, + uint32_t *out_control_point_count); const pf_subpath_t *pf_legalizer_subpaths(const pf_legalizer_t *legalizer, uint32_t *out_subpaths_count); @@ -131,8 +125,8 @@ void pf_partitioner_destroy(pf_partitioner_t *partitioner); void pf_partitioner_init(pf_partitioner_t *partitioner, const pf_endpoint_t *endpoints, uint32_t endpoint_count, - const pf_control_points_t *control_points, - uint32_t control_points_count, + const pf_point2d_f32_t *control_points, + uint32_t control_point_count, const pf_subpath_t *subpaths, uint32_t subpath_count); @@ -145,8 +139,8 @@ const pf_b_quad_t *pf_partitioner_b_quads(pf_partitioner_t *partitioner, pf_tessellator_t *pf_tessellator_new(const pf_endpoint_t *endpoints, uint32_t endpoint_count, - const pf_control_points_t *control_points, - uint32_t control_points_index, + const pf_point2d_f32_t *control_points, + uint32_t control_point_index, const pf_b_quad_t *b_quads, uint32_t b_quad_count, pf_antialiasing_mode_t antialiasing_mode); diff --git a/partitionfinder/src/tessellator.rs b/partitionfinder/src/tessellator.rs index 80477a78..7d20a7f0 100644 --- a/partitionfinder/src/tessellator.rs +++ b/partitionfinder/src/tessellator.rs @@ -2,17 +2,17 @@ #![allow(dead_code)] -use euclid::{Length, Transform2D}; +use euclid::{Length, Point2D, Transform2D}; use half::{f16, self}; use std::cmp; use std::u32; -use {AntialiasingMode, BQuad, ControlPoints, EdgeInstance, Endpoint, Vertex}; +use {AntialiasingMode, BQuad, EdgeInstance, Endpoint, Vertex}; const TOLERANCE: f32 = 0.25; pub struct Tessellator<'a> { endpoints: &'a [Endpoint], - control_points: &'a [ControlPoints], + control_points: &'a [Point2D], b_quads: &'a [BQuad], antialiasing_mode: AntialiasingMode, @@ -42,7 +42,7 @@ impl QuadTessLevels { impl<'a> Tessellator<'a> { pub fn new<'b>(endpoints: &'b [Endpoint], - control_points: &'b [ControlPoints], + control_points: &'b [Point2D], b_quads: &'b [BQuad], antialiasing_mode: AntialiasingMode) -> Tessellator<'b> { @@ -190,10 +190,10 @@ fn tess_level_for_edge(prev_endpoint_index: u32, right_time: f32, transform: &Transform2D, endpoints: &[Endpoint], - control_points: &[ControlPoints]) + control_points: &[Point2D]) -> u32 { - let control_points_index = endpoints[next_endpoint_index as usize].control_points_index; - if control_points_index == u32::MAX { + let control_point_index = endpoints[next_endpoint_index as usize].control_point_index; + if control_point_index == u32::MAX { return 1 } @@ -201,13 +201,13 @@ fn tess_level_for_edge(prev_endpoint_index: u32, let prev_endpoint = &endpoints[prev_endpoint_index as usize]; let next_endpoint = &endpoints[next_endpoint_index as usize]; - let control_points = &control_points[control_points_index as usize]; + let control_point = &control_points[control_point_index as usize]; let p0 = transform.transform_point(&prev_endpoint.position); - let p1 = transform.transform_point(&control_points.point1); - let p2 = transform.transform_point(&control_points.point2); - let p3 = transform.transform_point(&next_endpoint.position); + let p1 = transform.transform_point(control_point); + let p2 = transform.transform_point(&next_endpoint.position); - let length = (p1 - p0).length() + (p2 - p1).length() + (p3 - p2).length(); + // FIXME(pcwalton): Is this good for quadratics? + let length = (p1 - p0).length() + (p2 - p1).length(); 1 + (length * TOLERANCE * (next_time - prev_time)) as u32 }