diff --git a/sixtyfps_runtime/corelib/font/mod.rs b/sixtyfps_runtime/corelib/font/mod.rs index 43732b675..0a0ac5d24 100644 --- a/sixtyfps_runtime/corelib/font/mod.rs +++ b/sixtyfps_runtime/corelib/font/mod.rs @@ -27,12 +27,21 @@ struct FontMatch { fonts_per_pixel_size: Vec>, } +#[derive(Debug, Clone, PartialEq)] +#[repr(C)] +pub struct FontRequest { + family: SharedString, + pixel_size: f32, +} + pub trait HasFont { fn font_family(&self) -> SharedString; fn font_pixel_size(&self, window: &crate::eventloop::ComponentWindow) -> f32; + fn font_request(&self, window: &crate::eventloop::ComponentWindow) -> FontRequest { + FontRequest { family: self.font_family(), pixel_size: self.font_pixel_size(window) } + } fn font(&self, window: &crate::eventloop::ComponentWindow) -> Rc { - crate::font::FONT_CACHE - .with(|fc| fc.find_font(&self.font_family(), self.font_pixel_size(window))) + crate::font::FONT_CACHE.with(|fc| fc.find_font(&self.font_request(window))) } } @@ -43,21 +52,29 @@ pub struct FontCache { } impl FontCache { - pub fn find_font(&self, family: &SharedString, pixel_size: f32) -> Rc { - assert_ne!(pixel_size, 0.0); + pub fn find_font(&self, request: &FontRequest) -> Rc { + assert_ne!(request.pixel_size, 0.0); let mut loaded_fonts = self.loaded_fonts.borrow_mut(); - let font_match = loaded_fonts.entry(family.clone()).or_insert_with(|| FontMatch { - handle: FontHandle::new_from_match(family), + let font_match = loaded_fonts.entry(request.family.clone()).or_insert_with(|| FontMatch { + handle: FontHandle::new_from_match(&request.family), fonts_per_pixel_size: Vec::new(), }); font_match .fonts_per_pixel_size .iter() - .find_map(|font| if font.pixel_size == pixel_size { Some(font.clone()) } else { None }) + .find_map( + |font| { + if font.pixel_size == request.pixel_size { + Some(font.clone()) + } else { + None + } + }, + ) .unwrap_or_else(|| { - let fnt = Rc::new(font_match.handle.load(pixel_size).unwrap()); + let fnt = Rc::new(font_match.handle.load(request.pixel_size).unwrap()); font_match.fonts_per_pixel_size.push(fnt.clone()); fnt }) diff --git a/sixtyfps_runtime/corelib/graphics.rs b/sixtyfps_runtime/corelib/graphics.rs index 5ad67fbc5..c7d03c1b9 100644 --- a/sixtyfps_runtime/corelib/graphics.rs +++ b/sixtyfps_runtime/corelib/graphics.rs @@ -285,7 +285,7 @@ pub enum HighLevelRenderingPrimitive { /// Expected rendering variables: /// * [`RenderingVariable::Color`]: The color to use for rendering the glyphs. /// * [`RenderingVariable::TextCursor`]: Draw a text cursor. - Text { text: crate::SharedString, font_family: crate::SharedString, font_size: f32 }, + Text { text: crate::SharedString, font_request: super::font::FontRequest }, /// Renders a path specified by the `elements` parameter. The path will be scaled to fit into the given /// `width` and `height`. If the `stroke_width` is greater than zero, then path will also be outlined. /// diff --git a/sixtyfps_runtime/corelib/items.rs b/sixtyfps_runtime/corelib/items.rs index eca30f613..b7c3aae21 100644 --- a/sixtyfps_runtime/corelib/items.rs +++ b/sixtyfps_runtime/corelib/items.rs @@ -529,8 +529,7 @@ impl Item for Text { ) -> HighLevelRenderingPrimitive { HighLevelRenderingPrimitive::Text { text: Self::FIELD_OFFSETS.text.apply_pin(self).get(), - font_family: Self::FIELD_OFFSETS.font_family.apply_pin(self).get(), - font_size: Text::font_pixel_size(self, window), + font_request: self.font_request(window), } } @@ -562,16 +561,12 @@ impl Item for Text { } fn layouting_info(self: Pin<&Self>, window: &ComponentWindow) -> LayoutInfo { - let font_family = Self::FIELD_OFFSETS.font_family.apply_pin(self).get(); - let font_size = Text::font_pixel_size(self, window); let text = Self::FIELD_OFFSETS.text.apply_pin(self).get(); - crate::font::FONT_CACHE.with(|fc| { - let font = fc.find_font(&font_family, font_size); - let width = font.text_width(&text); - let height = font.height(); - LayoutInfo { min_width: width, min_height: height, ..LayoutInfo::default() } - }) + let font = self.font(window); + let width = font.text_width(&text); + let height = font.height(); + LayoutInfo { min_width: width, min_height: height, ..LayoutInfo::default() } } fn input_event( @@ -596,17 +591,6 @@ impl ItemConsts for Text { Text::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection(); } -impl Text { - fn font_pixel_size(self: Pin<&Self>, window: &ComponentWindow) -> f32 { - let font_size = Self::FIELD_OFFSETS.font_size.apply_pin(self).get(); - if font_size == 0.0 { - DEFAULT_FONT_SIZE * window.scale_factor() - } else { - font_size - } - } -} - impl HasFont for Pin<&Text> { fn font_family(&self) -> SharedString { ::Target::FIELD_OFFSETS.font_family.apply_pin(*self).get() @@ -1140,8 +1124,7 @@ impl Item for TextInput { ) -> HighLevelRenderingPrimitive { HighLevelRenderingPrimitive::Text { text: Self::FIELD_OFFSETS.text.apply_pin(self).get(), - font_family: Self::FIELD_OFFSETS.font_family.apply_pin(self).get(), - font_size: TextInput::font_pixel_size(self, window), + font_request: self.font_request(window), } } @@ -1369,17 +1352,6 @@ impl Item for TextInput { } } -impl TextInput { - fn font_pixel_size(self: Pin<&Self>, window: &ComponentWindow) -> f32 { - let font_size = Self::FIELD_OFFSETS.font_size.apply_pin(self).get(); - if font_size == 0.0 { - DEFAULT_FONT_SIZE * window.scale_factor() - } else { - font_size - } - } -} - impl ItemConsts for TextInput { const cached_rendering_data_offset: const_field_offset::FieldOffset< TextInput, diff --git a/sixtyfps_runtime/rendering_backends/gl/glyphcache.rs b/sixtyfps_runtime/rendering_backends/gl/glyphcache.rs index 13d098004..2ed089bfc 100644 --- a/sixtyfps_runtime/rendering_backends/gl/glyphcache.rs +++ b/sixtyfps_runtime/rendering_backends/gl/glyphcache.rs @@ -12,9 +12,7 @@ use super::texture::{AtlasAllocation, TextureAtlas}; use super::Vertex; use collections::hash_map::HashMap; use itertools::Itertools; -use sixtyfps_corelib::font::Font; -use sixtyfps_corelib::font::FontHandle; -use sixtyfps_corelib::SharedString; +use sixtyfps_corelib::font::{Font, FontHandle, FontRequest}; use std::cell::RefCell; use std::{collections, rc::Rc}; @@ -28,13 +26,8 @@ pub(crate) struct GlyphCache { } impl GlyphCache { - pub fn find_font( - &self, - font_family: &SharedString, - pixel_size: f32, - ) -> Rc> { - let font = - sixtyfps_corelib::font::FONT_CACHE.with(|fc| fc.find_font(font_family, pixel_size)); + pub fn find_font(&self, request: &FontRequest) -> Rc> { + let font = sixtyfps_corelib::font::FONT_CACHE.with(|fc| fc.find_font(request)); let font_handle = font.handle(); diff --git a/sixtyfps_runtime/rendering_backends/gl/lib.rs b/sixtyfps_runtime/rendering_backends/gl/lib.rs index ed24aecb2..bb81ae014 100644 --- a/sixtyfps_runtime/rendering_backends/gl/lib.rs +++ b/sixtyfps_runtime/rendering_backends/gl/lib.rs @@ -14,7 +14,7 @@ use lyon::tessellation::{ FillAttributes, FillOptions, FillTessellator, StrokeAttributes, StrokeOptions, StrokeTessellator, }; -use sixtyfps_corelib::{eventloop::ComponentWindow, SharedString}; +use sixtyfps_corelib::{eventloop::ComponentWindow, font::FontRequest}; use sixtyfps_corelib::{ graphics::{ Color, Frame as GraphicsFrame, GraphicsBackend, GraphicsWindow, @@ -532,8 +532,8 @@ impl RenderingPrimitivesBuilder for GLRenderingPrimitivesBuilder { Resource::None => SmallVec::new(), } } - HighLevelRenderingPrimitive::Text { text, font_family, font_size } => { - smallvec![self.create_glyph_runs(text, font_family, *font_size)] + HighLevelRenderingPrimitive::Text { text, font_request } => { + smallvec![self.create_glyph_runs(text, font_request)] } HighLevelRenderingPrimitive::Path { width, height, elements, stroke_width } => { let mut primitives = SmallVec::new(); @@ -725,10 +725,9 @@ impl GLRenderingPrimitivesBuilder { fn create_glyph_runs( &mut self, text: &str, - font_family: &SharedString, - pixel_size: f32, + font_request: &FontRequest, ) -> GLRenderingPrimitive { - let cached_glyphs = self.platform_data.glyph_cache.find_font(font_family, pixel_size); + let cached_glyphs = self.platform_data.glyph_cache.find_font(font_request); let mut cached_glyphs = cached_glyphs.borrow_mut(); let mut atlas = self.texture_atlas.borrow_mut(); let glyphs_runs = cached_glyphs.render_glyphs(&self.context, &mut atlas, text); @@ -739,11 +738,9 @@ impl GLRenderingPrimitivesBuilder { fn create_glyph_runs( &mut self, text: &str, - font_family: &SharedString, - pixel_size: f32, + font_request: &FontRequest, ) -> GLRenderingPrimitive { - let font = - sixtyfps_corelib::font::FONT_CACHE.with(|fc| fc.find_font(font_family, pixel_size)); + let font = sixtyfps_corelib::font::FONT_CACHE.with(|fc| fc.find_font(font_request)); let text_canvas = font.render_text(text); let texture = Rc::new(GLTexture::new_from_canvas(&self.context, &text_canvas));