Precompute the curve for a quarter-circle arc
This commit is contained in:
parent
48f825077c
commit
712c69faf1
|
@ -385,12 +385,15 @@ impl Contour {
|
||||||
loop {
|
loop {
|
||||||
let mut sweep_vector = end_vector.rev_rotate_by(vector);
|
let mut sweep_vector = end_vector.rev_rotate_by(vector);
|
||||||
let last = sweep_vector.0.x() >= -EPSILON && sweep_vector.0.y() >= -EPSILON;
|
let last = sweep_vector.0.x() >= -EPSILON && sweep_vector.0.y() >= -EPSILON;
|
||||||
|
|
||||||
|
let mut segment;
|
||||||
if !last {
|
if !last {
|
||||||
sweep_vector = UnitVector(Point2DF::new(0.0, 1.0));
|
sweep_vector = UnitVector(Point2DF::new(0.0, 1.0));
|
||||||
|
segment = Segment::quarter_circle_arc();
|
||||||
|
} else {
|
||||||
|
segment = Segment::arc_from_cos(sweep_vector.0.x());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(pcwalton): Cache 90 degree arc segments so we aren't calling this all the time.
|
|
||||||
let mut segment = Segment::arc_from_cos(sweep_vector.0.x());
|
|
||||||
let rotation =
|
let rotation =
|
||||||
Transform2DF::from_rotation_vector(sweep_vector.halve_angle().rotate_by(vector));
|
Transform2DF::from_rotation_vector(sweep_vector.halve_angle().rotate_by(vector));
|
||||||
segment = segment.transform(&rotation.post_mul(&transform));
|
segment = segment.transform(&rotation.post_mul(&transform));
|
||||||
|
@ -413,23 +416,15 @@ impl Contour {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_ellipse(&mut self, transform: &Transform2DF) {
|
pub fn push_ellipse(&mut self, transform: &Transform2DF) {
|
||||||
let rotations = [
|
let segment = Segment::quarter_circle_arc();
|
||||||
Transform2DF::default(),
|
let mut rotation;
|
||||||
Transform2DF::from_rotation_vector(UnitVector(Point2DF::new( 0.0, 1.0))),
|
self.push_full_segment(&segment.transform(transform), true);
|
||||||
Transform2DF::from_rotation_vector(UnitVector(Point2DF::new(-1.0, 0.0))),
|
rotation = Transform2DF::from_rotation_vector(UnitVector(Point2DF::new( 0.0, 1.0)));
|
||||||
Transform2DF::from_rotation_vector(UnitVector(Point2DF::new( 0.0, -1.0))),
|
self.push_segment(segment.transform(&rotation.post_mul(&transform)), true);
|
||||||
];
|
rotation = Transform2DF::from_rotation_vector(UnitVector(Point2DF::new(-1.0, 0.0)));
|
||||||
|
self.push_segment(segment.transform(&rotation.post_mul(&transform)), true);
|
||||||
let base_segment = Segment::arc_from_cos(0.0);
|
rotation = Transform2DF::from_rotation_vector(UnitVector(Point2DF::new( 0.0, -1.0)));
|
||||||
|
self.push_segment(segment.transform(&rotation.post_mul(&transform)), true);
|
||||||
for (rotation_index, rotation) in rotations.iter().enumerate() {
|
|
||||||
let segment = base_segment.transform(&rotation.post_mul(&transform));
|
|
||||||
if rotation_index == 0 {
|
|
||||||
self.push_full_segment(&segment, true);
|
|
||||||
} else {
|
|
||||||
self.push_segment(segment, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -94,6 +94,15 @@ impl Segment {
|
||||||
const K: f32 = 4.0 / 3.0 * (SQRT_2 - 1.0);
|
const K: f32 = 4.0 / 3.0 * (SQRT_2 - 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn quarter_circle_arc() -> Segment {
|
||||||
|
let p0 = Point2DF::splat(SQRT_2 * 0.5);
|
||||||
|
let p1 = Point2DF::new(-SQRT_2 / 6.0 + 4.0 / 3.0, 7.0 * SQRT_2 / 6.0 - 4.0 / 3.0);
|
||||||
|
let flip = Point2DF::new(1.0, -1.0);
|
||||||
|
let (p2, p3) = (p1.scale_xy(flip), p0.scale_xy(flip));
|
||||||
|
Segment::cubic(&LineSegmentF::new(p3, p0), &LineSegmentF::new(p2, p1))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_line_segment(&self) -> LineSegmentF {
|
pub fn as_line_segment(&self) -> LineSegmentF {
|
||||||
debug_assert!(self.is_line());
|
debug_assert!(self.is_line());
|
||||||
|
|
|
@ -122,6 +122,7 @@ impl<'a> OutlineStrokeToFill<'a> {
|
||||||
|
|
||||||
match self.style.line_cap {
|
match self.style.line_cap {
|
||||||
LineCap::Butt => unreachable!(),
|
LineCap::Butt => unreachable!(),
|
||||||
|
|
||||||
LineCap::Square => {
|
LineCap::Square => {
|
||||||
let offset = gradient.scale(width * 0.5);
|
let offset = gradient.scale(width * 0.5);
|
||||||
|
|
||||||
|
@ -133,6 +134,7 @@ impl<'a> OutlineStrokeToFill<'a> {
|
||||||
contour.push_endpoint(p3);
|
contour.push_endpoint(p3);
|
||||||
contour.push_endpoint(p4);
|
contour.push_endpoint(p4);
|
||||||
}
|
}
|
||||||
|
|
||||||
LineCap::Round => {
|
LineCap::Round => {
|
||||||
let scale = Point2DF::splat(width * 0.5);
|
let scale = Point2DF::splat(width * 0.5);
|
||||||
let offset = gradient.yx().scale_xy(Point2DF::new(-1.0, 1.0));
|
let offset = gradient.yx().scale_xy(Point2DF::new(-1.0, 1.0));
|
||||||
|
|
Loading…
Reference in New Issue