Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 39 additions & 6 deletions iOverlay/src/float/overlay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ use i_shape::float::despike::DeSpikeContour;
use i_shape::float::simple::SimplifyContour;
use i_tree::{Expiration, LayoutNumber};

/// Returns true when both coordinates of the point are finite (not NaN or infinite).
#[inline(always)]
pub(crate) fn is_finite_point<P: FloatPointCompatible>(point: &P) -> bool {
point.x().to_f64().is_finite() && point.y().to_f64().is_finite()
}

/// Returns true if the contour contains any non-finite point.
#[inline(always)]
pub(crate) fn contour_has_non_finite<P: FloatPointCompatible>(contour: &[P]) -> bool {
contour.iter().any(|p| !is_finite_point(p))
}

/// Checks finiteness for `&&P` (used with iterator adapters that double-reference).
#[inline(always)]
pub(crate) fn is_finite_point_ref<P: FloatPointCompatible>(point: &&P) -> bool {
is_finite_point(*point)
}

/// Options for float overlay extraction.
///
/// `F` is the floating-point scalar type (`f32` or `f64`). `I` is the integer engine
Expand Down Expand Up @@ -149,7 +167,11 @@ where
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let iter = subj
.iter_paths()
.chain(clip.iter_paths())
.flatten()
.filter(is_finite_point_ref);
let adapter = FloatPointAdapter::with_iter(iter);
let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len());
let clip_capacity = clip.iter_paths().fold(0, |s, c| s + c.len());
Expand Down Expand Up @@ -178,7 +200,11 @@ where
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let iter = subj
.iter_paths()
.chain(clip.iter_paths())
.flatten()
.filter(is_finite_point_ref);
let adapter = FloatPointAdapter::with_iter(iter);
let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len());
let clip_capacity = clip.iter_paths().fold(0, |s, c| s + c.len());
Expand All @@ -198,7 +224,7 @@ where
where
R: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().flatten();
let iter = subj.iter_paths().flatten().filter(is_finite_point_ref);
let adapter = FloatPointAdapter::with_iter(iter);
let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len());

Expand All @@ -217,7 +243,7 @@ where
where
R: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().flatten();
let iter = subj.iter_paths().flatten().filter(is_finite_point_ref);
let adapter = FloatPointAdapter::with_iter(iter);
let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len());

