diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/rust/aa-stroke/src/c_bindings.rs | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/aa-stroke/src/c_bindings.rs')
-rw-r--r-- | third_party/rust/aa-stroke/src/c_bindings.rs | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/third_party/rust/aa-stroke/src/c_bindings.rs b/third_party/rust/aa-stroke/src/c_bindings.rs new file mode 100644 index 0000000000..fb21791fda --- /dev/null +++ b/third_party/rust/aa-stroke/src/c_bindings.rs @@ -0,0 +1,169 @@ +use crate::{filled_circle_with_path_builder, PathBuilder, Point, StrokeStyle, Stroker}; + +type OutputVertex = crate::Vertex; + +#[repr(C)] +pub struct VertexBuffer { + data: *const OutputVertex, + len: usize +} + +#[no_mangle] +pub extern "C" fn aa_stroke_new( + style: &StrokeStyle, + output_ptr: *mut OutputVertex, + output_capacity: usize, +) -> *mut Stroker { + let mut s = Stroker::new(style); + if output_ptr != std::ptr::null_mut() { + let slice = unsafe { std::slice::from_raw_parts_mut(output_ptr, output_capacity) }; + s.set_output_buffer(slice); + } + Box::into_raw(Box::new(s)) +} + +#[no_mangle] +pub extern "C" fn aa_stroke_move_to(s: &mut Stroker, x: f32, y: f32, closed: bool) { + s.move_to(Point::new(x, y), closed); +} + +#[no_mangle] +pub extern "C" fn aa_stroke_line_to(s: &mut Stroker, x: f32, y: f32, end: bool) { + if end { + s.line_to_capped(Point::new(x, y)) + } else { + s.line_to(Point::new(x, y)); + } +} + +#[no_mangle] +pub extern "C" fn aa_stroke_curve_to(s: &mut Stroker, c1x: f32, c1y: f32, c2x: f32, c2y: f32, x: f32, y: f32, end: bool) { + if end { + s.curve_to_capped(Point::new(c1x, c1y), Point::new(c2x, c2y), Point::new(x, y)); + } else { + s.curve_to(Point::new(c1x, c1y), Point::new(c2x, c2y), Point::new(x, y)); + } +} + +/* +#[no_mangle] +pub extern "C" fn aa_stroke_quad_to(s: &mut Stroker, cx: f32, cy: f32, x: f32, y: f32) { + s.quad_to(cx, cy, x, y); +}*/ + +#[no_mangle] +pub extern "C" fn aa_stroke_close(s: &mut Stroker) { + s.close(); +} + +#[no_mangle] +pub extern "C" fn aa_stroke_finish(s: &mut Stroker) -> VertexBuffer { + let stroked_path = s.get_stroked_path(); + if let Some(output_buffer_size) = stroked_path.get_output_buffer_size() { + // if let Some(output_buffer) = stroked_path.output_buffer { + // dbg!(&output_buffer[0..output_buffer_size]); + // } + VertexBuffer { + data: std::ptr::null(), + len: output_buffer_size, + } + } else { + let result = s.finish(); + let len = result.len(); + let vb = VertexBuffer { data: Box::leak(result).as_ptr(), len }; + vb + } +} + +#[no_mangle] +pub extern "C" fn aa_stroke_vertex_buffer_release(vb: VertexBuffer) +{ + if vb.data != std::ptr::null() { + unsafe { + drop(Box::from_raw(std::slice::from_raw_parts_mut(vb.data as *mut OutputVertex, vb.len))); + } + } +} + +#[no_mangle] +pub unsafe extern "C" fn aa_stroke_release(s: *mut Stroker) { + drop(Box::from_raw(s)); +} + +#[no_mangle] +pub extern "C" fn aa_stroke_filled_circle( + cx: f32, cy: f32, radius: f32, output_ptr: *mut OutputVertex, output_capacity: usize +) -> VertexBuffer { + let mut path_builder = PathBuilder::new(1.); + if output_ptr != std::ptr::null_mut() { + let slice = unsafe { std::slice::from_raw_parts_mut(output_ptr, output_capacity) }; + path_builder.set_output_buffer(slice); + } + + filled_circle_with_path_builder(&mut path_builder, Point::new(cx, cy), radius); + + if let Some(output_buffer_size) = path_builder.get_output_buffer_size() { + VertexBuffer { + data: std::ptr::null(), + len: output_buffer_size, + } + } else { + let result = path_builder.finish(); + let len = result.len(); + let vb = VertexBuffer { data: Box::leak(result).as_ptr(), len }; + vb + } +} + + +#[test] +fn simple() { + let style = StrokeStyle::default(); + let s = unsafe { &mut *aa_stroke_new(&style, std::ptr::null_mut(), 0) } ; + aa_stroke_move_to(s, 10., 10., false); + aa_stroke_line_to(s, 100., 100., false); + aa_stroke_line_to(s, 100., 10., true); + let vb = aa_stroke_finish(s); + aa_stroke_vertex_buffer_release(vb); + unsafe { aa_stroke_release(s) } ; +} + +#[test] +fn output_buffer() { + let style = StrokeStyle::default(); + let mut output = Vec::new(); + output.resize_with(1000, || OutputVertex{x: 0., y: 0., coverage: 0.}); + let s = unsafe { &mut *aa_stroke_new(&style, output.as_mut_ptr(), output.len()) } ; + aa_stroke_move_to(s, 10., 10., false); + aa_stroke_line_to(s, 100., 100., false); + aa_stroke_line_to(s, 100., 10., true); + + let vb = aa_stroke_finish(s); + assert_ne!(vb.len, 0); + assert_eq!(vb.data, std::ptr::null()); + aa_stroke_vertex_buffer_release(vb); + unsafe { aa_stroke_release(s) } ; +} + +#[test] +fn filled_circle_output_buffer() { + use crate::Vertex; + let mut output = Vec::new(); + output.resize_with(1000, || OutputVertex{x: 0., y: 0., coverage: 0.}); + let center = Point::new(100., 100.); + let radius = 33.; + + let vb = aa_stroke_filled_circle(center.x, center.y, radius, output.as_mut_ptr(), output.len()); + assert_ne!(vb.len, 0); + assert_eq!(vb.data, std::ptr::null()); + let result = &output[0..vb.len]; + let min_x = result.iter().map(|v: &Vertex| v.x).reduce(|a, b| a.min(b)).unwrap(); + let max_x = result.iter().map(|v: &Vertex| v.x).reduce(|a, b| a.max(b)).unwrap(); + let min_y = result.iter().map(|v: &Vertex| v.y).reduce(|a, b| a.min(b)).unwrap(); + let max_y = result.iter().map(|v: &Vertex| v.y).reduce(|a, b| a.max(b)).unwrap(); + assert_eq!(min_x, center.x - (radius + 0.5)); + assert_eq!(max_x, center.x + (radius + 0.5)); + assert_eq!(min_y, center.y - (radius + 0.5)); + assert_eq!(max_y, center.y + (radius + 0.5)); +} + |