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 ));
}
Messung V0.5 in Prozent C=88 H=99 G=93
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-19)
¤
*© Formatika GbR, Deutschland