Precompute the curve for a quarter-circle arc
This commit is contained in:
parent
48f825077c
commit
712c69faf1
|
@ -385,12 +385,15 @@ impl Contour {
|
|||
loop {
|
||||
let mut sweep_vector = end_vector.rev_rotate_by(vector);
|
||||
let last = sweep_vector.0.x() >= -EPSILON && sweep_vector.0.y() >= -EPSILON;
|
||||
|
||||
let mut segment;
|
||||
if !last {
|
||||
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 =
|
||||
Transform2DF::from_rotation_vector(sweep_vector.halve_angle().rotate_by(vector));
|
||||
segment = segment.transform(&rotation.post_mul(&transform));
|
||||
|
@ -413,23 +416,15 @@ impl Contour {
|
|||
}
|
||||
|
||||
pub fn push_ellipse(&mut self, transform: &Transform2DF) {
|
||||
let rotations = [
|
||||
Transform2DF::default(),
|
||||
Transform2DF::from_rotation_vector(UnitVector(Point2DF::new( 0.0, 1.0))),
|
||||
Transform2DF::from_rotation_vector(UnitVector(Point2DF::new(-1.0, 0.0))),
|
||||
Transform2DF::from_rotation_vector(UnitVector(Point2DF::new( 0.0, -1.0))),
|
||||
];
|
||||
|
||||
let base_segment = Segment::arc_from_cos(0.0);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
let segment = Segment::quarter_circle_arc();
|
||||
let mut rotation;
|
||||
self.push_full_segment(&segment.transform(transform), true);
|
||||
rotation = 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);
|
||||
rotation = Transform2DF::from_rotation_vector(UnitVector(Point2DF::new( 0.0, -1.0)));
|
||||
self.push_segment(segment.transform(&rotation.post_mul(&transform)), true);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -94,6 +94,15 @@ impl Segment {
|
|||
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]
|
||||
pub fn as_line_segment(&self) -> LineSegmentF {
|
||||
debug_assert!(self.is_line());
|
||||
|
|
|
@ -122,6 +122,7 @@ impl<'a> OutlineStrokeToFill<'a> {
|
|||
|
||||
match self.style.line_cap {
|
||||
LineCap::Butt => unreachable!(),
|
||||
|
||||
LineCap::Square => {
|
||||
let offset = gradient.scale(width * 0.5);
|
||||
|
||||
|
@ -133,6 +134,7 @@ impl<'a> OutlineStrokeToFill<'a> {
|
|||
contour.push_endpoint(p3);
|
||||
contour.push_endpoint(p4);
|
||||
}
|
||||
|
||||
LineCap::Round => {
|
||||
let scale = Point2DF::splat(width * 0.5);
|
||||
let offset = gradient.yx().scale_xy(Point2DF::new(-1.0, 1.0));
|
||||
|
|
Loading…
Reference in New Issue