Pass in the font context to the canvas rendering context constructor so that it
can be reused. Creating a system font source can do I/O on some platforms, so obviously we don't want to do it every frame.
This commit is contained in:
parent
e1bcc11ace
commit
9138e1e0bb
|
@ -39,6 +39,8 @@ struct PFCanvas;
|
||||||
typedef struct PFCanvas *PFCanvasRef;
|
typedef struct PFCanvas *PFCanvasRef;
|
||||||
struct PFPath;
|
struct PFPath;
|
||||||
typedef struct PFPath *PFPathRef;
|
typedef struct PFPath *PFPathRef;
|
||||||
|
struct PFCanvasFontContext;
|
||||||
|
typedef struct PFCanvasFontContext *PFCanvasFontContextRef;
|
||||||
|
|
||||||
// `geometry`
|
// `geometry`
|
||||||
|
|
||||||
|
@ -103,8 +105,10 @@ typedef struct PFSceneProxy *PFSceneProxyRef;
|
||||||
|
|
||||||
// `canvas`
|
// `canvas`
|
||||||
|
|
||||||
PFCanvasRef PFCanvasCreate(const PFPoint2DF *size);
|
PFCanvasRef PFCanvasCreate(PFCanvasFontContextRef font_context, const PFPoint2DF *size);
|
||||||
void PFCanvasDestroy(PFCanvasRef canvas);
|
void PFCanvasDestroy(PFCanvasRef canvas);
|
||||||
|
PFCanvasFontContextRef PFCanvasFontContextCreate();
|
||||||
|
void PFCanvasFontContextDestroy(PFCanvasFontContextRef font_context);
|
||||||
PFSceneRef PFCanvasCreateScene(PFCanvasRef canvas);
|
PFSceneRef PFCanvasCreateScene(PFCanvasRef canvas);
|
||||||
void PFCanvasFillRect(PFCanvasRef canvas, const PFRectF *rect);
|
void PFCanvasFillRect(PFCanvasRef canvas, const PFRectF *rect);
|
||||||
void PFCanvasStrokeRect(PFCanvasRef canvas, const PFRectF *rect);
|
void PFCanvasStrokeRect(PFCanvasRef canvas, const PFRectF *rect);
|
||||||
|
|
20
c/src/lib.rs
20
c/src/lib.rs
|
@ -11,7 +11,7 @@
|
||||||
//! C bindings to Pathfinder.
|
//! C bindings to Pathfinder.
|
||||||
|
|
||||||
use gl;
|
use gl;
|
||||||
use pathfinder_canvas::{CanvasRenderingContext2D, Path2D};
|
use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, Path2D};
|
||||||
use pathfinder_geometry::basic::point::{Point2DF, Point2DI};
|
use pathfinder_geometry::basic::point::{Point2DF, Point2DI};
|
||||||
use pathfinder_geometry::basic::rect::{RectF, RectI};
|
use pathfinder_geometry::basic::rect::{RectF, RectI};
|
||||||
use pathfinder_geometry::color::ColorF;
|
use pathfinder_geometry::color::ColorF;
|
||||||
|
@ -39,6 +39,7 @@ pub const PF_CLEAR_FLAGS_HAS_RECT: u8 = 0x8;
|
||||||
// `canvas`
|
// `canvas`
|
||||||
pub type PFCanvasRef = *mut CanvasRenderingContext2D;
|
pub type PFCanvasRef = *mut CanvasRenderingContext2D;
|
||||||
pub type PFPathRef = *mut Path2D;
|
pub type PFPathRef = *mut Path2D;
|
||||||
|
pub type PFCanvasFontContextRef = *mut CanvasFontContext;
|
||||||
|
|
||||||
// `geometry`
|
// `geometry`
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -102,8 +103,11 @@ pub struct PFRenderOptions {
|
||||||
// `canvas`
|
// `canvas`
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn PFCanvasCreate(size: *const PFPoint2DF) -> PFCanvasRef {
|
pub unsafe extern "C" fn PFCanvasCreate(font_context: PFCanvasFontContextRef,
|
||||||
Box::into_raw(Box::new(CanvasRenderingContext2D::new((*size).to_rust())))
|
size: *const PFPoint2DF)
|
||||||
|
-> PFCanvasRef {
|
||||||
|
Box::into_raw(Box::new(CanvasRenderingContext2D::new(*Box::from_raw(font_context),
|
||||||
|
(*size).to_rust())))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -111,6 +115,16 @@ pub unsafe extern "C" fn PFCanvasDestroy(canvas: PFCanvasRef) {
|
||||||
drop(Box::from_raw(canvas))
|
drop(Box::from_raw(canvas))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFCanvasFontContextCreate() -> PFCanvasFontContextRef {
|
||||||
|
Box::into_raw(Box::new(CanvasFontContext::new()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFCanvasFontContextDestroy(font_context: PFCanvasFontContextRef) {
|
||||||
|
drop(Box::from_raw(font_context))
|
||||||
|
}
|
||||||
|
|
||||||
/// Consumes the canvas.
|
/// Consumes the canvas.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn PFCanvasCreateScene(canvas: PFCanvasRef) -> PFSceneRef {
|
pub unsafe extern "C" fn PFCanvasCreateScene(canvas: PFCanvasRef) -> PFSceneRef {
|
||||||
|
|
|
@ -35,41 +35,24 @@ pub struct CanvasRenderingContext2D {
|
||||||
scene: Scene,
|
scene: Scene,
|
||||||
current_state: State,
|
current_state: State,
|
||||||
saved_states: Vec<State>,
|
saved_states: Vec<State>,
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
font_source: SystemSource,
|
font_context: CanvasFontContext,
|
||||||
#[allow(dead_code)]
|
|
||||||
default_font_collection: Arc<FontCollection>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CanvasRenderingContext2D {
|
impl CanvasRenderingContext2D {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(size: Point2DF) -> CanvasRenderingContext2D {
|
pub fn new(font_context: CanvasFontContext, size: Point2DF) -> CanvasRenderingContext2D {
|
||||||
let mut scene = Scene::new();
|
let mut scene = Scene::new();
|
||||||
scene.set_view_box(RectF::new(Point2DF::default(), size));
|
scene.set_view_box(RectF::new(Point2DF::default(), size));
|
||||||
CanvasRenderingContext2D::from_scene(scene)
|
CanvasRenderingContext2D::from_scene(font_context, scene)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_scene(scene: Scene) -> CanvasRenderingContext2D {
|
pub fn from_scene(font_context: CanvasFontContext, scene: Scene) -> CanvasRenderingContext2D {
|
||||||
// TODO(pcwalton): Allow the user to cache this?
|
|
||||||
let font_source = SystemSource::new();
|
|
||||||
|
|
||||||
let mut default_font_collection = FontCollection::new();
|
|
||||||
let default_font =
|
|
||||||
font_source.select_best_match(&[FamilyName::SansSerif], &Properties::new())
|
|
||||||
.expect("Failed to select the default font!")
|
|
||||||
.load()
|
|
||||||
.expect("Failed to load the default font!");
|
|
||||||
default_font_collection.add_family(FontFamily::new_from_font(default_font));
|
|
||||||
let default_font_collection = Arc::new(default_font_collection);
|
|
||||||
|
|
||||||
CanvasRenderingContext2D {
|
CanvasRenderingContext2D {
|
||||||
scene,
|
scene,
|
||||||
current_state: State::default(default_font_collection.clone()),
|
current_state: State::default(font_context.default_font_collection.clone()),
|
||||||
saved_states: vec![],
|
saved_states: vec![],
|
||||||
|
font_context,
|
||||||
font_source,
|
|
||||||
default_font_collection,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,3 +318,31 @@ impl FillStyle {
|
||||||
match *self { FillStyle::Color(color) => Paint { color } }
|
match *self { FillStyle::Color(color) => Paint { color } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CanvasFontContext {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
font_source: Arc<SystemSource>,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
default_font_collection: Arc<FontCollection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CanvasFontContext {
|
||||||
|
pub fn new() -> CanvasFontContext {
|
||||||
|
let font_source = Arc::new(SystemSource::new());
|
||||||
|
|
||||||
|
let mut default_font_collection = FontCollection::new();
|
||||||
|
let default_font =
|
||||||
|
font_source.select_best_match(&[FamilyName::SansSerif], &Properties::new())
|
||||||
|
.expect("Failed to select the default font!")
|
||||||
|
.load()
|
||||||
|
.expect("Failed to load the default font!");
|
||||||
|
default_font_collection.add_family(FontFamily::new_from_font(default_font));
|
||||||
|
let default_font_collection = Arc::new(default_font_collection);
|
||||||
|
|
||||||
|
CanvasFontContext {
|
||||||
|
font_source,
|
||||||
|
default_font_collection,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -66,7 +66,8 @@ int main(int argc, const char **argv) {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Make a canvas. We're going to draw a house.
|
// Make a canvas. We're going to draw a house.
|
||||||
PFCanvasRef canvas = PFCanvasCreate(&(PFPoint2DF){640.0f, 480.0f});
|
PFCanvasRef canvas = PFCanvasCreate(PFCanvasFontContextCreate(),
|
||||||
|
&(PFPoint2DF){640.0f, 480.0f});
|
||||||
|
|
||||||
// Set line width.
|
// Set line width.
|
||||||
PFCanvasSetLineWidth(canvas, 10.0f);
|
PFCanvasSetLineWidth(canvas, 10.0f);
|
||||||
|
|
|
@ -8,11 +8,10 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use pathfinder_canvas::{CanvasRenderingContext2D, Path2D};
|
use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, Path2D};
|
||||||
use pathfinder_geometry::basic::point::{Point2DF, Point2DI};
|
use pathfinder_geometry::basic::point::{Point2DF, Point2DI};
|
||||||
use pathfinder_geometry::basic::rect::RectF;
|
use pathfinder_geometry::basic::rect::RectF;
|
||||||
use pathfinder_geometry::color::ColorF;
|
use pathfinder_geometry::color::ColorF;
|
||||||
use pathfinder_geometry::stroke::LineJoin;
|
|
||||||
use pathfinder_gl::{GLDevice, GLVersion};
|
use pathfinder_gl::{GLDevice, GLVersion};
|
||||||
use pathfinder_gpu::resources::FilesystemResourceLoader;
|
use pathfinder_gpu::resources::FilesystemResourceLoader;
|
||||||
use pathfinder_gpu::{ClearParams, Device};
|
use pathfinder_gpu::{ClearParams, Device};
|
||||||
|
@ -55,7 +54,7 @@ fn main() {
|
||||||
renderer.device.clear(&ClearParams { color: Some(ColorF::white()), ..ClearParams::default() });
|
renderer.device.clear(&ClearParams { color: Some(ColorF::white()), ..ClearParams::default() });
|
||||||
|
|
||||||
// Make a canvas. We're going to draw a house.
|
// Make a canvas. We're going to draw a house.
|
||||||
let mut canvas = CanvasRenderingContext2D::new(window_size.to_f32());
|
let mut canvas = CanvasRenderingContext2D::new(CanvasFontContext::new(), window_size.to_f32());
|
||||||
|
|
||||||
// Set line width.
|
// Set line width.
|
||||||
canvas.set_line_width(10.0);
|
canvas.set_line_width(10.0);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use pathfinder_canvas::{CanvasRenderingContext2D, FillStyle, Path2D};
|
use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, FillStyle, Path2D};
|
||||||
use pathfinder_geometry::basic::point::{Point2DF, Point2DI};
|
use pathfinder_geometry::basic::point::{Point2DF, Point2DI};
|
||||||
use pathfinder_geometry::color::{ColorF, ColorU};
|
use pathfinder_geometry::color::{ColorF, ColorU};
|
||||||
use pathfinder_gl::{GLDevice, GLVersion};
|
use pathfinder_gl::{GLDevice, GLVersion};
|
||||||
|
@ -85,6 +85,7 @@ fn main() {
|
||||||
|
|
||||||
struct MoireRenderer {
|
struct MoireRenderer {
|
||||||
renderer: Renderer<GLDevice>,
|
renderer: Renderer<GLDevice>,
|
||||||
|
font_context: CanvasFontContext,
|
||||||
scene: SceneProxy,
|
scene: SceneProxy,
|
||||||
frame: i32,
|
frame: i32,
|
||||||
window_size: Point2DI,
|
window_size: Point2DI,
|
||||||
|
@ -98,6 +99,7 @@ impl MoireRenderer {
|
||||||
-> MoireRenderer {
|
-> MoireRenderer {
|
||||||
MoireRenderer {
|
MoireRenderer {
|
||||||
renderer,
|
renderer,
|
||||||
|
font_context: CanvasFontContext::new(),
|
||||||
scene: SceneProxy::new(RayonExecutor),
|
scene: SceneProxy::new(RayonExecutor),
|
||||||
frame: 0,
|
frame: 0,
|
||||||
window_size,
|
window_size,
|
||||||
|
@ -128,7 +130,8 @@ impl MoireRenderer {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Make a canvas.
|
// Make a canvas.
|
||||||
let mut canvas = CanvasRenderingContext2D::new(self.drawable_size.to_f32());
|
let mut canvas = CanvasRenderingContext2D::new(self.font_context.clone(),
|
||||||
|
self.drawable_size.to_f32());
|
||||||
canvas.set_line_width(CIRCLE_THICKNESS * self.device_pixel_ratio);
|
canvas.set_line_width(CIRCLE_THICKNESS * self.device_pixel_ratio);
|
||||||
canvas.set_stroke_style(FillStyle::Color(foreground_color.to_u8()));
|
canvas.set_stroke_style(FillStyle::Color(foreground_color.to_u8()));
|
||||||
canvas.set_global_alpha(0.75);
|
canvas.set_global_alpha(0.75);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use pathfinder_canvas::CanvasRenderingContext2D;
|
use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D};
|
||||||
use pathfinder_geometry::basic::point::{Point2DF, Point2DI};
|
use pathfinder_geometry::basic::point::{Point2DF, Point2DI};
|
||||||
use pathfinder_geometry::color::ColorF;
|
use pathfinder_geometry::color::ColorF;
|
||||||
use pathfinder_gl::{GLDevice, GLVersion};
|
use pathfinder_gl::{GLDevice, GLVersion};
|
||||||
|
@ -53,7 +53,7 @@ fn main() {
|
||||||
renderer.device.clear(&ClearParams { color: Some(ColorF::white()), ..ClearParams::default() });
|
renderer.device.clear(&ClearParams { color: Some(ColorF::white()), ..ClearParams::default() });
|
||||||
|
|
||||||
// Make a canvas. We're going to draw some text.
|
// Make a canvas. We're going to draw some text.
|
||||||
let mut canvas = CanvasRenderingContext2D::new(window_size.to_f32());
|
let mut canvas = CanvasRenderingContext2D::new(CanvasFontContext::new(), window_size.to_f32());
|
||||||
|
|
||||||
// Draw the text.
|
// Draw the text.
|
||||||
canvas.set_font_size(32.0);
|
canvas.set_font_size(32.0);
|
||||||
|
|
Loading…
Reference in New Issue