1 use super::{FontData, FontFamily, FontStyle, LayoutBox}; 2 use wasm_bindgen::JsCast; 3 use web_sys::{window, HtmlElement}; 4 5 #[derive(Debug, Clone)] 6 pub enum FontError { 7 UnknownError, 8 } 9 10 impl std::fmt::Display for FontError { fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>11 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { 12 match self { 13 _ => write!(fmt, "Unknown error"), 14 } 15 } 16 } 17 18 impl std::error::Error for FontError {} 19 20 #[derive(Clone)] 21 pub struct FontDataInternal(String, String); 22 23 impl FontData for FontDataInternal { 24 type ErrorType = FontError; new(family: FontFamily, style: FontStyle) -> Result<Self, FontError>25 fn new(family: FontFamily, style: FontStyle) -> Result<Self, FontError> { 26 Ok(FontDataInternal( 27 family.as_str().into(), 28 style.as_str().into(), 29 )) 30 } estimate_layout(&self, size: f64, text: &str) -> Result<LayoutBox, Self::ErrorType>31 fn estimate_layout(&self, size: f64, text: &str) -> Result<LayoutBox, Self::ErrorType> { 32 let window = window().unwrap(); 33 let document = window.document().unwrap(); 34 let body = document.body().unwrap(); 35 let span = document.create_element("span").unwrap(); 36 span.set_text_content(Some(text)); 37 span.set_attribute("style", &format!("display: inline-block; font-family:{}; font-size: {}px; position: fixed; top: 100%", self.0, size)).unwrap(); 38 let span = span.into(); 39 body.append_with_node_1(&span).unwrap(); 40 let elem = JsCast::dyn_into::<HtmlElement>(span).unwrap(); 41 let height = elem.offset_height() as i32; 42 let width = elem.offset_width() as i32; 43 elem.remove(); 44 Ok(((0, 0), (width, height))) 45 } 46 } 47