1#![warn(missing_docs)]
182#![warn(clippy::all)]
183#![allow(clippy::missing_safety_doc)]
184#![allow(unsafe_op_in_unsafe_fn)]
185#![allow(non_camel_case_types)] pub mod abi;
188
189use std::ffi::{c_char, c_void};
190use std::panic::{self, AssertUnwindSafe};
191use std::ptr;
192use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
193
194static LAST_PANIC: AtomicBool = AtomicBool::new(false);
200
201#[unsafe(no_mangle)]
206pub extern "C" fn sk_last_call_panicked() -> bool {
207 LAST_PANIC.swap(false, Ordering::SeqCst)
208}
209
210#[inline]
212fn catch_panic<T: Default, F: FnOnce() -> T + panic::UnwindSafe>(f: F) -> T {
213 match panic::catch_unwind(f) {
214 Ok(result) => result,
215 Err(_) => {
216 LAST_PANIC.store(true, Ordering::SeqCst);
217 T::default()
218 }
219 }
220}
221
222#[inline]
224fn catch_panic_void<F: FnOnce() + panic::UnwindSafe>(f: F) {
225 if panic::catch_unwind(f).is_err() {
226 LAST_PANIC.store(true, Ordering::SeqCst);
227 }
228}
229
230#[repr(C)]
241pub struct RefCounted<T> {
242 refcnt: AtomicU32,
244 value: T,
246}
247
248impl<T> RefCounted<T> {
249 pub fn new(value: T) -> *mut Self {
251 Box::into_raw(Box::new(Self {
252 refcnt: AtomicU32::new(1),
253 value,
254 }))
255 }
256
257 pub unsafe fn ref_ptr(ptr: *mut Self) {
262 if let Some(rc) = ptr.as_ref() {
263 rc.refcnt.fetch_add(1, Ordering::Relaxed);
264 }
265 }
266
267 pub unsafe fn unref_ptr(ptr: *mut Self) -> bool {
273 if ptr.is_null() {
274 return false;
275 }
276
277 let rc = &*ptr;
278 if rc.refcnt.fetch_sub(1, Ordering::AcqRel) == 1 {
280 drop(Box::from_raw(ptr));
282 true
283 } else {
284 false
285 }
286 }
287
288 pub unsafe fn get_count(ptr: *const Self) -> u32 {
293 if let Some(rc) = ptr.as_ref() {
294 rc.refcnt.load(Ordering::Relaxed)
295 } else {
296 0
297 }
298 }
299
300 pub unsafe fn is_unique(ptr: *const Self) -> bool {
305 Self::get_count(ptr) == 1
306 }
307
308 pub unsafe fn get_ref<'a>(ptr: *const Self) -> Option<&'a T> {
313 ptr.as_ref().map(|rc| &rc.value)
314 }
315
316 pub unsafe fn get_mut<'a>(ptr: *mut Self) -> Option<&'a mut T> {
322 ptr.as_mut().map(|rc| &mut rc.value)
323 }
324}
325
326pub type sk_refcnt_t = c_void;
332
333#[unsafe(no_mangle)]
337pub unsafe extern "C" fn sk_refcnt_get_count(ptr: *const sk_refcnt_t) -> u32 {
338 if ptr.is_null() {
340 return 0;
341 }
342 let refcnt = ptr as *const AtomicU32;
343 (*refcnt).load(Ordering::Relaxed)
344}
345
346#[unsafe(no_mangle)]
348pub unsafe extern "C" fn sk_refcnt_is_unique(ptr: *const sk_refcnt_t) -> bool {
349 sk_refcnt_get_count(ptr) == 1
350}
351
352use skia_rs_canvas::{PixelBuffer, RasterCanvas, Surface};
354use skia_rs_core::{
355 AlphaType, Color, ColorType, IPoint, IRect, ISize, ImageInfo, Matrix, Point, Rect, Scalar, Size,
356};
357use skia_rs_paint::{BlendMode, Paint, Style};
358use skia_rs_path::{FillType, Path, PathBuilder};
359
360#[repr(C)]
372#[derive(Debug, Clone, Copy, Default)]
373pub struct sk_point_t {
374 pub x: f32,
376 pub y: f32,
378}
379
380#[repr(C)]
382#[derive(Debug, Clone, Copy, Default)]
383pub struct sk_ipoint_t {
384 pub x: i32,
386 pub y: i32,
388}
389
390#[repr(C)]
392#[derive(Debug, Clone, Copy, Default)]
393pub struct sk_size_t {
394 pub width: f32,
396 pub height: f32,
398}
399
400#[repr(C)]
402#[derive(Debug, Clone, Copy, Default)]
403pub struct sk_isize_t {
404 pub width: i32,
406 pub height: i32,
408}
409
410#[repr(C)]
412#[derive(Debug, Clone, Copy, Default)]
413pub struct sk_rect_t {
414 pub left: f32,
416 pub top: f32,
418 pub right: f32,
420 pub bottom: f32,
422}
423
424#[repr(C)]
426#[derive(Debug, Clone, Copy, Default)]
427pub struct sk_irect_t {
428 pub left: i32,
430 pub top: i32,
432 pub right: i32,
434 pub bottom: i32,
436}
437
438#[repr(C)]
440#[derive(Debug, Clone, Copy)]
441pub struct sk_matrix_t {
442 pub values: [f32; 9],
444}
445
446impl Default for sk_matrix_t {
447 fn default() -> Self {
448 Self {
449 values: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
450 }
451 }
452}
453
454#[repr(C)]
456#[derive(Debug, Clone, Copy)]
457pub struct sk_imageinfo_t {
458 pub width: i32,
460 pub height: i32,
462 pub color_type: u32,
464 pub alpha_type: u32,
466}
467
468pub type sk_color_t = u32;
470
471impl From<Point> for sk_point_t {
476 fn from(p: Point) -> Self {
477 Self { x: p.x, y: p.y }
478 }
479}
480
481impl From<sk_point_t> for Point {
482 fn from(p: sk_point_t) -> Self {
483 Point::new(p.x, p.y)
484 }
485}
486
487impl From<Rect> for sk_rect_t {
488 fn from(r: Rect) -> Self {
489 Self {
490 left: r.left,
491 top: r.top,
492 right: r.right,
493 bottom: r.bottom,
494 }
495 }
496}
497
498impl From<sk_rect_t> for Rect {
499 fn from(r: sk_rect_t) -> Self {
500 Rect::new(r.left, r.top, r.right, r.bottom)
501 }
502}
503
504impl From<Matrix> for sk_matrix_t {
505 fn from(m: Matrix) -> Self {
506 Self { values: m.values }
507 }
508}
509
510impl From<sk_matrix_t> for Matrix {
511 fn from(m: sk_matrix_t) -> Self {
512 Matrix { values: m.values }
513 }
514}
515
516pub type sk_surface_t = RefCounted<Surface>;
522
523#[unsafe(no_mangle)]
527pub unsafe extern "C" fn sk_surface_new_raster(width: i32, height: i32) -> *mut sk_surface_t {
528 catch_panic(|| match Surface::new_raster_n32_premul(width, height) {
529 Some(surface) => RefCounted::new(surface),
530 None => ptr::null_mut(),
531 })
532}
533
534#[unsafe(no_mangle)]
538pub unsafe extern "C" fn sk_surface_new_raster_with_info(
539 info: *const sk_imageinfo_t,
540) -> *mut sk_surface_t {
541 if info.is_null() {
542 return ptr::null_mut();
543 }
544
545 let info = &*info;
546 let color_type = match info.color_type {
547 0 => ColorType::Unknown,
548 1 => ColorType::Alpha8,
549 2 => ColorType::Rgb565,
550 3 => ColorType::Argb4444,
551 4 => ColorType::Rgba8888,
552 5 => ColorType::Bgra8888,
553 _ => ColorType::Rgba8888,
554 };
555
556 let alpha_type = match info.alpha_type {
557 0 => AlphaType::Unknown,
558 1 => AlphaType::Opaque,
559 2 => AlphaType::Premul,
560 3 => AlphaType::Unpremul,
561 _ => AlphaType::Premul,
562 };
563
564 let img_info = match ImageInfo::new(info.width, info.height, color_type, alpha_type) {
565 Ok(i) => i,
566 Err(_) => return ptr::null_mut(),
567 };
568
569 match Surface::new_raster(&img_info, None) {
570 Some(surface) => RefCounted::new(surface),
571 None => ptr::null_mut(),
572 }
573}
574
575#[unsafe(no_mangle)]
577pub unsafe extern "C" fn sk_surface_ref(surface: *mut sk_surface_t) {
578 RefCounted::ref_ptr(surface);
579}
580
581#[unsafe(no_mangle)]
585pub unsafe extern "C" fn sk_surface_unref(surface: *mut sk_surface_t) {
586 catch_panic_void(AssertUnwindSafe(|| {
587 RefCounted::unref_ptr(surface);
588 }));
589}
590
591#[unsafe(no_mangle)]
593pub unsafe extern "C" fn sk_surface_get_refcnt(surface: *const sk_surface_t) -> u32 {
594 RefCounted::get_count(surface)
595}
596
597#[unsafe(no_mangle)]
599pub unsafe extern "C" fn sk_surface_is_unique(surface: *const sk_surface_t) -> bool {
600 RefCounted::is_unique(surface)
601}
602
603#[unsafe(no_mangle)]
605pub unsafe extern "C" fn sk_surface_get_width(surface: *const sk_surface_t) -> i32 {
606 RefCounted::get_ref(surface).map_or(0, |s| s.width())
607}
608
609#[unsafe(no_mangle)]
611pub unsafe extern "C" fn sk_surface_get_height(surface: *const sk_surface_t) -> i32 {
612 RefCounted::get_ref(surface).map_or(0, |s| s.height())
613}
614
615#[unsafe(no_mangle)]
617pub unsafe extern "C" fn sk_surface_peek_pixels(
618 surface: *const sk_surface_t,
619 out_pixels: *mut *const u8,
620 out_row_bytes: *mut usize,
621) -> bool {
622 if out_pixels.is_null() || out_row_bytes.is_null() {
623 return false;
624 }
625
626 if let Some(s) = RefCounted::get_ref(surface) {
627 *out_pixels = s.pixels().as_ptr();
628 *out_row_bytes = s.row_bytes();
629 true
630 } else {
631 false
632 }
633}
634
635pub type sk_paint_t = RefCounted<Paint>;
641
642#[unsafe(no_mangle)]
646pub unsafe extern "C" fn sk_paint_new() -> *mut sk_paint_t {
647 catch_panic(|| RefCounted::new(Paint::new()))
648}
649
650#[unsafe(no_mangle)]
654pub unsafe extern "C" fn sk_paint_clone(paint: *const sk_paint_t) -> *mut sk_paint_t {
655 RefCounted::get_ref(paint).map_or(ptr::null_mut(), |p| RefCounted::new(p.clone()))
656}
657
658#[unsafe(no_mangle)]
660pub unsafe extern "C" fn sk_paint_ref(paint: *mut sk_paint_t) {
661 RefCounted::ref_ptr(paint);
662}
663
664#[unsafe(no_mangle)]
666pub unsafe extern "C" fn sk_paint_delete(paint: *mut sk_paint_t) {
667 RefCounted::unref_ptr(paint);
668}
669
670#[unsafe(no_mangle)]
674pub unsafe extern "C" fn sk_paint_unref(paint: *mut sk_paint_t) {
675 RefCounted::unref_ptr(paint);
676}
677
678#[unsafe(no_mangle)]
680pub unsafe extern "C" fn sk_paint_get_refcnt(paint: *const sk_paint_t) -> u32 {
681 RefCounted::get_count(paint)
682}
683
684#[unsafe(no_mangle)]
686pub unsafe extern "C" fn sk_paint_set_color(paint: *mut sk_paint_t, color: sk_color_t) {
687 if let Some(p) = RefCounted::get_mut(paint) {
688 p.set_color32(Color(color));
689 }
690}
691
692#[unsafe(no_mangle)]
694pub unsafe extern "C" fn sk_paint_get_color(paint: *const sk_paint_t) -> sk_color_t {
695 RefCounted::get_ref(paint).map_or(0, |p| p.color32().0)
696}
697
698#[unsafe(no_mangle)]
700pub unsafe extern "C" fn sk_paint_set_style(paint: *mut sk_paint_t, style: u32) {
701 if let Some(p) = RefCounted::get_mut(paint) {
702 let style = match style {
703 0 => Style::Fill,
704 1 => Style::Stroke,
705 2 => Style::StrokeAndFill,
706 _ => Style::Fill,
707 };
708 p.set_style(style);
709 }
710}
711
712#[unsafe(no_mangle)]
714pub unsafe extern "C" fn sk_paint_set_stroke_width(paint: *mut sk_paint_t, width: f32) {
715 if let Some(p) = RefCounted::get_mut(paint) {
716 p.set_stroke_width(width);
717 }
718}
719
720#[unsafe(no_mangle)]
722pub unsafe extern "C" fn sk_paint_get_stroke_width(paint: *const sk_paint_t) -> f32 {
723 RefCounted::get_ref(paint).map_or(0.0, |p| p.stroke_width())
724}
725
726#[unsafe(no_mangle)]
728pub unsafe extern "C" fn sk_paint_set_antialias(paint: *mut sk_paint_t, aa: bool) {
729 if let Some(p) = RefCounted::get_mut(paint) {
730 p.set_anti_alias(aa);
731 }
732}
733
734#[unsafe(no_mangle)]
736pub unsafe extern "C" fn sk_paint_is_antialias(paint: *const sk_paint_t) -> bool {
737 RefCounted::get_ref(paint).map_or(false, |p| p.is_anti_alias())
738}
739
740pub type sk_path_t = RefCounted<Path>;
746
747#[unsafe(no_mangle)]
751pub unsafe extern "C" fn sk_path_new() -> *mut sk_path_t {
752 RefCounted::new(Path::new())
753}
754
755#[unsafe(no_mangle)]
759pub unsafe extern "C" fn sk_path_clone(path: *const sk_path_t) -> *mut sk_path_t {
760 RefCounted::get_ref(path).map_or(ptr::null_mut(), |p| RefCounted::new(p.clone()))
761}
762
763#[unsafe(no_mangle)]
765pub unsafe extern "C" fn sk_path_ref(path: *mut sk_path_t) {
766 RefCounted::ref_ptr(path);
767}
768
769#[unsafe(no_mangle)]
771pub unsafe extern "C" fn sk_path_delete(path: *mut sk_path_t) {
772 RefCounted::unref_ptr(path);
773}
774
775#[unsafe(no_mangle)]
779pub unsafe extern "C" fn sk_path_unref(path: *mut sk_path_t) {
780 RefCounted::unref_ptr(path);
781}
782
783#[unsafe(no_mangle)]
785pub unsafe extern "C" fn sk_path_get_refcnt(path: *const sk_path_t) -> u32 {
786 RefCounted::get_count(path)
787}
788
789#[unsafe(no_mangle)]
791pub unsafe extern "C" fn sk_path_get_bounds(path: *const sk_path_t, bounds: *mut sk_rect_t) {
792 if let (Some(p), Some(b)) = (RefCounted::get_ref(path), bounds.as_mut()) {
793 let rect = p.bounds();
794 *b = rect.into();
795 }
796}
797
798#[unsafe(no_mangle)]
800pub unsafe extern "C" fn sk_path_is_empty(path: *const sk_path_t) -> bool {
801 RefCounted::get_ref(path).map_or(true, |p| p.is_empty())
802}
803
804#[unsafe(no_mangle)]
806pub unsafe extern "C" fn sk_path_get_filltype(path: *const sk_path_t) -> u32 {
807 RefCounted::get_ref(path).map_or(0, |p| match p.fill_type() {
808 FillType::Winding => 0,
809 FillType::EvenOdd => 1,
810 FillType::InverseWinding => 2,
811 FillType::InverseEvenOdd => 3,
812 })
813}
814
815#[unsafe(no_mangle)]
817pub unsafe extern "C" fn sk_path_set_filltype(path: *mut sk_path_t, fill_type: u32) {
818 if let Some(p) = RefCounted::get_mut(path) {
819 let ft = match fill_type {
820 0 => FillType::Winding,
821 1 => FillType::EvenOdd,
822 2 => FillType::InverseWinding,
823 3 => FillType::InverseEvenOdd,
824 _ => FillType::Winding,
825 };
826 p.set_fill_type(ft);
827 }
828}
829
830#[unsafe(no_mangle)]
832pub unsafe extern "C" fn sk_path_contains(path: *const sk_path_t, x: f32, y: f32) -> bool {
833 RefCounted::get_ref(path).map_or(false, |p| p.contains(Point::new(x, y)))
834}
835
836pub type sk_pathbuilder_t = RefCounted<PathBuilder>;
842
843#[unsafe(no_mangle)]
847pub unsafe extern "C" fn sk_pathbuilder_new() -> *mut sk_pathbuilder_t {
848 RefCounted::new(PathBuilder::new())
849}
850
851#[unsafe(no_mangle)]
853pub unsafe extern "C" fn sk_pathbuilder_ref(builder: *mut sk_pathbuilder_t) {
854 RefCounted::ref_ptr(builder);
855}
856
857#[unsafe(no_mangle)]
859pub unsafe extern "C" fn sk_pathbuilder_delete(builder: *mut sk_pathbuilder_t) {
860 RefCounted::unref_ptr(builder);
861}
862
863#[unsafe(no_mangle)]
867pub unsafe extern "C" fn sk_pathbuilder_unref(builder: *mut sk_pathbuilder_t) {
868 RefCounted::unref_ptr(builder);
869}
870
871#[unsafe(no_mangle)]
873pub unsafe extern "C" fn sk_pathbuilder_move_to(builder: *mut sk_pathbuilder_t, x: f32, y: f32) {
874 if let Some(b) = RefCounted::get_mut(builder) {
875 b.move_to(x, y);
876 }
877}
878
879#[unsafe(no_mangle)]
881pub unsafe extern "C" fn sk_pathbuilder_line_to(builder: *mut sk_pathbuilder_t, x: f32, y: f32) {
882 if let Some(b) = RefCounted::get_mut(builder) {
883 b.line_to(x, y);
884 }
885}
886
887#[unsafe(no_mangle)]
889pub unsafe extern "C" fn sk_pathbuilder_quad_to(
890 builder: *mut sk_pathbuilder_t,
891 cx: f32,
892 cy: f32,
893 x: f32,
894 y: f32,
895) {
896 if let Some(b) = RefCounted::get_mut(builder) {
897 b.quad_to(cx, cy, x, y);
898 }
899}
900
901#[unsafe(no_mangle)]
903pub unsafe extern "C" fn sk_pathbuilder_cubic_to(
904 builder: *mut sk_pathbuilder_t,
905 c1x: f32,
906 c1y: f32,
907 c2x: f32,
908 c2y: f32,
909 x: f32,
910 y: f32,
911) {
912 if let Some(b) = RefCounted::get_mut(builder) {
913 b.cubic_to(c1x, c1y, c2x, c2y, x, y);
914 }
915}
916
917#[unsafe(no_mangle)]
919pub unsafe extern "C" fn sk_pathbuilder_close(builder: *mut sk_pathbuilder_t) {
920 if let Some(b) = RefCounted::get_mut(builder) {
921 b.close();
922 }
923}
924
925#[unsafe(no_mangle)]
927pub unsafe extern "C" fn sk_pathbuilder_add_rect(
928 builder: *mut sk_pathbuilder_t,
929 rect: *const sk_rect_t,
930) {
931 if let (Some(b), Some(r)) = (RefCounted::get_mut(builder), rect.as_ref()) {
932 b.add_rect(&Rect::from(*r));
933 }
934}
935
936#[unsafe(no_mangle)]
938pub unsafe extern "C" fn sk_pathbuilder_add_oval(
939 builder: *mut sk_pathbuilder_t,
940 rect: *const sk_rect_t,
941) {
942 if let (Some(b), Some(r)) = (RefCounted::get_mut(builder), rect.as_ref()) {
943 b.add_oval(&Rect::from(*r));
944 }
945}
946
947#[unsafe(no_mangle)]
949pub unsafe extern "C" fn sk_pathbuilder_add_circle(
950 builder: *mut sk_pathbuilder_t,
951 cx: f32,
952 cy: f32,
953 radius: f32,
954) {
955 if let Some(b) = RefCounted::get_mut(builder) {
956 b.add_circle(cx, cy, radius);
957 }
958}
959
960#[unsafe(no_mangle)]
965pub unsafe extern "C" fn sk_pathbuilder_detach(builder: *mut sk_pathbuilder_t) -> *mut sk_path_t {
966 if let Some(b) = RefCounted::get_mut(builder) {
967 let path = std::mem::replace(b, PathBuilder::new()).build();
968 RefCounted::new(path)
969 } else {
970 ptr::null_mut()
971 }
972}
973
974#[unsafe(no_mangle)]
979pub unsafe extern "C" fn sk_pathbuilder_snapshot(
980 builder: *const sk_pathbuilder_t,
981) -> *mut sk_path_t {
982 RefCounted::get_ref(builder).map_or(ptr::null_mut(), |b| RefCounted::new(b.clone().build()))
983}
984
985#[unsafe(no_mangle)]
991pub unsafe extern "C" fn sk_matrix_set_identity(matrix: *mut sk_matrix_t) {
992 if let Some(m) = matrix.as_mut() {
993 *m = sk_matrix_t::default();
994 }
995}
996
997#[unsafe(no_mangle)]
999pub unsafe extern "C" fn sk_matrix_set_translate(matrix: *mut sk_matrix_t, dx: f32, dy: f32) {
1000 if let Some(m) = matrix.as_mut() {
1001 *m = Matrix::translate(dx, dy).into();
1002 }
1003}
1004
1005#[unsafe(no_mangle)]
1007pub unsafe extern "C" fn sk_matrix_set_scale(matrix: *mut sk_matrix_t, sx: f32, sy: f32) {
1008 if let Some(m) = matrix.as_mut() {
1009 *m = Matrix::scale(sx, sy).into();
1010 }
1011}
1012
1013#[unsafe(no_mangle)]
1015pub unsafe extern "C" fn sk_matrix_set_rotate(matrix: *mut sk_matrix_t, degrees: f32) {
1016 if let Some(m) = matrix.as_mut() {
1017 let radians = degrees * std::f32::consts::PI / 180.0;
1018 *m = Matrix::rotate(radians).into();
1019 }
1020}
1021
1022#[unsafe(no_mangle)]
1024pub unsafe extern "C" fn sk_matrix_concat(
1025 result: *mut sk_matrix_t,
1026 a: *const sk_matrix_t,
1027 b: *const sk_matrix_t,
1028) {
1029 if let (Some(r), Some(a), Some(b)) = (result.as_mut(), a.as_ref(), b.as_ref()) {
1030 let ma: Matrix = (*a).into();
1031 let mb: Matrix = (*b).into();
1032 *r = ma.concat(&mb).into();
1033 }
1034}
1035
1036#[unsafe(no_mangle)]
1038pub unsafe extern "C" fn sk_matrix_map_point(
1039 matrix: *const sk_matrix_t,
1040 point: *const sk_point_t,
1041 result: *mut sk_point_t,
1042) {
1043 if let (Some(m), Some(p), Some(r)) = (matrix.as_ref(), point.as_ref(), result.as_mut()) {
1044 let mat: Matrix = (*m).into();
1045 let pt: Point = (*p).into();
1046 *r = mat.map_point(pt).into();
1047 }
1048}
1049
1050#[unsafe(no_mangle)]
1056pub unsafe extern "C" fn sk_version() -> *const c_char {
1057 static VERSION: &[u8] = b"skia-rs 0.1.0\0";
1058 VERSION.as_ptr() as *const c_char
1059}
1060
1061#[unsafe(no_mangle)]
1063pub unsafe extern "C" fn sk_is_available() -> bool {
1064 true
1065}
1066
1067#[unsafe(no_mangle)]
1073pub unsafe extern "C" fn sk_surface_clear(surface: *mut sk_surface_t, color: sk_color_t) {
1074 if let Some(s) = RefCounted::get_mut(surface) {
1075 let mut canvas = s.raster_canvas();
1076 canvas.clear(Color(color));
1077 }
1078}
1079
1080#[unsafe(no_mangle)]
1082pub unsafe extern "C" fn sk_surface_draw_rect(
1083 surface: *mut sk_surface_t,
1084 rect: *const sk_rect_t,
1085 paint: *const sk_paint_t,
1086) {
1087 if let (Some(s), Some(r), Some(p)) = (
1088 RefCounted::get_mut(surface),
1089 rect.as_ref(),
1090 RefCounted::get_ref(paint),
1091 ) {
1092 let mut canvas = s.raster_canvas();
1093 canvas.draw_rect(&Rect::from(*r), p);
1094 }
1095}
1096
1097#[unsafe(no_mangle)]
1099pub unsafe extern "C" fn sk_surface_draw_circle(
1100 surface: *mut sk_surface_t,
1101 cx: f32,
1102 cy: f32,
1103 radius: f32,
1104 paint: *const sk_paint_t,
1105) {
1106 if let (Some(s), Some(p)) = (RefCounted::get_mut(surface), RefCounted::get_ref(paint)) {
1107 let mut canvas = s.raster_canvas();
1108 canvas.draw_circle(Point::new(cx, cy), radius, p);
1109 }
1110}
1111
1112#[unsafe(no_mangle)]
1114pub unsafe extern "C" fn sk_surface_draw_path(
1115 surface: *mut sk_surface_t,
1116 path: *const sk_path_t,
1117 paint: *const sk_paint_t,
1118) {
1119 if let (Some(s), Some(path), Some(p)) = (
1120 RefCounted::get_mut(surface),
1121 RefCounted::get_ref(path),
1122 RefCounted::get_ref(paint),
1123 ) {
1124 let mut canvas = s.raster_canvas();
1125 canvas.draw_path(path, p);
1126 }
1127}
1128
1129#[unsafe(no_mangle)]
1131pub unsafe extern "C" fn sk_surface_draw_line(
1132 surface: *mut sk_surface_t,
1133 x0: f32,
1134 y0: f32,
1135 x1: f32,
1136 y1: f32,
1137 paint: *const sk_paint_t,
1138) {
1139 if let (Some(s), Some(p)) = (RefCounted::get_mut(surface), RefCounted::get_ref(paint)) {
1140 let mut canvas = s.raster_canvas();
1141 canvas.draw_line(Point::new(x0, y0), Point::new(x1, y1), p);
1142 }
1143}
1144
1145#[cfg(test)]
1146mod tests {
1147 use super::*;
1148
1149 #[test]
1150 fn test_surface_creation() {
1151 unsafe {
1152 let surface = sk_surface_new_raster(100, 100);
1153 assert!(!surface.is_null());
1154 assert_eq!(sk_surface_get_width(surface), 100);
1155 assert_eq!(sk_surface_get_height(surface), 100);
1156 assert_eq!(sk_surface_get_refcnt(surface), 1);
1157 sk_surface_unref(surface);
1158 }
1159 }
1160
1161 #[test]
1162 fn test_surface_refcounting() {
1163 unsafe {
1164 let surface = sk_surface_new_raster(100, 100);
1165 assert_eq!(sk_surface_get_refcnt(surface), 1);
1166 assert!(sk_surface_is_unique(surface));
1167
1168 sk_surface_ref(surface);
1169 assert_eq!(sk_surface_get_refcnt(surface), 2);
1170 assert!(!sk_surface_is_unique(surface));
1171
1172 sk_surface_unref(surface);
1173 assert_eq!(sk_surface_get_refcnt(surface), 1);
1174 assert!(sk_surface_is_unique(surface));
1175
1176 sk_surface_unref(surface); }
1178 }
1179
1180 #[test]
1181 fn test_paint_operations() {
1182 unsafe {
1183 let paint = sk_paint_new();
1184 assert!(!paint.is_null());
1185 assert_eq!(sk_paint_get_refcnt(paint), 1);
1186
1187 sk_paint_set_color(paint, 0xFF0000FF); assert_eq!(sk_paint_get_color(paint), 0xFF0000FF);
1189
1190 sk_paint_set_stroke_width(paint, 2.0);
1191 assert_eq!(sk_paint_get_stroke_width(paint), 2.0);
1192
1193 sk_paint_delete(paint);
1194 }
1195 }
1196
1197 #[test]
1198 fn test_paint_refcounting() {
1199 unsafe {
1200 let paint = sk_paint_new();
1201 assert_eq!(sk_paint_get_refcnt(paint), 1);
1202
1203 sk_paint_ref(paint);
1204 assert_eq!(sk_paint_get_refcnt(paint), 2);
1205
1206 sk_paint_unref(paint);
1207 assert_eq!(sk_paint_get_refcnt(paint), 1);
1208
1209 let paint2 = sk_paint_clone(paint);
1211 assert_eq!(sk_paint_get_refcnt(paint), 1);
1212 assert_eq!(sk_paint_get_refcnt(paint2), 1);
1213
1214 sk_paint_unref(paint);
1215 sk_paint_unref(paint2);
1216 }
1217 }
1218
1219 #[test]
1220 fn test_path_builder() {
1221 unsafe {
1222 let builder = sk_pathbuilder_new();
1223 assert!(!builder.is_null());
1224
1225 sk_pathbuilder_move_to(builder, 0.0, 0.0);
1226 sk_pathbuilder_line_to(builder, 100.0, 0.0);
1227 sk_pathbuilder_line_to(builder, 100.0, 100.0);
1228 sk_pathbuilder_close(builder);
1229
1230 let path = sk_pathbuilder_detach(builder);
1231 assert!(!path.is_null());
1232 assert!(!sk_path_is_empty(path));
1233 assert_eq!(sk_path_get_refcnt(path), 1);
1234
1235 let mut bounds = sk_rect_t::default();
1236 sk_path_get_bounds(path, &mut bounds);
1237 assert_eq!(bounds.left, 0.0);
1238 assert_eq!(bounds.right, 100.0);
1239
1240 sk_path_delete(path);
1241 sk_pathbuilder_delete(builder);
1242 }
1243 }
1244
1245 #[test]
1246 fn test_path_refcounting() {
1247 unsafe {
1248 let path = sk_path_new();
1249 assert_eq!(sk_path_get_refcnt(path), 1);
1250
1251 sk_path_ref(path);
1252 assert_eq!(sk_path_get_refcnt(path), 2);
1253
1254 let path2 = sk_path_clone(path);
1255 assert_eq!(sk_path_get_refcnt(path), 2);
1256 assert_eq!(sk_path_get_refcnt(path2), 1);
1257
1258 sk_path_unref(path);
1259 assert_eq!(sk_path_get_refcnt(path), 1);
1260
1261 sk_path_unref(path);
1262 sk_path_unref(path2);
1263 }
1264 }
1265
1266 #[test]
1267 fn test_matrix_operations() {
1268 unsafe {
1269 let mut matrix = sk_matrix_t::default();
1270 sk_matrix_set_translate(&mut matrix, 10.0, 20.0);
1271
1272 let point = sk_point_t { x: 0.0, y: 0.0 };
1273 let mut result = sk_point_t::default();
1274 sk_matrix_map_point(&matrix, &point, &mut result);
1275
1276 assert_eq!(result.x, 10.0);
1277 assert_eq!(result.y, 20.0);
1278 }
1279 }
1280
1281 #[test]
1282 fn test_draw_rect() {
1283 unsafe {
1284 let surface = sk_surface_new_raster(100, 100);
1285 let paint = sk_paint_new();
1286 sk_paint_set_color(paint, 0xFFFF0000); sk_surface_clear(surface, 0xFFFFFFFF); let rect = sk_rect_t {
1291 left: 10.0,
1292 top: 10.0,
1293 right: 50.0,
1294 bottom: 50.0,
1295 };
1296 sk_surface_draw_rect(surface, &rect, paint);
1297
1298 sk_paint_delete(paint);
1299 sk_surface_unref(surface);
1300 }
1301 }
1302
1303 #[test]
1304 fn test_refcnt_utility() {
1305 unsafe {
1306 let surface = sk_surface_new_raster(100, 100);
1307
1308 let ptr = surface as *const sk_refcnt_t;
1310 assert_eq!(sk_refcnt_get_count(ptr), 1);
1311 assert!(sk_refcnt_is_unique(ptr));
1312
1313 sk_surface_ref(surface);
1314 assert_eq!(sk_refcnt_get_count(ptr), 2);
1315 assert!(!sk_refcnt_is_unique(ptr));
1316
1317 sk_surface_unref(surface);
1318 sk_surface_unref(surface);
1319 }
1320 }
1321}