Clean up `Outline::push_segment` and `Outline::push_full_segment`

This commit is contained in:
Patrick Walton 2019-06-01 12:02:53 -07:00
parent 44167beff5
commit 99c1cca05c
3 changed files with 34 additions and 45 deletions

View File

@ -11,7 +11,7 @@
use crate::basic::line_segment::LineSegmentF; use crate::basic::line_segment::LineSegmentF;
use crate::basic::point::{Point2DF, Point3DF}; use crate::basic::point::{Point2DF, Point3DF};
use crate::basic::rect::RectF; use crate::basic::rect::RectF;
use crate::outline::{Contour, PointFlags}; use crate::outline::{Contour, PointFlags, PushSegmentFlags};
use crate::segment::{CubicSegment, Segment}; use crate::segment::{CubicSegment, Segment};
use crate::util::lerp; use crate::util::lerp;
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
@ -261,7 +261,7 @@ where
} }
} }
contour.push_segment(*segment, true); contour.push_segment(segment, PushSegmentFlags::UPDATE_BOUNDS);
} }
fn check_for_fast_clip(&mut self, edge: &Self::Edge) -> FastClipResult { fn check_for_fast_clip(&mut self, edge: &Self::Edge) -> FastClipResult {

View File

@ -45,6 +45,13 @@ bitflags! {
} }
} }
bitflags! {
pub struct PushSegmentFlags: u8 {
const UPDATE_BOUNDS = 0x01;
const INCLUDE_FROM_POINT = 0x02;
}
}
impl Outline { impl Outline {
#[inline] #[inline]
pub fn new() -> Outline { pub fn new() -> Outline {
@ -319,35 +326,12 @@ impl Contour {
} }
#[inline] #[inline]
pub(crate) fn push_segment(&mut self, segment: Segment, update_bounds: bool) { pub(crate) fn push_segment(&mut self, segment: &Segment, flags: PushSegmentFlags) {
if segment.is_none() { if segment.is_none() {
return; return;
} }
if self.is_empty() { let update_bounds = flags.contains(PushSegmentFlags::UPDATE_BOUNDS);
self.push_point(segment.baseline.from(), PointFlags::empty(), update_bounds);
}
if !segment.is_line() {
self.push_point(
segment.ctrl.from(),
PointFlags::CONTROL_POINT_0,
update_bounds,
);
if !segment.is_quadratic() {
self.push_point(
segment.ctrl.to(),
PointFlags::CONTROL_POINT_1,
update_bounds,
);
}
}
self.push_point(segment.baseline.to(), PointFlags::empty(), update_bounds);
}
#[inline]
pub(crate) fn push_full_segment(&mut self, segment: &Segment, update_bounds: bool) {
self.push_point(segment.baseline.from(), PointFlags::empty(), update_bounds); self.push_point(segment.baseline.from(), PointFlags::empty(), update_bounds);
if !segment.is_line() { if !segment.is_line() {
@ -398,12 +382,12 @@ impl Contour {
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));
let mut push_segment_flags = PushSegmentFlags::UPDATE_BOUNDS;
if first_segment { if first_segment {
self.push_full_segment(&segment, true); push_segment_flags.insert(PushSegmentFlags::INCLUDE_FROM_POINT);
first_segment = false; first_segment = false;
} else {
self.push_segment(segment, true);
} }
self.push_segment(&segment, push_segment_flags);
if last { if last {
break; break;
@ -418,13 +402,17 @@ impl Contour {
pub fn push_ellipse(&mut self, transform: &Transform2DF) { pub fn push_ellipse(&mut self, transform: &Transform2DF) {
let segment = Segment::quarter_circle_arc(); let segment = Segment::quarter_circle_arc();
let mut rotation; let mut rotation;
self.push_full_segment(&segment.transform(transform), true); self.push_segment(&segment.transform(transform),
PushSegmentFlags::UPDATE_BOUNDS | PushSegmentFlags::INCLUDE_FROM_POINT);
rotation = Transform2DF::from_rotation_vector(UnitVector(Point2DF::new( 0.0, 1.0))); rotation = Transform2DF::from_rotation_vector(UnitVector(Point2DF::new( 0.0, 1.0)));
self.push_segment(segment.transform(&rotation.post_mul(&transform)), true); self.push_segment(&segment.transform(&rotation.post_mul(&transform)),
PushSegmentFlags::UPDATE_BOUNDS);
rotation = Transform2DF::from_rotation_vector(UnitVector(Point2DF::new(-1.0, 0.0))); rotation = Transform2DF::from_rotation_vector(UnitVector(Point2DF::new(-1.0, 0.0)));
self.push_segment(segment.transform(&rotation.post_mul(&transform)), true); self.push_segment(&segment.transform(&rotation.post_mul(&transform)),
PushSegmentFlags::UPDATE_BOUNDS);
rotation = Transform2DF::from_rotation_vector(UnitVector(Point2DF::new( 0.0, -1.0))); rotation = Transform2DF::from_rotation_vector(UnitVector(Point2DF::new( 0.0, -1.0)));
self.push_segment(segment.transform(&rotation.post_mul(&transform)), true); self.push_segment(&segment.transform(&rotation.post_mul(&transform)),
PushSegmentFlags::UPDATE_BOUNDS);
} }
#[inline] #[inline]
@ -608,14 +596,14 @@ impl Contour {
let ctrl_position = &contour.points[ctrl_point_index]; let ctrl_position = &contour.points[ctrl_point_index];
handle_cubic( handle_cubic(
self, self,
Segment::quadratic(&baseline, *ctrl_position).to_cubic(), &Segment::quadratic(&baseline, *ctrl_position).to_cubic(),
); );
} else if point_count == 4 { } else if point_count == 4 {
let first_ctrl_point_index = last_endpoint_index as usize + 1; let first_ctrl_point_index = last_endpoint_index as usize + 1;
let ctrl_position_0 = &contour.points[first_ctrl_point_index + 0]; let ctrl_position_0 = &contour.points[first_ctrl_point_index + 0];
let ctrl_position_1 = &contour.points[first_ctrl_point_index + 1]; let ctrl_position_1 = &contour.points[first_ctrl_point_index + 1];
let ctrl = LineSegmentF::new(*ctrl_position_0, *ctrl_position_1); let ctrl = LineSegmentF::new(*ctrl_position_0, *ctrl_position_1);
handle_cubic(self, Segment::cubic(&baseline, &ctrl)); handle_cubic(self, &Segment::cubic(&baseline, &ctrl));
} }
self.push_point( self.push_point(
@ -628,23 +616,23 @@ impl Contour {
last_endpoint_index = Some(point_index); last_endpoint_index = Some(point_index);
} }
fn handle_cubic(contour: &mut Contour, segment: Segment) { fn handle_cubic(contour: &mut Contour, segment: &Segment) {
debug!("handle_cubic({:?})", segment); debug!("handle_cubic({:?})", segment);
match segment.as_cubic_segment().y_extrema() { match segment.as_cubic_segment().y_extrema() {
(Some(t0), Some(t1)) => { (Some(t0), Some(t1)) => {
let (segments_01, segment_2) = segment.as_cubic_segment().split(t1); let (segments_01, segment_2) = segment.as_cubic_segment().split(t1);
let (segment_0, segment_1) = segments_01.as_cubic_segment().split(t0 / t1); let (segment_0, segment_1) = segments_01.as_cubic_segment().split(t0 / t1);
contour.push_segment(segment_0, false); contour.push_segment(&segment_0, PushSegmentFlags::empty());
contour.push_segment(segment_1, false); contour.push_segment(&segment_1, PushSegmentFlags::empty());
contour.push_segment(segment_2, false); contour.push_segment(&segment_2, PushSegmentFlags::empty());
} }
(Some(t0), None) | (None, Some(t0)) => { (Some(t0), None) | (None, Some(t0)) => {
let (segment_0, segment_1) = segment.as_cubic_segment().split(t0); let (segment_0, segment_1) = segment.as_cubic_segment().split(t0);
contour.push_segment(segment_0, false); contour.push_segment(&segment_0, PushSegmentFlags::empty());
contour.push_segment(segment_1, false); contour.push_segment(&segment_1, PushSegmentFlags::empty());
} }
(None, None) => contour.push_segment(segment, false), (None, None) => contour.push_segment(segment, PushSegmentFlags::empty()),
} }
} }
} }

View File

@ -14,7 +14,7 @@ use crate::basic::line_segment::LineSegmentF;
use crate::basic::point::Point2DF; use crate::basic::point::Point2DF;
use crate::basic::rect::RectF; use crate::basic::rect::RectF;
use crate::basic::transform2d::Transform2DF; use crate::basic::transform2d::Transform2DF;
use crate::outline::{Contour, Outline}; use crate::outline::{Contour, Outline, PushSegmentFlags};
use crate::segment::Segment; use crate::segment::Segment;
use std::f32; use std::f32;
@ -238,7 +238,8 @@ impl Offset for Segment {
} }
// Push segment. // Push segment.
contour.push_full_segment(self, true); let flags = PushSegmentFlags::UPDATE_BOUNDS | PushSegmentFlags::INCLUDE_FROM_POINT;
contour.push_segment(self, flags);
} }
fn offset_once(&self, distance: f32) -> Segment { fn offset_once(&self, distance: f32) -> Segment {