Expand Down Expand Up @@ -260,6 +286,9 @@ where
#[inline]
fn add_source<R: ShapeResource<P> + ?Sized>(&mut self, resource: &R, shape_type: ShapeType) {
for contour in resource.iter_paths() {
if contour_has_non_finite(contour) {
continue;
}
self.overlay
.add_path_iter(contour.iter().map(|p| self.adapter.float_to_int(p)), shape_type);
}
Expand All @@ -279,7 +308,11 @@ where
{
self.clear();

let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let iter = subj
.iter_paths()
.chain(clip.iter_paths())
.flatten()
.filter(is_finite_point_ref);
self.adapter = FloatPointAdapter::with_iter(iter);
self.add_source(subj, ShapeType::Subject);
self.add_source(clip, ShapeType::Clip);
Expand All @@ -297,7 +330,7 @@ where
{
self.clear();

let iter = subj.iter_paths().flatten();
let iter = subj.iter_paths().flatten().filter(is_finite_point_ref);
self.adapter = FloatPointAdapter::with_iter(iter);
self.add_source(subj, ShapeType::Subject);
}
Expand Down
16 changes: 14 additions & 2 deletions iOverlay/src/float/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::core::fill_rule::FillRule;
use crate::core::overlay::ShapeType;
use crate::core::relate::PredicateOverlay;
use crate::core::solver::Solver;
use crate::float::overlay::{contour_has_non_finite, is_finite_point_ref};
use i_float::adapter::FloatPointAdapter;
use i_float::float::compatible::FloatPointCompatible;
use i_float::int::number::int::IntNumber;
Expand Down Expand Up @@ -82,7 +83,11 @@ where
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let iter = subj
.iter_paths()
.chain(clip.iter_paths())
.flatten()
.filter(is_finite_point_ref);
let adapter = FloatPointAdapter::<_, I>::with_iter(iter);
let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len());
let clip_capacity = clip.iter_paths().fold(0, |s, c| s + c.len());
Expand All @@ -107,7 +112,11 @@ where
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let iter = subj
.iter_paths()
.chain(clip.iter_paths())
.flatten()
.filter(is_finite_point_ref);
let adapter = FloatPointAdapter::<_, I>::with_iter(iter);
let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len());
let clip_capacity = clip.iter_paths().fold(0, |s, c| s + c.len());
Expand All @@ -129,6 +138,9 @@ where
/// * `shape_type` - Whether to add as `Subject` or `Clip`.
pub fn add_source<R: ShapeResource<P> + ?Sized>(&mut self, resource: &R, shape_type: ShapeType) {
for contour in resource.iter_paths() {
if contour_has_non_finite(contour) {
continue;
}
self.overlay
.add_path_iter(contour.iter().map(|p| self.adapter.float_to_int(p)), shape_type);
}
Expand Down
26 changes: 21 additions & 5 deletions iOverlay/src/float/scale.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::core::fill_rule::FillRule;
use crate::core::overlay::ShapeType;
use crate::core::overlay_rule::OverlayRule;
use crate::core::solver::Solver;
use crate::float::overlay::{FloatOverlay, OverlayOptions};
use crate::float::overlay::{FloatOverlay, OverlayOptions, is_finite_point_ref};
use crate::float::relate::FloatPredicateOverlay;
use i_float::adapter::{FloatPointAdapter, FloatPointAdapterScaleError};
use i_float::float::compatible::FloatPointCompatible;
Expand Down Expand Up @@ -178,7 +178,11 @@ where
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let iter = subj
.iter_paths()
.chain(clip.iter_paths())
.flatten()
.filter(is_finite_point_ref);
let adapter = FloatPointAdapter::with_iter_and_scale_checked(iter, scale)?;

let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len());
Expand Down Expand Up @@ -214,7 +218,11 @@ where
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let iter = subj
.iter_paths()
.chain(clip.iter_paths())
.flatten()
.filter(is_finite_point_ref);
let adapter = FloatPointAdapter::with_iter_and_scale_checked(iter, scale)?;

let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len());
Expand Down Expand Up @@ -287,7 +295,11 @@ where
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let iter = subj
.iter_paths()
.chain(clip.iter_paths())
.flatten()
.filter(is_finite_point_ref);
let adapter = FloatPointAdapter::with_iter_and_scale_checked(iter, scale)?;

let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len());
Expand Down Expand Up @@ -319,7 +331,11 @@ where
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let iter = subj
.iter_paths()
.chain(clip.iter_paths())
.flatten()
.filter(is_finite_point_ref);
let adapter = FloatPointAdapter::with_iter_and_scale_checked(iter, scale)?;

