Remove monotonic conversion, since it's no longer required
This commit is contained in:
parent
440510a126
commit
37c993eee6
|
@ -195,16 +195,6 @@ impl Outline {
|
||||||
self.bounds = self.bounds.dilate(amount);
|
self.bounds = self.bounds.dilate(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare_for_tiling(&mut self, view_box: RectF) {
|
|
||||||
self.contours
|
|
||||||
.iter_mut()
|
|
||||||
.for_each(|contour| contour.prepare_for_tiling(view_box));
|
|
||||||
self.bounds = self
|
|
||||||
.bounds
|
|
||||||
.intersection(view_box)
|
|
||||||
.unwrap_or_else(|| RectF::default());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_outside_polygon(&self, clip_polygon: &[Vector2F]) -> bool {
|
pub fn is_outside_polygon(&self, clip_polygon: &[Vector2F]) -> bool {
|
||||||
clip::rect_is_outside_polygon(self.bounds, clip_polygon)
|
clip::rect_is_outside_polygon(self.bounds, clip_polygon)
|
||||||
}
|
}
|
||||||
|
@ -621,149 +611,6 @@ impl Contour {
|
||||||
self.bounds = self.bounds.dilate(amount);
|
self.bounds = self.bounds.dilate(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_for_tiling(&mut self, view_box: RectF) {
|
|
||||||
// Snap points to the view box bounds. This mops up floating point error from the clipping
|
|
||||||
// process.
|
|
||||||
let (mut last_endpoint_index, mut contour_is_monotonic) = (None, true);
|
|
||||||
for point_index in 0..(self.points.len() as u32) {
|
|
||||||
if contour_is_monotonic {
|
|
||||||
if self.point_is_endpoint(point_index) {
|
|
||||||
if let Some(last_endpoint_index) = last_endpoint_index {
|
|
||||||
if !self.curve_with_endpoints_is_monotonic(last_endpoint_index,
|
|
||||||
point_index) {
|
|
||||||
contour_is_monotonic = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
last_endpoint_index = Some(point_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert to monotonic, if necessary.
|
|
||||||
if !contour_is_monotonic {
|
|
||||||
self.make_monotonic();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update bounds.
|
|
||||||
self.bounds = self
|
|
||||||
.bounds
|
|
||||||
.intersection(view_box)
|
|
||||||
.unwrap_or_else(|| RectF::default());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_monotonic(&mut self) {
|
|
||||||
debug!("--- make_monotonic() ---");
|
|
||||||
|
|
||||||
let contour = self.take();
|
|
||||||
self.bounds = contour.bounds;
|
|
||||||
|
|
||||||
let mut last_endpoint_index = None;
|
|
||||||
let input_point_count = contour.points.len() as u32;
|
|
||||||
for point_index in 0..(input_point_count + 1) {
|
|
||||||
if point_index < input_point_count && !contour.point_is_endpoint(point_index) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(last_endpoint_index) = last_endpoint_index {
|
|
||||||
let position_index = if point_index == input_point_count {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
point_index
|
|
||||||
};
|
|
||||||
let baseline = LineSegment2F::new(
|
|
||||||
contour.points[last_endpoint_index as usize],
|
|
||||||
contour.points[position_index as usize],
|
|
||||||
);
|
|
||||||
let point_count = point_index - last_endpoint_index + 1;
|
|
||||||
if point_count == 3 {
|
|
||||||
let ctrl_point_index = last_endpoint_index as usize + 1;
|
|
||||||
let ctrl_position = &contour.points[ctrl_point_index];
|
|
||||||
handle_cubic(
|
|
||||||
self,
|
|
||||||
&Segment::quadratic(baseline, *ctrl_position).to_cubic(),
|
|
||||||
);
|
|
||||||
} else if point_count == 4 {
|
|
||||||
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_1 = &contour.points[first_ctrl_point_index + 1];
|
|
||||||
let ctrl = LineSegment2F::new(*ctrl_position_0, *ctrl_position_1);
|
|
||||||
handle_cubic(self, &Segment::cubic(baseline, ctrl));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.push_point(
|
|
||||||
contour.points[position_index as usize],
|
|
||||||
PointFlags::empty(),
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
last_endpoint_index = Some(point_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_cubic(contour: &mut Contour, segment: &Segment) {
|
|
||||||
debug!("handle_cubic({:?})", segment);
|
|
||||||
|
|
||||||
match segment.as_cubic_segment().y_extrema() {
|
|
||||||
(Some(t0), Some(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);
|
|
||||||
contour.push_segment(&segment_0, PushSegmentFlags::empty());
|
|
||||||
contour.push_segment(&segment_1, PushSegmentFlags::empty());
|
|
||||||
contour.push_segment(&segment_2, PushSegmentFlags::empty());
|
|
||||||
}
|
|
||||||
(Some(t0), None) | (None, Some(t0)) => {
|
|
||||||
let (segment_0, segment_1) = segment.as_cubic_segment().split(t0);
|
|
||||||
contour.push_segment(&segment_0, PushSegmentFlags::empty());
|
|
||||||
contour.push_segment(&segment_1, PushSegmentFlags::empty());
|
|
||||||
}
|
|
||||||
(None, None) => contour.push_segment(segment, PushSegmentFlags::empty()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn curve_with_endpoints_is_monotonic(
|
|
||||||
&self,
|
|
||||||
start_endpoint_index: u32,
|
|
||||||
end_endpoint_index: u32,
|
|
||||||
) -> bool {
|
|
||||||
let start_position = self.points[start_endpoint_index as usize];
|
|
||||||
let end_position = self.points[end_endpoint_index as usize];
|
|
||||||
|
|
||||||
if start_position.x() <= end_position.x() {
|
|
||||||
for point_index in start_endpoint_index..end_endpoint_index {
|
|
||||||
if self.points[point_index as usize].x() > self.points[point_index as usize + 1].x()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for point_index in start_endpoint_index..end_endpoint_index {
|
|
||||||
if self.points[point_index as usize].x() < self.points[point_index as usize + 1].x()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if start_position.y() <= end_position.y() {
|
|
||||||
for point_index in start_endpoint_index..end_endpoint_index {
|
|
||||||
if self.points[point_index as usize].y() > self.points[point_index as usize + 1].y()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for point_index in start_endpoint_index..end_endpoint_index {
|
|
||||||
if self.points[point_index as usize].y() < self.points[point_index as usize + 1].y()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use this function to keep bounds up to date when mutating paths. See `Outline::transform()`
|
// Use this function to keep bounds up to date when mutating paths. See `Outline::transform()`
|
||||||
// for an example of use.
|
// for an example of use.
|
||||||
pub(crate) fn update_bounds(&self, bounds: &mut Option<RectF>) {
|
pub(crate) fn update_bounds(&self, bounds: &mut Option<RectF>) {
|
||||||
|
|
|
@ -228,9 +228,6 @@ impl Scene {
|
||||||
outline.dilate(options.dilation);
|
outline.dilate(options.dilation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(pcwalton): Fold this into previous passes to avoid unnecessary clones during
|
|
||||||
// monotonic conversion.
|
|
||||||
outline.prepare_for_tiling(self.effective_view_box(options));
|
|
||||||
outline
|
outline
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue