mirror of
https://github.com/penpot/penpot.git
synced 2025-01-21 14:12:36 -05:00
🎉 Basic wasm fonts support
This commit is contained in:
parent
74f6062ffc
commit
c0cfa8dc42
4 changed files with 77 additions and 3 deletions
|
@ -130,6 +130,32 @@
|
||||||
(aget buffer 3))))
|
(aget buffer 3))))
|
||||||
shape-ids))
|
shape-ids))
|
||||||
|
|
||||||
|
(defn- get-string-length [string] (+ (count string) 1))
|
||||||
|
|
||||||
|
;; IMPORTANT: It should be noted that only TTF fonts can be stored.
|
||||||
|
(defn- store-font
|
||||||
|
[family-name font-array-buffer]
|
||||||
|
(let [family-name-size (get-string-length family-name)
|
||||||
|
font-array-buffer-size (.-byteLength font-array-buffer)
|
||||||
|
size (+ font-array-buffer-size family-name-size)
|
||||||
|
ptr (h/call internal-module "_alloc_bytes" size)
|
||||||
|
family-name-ptr (+ ptr font-array-buffer-size)
|
||||||
|
heap (gobj/get ^js internal-module "HEAPU8")
|
||||||
|
mem (js/Uint8Array. (.-buffer heap) ptr size)]
|
||||||
|
(.set mem (js/Uint8Array. font-array-buffer))
|
||||||
|
(h/call internal-module "stringToUTF8" family-name family-name-ptr family-name-size)
|
||||||
|
(h/call internal-module "_store_font" family-name-size font-array-buffer-size)))
|
||||||
|
|
||||||
|
;; This doesn't work
|
||||||
|
#_(store-font-url "roboto-thin-italic" "https://fonts.gstatic.com/s/roboto/v32/KFOiCnqEu92Fr1Mu51QrEzAdLw.woff2")
|
||||||
|
;; This does
|
||||||
|
#_(store-font-url "sourcesanspro-regular" "http://localhost:3449/fonts/sourcesanspro-regular.ttf")
|
||||||
|
(defn- store-font-url
|
||||||
|
[family-name font-url]
|
||||||
|
(-> (p/then (js/fetch font-url)
|
||||||
|
(fn [response] (.arrayBuffer response)))
|
||||||
|
(p/then (fn [array-buffer] (store-font family-name array-buffer)))))
|
||||||
|
|
||||||
(defn- store-image
|
(defn- store-image
|
||||||
[id]
|
[id]
|
||||||
(let [buffer (uuid/get-u32 id)
|
(let [buffer (uuid/get-u32 id)
|
||||||
|
|
|
@ -252,6 +252,27 @@ pub extern "C" fn add_shape_fill_stops(ptr: *mut shapes::RawStopData, n_stops: u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn store_font(family_name_size: u32, font_size: u32) {
|
||||||
|
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
|
||||||
|
unsafe {
|
||||||
|
let font_bytes =
|
||||||
|
Vec::<u8>::from_raw_parts(mem::buffer_ptr(), font_size as usize, font_size as usize);
|
||||||
|
let family_name = String::from_raw_parts(
|
||||||
|
mem::buffer_ptr().add(font_size as usize),
|
||||||
|
family_name_size as usize,
|
||||||
|
family_name_size as usize,
|
||||||
|
);
|
||||||
|
match state.render_state().add_font(family_name, &font_bytes) {
|
||||||
|
Err(msg) => {
|
||||||
|
eprintln!("{}", msg);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
mem::free_bytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn store_image(a: u32, b: u32, c: u32, d: u32, size: u32) {
|
pub extern "C" fn store_image(a: u32, b: u32, c: u32, d: u32, size: u32) {
|
||||||
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
|
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
|
||||||
|
|
|
@ -19,7 +19,12 @@ pub use blend::BlendMode;
|
||||||
pub use images::*;
|
pub use images::*;
|
||||||
|
|
||||||
pub trait Renderable {
|
pub trait Renderable {
|
||||||
fn render(&self, surface: &mut skia::Surface, images: &ImageStore) -> Result<(), String>;
|
fn render(
|
||||||
|
&self,
|
||||||
|
surface: &mut skia::Surface,
|
||||||
|
images: &ImageStore,
|
||||||
|
font_provider: &skia::textlayout::TypefaceFontProvider,
|
||||||
|
) -> Result<(), String>;
|
||||||
fn blend_mode(&self) -> BlendMode;
|
fn blend_mode(&self) -> BlendMode;
|
||||||
fn opacity(&self) -> f32;
|
fn opacity(&self) -> f32;
|
||||||
fn bounds(&self) -> math::Rect;
|
fn bounds(&self) -> math::Rect;
|
||||||
|
@ -45,6 +50,7 @@ pub(crate) struct RenderState {
|
||||||
pub final_surface: skia::Surface,
|
pub final_surface: skia::Surface,
|
||||||
pub drawing_surface: skia::Surface,
|
pub drawing_surface: skia::Surface,
|
||||||
pub debug_surface: skia::Surface,
|
pub debug_surface: skia::Surface,
|
||||||
|
pub font_provider: skia::textlayout::TypefaceFontProvider,
|
||||||
pub cached_surface_image: Option<CachedSurfaceImage>,
|
pub cached_surface_image: Option<CachedSurfaceImage>,
|
||||||
options: RenderOptions,
|
options: RenderOptions,
|
||||||
pub viewbox: Viewbox,
|
pub viewbox: Viewbox,
|
||||||
|
@ -64,12 +70,19 @@ impl RenderState {
|
||||||
.new_surface_with_dimensions((width, height))
|
.new_surface_with_dimensions((width, height))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let mut font_provider = skia::textlayout::TypefaceFontProvider::new();
|
||||||
|
let default_font = skia::FontMgr::default()
|
||||||
|
.new_from_data(include_bytes!("fonts/RobotoMono-Regular.ttf"), None)
|
||||||
|
.expect("Failed to load font");
|
||||||
|
font_provider.register_typeface(default_font, "robotomono-regular");
|
||||||
|
|
||||||
RenderState {
|
RenderState {
|
||||||
gpu_state,
|
gpu_state,
|
||||||
final_surface,
|
final_surface,
|
||||||
drawing_surface,
|
drawing_surface,
|
||||||
debug_surface,
|
debug_surface,
|
||||||
cached_surface_image: None,
|
cached_surface_image: None,
|
||||||
|
font_provider,
|
||||||
options: RenderOptions::default(),
|
options: RenderOptions::default(),
|
||||||
viewbox: Viewbox::new(width as f32, height as f32),
|
viewbox: Viewbox::new(width as f32, height as f32),
|
||||||
images: ImageStore::new(),
|
images: ImageStore::new(),
|
||||||
|
@ -77,6 +90,15 @@ impl RenderState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_font(&mut self, family_name: String, font_data: &[u8]) -> Result<(), String> {
|
||||||
|
let typeface = skia::FontMgr::default()
|
||||||
|
.new_from_data(font_data, None)
|
||||||
|
.expect("Failed to add font");
|
||||||
|
self.font_provider
|
||||||
|
.register_typeface(typeface, family_name.as_ref());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_image(&mut self, id: Uuid, image_data: &[u8]) -> Result<(), String> {
|
pub fn add_image(&mut self, id: Uuid, image_data: &[u8]) -> Result<(), String> {
|
||||||
self.images.add(id, image_data)
|
self.images.add(id, image_data)
|
||||||
}
|
}
|
||||||
|
@ -153,7 +175,7 @@ impl RenderState {
|
||||||
|
|
||||||
pub fn render_single_element(&mut self, element: &impl Renderable) {
|
pub fn render_single_element(&mut self, element: &impl Renderable) {
|
||||||
element
|
element
|
||||||
.render(&mut self.drawing_surface, &self.images)
|
.render(&mut self.drawing_surface, &self.images, &self.font_provider)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut paint = skia::Paint::default();
|
let mut paint = skia::Paint::default();
|
||||||
|
|
|
@ -6,7 +6,12 @@ use crate::math::Rect;
|
||||||
use crate::render::{ImageStore, Renderable};
|
use crate::render::{ImageStore, Renderable};
|
||||||
|
|
||||||
impl Renderable for Shape {
|
impl Renderable for Shape {
|
||||||
fn render(&self, surface: &mut skia_safe::Surface, images: &ImageStore) -> Result<(), String> {
|
fn render(
|
||||||
|
&self,
|
||||||
|
surface: &mut skia_safe::Surface,
|
||||||
|
images: &ImageStore,
|
||||||
|
font_provider: &skia::textlayout::TypefaceFontProvider,
|
||||||
|
) -> Result<(), String> {
|
||||||
let transform = self.transform.to_skia_matrix();
|
let transform = self.transform.to_skia_matrix();
|
||||||
|
|
||||||
// Check transform-matrix code from common/src/app/common/geom/shapes/transforms.cljc
|
// Check transform-matrix code from common/src/app/common/geom/shapes/transforms.cljc
|
||||||
|
|
Loading…
Add table
Reference in a new issue