let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len());
Expand Down
19 changes: 17 additions & 2 deletions iOverlay/src/float/string_overlay.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::core::fill_rule::FillRule;
use crate::core::solver::Solver;
use crate::float::overlay::{contour_has_non_finite, is_finite_point_ref};
use crate::float::scale::FixedScaleOverlayError;
use crate::float::string_graph::FloatStringGraph;
use crate::string::clip::ClipRule;
Expand Down Expand Up @@ -64,7 +65,11 @@ where
R0: ShapeResource<P>,
R1: ShapeResource<P>,
{
let iter = shape.iter_paths().chain(string.iter_paths()).flatten();
let iter = shape
.iter_paths()
.chain(string.iter_paths())
.flatten()
.filter(is_finite_point_ref);
let adapter = FloatPointAdapter::with_iter(iter);
let shape_capacity = shape.iter_paths().fold(0, |s, c| s + c.len());
let string_capacity = string.iter_paths().fold(0, |s, c| s + c.len());
Expand All @@ -87,7 +92,11 @@ where
R0: ShapeResource<P>,
R1: ShapeResource<P>,
{
let iter = shape.iter_paths().chain(string.iter_paths()).flatten();
let iter = shape
.iter_paths()
.chain(string.iter_paths())
.flatten()
.filter(is_finite_point_ref);
let adapter = FloatPointAdapter::with_iter_and_scale_checked(iter, scale)?;

let shape_capacity = shape.iter_paths().fold(0, |s, c| s + c.len());
Expand All @@ -108,6 +117,9 @@ where
#[inline]
pub fn unsafe_add_shapes<S: ShapeResource<P>>(mut self, source: &S) -> Self {
for contour in source.iter_paths() {
if contour_has_non_finite(contour) {
continue;
}
self = self.unsafe_add_shape_contour(contour);
}
self
Expand All @@ -122,6 +134,9 @@ where
#[inline]
pub fn unsafe_add_string_lines<S: ShapeResource<P>>(mut self, resource: &S) -> Self {
for path in resource.iter_paths() {
if contour_has_non_finite(path) {
continue;
}
self = self.unsafe_add_string_line(path);
}
self
Expand Down
2 changes: 1 addition & 1 deletion iOverlay/src/geom/v_segment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl<I: IntNumber> BottomSegment<I> for Option<VSegment<I>> {
#[inline(always)]
fn update_if_under(&mut self, segment: VSegment<I>) {
if let Some(best) = self {
if segment.is_under_segment(&best) {
if segment.is_under_segment(best) {
*best = segment
}
} else {
Expand Down
7 changes: 6 additions & 1 deletion iOverlay/src/mesh/outline/offset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::core::overlay::ShapeType::Subject;
use crate::core::overlay::{ContourDirection, Overlay};
use crate::core::overlay_rule::OverlayRule;
use crate::float::overlay::OverlayOptions;
use crate::float::overlay::{contour_has_non_finite, is_finite_point_ref};
use crate::float::scale::FixedScaleOverlayError;
use crate::mesh::outline::builder::OutlineBuilder;
use crate::mesh::style::OutlineStyle;
Expand Down Expand Up @@ -446,7 +447,8 @@ where

let additional_offset = outer_additional_offset.abs() + inner_additional_offset.abs();

let mut rect = FloatRect::with_iter(source.iter_paths().flatten()).unwrap_or(FloatRect::zero());
let mut rect = FloatRect::with_iter(source.iter_paths().flatten().filter(is_finite_point_ref))
.unwrap_or(FloatRect::zero());
rect.add_offset(additional_offset);

let adapter = FloatPointAdapter::<P, I>::new(rect);
Expand Down Expand Up @@ -485,6 +487,9 @@ where
let mut flat_buffer = FlatContoursBuffer::<I>::with_capacity(0);

for path in source.iter_paths() {
if contour_has_non_finite(path) {
continue;
}
let area = path.unsafe_int_area(&self.adapter);
if area.unsigned_abs() <= <I::WideUInt as UIntNumber>::from_u64(1) {
// ignore degenerate paths
Expand Down
10 changes: 9 additions & 1 deletion iOverlay/src/mesh/stroke/offset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::core::fill_rule::FillRule;
use crate::core::overlay::Overlay;
use crate::core::overlay_rule::OverlayRule;
use crate::float::overlay::OverlayOptions;
use crate::float::overlay::{contour_has_non_finite, is_finite_point_ref};
use crate::float::scale::FixedScaleOverlayError;
use crate::i_shape::source::resource::ShapeResource;
use crate::mesh::stroke::builder::StrokeBuilder;
Expand Down Expand Up @@ -483,7 +484,8 @@ where
let builder = StrokeBuilder::<P, I>::new(style);
let a = builder.additional_offset(r);

let mut rect = FloatRect::with_iter(source.iter_paths().flatten()).unwrap_or(FloatRect::zero());
let mut rect = FloatRect::with_iter(source.iter_paths().flatten().filter(is_finite_point_ref))
.unwrap_or(FloatRect::zero());
rect.add_offset(a);
let adapter = FloatPointAdapter::<P, I>::new(rect);

Expand Down Expand Up @@ -519,6 +521,9 @@ where
let mut segments = Vec::with_capacity(capacity);

for path in source.iter_paths() {
if contour_has_non_finite(path) {
continue;
}
self.builder
.build(path, is_closed_path, &self.adapter, &mut segments);
}
Expand Down Expand Up @@ -561,6 +566,9 @@ where
let mut segments = Vec::with_capacity(capacity);

for path in source.iter_paths() {
if contour_has_non_finite(path) {
continue;
}
self.builder
.build(path, is_closed_path, &self.adapter, &mut segments);
}
Expand Down
1 change: 1 addition & 0 deletions iOverlay/tests/crash_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ mod tests {
}
}

#[allow(clippy::excessive_precision)]
#[test]
fn test_01() {
let subj = [
Expand Down
Loading