Adjust C APIs to improve performance and clean-up a tiny bit

This commit is contained in:
Michael Pfaff 2024-06-19 00:07:55 -04:00
parent 4ac0bbae7e
commit 5fa9e8f883
3 changed files with 70 additions and 31 deletions

View File

@ -4,9 +4,6 @@ version = "0.1.0"
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
edition = "2018"
[features]
capi = []
[lib]
crate-type = ["staticlib", "cdylib"]
name = "pathfinder"

View File

@ -10,6 +10,7 @@
//! C bindings to Pathfinder.
use font_kit::font::Font;
use font_kit::handle::Handle;
use gl;
use pathfinder_canvas::{Canvas, CanvasFontContext, CanvasRenderingContext2D, FillStyle, LineJoin};
@ -40,7 +41,7 @@ use pathfinder_svg::SVGScene;
use std::ffi::CString;
use std::os::raw::{c_char, c_void};
use std::path::PathBuf;
use std::ptr;
use std::ptr::{self, NonNull};
use std::slice;
use std::str;
use usvg::{Options, Tree};
@ -108,6 +109,7 @@ pub type FKHandleRef = *mut Handle;
pub type PFCanvasRef = *mut CanvasRenderingContext2D;
pub type PFPathRef = *mut Path2D;
pub type PFCanvasFontContextRef = *mut CanvasFontContext;
pub type FKFontRef = NonNull<Font>;
pub type PFFillStyleRef = *mut FillStyle;
pub type PFLineCap = u8;
pub type PFLineJoin = u8;
@ -324,9 +326,8 @@ pub unsafe extern "C" fn PFCanvasStrokeText(canvas: PFCanvasRef,
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()
out_text_metrics: NonNull<PFTextMetrics>) {
out_text_metrics.write((*canvas).measure_text(to_rust_string(&string, string_len)).to_c())
}
#[no_mangle]
@ -393,14 +394,30 @@ pub unsafe extern "C" fn PFCanvasSetLineDashOffset(canvas: PFCanvasRef, new_offs
}
#[no_mangle]
pub unsafe extern "C" fn PFCanvasSetFontByPostScriptName(canvas: PFCanvasRef,
pub unsafe extern "C" fn PFCanvasFontContextGetFontByPostScriptName(context: PFCanvasFontContextRef,
postscript_name: *const c_char,
postscript_name_len: usize) -> i32 {
postscript_name_len: usize) -> Option<FKFontRef> {
let name = to_rust_string(&postscript_name, postscript_name_len);
match (*canvas).set_font(name) {
match (*context).get_font_by_postscript_name(name) {
Ok(font) => NonNull::new(Box::into_raw(Box::new(font))),
Err(e) => {
log::error!("Failed to get font {:?}: {:?}", name, e);
None
}
}
}
#[no_mangle]
pub unsafe extern "C" fn FKFontDestroy(font: FKFontRef) {
drop(Box::from_raw(font.as_ptr()))
}
#[no_mangle]
pub unsafe extern "C" fn PFCanvasSetFont(canvas: PFCanvasRef, font: FKFontRef) -> i32 {
match (*canvas).set_font(font.as_ref().clone()) {
Ok(_) => 0,
Err(e) => {
log::error!("Failed to set font to {:?}: {:?}", name, e);
log::error!("Failed to set font: {:?}", e);
1
}
}
@ -646,6 +663,33 @@ pub unsafe extern "C" fn PFGLRendererGetDevice(renderer: PFGLRendererRef) -> PFG
(*renderer).device_mut()
}
#[no_mangle]
pub unsafe extern "C" fn PFGLRendererSetViewport(renderer: PFGLRendererRef, new_viewport: PFRectI) -> i32 {
match (*renderer).options_mut().dest {
DestFramebuffer::Default { ref mut viewport, .. } => {
*viewport = new_viewport.to_rust();
0
}
DestFramebuffer::Other(_) => 1,
}
}
#[no_mangle]
pub unsafe extern "C" fn PFGLRendererSetWindowSize(renderer: PFGLRendererRef, new_window_size: PFVector2I) -> i32 {
match (*renderer).options_mut().dest {
DestFramebuffer::Default { ref mut window_size, .. } => {
*window_size = new_window_size.to_rust();
0
}
DestFramebuffer::Other(_) => 1,
}
}
#[no_mangle]
pub unsafe extern "C" fn PFGLRendererDestFramebufferSizeChanged(renderer: PFGLRendererRef) {
(*renderer).dest_framebuffer_size_changed()
}
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
#[no_mangle]
pub unsafe extern "C" fn PFMetalDestFramebufferCreateFullWindow(window_size: *const PFVector2I)
@ -810,21 +854,18 @@ pub unsafe extern "C" fn PFSceneDestroy(scene: PFSceneRef) {
}
#[no_mangle]
pub unsafe extern "C" fn PFSceneProxyCreateFromSceneAndSequentialExecutor(scene: PFSceneRef,
level: PFRendererLevel)
-> PFSceneProxyRef {
Box::into_raw(Box::new(SceneProxy::from_scene(*Box::from_raw(scene),
to_rust_renderer_level(level),
SequentialExecutor)))
pub unsafe extern "C" fn PFSceneProxyCreateWithSequentialExecutor(level: PFRendererLevel) -> PFSceneProxyRef {
Box::into_raw(Box::new(SceneProxy::new(to_rust_renderer_level(level), SequentialExecutor)))
}
#[no_mangle]
pub unsafe extern "C" fn PFSceneProxyCreateFromSceneAndRayonExecutor(scene: PFSceneRef,
level: PFRendererLevel)
-> PFSceneProxyRef {
Box::into_raw(Box::new(SceneProxy::from_scene(*Box::from_raw(scene),
to_rust_renderer_level(level),
RayonExecutor)))
pub unsafe extern "C" fn PFSceneProxyCreateWithRayonExecutor(level: PFRendererLevel) -> PFSceneProxyRef {
Box::into_raw(Box::new(SceneProxy::new(to_rust_renderer_level(level), RayonExecutor)))
}
#[no_mangle]
pub unsafe extern "C" fn PFSceneProxyReplaceScene(scene_proxy: PFSceneProxyRef, scene: PFSceneRef) {
(*scene_proxy).replace_scene(*Box::from_raw(scene))
}
#[no_mangle]

View File

@ -154,13 +154,7 @@ pub trait ToTextLayout {
impl ToTextLayout for str {
fn layout(&self, state: CanvasState) -> Cow<TextMetrics> {
let skribo_layout = Rc::new(skribo::layout(&TextStyle { size: state.0.font_size },
&state.0.font_collection,
self));
Cow::Owned(TextMetrics::new(skribo_layout,
state.0.font_size,
state.0.text_align,
state.0.text_baseline))
Cow::Owned(TextMetrics::layout(self, &state.0.font_collection, state.0.font_size, state.0.text_align, state.0.text_baseline))
}
}
@ -233,7 +227,7 @@ impl CanvasFontContext {
CanvasFontContext::new(Arc::new(MemSource::from_fonts(fonts).unwrap()))
}
fn get_font_by_postscript_name(&self, postscript_name: &str) -> Result<Font, FontError> {
pub fn get_font_by_postscript_name(&self, postscript_name: &str) -> Result<Font, FontError> {
let this = self.0.borrow();
if let Some(cached_font) = this.font_context.get_cached_font(postscript_name) {
return Ok((*cached_font).clone());
@ -322,6 +316,13 @@ impl TextMetrics {
}
}
pub fn layout(string: &str, font_collection: &FontCollection, font_size: f32, text_align: TextAlign, text_baseline: TextBaseline) -> TextMetrics {
let skribo_layout = Rc::new(skribo::layout(&TextStyle { size: font_size },
font_collection,
string));
TextMetrics::new(skribo_layout, font_size, text_align, text_baseline)
}
pub fn text_x_offset(&self) -> f32 {
if self.text_x_offset.get().is_none() {
self.text_x_offset.set(Some(match self.align {