diff --git a/c/Cargo.toml b/c/Cargo.toml index ad5125f8..2d0ba52e 100644 --- a/c/Cargo.toml +++ b/c/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" capi = [] [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib", "cdylib"] name = "pathfinder" [dependencies] @@ -16,8 +16,13 @@ font-kit = "0.6" foreign-types = "0.3" gl = "0.14" libc = "0.2" +simple_logger = "4.3" usvg = "0.9" +[dependencies.log] +version = "0.4" +features = ["max_level_info"] + [dependencies.pathfinder_canvas] features = ["pf-text"] path = "../canvas" diff --git a/c/src/lib.rs b/c/src/lib.rs index 75aa15da..94461f46 100644 --- a/c/src/lib.rs +++ b/c/src/lib.rs @@ -27,6 +27,7 @@ use pathfinder_gpu::Device; use pathfinder_resources::ResourceLoader; use pathfinder_resources::fs::FilesystemResourceLoader; use pathfinder_resources::embedded::EmbeddedResourceLoader; +use pathfinder_renderer::concurrent::executor::SequentialExecutor; use pathfinder_renderer::concurrent::rayon::RayonExecutor; use pathfinder_renderer::concurrent::scene_proxy::SceneProxy; use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererLevel}; @@ -51,6 +52,11 @@ use metal::{self, CoreAnimationDrawableRef, DeviceRef as NativeMetalDeviceRef}; #[cfg(all(target_os = "macos", not(feature = "pf-gl")))] use pathfinder_metal::MetalDevice; +#[no_mangle] +pub extern "system" fn init_logging() { + simple_logger::init_with_env().unwrap(); +} + // Constants // `canvas` @@ -272,6 +278,13 @@ pub unsafe extern "C" fn PFCanvasCreateScene(canvas: PFCanvasRef) -> PFSceneRef Box::into_raw(Box::new(Box::from_raw(canvas).into_canvas().into_scene())) } +// Extensions + +#[no_mangle] +pub unsafe extern "C" fn PFCanvasClear(canvas: PFCanvasRef) { + (*canvas).clear() +} + // Drawing rectangles #[no_mangle] @@ -284,6 +297,11 @@ pub unsafe extern "C" fn PFCanvasStrokeRect(canvas: PFCanvasRef, rect: *const PF (*canvas).stroke_rect((*rect).to_rust()) } +#[no_mangle] +pub unsafe extern "C" fn PFCanvasClearRect(canvas: PFCanvasRef, rect: *const PFRectF) { + (*canvas).clear_rect((*rect).to_rust()) +} + // Drawing text #[no_mangle] @@ -378,9 +396,13 @@ pub unsafe extern "C" fn PFCanvasSetLineDashOffset(canvas: PFCanvasRef, new_offs pub unsafe extern "C" fn PFCanvasSetFontByPostScriptName(canvas: PFCanvasRef, postscript_name: *const c_char, postscript_name_len: usize) -> i32 { - match (*canvas).set_font(to_rust_string(&postscript_name, postscript_name_len)) { + let name = to_rust_string(&postscript_name, postscript_name_len); + match (*canvas).set_font(name) { Ok(_) => 0, - Err(_) => 1 + Err(e) => { + log::error!("Failed to set font to {:?}: {:?}", name, e); + 1 + } } } @@ -787,6 +809,15 @@ pub unsafe extern "C" fn PFSceneDestroy(scene: PFSceneRef) { drop(Box::from_raw(scene)) } +#[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))) +} + #[no_mangle] pub unsafe extern "C" fn PFSceneProxyCreateFromSceneAndRayonExecutor(scene: PFSceneRef, level: PFRendererLevel) diff --git a/examples/canvas_text/src/main.rs b/examples/canvas_text/src/main.rs index 39dd1e91..98292f72 100644 --- a/examples/canvas_text/src/main.rs +++ b/examples/canvas_text/src/main.rs @@ -25,6 +25,7 @@ use sdl2::keyboard::Keycode; use sdl2::video::GLProfile; use std::iter; use std::sync::Arc; +use std::time::{Duration, Instant}; fn main() { // Set up SDL2. @@ -34,7 +35,10 @@ fn main() { // Make sure we have at least a GL 3.0 context. Pathfinder requires this. let gl_attributes = video.gl_attr(); gl_attributes.set_context_profile(GLProfile::Core); - gl_attributes.set_context_version(3, 3); + gl_attributes.set_context_version(4, 1); + gl_attributes.set_context_flags() + .forward_compatible() + .set(); // Open a window. let window_size = vec2i(640, 480); @@ -66,17 +70,33 @@ fn main() { // Wait for a keypress. let mut event_pump = sdl_context.event_pump().unwrap(); + let mut n = 0; + let start = Instant::now(); + let mut last_update = Instant::now(); + let mut fps_buf = String::new(); loop { - match event_pump.wait_event() { - Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => return, - Event::Window { win_event: WindowEvent::Exposed, .. } => { + match event_pump.poll_event() { + Some(Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. }) => return, + Some(Event::Window { win_event: WindowEvent::Exposed, .. }) | None => { // Make a canvas. let mut canvas = Canvas::new(window_size.to_f32()).get_context_2d(font_context.clone()); // Draw the text. canvas.set_font("Overpass-Regular"); canvas.set_font_size(32.0); + let now = Instant::now(); + let elapsed = now.duration_since(last_update); + if elapsed >= Duration::from_millis(500) { + last_update = now; + let fps = (n as f64) * ((Duration::from_secs(1).as_micros() as f64) / (elapsed.as_micros() as f64)); + fps_buf.clear(); + fps_buf.push_str("FPS: "); + use std::fmt::Write; + write!(fps_buf, "{fps:.2}").unwrap(); + n = 0; + } canvas.fill_text("Hello Pathfinder!", vec2f(32.0, 48.0)); + canvas.fill_text(&fps_buf, vec2f(32.0, 96.0)); canvas.set_text_align(TextAlign::Right); canvas.stroke_text("Goodbye Pathfinder!", vec2f(608.0, 464.0)); @@ -86,6 +106,8 @@ fn main() { RayonExecutor); scene.build_and_render(&mut renderer, BuildOptions::default()); window.gl_swap_window(); + + n += 1; }, _ => {} }