Implement `Path2D::arc_to`.
This commit is contained in:
parent
f20d41800c
commit
44167beff5
|
@ -14,6 +14,7 @@ use font_kit::family_name::FamilyName;
|
|||
use font_kit::hinting::HintingOptions;
|
||||
use font_kit::properties::Properties;
|
||||
use font_kit::source::SystemSource;
|
||||
use pathfinder_geometry::basic::line_segment::LineSegmentF;
|
||||
use pathfinder_geometry::basic::point::Point2DF;
|
||||
use pathfinder_geometry::basic::rect::RectF;
|
||||
use pathfinder_geometry::basic::transform2d::Transform2DF;
|
||||
|
@ -341,6 +342,24 @@ impl Path2D {
|
|||
self.current_contour.push_arc(&transform, start_angle, end_angle);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn arc_to(&mut self, ctrl: Point2DF, to: Point2DF, radius: f32) {
|
||||
// FIXME(pcwalton): What should we do if there's no initial point?
|
||||
let from = self.current_contour.last_position().unwrap_or_default();
|
||||
let (v0, v1) = (from - ctrl, to - ctrl);
|
||||
let (vu0, vu1) = (v0.normalize(), v1.normalize());
|
||||
let hypot = radius / f32::sqrt(0.5 * (1.0 - vu0.dot(vu1)));
|
||||
let bisector = vu0 + vu1;
|
||||
let center = ctrl + bisector.scale(hypot / bisector.length());
|
||||
|
||||
let mut transform = Transform2DF::from_scale(Point2DF::splat(radius));
|
||||
transform = transform.post_mul(&Transform2DF::from_translation(center));
|
||||
|
||||
let chord = LineSegmentF::new(vu0.yx().scale_xy(Point2DF::new(-1.0, 1.0)),
|
||||
vu1.yx().scale_xy(Point2DF::new(1.0, -1.0)));
|
||||
self.current_contour.push_arc_from_unit_chord(&transform, chord);
|
||||
}
|
||||
|
||||
pub fn rect(&mut self, rect: RectF) {
|
||||
self.flush_current_contour();
|
||||
self.current_contour.push_endpoint(rect.origin());
|
||||
|
|
|
@ -269,13 +269,13 @@ impl Contour {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn position_of_last(&self, index: u32) -> Point2DF {
|
||||
self.points[self.points.len() - index as usize]
|
||||
pub fn last_position(&self) -> Option<Point2DF> {
|
||||
self.points.last().cloned()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn last_position(&self) -> Option<Point2DF> {
|
||||
self.points.last().cloned()
|
||||
pub(crate) fn position_of_last(&self, index: u32) -> Point2DF {
|
||||
self.points[self.points.len() - index as usize]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -409,7 +409,7 @@ impl Contour {
|
|||
break;
|
||||
}
|
||||
|
||||
vector = sweep_vector.rotate_by(vector);
|
||||
vector = vector.rotate_by(sweep_vector);
|
||||
}
|
||||
|
||||
const EPSILON: f32 = 0.001;
|
||||
|
|
Loading…
Reference in New Issue