Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

subtract overflow → Infinite loop #1

Open
NathanRoyer opened this issue Mar 2, 2022 · 2 comments
Open

subtract overflow → Infinite loop #1

NathanRoyer opened this issue Mar 2, 2022 · 2 comments

Comments

@NathanRoyer
Copy link

NathanRoyer commented Mar 2, 2022

Hi, I was looking for a crate with which I could render SVG commands cpu-side, and I'm very satisfied with the performance of zeno, also with the fact that it has no dependency to other crates.

However, I encountered a problem in one specific configuration.
I'm drawing circles using successive calls to line_to (which is not not the canonical way, one would normally use arc).
When drawing a circle of radius 40px on a 2000x2000 canvas centered at 1500x500, the program:

  • panics when built with the debug profile
  • loops infinitely when built with the release profile

The panic says attempt to subtract with overflow @ zeno-0.2.2/src/raster.rs:285:18

Using GDB, I was able to determine that sin_half is the first f32 to become NaN, then the NaNs propagate in the following computations. I am not sure which loop never ends exactly.

Here is a minimal reproduction of my code which is enough to trigger the bug on my machine:

use zeno::PathBuilder;
use zeno::Vector;
use zeno::Stroke;
use zeno::Mask;

use std::f32::consts::TAU;

fn main() {
	let w = 2000;
	let h = 2000;
	let mut zeno_path = Vec::new();
	let center = Vector::new(1500.0, 500.0);
	let radius: f32 = 40.0;
	// steps is complex to compute in my real code,
	// so I just put it that way to be sure of its value
	let steps = f32::from_be_bytes([67, 123, 0, 0]); // ~251
	let a_delta = TAU / steps;
	// angle which will go from 0 to TAU
	let mut a: f32 = 0.0;
	let p = |a: f32| {
		let (y, x) = a.sin_cos();
		Vector::new(center.x + x * radius, center.y + y * radius)
	};
	zeno_path.move_to(p(a));
	while a < TAU {
		a += a_delta;
		zeno_path.line_to(p(a));
	}
	zeno_path.close();
	let mut zeno_mask = Mask::new(&zeno_path);
	zeno_mask.size(w, h);
	zeno_mask.style(Stroke::new(10.0));
	let mut buffer = vec![0; (w * h) as usize];
	// infinite loop w/ release and crash with debug:
	zeno_mask.render_into(&mut buffer, None);
}

I'm currently figuring out the way Segments work to eventually figure out a solution to this problem; if you have clues or thoughts about this, please let me know.

@NathanRoyer
Copy link
Author

I was not able to fix the bug, however I found a workaround: setting zeno::Join::Bevel via the join setter on a Stroke object prevents the buggy code to run.

@markusmoenig
Copy link

Sadly it seems they have abandoned this project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants