Quadratics work now for simple cases
This commit is contained in:
parent
a7ba7d200e
commit
8730df37a7
|
@ -133,13 +133,13 @@ pub unsafe extern fn pf_partitioner_init<'a>(partitioner: *mut Partitioner<'a>,
|
||||||
endpoints: *const Endpoint,
|
endpoints: *const Endpoint,
|
||||||
endpoint_count: u32,
|
endpoint_count: u32,
|
||||||
control_points: *const Point2DF32,
|
control_points: *const Point2DF32,
|
||||||
control_points_count: u32,
|
control_point_count: u32,
|
||||||
subpaths: *const Subpath,
|
subpaths: *const Subpath,
|
||||||
subpath_count: u32) {
|
subpath_count: u32) {
|
||||||
// FIXME(pcwalton): This is unsafe! `Point2D<f32>` and `Point2DF32` may have different layouts!
|
// FIXME(pcwalton): This is unsafe! `Point2D<f32>` and `Point2DF32` may have different layouts!
|
||||||
(*partitioner).init(slice::from_raw_parts(endpoints, endpoint_count as usize),
|
(*partitioner).init(slice::from_raw_parts(endpoints, endpoint_count as usize),
|
||||||
slice::from_raw_parts(control_points as *const Point2D<f32>,
|
slice::from_raw_parts(control_points as *const Point2D<f32>,
|
||||||
control_points_count as usize),
|
control_point_count as usize),
|
||||||
slice::from_raw_parts(subpaths, subpath_count as usize))
|
slice::from_raw_parts(subpaths, subpath_count as usize))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ pub unsafe extern fn pf_partitioner_b_quads<'a>(partitioner: *mut Partitioner<'a
|
||||||
pub unsafe extern fn pf_tessellator_new(endpoints: *const Endpoint,
|
pub unsafe extern fn pf_tessellator_new(endpoints: *const Endpoint,
|
||||||
endpoint_count: u32,
|
endpoint_count: u32,
|
||||||
control_points: *const Point2D<f32>,
|
control_points: *const Point2D<f32>,
|
||||||
control_points_count: u32,
|
control_point_count: u32,
|
||||||
b_quads: *const BQuad,
|
b_quads: *const BQuad,
|
||||||
b_quad_count: u32,
|
b_quad_count: u32,
|
||||||
antialiasing_mode: AntialiasingMode)
|
antialiasing_mode: AntialiasingMode)
|
||||||
|
@ -174,7 +174,7 @@ pub unsafe extern fn pf_tessellator_new(endpoints: *const Endpoint,
|
||||||
let mut tessellator =
|
let mut tessellator =
|
||||||
Box::new(Tessellator::new(slice::from_raw_parts(endpoints, endpoint_count as usize),
|
Box::new(Tessellator::new(slice::from_raw_parts(endpoints, endpoint_count as usize),
|
||||||
slice::from_raw_parts(control_points,
|
slice::from_raw_parts(control_points,
|
||||||
control_points_count as usize),
|
control_point_count as usize),
|
||||||
slice::from_raw_parts(b_quads, b_quad_count as usize),
|
slice::from_raw_parts(b_quads, b_quad_count as usize),
|
||||||
antialiasing_mode));
|
antialiasing_mode));
|
||||||
let tessellator_ptr: *mut Tessellator<'static> = &mut *tessellator;
|
let tessellator_ptr: *mut Tessellator<'static> = &mut *tessellator;
|
||||||
|
|
|
@ -94,15 +94,6 @@ pub fn sample_quadratic_bezier_deriv(t: f32,
|
||||||
return ((*p1 - *p0) * (1.0 - t) + (*p2 - *p1) * t) * 2.0
|
return ((*p1 - *p0) * (1.0 - t) + (*p2 - *p1) * t) * 2.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sample_quadratic_bezier_deriv_deriv(p0: &Point2D<f32>,
|
|
||||||
p1: &Point2D<f32>,
|
|
||||||
p2: &Point2D<f32>)
|
|
||||||
-> Vector2D<f32> {
|
|
||||||
// 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()) * 2.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn solve_line_y_for_x(x: f32, a: &Point2D<f32>, b: &Point2D<f32>) -> f32 {
|
pub fn solve_line_y_for_x(x: f32, a: &Point2D<f32>, b: &Point2D<f32>) -> f32 {
|
||||||
a.lerp(*b, (x - a.x) / (b.x - a.x)).y
|
a.lerp(*b, (x - a.x) / (b.x - a.x)).y
|
||||||
}
|
}
|
||||||
|
@ -139,6 +130,31 @@ pub fn solve_quadratic_bezier_y_for_x(x: f32,
|
||||||
sample_quadratic_bezier(solve_quadratic_bezier_t_for_x(x, p0, p1, p2), p0, p1, p2).y
|
sample_quadratic_bezier(solve_quadratic_bezier_t_for_x(x, p0, p1, p2), p0, p1, p2).y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn quadratic_bezier_axis_inflection_point(p0: f32, p1: f32, p2: f32) -> Option<f32> {
|
||||||
|
let t = (p0 - p1) / (p0 - 2.0 * p1 + p2);
|
||||||
|
if t > f32::approx_epsilon() && t < 1.0 - f32::approx_epsilon() {
|
||||||
|
Some(t)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct QuadraticBezierInflectionPoints {
|
||||||
|
pub xt: Option<f32>,
|
||||||
|
pub yt: Option<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QuadraticBezierInflectionPoints {
|
||||||
|
pub fn calculate(p0: &Point2D<f32>, p1: &Point2D<f32>, p2: &Point2D<f32>)
|
||||||
|
-> QuadraticBezierInflectionPoints {
|
||||||
|
QuadraticBezierInflectionPoints {
|
||||||
|
xt: quadratic_bezier_axis_inflection_point(p0.x, p1.x, p2.x),
|
||||||
|
yt: quadratic_bezier_axis_inflection_point(p0.y, p1.y, p2.y),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct SubdividedQuadraticBezier {
|
pub struct SubdividedQuadraticBezier {
|
||||||
pub ap0: Point2D<f32>,
|
pub ap0: Point2D<f32>,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// partitionfinder/legalizer.rs
|
// partitionfinder/legalizer.rs
|
||||||
|
|
||||||
use euclid::Point2D;
|
use euclid::Point2D;
|
||||||
|
use geometry::{QuadraticBezierInflectionPoints, SubdividedQuadraticBezier};
|
||||||
use std::u32;
|
use std::u32;
|
||||||
use {Endpoint, Subpath};
|
use {Endpoint, Subpath};
|
||||||
|
|
||||||
|
@ -64,11 +65,12 @@ impl Legalizer {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
fn monotone_quadratic_curve_to(&mut self,
|
||||||
pub fn quadratic_curve_to(&mut self, control_point: &Point2D<f32>, endpoint: &Point2D<f32>) {
|
control_point: &Point2D<f32>,
|
||||||
|
endpoint: &Point2D<f32>) {
|
||||||
self.subpaths
|
self.subpaths
|
||||||
.last_mut()
|
.last_mut()
|
||||||
.expect("`line_to()` called with no current subpath")
|
.expect("`quadratic_curve_to()` called with no current subpath")
|
||||||
.last_endpoint_index += 1;
|
.last_endpoint_index += 1;
|
||||||
self.endpoints.push(Endpoint {
|
self.endpoints.push(Endpoint {
|
||||||
position: *endpoint,
|
position: *endpoint,
|
||||||
|
@ -78,6 +80,51 @@ impl Legalizer {
|
||||||
self.control_points.push(*control_point)
|
self.control_points.push(*control_point)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn quadratic_curve_to(&mut self, control_point: &Point2D<f32>, endpoint: &Point2D<f32>) {
|
||||||
|
let last_endpoint_index =
|
||||||
|
self.subpaths
|
||||||
|
.last()
|
||||||
|
.expect("`quadratic_curve_to()` called with no current subpath")
|
||||||
|
.last_endpoint_index;
|
||||||
|
let point0 = self.endpoints[last_endpoint_index as usize - 1].position;
|
||||||
|
|
||||||
|
match QuadraticBezierInflectionPoints::calculate(&point0, control_point, endpoint) {
|
||||||
|
QuadraticBezierInflectionPoints {
|
||||||
|
xt: Some(xt),
|
||||||
|
yt: Some(yt),
|
||||||
|
} => {
|
||||||
|
let subdivision = SubdividedQuadraticBezier::new(f32::min(xt, yt),
|
||||||
|
&point0,
|
||||||
|
control_point,
|
||||||
|
endpoint);
|
||||||
|
self.monotone_quadratic_curve_to(&subdivision.ap1, &subdivision.ap2bp0);
|
||||||
|
self.quadratic_curve_to(&subdivision.bp1, &subdivision.bp2)
|
||||||
|
}
|
||||||
|
QuadraticBezierInflectionPoints {
|
||||||
|
xt: Some(t),
|
||||||
|
yt: None,
|
||||||
|
} |
|
||||||
|
QuadraticBezierInflectionPoints {
|
||||||
|
xt: None,
|
||||||
|
yt: Some(t),
|
||||||
|
} => {
|
||||||
|
let subdivision = SubdividedQuadraticBezier::new(t,
|
||||||
|
&point0,
|
||||||
|
control_point,
|
||||||
|
endpoint);
|
||||||
|
self.monotone_quadratic_curve_to(&subdivision.ap1, &subdivision.ap2bp0);
|
||||||
|
self.quadratic_curve_to(&subdivision.bp1, &subdivision.bp2)
|
||||||
|
}
|
||||||
|
QuadraticBezierInflectionPoints {
|
||||||
|
xt: None,
|
||||||
|
yt: None,
|
||||||
|
} => {
|
||||||
|
self.monotone_quadratic_curve_to(control_point, endpoint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn bezier_curve_to(&mut self,
|
pub fn bezier_curve_to(&mut self,
|
||||||
point1: &Point2D<f32>,
|
point1: &Point2D<f32>,
|
||||||
point2: &Point2D<f32>,
|
point2: &Point2D<f32>,
|
||||||
|
|
|
@ -65,7 +65,7 @@ typedef struct pf_b_quad pf_b_quad_t;
|
||||||
|
|
||||||
struct pf_endpoint {
|
struct pf_endpoint {
|
||||||
pf_point2d_f32_t position;
|
pf_point2d_f32_t position;
|
||||||
uint32_t control_points_index;
|
uint32_t control_point_index;
|
||||||
uint32_t subpath_index;
|
uint32_t subpath_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue