From 36db39883cbfa6ea989bcd283cac2e4c5f40aed0 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 20 Jun 2019 16:07:38 -0700 Subject: [PATCH] Add C bindings to the canvas text APIs --- Cargo.lock | 1 + c/Cargo.toml | 1 + c/include/pathfinder/pathfinder.h | 16 +++++++++ c/src/lib.rs | 56 ++++++++++++++++++++++++++++++- 4 files changed, 73 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index c35ee108..55ca57e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1318,6 +1318,7 @@ name = "pathfinder_c" version = "0.1.0" dependencies = [ "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", diff --git a/c/Cargo.toml b/c/Cargo.toml index 7c17d4b2..ea2c8146 100644 --- a/c/Cargo.toml +++ b/c/Cargo.toml @@ -9,6 +9,7 @@ crate-type = ["staticlib"] [dependencies] gl = "0.6" +libc = "0.2" [dependencies.pathfinder_canvas] path = "../canvas" diff --git a/c/include/pathfinder/pathfinder.h b/c/include/pathfinder/pathfinder.h index 6073bb51..2833da22 100644 --- a/c/include/pathfinder/pathfinder.h +++ b/c/include/pathfinder/pathfinder.h @@ -56,6 +56,10 @@ typedef struct PFCanvasFontContext *PFCanvasFontContextRef; typedef uint8_t PFLineCap; typedef uint8_t PFLineJoin; typedef uint8_t PFArcDirection; +struct PFTextMetrics { + float width; +}; +typedef struct PFTextMetrics PFTextMetrics; // `geometry` @@ -125,6 +129,18 @@ PFCanvasFontContextRef PFCanvasFontContextClone(PFCanvasFontContextRef font_cont PFSceneRef PFCanvasCreateScene(PFCanvasRef canvas); void PFCanvasFillRect(PFCanvasRef canvas, const PFRectF *rect); void PFCanvasStrokeRect(PFCanvasRef canvas, const PFRectF *rect); +void PFCanvasFillText(PFCanvasRef canvas, + const char *string, + size_t string_len, + const PFVector2F *position); +void PFCanvasStrokeText(PFCanvasRef canvas, + const char *string, + size_t string_len, + const PFVector2F *position); +void PFCanvasMeasureText(PFCanvasRef canvas, + const char *string, + size_t string_len, + PFTextMetrics *out_text_metrics); void PFCanvasSetLineWidth(PFCanvasRef canvas, float new_line_width); void PFCanvasSetLineCap(PFCanvasRef canvas, PFLineCap new_line_cap); void PFCanvasSetLineJoin(PFCanvasRef canvas, PFLineJoin new_line_join); diff --git a/c/src/lib.rs b/c/src/lib.rs index 4fc204f2..f071bdba 100644 --- a/c/src/lib.rs +++ b/c/src/lib.rs @@ -11,7 +11,8 @@ //! C bindings to Pathfinder. use gl; -use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, LineJoin, Path2D}; +use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, LineJoin}; +use pathfinder_canvas::{Path2D, TextMetrics}; use pathfinder_geometry::basic::rect::{RectF, RectI}; use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; use pathfinder_geometry::color::ColorF; @@ -29,6 +30,7 @@ use pathfinder_simd::default::F32x4; use std::ffi::CString; use std::os::raw::{c_char, c_void}; use std::slice; +use std::str; // Constants @@ -60,6 +62,10 @@ pub type PFCanvasFontContextRef = *mut CanvasFontContext; pub type PFLineCap = u8; pub type PFLineJoin = u8; pub type PFArcDirection = u8; +#[repr(C)] +pub struct PFTextMetrics { + pub width: f32, +} // `geometry` #[repr(C)] @@ -155,6 +161,8 @@ pub unsafe extern "C" fn PFCanvasCreateScene(canvas: PFCanvasRef) -> PFSceneRef Box::into_raw(Box::new(Box::from_raw(canvas).into_scene())) } +// Drawing rectangles + #[no_mangle] pub unsafe extern "C" fn PFCanvasFillRect(canvas: PFCanvasRef, rect: *const PFRectF) { (*canvas).fill_rect((*rect).to_rust()) @@ -165,6 +173,33 @@ pub unsafe extern "C" fn PFCanvasStrokeRect(canvas: PFCanvasRef, rect: *const PF (*canvas).stroke_rect((*rect).to_rust()) } +// Drawing text + +#[no_mangle] +pub unsafe extern "C" fn PFCanvasFillText(canvas: PFCanvasRef, + string: *const c_char, + string_len: usize, + position: *const PFVector2F) { + (*canvas).fill_text(to_rust_string(&string, string_len), (*position).to_rust()) +} + +#[no_mangle] +pub unsafe extern "C" fn PFCanvasStrokeText(canvas: PFCanvasRef, + string: *const c_char, + string_len: usize, + position: *const PFVector2F) { + (*canvas).stroke_text(to_rust_string(&string, string_len), (*position).to_rust()) +} + +#[no_mangle] +pub unsafe extern "C" fn PFCanvasMeasureText(canvas: PFCanvasRef, + string: *const c_char, + string_len: usize, + out_text_metrics: *mut PFTextMetrics) { + debug_assert!(!out_text_metrics.is_null()); + *out_text_metrics = (*canvas).measure_text(to_rust_string(&string, string_len)).to_c() +} + #[no_mangle] pub unsafe extern "C" fn PFCanvasSetLineWidth(canvas: PFCanvasRef, new_line_width: f32) { (*canvas).set_line_width(new_line_width) @@ -389,6 +424,25 @@ pub unsafe extern "C" fn PFSceneProxyDestroy(scene_proxy: PFSceneProxyRef) { drop(Box::from_raw(scene_proxy)) } +// Helpers for `canvas` + +unsafe fn to_rust_string(ptr: &*const c_char, mut len: usize) -> &str { + if len == 0 { + len = libc::strlen(*ptr); + } + str::from_utf8(slice::from_raw_parts(*ptr as *const u8, len)).unwrap() +} + +trait TextMetricsExt { + fn to_c(&self) -> PFTextMetrics; +} + +impl TextMetricsExt for TextMetrics { + fn to_c(&self) -> PFTextMetrics { + PFTextMetrics { width: self.width } + } +} + // Helpers for `geometry` impl PFColorF {