Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions vl-convert-canvas2d-deno/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,21 @@ pub use resource::{CanvasResource, Path2DResource};
/// Wraps a pre-built [`ResolvedFontConfig`](::vl_convert_canvas2d::ResolvedFontConfig)
/// so that canvas contexts clone the cached font database instead of rebuilding
/// it (and re-scanning system fonts) on every creation.
///
/// Includes a version counter so that existing canvas contexts can detect when
/// the font database has changed and refresh their local copy.
#[derive(Clone)]
pub struct SharedFontConfig(pub Arc<::vl_convert_canvas2d::ResolvedFontConfig>);
pub struct SharedFontConfig {
pub resolved: Arc<::vl_convert_canvas2d::ResolvedFontConfig>,
pub version: u64,
}

impl SharedFontConfig {
pub fn new(resolved: ::vl_convert_canvas2d::ResolvedFontConfig) -> Self {
Self(Arc::new(resolved))
pub fn new(resolved: ::vl_convert_canvas2d::ResolvedFontConfig, version: u64) -> Self {
Self {
resolved: Arc::new(resolved),
version,
}
}
}

Expand Down
8 changes: 6 additions & 2 deletions vl-convert-canvas2d-deno/src/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,19 @@ use vl_convert_canvas2d::Canvas2dContext;
/// If a SharedFontConfig is available in OpState, it will be used for the canvas.
#[op2(fast)]
pub fn op_canvas_create(state: &mut OpState, width: u32, height: u32) -> Result<u32, JsErrorBox> {
let font_config_version = state
.try_borrow::<SharedFontConfig>()
.map(|c| c.version)
.unwrap_or(0);
let ctx = if let Some(shared_config) = state.try_borrow::<SharedFontConfig>() {
Canvas2dContext::with_resolved(width, height, &shared_config.0)
Canvas2dContext::with_resolved(width, height, &shared_config.resolved)
.map_err(|e| JsErrorBox::generic(format!("Failed to create canvas: {}", e)))?
} else {
Canvas2dContext::new(width, height)
.map_err(|e| JsErrorBox::generic(format!("Failed to create canvas: {}", e)))?
};

let resource = CanvasResource::new(ctx);
let resource = CanvasResource::new(ctx, font_config_version);
let rid = state.resource_table.add(resource);
Ok(rid)
}
Expand Down
29 changes: 28 additions & 1 deletion vl-convert-canvas2d-deno/src/ops/text.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
//! Text rendering operations: font, alignment, baseline, measure, fill/stroke text.

use crate::CanvasResource;
use crate::{CanvasResource, SharedFontConfig};
use deno_core::op2;
use deno_core::{OpState, ResourceId};
use deno_error::JsErrorBox;
use vl_convert_canvas2d::{FontStretch, TextAlign, TextBaseline};

/// If the shared font configuration has been updated since this canvas was
/// created (or last refreshed), update the canvas context's font database so
/// that newly-registered fonts are available for text measurement / rendering.
fn refresh_canvas_fonts_if_needed(state: &OpState, resource: &CanvasResource) {
if let Some(shared_config) = state.try_borrow::<SharedFontConfig>() {
if shared_config.version != resource.font_config_version.get() {
resource
.ctx
.borrow_mut()
.update_font_database(&shared_config.resolved);
resource.font_config_version.set(shared_config.version);
}
}
}

/// Set the font from a CSS font string.
#[op2(fast)]
pub fn op_canvas_set_font(
Expand All @@ -18,6 +33,8 @@ pub fn op_canvas_set_font(
.get::<CanvasResource>(ResourceId::from(rid))
.map_err(|e| JsErrorBox::generic(format!("Invalid canvas resource: {}", e)))?;

refresh_canvas_fonts_if_needed(state, &resource);

resource
.ctx
.borrow_mut()
Expand Down Expand Up @@ -169,6 +186,8 @@ pub fn op_canvas_measure_text(
.get::<CanvasResource>(ResourceId::from(rid))
.map_err(|e| JsErrorBox::generic(format!("Invalid canvas resource: {}", e)))?;

refresh_canvas_fonts_if_needed(state, &resource);

let metrics = resource
.ctx
.borrow_mut()
Expand All @@ -192,6 +211,8 @@ pub fn op_canvas_fill_text(
.get::<CanvasResource>(ResourceId::from(rid))
.map_err(|e| JsErrorBox::generic(format!("Invalid canvas resource: {}", e)))?;

refresh_canvas_fonts_if_needed(state, &resource);

resource
.ctx
.borrow_mut()
Expand All @@ -213,6 +234,8 @@ pub fn op_canvas_stroke_text(
.get::<CanvasResource>(ResourceId::from(rid))
.map_err(|e| JsErrorBox::generic(format!("Invalid canvas resource: {}", e)))?;

refresh_canvas_fonts_if_needed(state, &resource);

resource
.ctx
.borrow_mut()
Expand All @@ -235,6 +258,8 @@ pub fn op_canvas_fill_text_max_width(
.get::<CanvasResource>(ResourceId::from(rid))
.map_err(|e| JsErrorBox::generic(format!("Invalid canvas resource: {}", e)))?;

refresh_canvas_fonts_if_needed(state, &resource);

resource
.ctx
.borrow_mut()
Expand All @@ -257,6 +282,8 @@ pub fn op_canvas_stroke_text_max_width(
.get::<CanvasResource>(ResourceId::from(rid))
.map_err(|e| JsErrorBox::generic(format!("Invalid canvas resource: {}", e)))?;

refresh_canvas_fonts_if_needed(state, &resource);

resource
.ctx
.borrow_mut()
Expand Down
5 changes: 4 additions & 1 deletion vl-convert-canvas2d-deno/src/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pub struct CanvasResource {
next_gradient_id: Cell<u32>,
/// Next pattern ID to assign
next_pattern_id: Cell<u32>,
/// Font config version this canvas was created with (or last updated to).
pub font_config_version: Cell<u64>,
}

/// Resource wrapper for Path2D objects to be stored in Deno's resource table.
Expand All @@ -28,13 +30,14 @@ pub struct Path2DResource {
}

impl CanvasResource {
pub fn new(ctx: Canvas2dContext) -> Self {
pub fn new(ctx: Canvas2dContext, font_config_version: u64) -> Self {
Self {
ctx: RefCell::new(ctx),
gradients: RefCell::new(HashMap::new()),
patterns: RefCell::new(HashMap::new()),
next_gradient_id: Cell::new(1),
next_pattern_id: Cell::new(1),
font_config_version: Cell::new(font_config_version),
}
}

Expand Down
12 changes: 12 additions & 0 deletions vl-convert-canvas2d/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,18 @@ impl Canvas2dContext {
})
}

/// Replace the font database used for text measurement and rendering.
///
/// Call this when the shared font configuration has changed (e.g., new font
/// directories were registered) so that existing canvas contexts pick up the
/// updated fonts.
pub fn update_font_database(&mut self, resolved: &ResolvedFontConfig) {
self.font_system =
FontSystem::new_with_locale_and_db("en".to_string(), resolved.fontdb.clone());
self.swash_cache = SwashCache::new();
self.hinting_enabled = resolved.hinting_enabled;
}

/// Get canvas width.
pub fn width(&self) -> u32 {
self.width
Expand Down
Loading
Loading