PistonDevelopers / graphics

A library for 2D graphics, written in Rust, that works with multiple back-ends
MIT License
479 stars 55 forks source link

triangulation.rs panics when drawing shapes with resolution above some limit #1158

Closed aderhall closed 1 year ago

aderhall commented 3 years ago

Hi all,

I was messing around and found that calling graphics::Rectangle::draw or graphics::Ellipse::draw panics when the Ellipse has resolution >= 171u32 or the Rectangle has rounded corners with resolution >= 43u32.

The panic message is: thread 'main' panicked at 'index out of bounds: the len is 1023 but the index is 1023', /Users/[my account]/.cargo/registry/src/github.com-1ecc6299db9ec823/piston2d-graphics-0.40.0/./src/triangulation.rs:498:9

Reproducible example:

extern crate glutin_window;
extern crate graphics;
extern crate opengl_graphics;
extern crate piston;

use glutin_window::GlutinWindow;
use piston::{
  window::WindowSettings,
  event_loop::{EventSettings, Events},
  input::{RenderEvent}
};
use opengl_graphics::{GlGraphics, OpenGL};

fn main() {
    let opengl_version = OpenGL::V3_2;
    let mut window: GlutinWindow = WindowSettings::new("Piston crash test", [500., 500.])
        .graphics_api(opengl_version)
        .build()
        .unwrap();

    let mut gl = GlGraphics::new(opengl_version);
    let mut events = Events::new(EventSettings::new());
    while let Some(e) = events.next(&mut window) {
        if let Some(args) = e.render_args() {
            let context = gl.draw_begin(args.viewport());

            let shape = graphics::Rectangle {
                border: Some(graphics::rectangle::Border {
                    color: [1., 0., 0., 1.],
                    radius: 1.,
                }),
                color: [0., 1., 1., 1.],
                // Here I'm supplying 43 as the resolution. 42 works, 43 reliably causes a panic every time.
                shape: graphics::rectangle::Shape::Round(50., 43),
            };
            shape.draw([10., 10., 100., 200.], &context.draw_state, context.transform, &mut gl);

            gl.draw_end();
        }
    }
}

The same thing happens for Ellipse, if you replace the line let shape... with

let shape = graphics::Ellipse {
    border: Some(graphics::ellipse::Border {
        color: [1., 0., 0., 1.],
        radius: 1.
    }),
    color: [0., 1., 1., 1.],
    // If this is 170 or lower, it works fine. 171 or higher, it reliably panics.
    resolution: 171,
};

I have no idea what could be causing this, or why those specific numbers. I couldn't find anything in the docs suggesting that resolution has a maximum to avoid panics, and this seems a little worrying since different shapes seem to have different upper limits? It was causing problems for me since I had code trying to determine at runtime the best resolution to use, and it would panic under certain conditions because of this issue.

My dependencies are:

piston = "0.53.0"
piston2d-graphics = "0.40.0"
pistoncore-glutin_window = "0.69.0"
piston2d-opengl_graphics = "0.78.0"

I'm running macOS Big Sur on a 13.3-inch macbook, with Intel HD Graphics 6000 1536 MB.

I hope this is helpful. If you're already aware of the issue, is there a range of resolution values I should stick to to avoid panics in general?