Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/aa-stroke/src/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 5 kB image not shown  

Quelle  c_bindings.rs   Sprache: unbekannt

 
Spracherkennung für: .rs vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

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));
}


[ Dauer der Verarbeitung: 0.34 Sekunden  ]