1use crate::TextOptions;
2use ab_glyph::{Font, FontVec, OutlinedGlyph};
3use wasm_bindgen::prelude::*;
4
5#[wasm_bindgen]
7pub struct SiFont {
8 pub(crate) font: FontVec,
9}
10
11#[wasm_bindgen]
12impl SiFont {
13 #[wasm_bindgen(constructor)]
15 pub fn new(vec: Vec<u8>) -> Self {
16 Self::from_vec(vec)
17 }
18
19 #[wasm_bindgen]
21 pub fn from_vec(vec: Vec<u8>) -> SiFont {
22 let font = FontVec::try_from_vec(vec).unwrap();
23 SiFont { font }
24 }
25
26 #[wasm_bindgen]
32 #[cfg(feature = "async")]
33 pub async fn from_network_async(url: &str) -> Result<SiFont, JsValue> {
34 let font_data: Vec<u8> = reqwest::get(url)
35 .await
36 .expect("Could not fetch font")
37 .bytes()
38 .await
39 .expect("Could not extract font")
40 .into();
41 let font = FontVec::try_from_vec(font_data).unwrap();
42 Ok(SiFont { font })
43 }
44
45 #[cfg(not(feature = "async"))]
47 pub fn from_network_async(_url: &str) {
48 panic!("async feature not enabled")
49 }
50
51 #[cfg(feature = "blocking")]
57 pub fn from_network(src: &str) -> SiFont {
58 let font_data: Vec<u8> = reqwest::blocking::get(src)
60 .expect("Could not fetch font")
61 .bytes()
62 .expect("Could not extract font")
63 .into();
64 let font = FontVec::try_from_vec(font_data).unwrap();
65 SiFont { font }
66 }
67
68 #[cfg(not(feature = "blocking"))]
70 pub fn from_network(url: &str) {
71 panic!("blocking feature not enabled")
72 }
73
74 pub(crate) fn layout(
75 &self,
76 text: &str,
77 scale: f32,
78 position: Position,
79 options: &TextOptions,
80 ) -> Vec<OutlinedGlyph> {
81 let mut res: Vec<OutlinedGlyph> = Vec::new();
82 let mut tmp_x: f32 = position.0;
83 for char in text.chars() {
84 if char.is_whitespace() {
85 tmp_x += options.space_width;
86 }
87 if let Some(glyph) = self.font.outline_glyph(
88 self.font
89 .glyph_id(char)
90 .with_scale_and_position(scale, ab_glyph::point(tmp_x, position.1)),
91 ) {
92 let bb = glyph.px_bounds();
93 res.push(glyph);
94 tmp_x += bb.width() + options.letter_spacing;
95 }
97 }
98 res
99 }
100}
101
102pub type Position = (f32, f32);