Add font_load() fn

This commit is contained in:
mars 2022-07-18 21:24:39 -06:00
parent d617eaaf64
commit b7df68195a
3 changed files with 63 additions and 11 deletions

View File

@ -35,13 +35,14 @@ impl PanelImpl for DummyPanel {
let ctx = draw::DrawContext::new(self.panel);
self.menu.draw(&ctx);
let text = "Hello, world!";
let font = Font::new("Iosevka Nerd Font");
let text = "";
let bg = Color::MAGENTA;
let fg = Color::BLACK;
let scale = 0.1;
let pos = Vec2::ZERO;
let layout = TextLayout::new(text);
let layout = TextLayout::new(&font, text);
let bounds = layout.get_bounds();
let bounds = draw::Rect {
bl: Vec2::from(bounds.bl) * scale,

View File

@ -133,12 +133,28 @@ impl Panel {
}
}
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct Font(u32);
impl Font {
pub fn new(family: &str) -> Self {
unsafe { Self(font_load(family.as_ptr() as u32, family.len() as u32)) }
}
}
#[repr(transparent)]
pub struct TextLayout(u32);
impl TextLayout {
pub fn new(text: &str) -> Self {
unsafe { Self(text_layout_new(text.as_ptr() as u32, text.len() as u32)) }
pub fn new(font: &Font, text: &str) -> Self {
unsafe {
Self(text_layout_new(
font.0,
text.as_ptr() as u32,
text.len() as u32,
))
}
}
pub fn get_bounds(&self) -> Rect {
@ -182,7 +198,9 @@ extern "C" {
a: f32,
);
fn text_layout_new(text_ptr: u32, text_len: u32) -> u32;
fn font_load(family_ptr: u32, family_len: u32) -> u32;
fn text_layout_new(font_id: u32, text_ptr: u32, text_len: u32) -> u32;
fn text_layout_delete(id: u32);
fn text_layout_get_bounds(id: u32, rect_ptr: u32);
fn text_layout_get_glyphs_num(id: u32) -> u32;

View File

@ -1,6 +1,8 @@
pub use canary_types::*;
use parking_lot::{Mutex, RwLock};
use slab::Slab;
use std::collections::HashMap;
use std::sync::Arc;
pub mod text;
@ -14,7 +16,9 @@ pub trait ScriptAbi {
fn draw_glyphs(&self, glyphs: &[GlyphPosition], offset: Vec2, scale: f32, color: Color);
fn with_draw_commands(&self, f: impl FnOnce(&[DrawCommand]));
fn text_layout_new(&self, text: &str) -> u32;
fn font_load(&self, family: &str) -> u32;
fn text_layout_new(&self, font_id: u32, text: &str) -> u32;
fn text_layout_delete(&self, id: u32);
fn text_layout_get_bounds(&self, id: u32, rect: &mut Rect);
fn text_layout_get_glyphs_num(&self, id: u32) -> u32;
@ -122,12 +126,21 @@ impl<T: ScriptAbi> WasmtimeScript<T> {
},
)?;
linker.func_wrap(
module,
"font_load",
|mut caller: wasmtime::Caller<'_, T>, family_ptr: u32, family_len: u32| {
let family = Self::get_memory_slice_str(&mut caller, family_ptr, family_len);
caller.data().font_load(family)
},
)?;
linker.func_wrap(
module,
"text_layout_new",
|mut caller: wasmtime::Caller<'_, T>, text_ptr: u32, text_len: u32| {
|mut caller: wasmtime::Caller<'_, T>, font_id: u32, text_ptr: u32, text_len: u32| {
let text = Self::get_memory_slice_str(&mut caller, text_ptr, text_len);
caller.data().text_layout_new(text)
caller.data().text_layout_new(font_id, text)
},
)?;
@ -235,6 +248,8 @@ impl<T: ScriptAbi> ScriptInstance for WasmtimeScript<T> {
pub struct ScriptAbiImpl {
draw_cmds: Mutex<Vec<DrawCommand>>,
font_store: text::FontStore,
font_families: Mutex<HashMap<String, u32>>,
loaded_fonts: RwLock<Vec<Arc<text::Font>>>,
text_layouts: RwLock<Slab<text::TextLayout>>,
}
@ -252,7 +267,9 @@ impl ScriptAbi for ScriptAbiImpl {
}
fn draw_glyphs(&self, glyphs: &[GlyphPosition], offset: Vec2, scale: f32, color: Color) {
let font = self.font_store.load_font("Liberation Sans");
// TODO multiple fonts per layout
let loaded = self.loaded_fonts.read();
let font = loaded.get(glyphs[0].face as usize).unwrap();
let cmds = font.draw(glyphs, offset, scale, color);
self.draw_cmds.lock().extend(cmds.into_iter());
}
@ -261,8 +278,24 @@ impl ScriptAbi for ScriptAbiImpl {
f(self.draw_cmds.lock().as_slice());
}
fn text_layout_new(&self, text: &str) -> u32 {
let font = self.font_store.load_font("Liberation Sans");
fn font_load(&self, family: &str) -> u32 {
let mut family_cache = self.font_families.lock();
if let Some(cached) = family_cache.get(family) {
return *cached;
}
let font = self.font_store.load_font(family);
let mut loaded = self.loaded_fonts.write();
let id = loaded.len() as u32;
family_cache.insert(family.to_string(), id);
loaded.push(font);
id
}
fn text_layout_new(&self, font_id: u32, text: &str) -> u32 {
let loaded = self.loaded_fonts.read();
let font = loaded.get(font_id as usize).unwrap();
let layout = font.shape(text);
self.text_layouts.write().insert(layout) as u32
}