clipper2c-sys 0.1.5

Exposing unsafe FFI for Clipper2 library for Rust.
Documentation
use crate::{
    clipper_allocate, clipper_clipper64, clipper_clipper64_add_clip, clipper_clipper64_add_subject,
    clipper_clipper64_execute, clipper_clipper64_size, clipper_delete_clipper64,
    clipper_delete_path64, clipper_delete_paths64, clipper_path64_of_points, clipper_path64_size,
    clipper_paths64_get_point, clipper_paths64_length, clipper_paths64_of_paths,
    clipper_paths64_path_length, clipper_paths64_size, ClipperClipType_DIFFERENCE,
    ClipperFillRule_EVEN_ODD, ClipperPoint64,
};

unsafe fn malloc(size: usize) -> *mut libc::c_void {
    clipper_allocate(size)
}

#[test]
fn test_difference_boolean_operation() {
    let mut triangle = vec![
        ClipperPoint64 { x: 0, y: 0 },
        ClipperPoint64 { x: 10, y: 0 },
        ClipperPoint64 { x: 5, y: 10 },
    ];

    let mut square = vec![
        ClipperPoint64 { x: 0, y: 0 },
        ClipperPoint64 { x: 4, y: 0 },
        ClipperPoint64 { x: 4, y: 4 },
        ClipperPoint64 { x: 0, y: 4 },
    ];

    for _ in 0..1_000 {
        let output = unsafe {
            let subject_mem = malloc(clipper_path64_size());
            let subject_ptr =
                clipper_path64_of_points(subject_mem, triangle.as_mut_ptr(), triangle.len());

            let subjects_mem = malloc(clipper_paths64_size());
            let subjects_ptr =
                clipper_paths64_of_paths(subjects_mem, [subject_ptr].as_mut_ptr(), 1);

            let clip_mem = malloc(clipper_path64_size());
            let clip_ptr = clipper_path64_of_points(clip_mem, square.as_mut_ptr(), square.len());

            let clips_mem = malloc(clipper_paths64_size());
            let clips_ptr = clipper_paths64_of_paths(clips_mem, [clip_ptr].as_mut_ptr(), 1);

            let clipper_mem = malloc(clipper_clipper64_size());
            let clipper_ptr = clipper_clipper64(clipper_mem);

            clipper_clipper64_add_subject(clipper_ptr, subjects_ptr);
            clipper_clipper64_add_clip(clipper_ptr, clips_ptr);

            clipper_delete_path64(subject_ptr);
            clipper_delete_paths64(subjects_ptr);
            clipper_delete_path64(clip_ptr);
            clipper_delete_paths64(clips_ptr);

            let closed_path_mem = malloc(clipper_paths64_size());
            let closed_path_ptr = clipper_paths64_of_paths(closed_path_mem, [].as_mut_ptr(), 0);

            let open_path_mem = malloc(clipper_paths64_size());
            let open_path_ptr = clipper_paths64_of_paths(open_path_mem, [].as_mut_ptr(), 0);

            let success = clipper_clipper64_execute(
                clipper_ptr,
                ClipperClipType_DIFFERENCE,
                ClipperFillRule_EVEN_ODD,
                closed_path_ptr,
                open_path_ptr,
            );

            assert_eq!(success, 1);

            let len: i32 = clipper_paths64_length(closed_path_ptr).try_into().unwrap();

            let output = (0..len)
                .map(|i| {
                    let point_len: i32 = clipper_paths64_path_length(closed_path_ptr, i)
                        .try_into()
                        .unwrap();
                    (0..point_len)
                        .map(|j| clipper_paths64_get_point(closed_path_ptr, i, j))
                        .map(|p| (p.x, p.y))
                        .collect::<Vec<_>>()
                })
                .collect::<Vec<_>>();

            clipper_delete_paths64(closed_path_ptr);
            clipper_delete_paths64(open_path_ptr);

            clipper_delete_clipper64(clipper_ptr);

            output
        };

        let expected_output = vec![vec![(5, 10), (2, 4), (4, 4), (4, 0), (10, 0)]];
        assert_eq!(output, expected_output);
    }
}