mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 06:11:16 +00:00
More font handling cleanup
Group all fields we need to determine a physical font into one FontRequest structure and use that throughout. That way adding more fields will require less changes.
This commit is contained in:
parent
05204a3185
commit
f0289192b7
5 changed files with 42 additions and 63 deletions
|
@ -27,12 +27,21 @@ struct FontMatch {
|
||||||
fonts_per_pixel_size: Vec<Rc<Font>>,
|
fonts_per_pixel_size: Vec<Rc<Font>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct FontRequest {
|
||||||
|
family: SharedString,
|
||||||
|
pixel_size: f32,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait HasFont {
|
pub trait HasFont {
|
||||||
fn font_family(&self) -> SharedString;
|
fn font_family(&self) -> SharedString;
|
||||||
fn font_pixel_size(&self, window: &crate::eventloop::ComponentWindow) -> f32;
|
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<Font> {
|
fn font(&self, window: &crate::eventloop::ComponentWindow) -> Rc<Font> {
|
||||||
crate::font::FONT_CACHE
|
crate::font::FONT_CACHE.with(|fc| fc.find_font(&self.font_request(window)))
|
||||||
.with(|fc| fc.find_font(&self.font_family(), self.font_pixel_size(window)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,21 +52,29 @@ pub struct FontCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontCache {
|
impl FontCache {
|
||||||
pub fn find_font(&self, family: &SharedString, pixel_size: f32) -> Rc<Font> {
|
pub fn find_font(&self, request: &FontRequest) -> Rc<Font> {
|
||||||
assert_ne!(pixel_size, 0.0);
|
assert_ne!(request.pixel_size, 0.0);
|
||||||
|
|
||||||
let mut loaded_fonts = self.loaded_fonts.borrow_mut();
|
let mut loaded_fonts = self.loaded_fonts.borrow_mut();
|
||||||
let font_match = loaded_fonts.entry(family.clone()).or_insert_with(|| FontMatch {
|
let font_match = loaded_fonts.entry(request.family.clone()).or_insert_with(|| FontMatch {
|
||||||
handle: FontHandle::new_from_match(family),
|
handle: FontHandle::new_from_match(&request.family),
|
||||||
fonts_per_pixel_size: Vec::new(),
|
fonts_per_pixel_size: Vec::new(),
|
||||||
});
|
});
|
||||||
|
|
||||||
font_match
|
font_match
|
||||||
.fonts_per_pixel_size
|
.fonts_per_pixel_size
|
||||||
.iter()
|
.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(|| {
|
.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());
|
font_match.fonts_per_pixel_size.push(fnt.clone());
|
||||||
fnt
|
fnt
|
||||||
})
|
})
|
||||||
|
|
|
@ -285,7 +285,7 @@ pub enum HighLevelRenderingPrimitive {
|
||||||
/// Expected rendering variables:
|
/// Expected rendering variables:
|
||||||
/// * [`RenderingVariable::Color`]: The color to use for rendering the glyphs.
|
/// * [`RenderingVariable::Color`]: The color to use for rendering the glyphs.
|
||||||
/// * [`RenderingVariable::TextCursor`]: Draw a text cursor.
|
/// * [`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
|
/// 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.
|
/// `width` and `height`. If the `stroke_width` is greater than zero, then path will also be outlined.
|
||||||
///
|
///
|
||||||
|
|
|
@ -529,8 +529,7 @@ impl Item for Text {
|
||||||
) -> HighLevelRenderingPrimitive {
|
) -> HighLevelRenderingPrimitive {
|
||||||
HighLevelRenderingPrimitive::Text {
|
HighLevelRenderingPrimitive::Text {
|
||||||
text: Self::FIELD_OFFSETS.text.apply_pin(self).get(),
|
text: Self::FIELD_OFFSETS.text.apply_pin(self).get(),
|
||||||
font_family: Self::FIELD_OFFSETS.font_family.apply_pin(self).get(),
|
font_request: self.font_request(window),
|
||||||
font_size: Text::font_pixel_size(self, window),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,16 +561,12 @@ impl Item for Text {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layouting_info(self: Pin<&Self>, window: &ComponentWindow) -> LayoutInfo {
|
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();
|
let text = Self::FIELD_OFFSETS.text.apply_pin(self).get();
|
||||||
|
|
||||||
crate::font::FONT_CACHE.with(|fc| {
|
let font = self.font(window);
|
||||||
let font = fc.find_font(&font_family, font_size);
|
let width = font.text_width(&text);
|
||||||
let width = font.text_width(&text);
|
let height = font.height();
|
||||||
let height = font.height();
|
LayoutInfo { min_width: width, min_height: height, ..LayoutInfo::default() }
|
||||||
LayoutInfo { min_width: width, min_height: height, ..LayoutInfo::default() }
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn input_event(
|
fn input_event(
|
||||||
|
@ -596,17 +591,6 @@ impl ItemConsts for Text {
|
||||||
Text::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
|
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> {
|
impl HasFont for Pin<&Text> {
|
||||||
fn font_family(&self) -> SharedString {
|
fn font_family(&self) -> SharedString {
|
||||||
<Self as core::ops::Deref>::Target::FIELD_OFFSETS.font_family.apply_pin(*self).get()
|
<Self as core::ops::Deref>::Target::FIELD_OFFSETS.font_family.apply_pin(*self).get()
|
||||||
|
@ -1140,8 +1124,7 @@ impl Item for TextInput {
|
||||||
) -> HighLevelRenderingPrimitive {
|
) -> HighLevelRenderingPrimitive {
|
||||||
HighLevelRenderingPrimitive::Text {
|
HighLevelRenderingPrimitive::Text {
|
||||||
text: Self::FIELD_OFFSETS.text.apply_pin(self).get(),
|
text: Self::FIELD_OFFSETS.text.apply_pin(self).get(),
|
||||||
font_family: Self::FIELD_OFFSETS.font_family.apply_pin(self).get(),
|
font_request: self.font_request(window),
|
||||||
font_size: TextInput::font_pixel_size(self, 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 {
|
impl ItemConsts for TextInput {
|
||||||
const cached_rendering_data_offset: const_field_offset::FieldOffset<
|
const cached_rendering_data_offset: const_field_offset::FieldOffset<
|
||||||
TextInput,
|
TextInput,
|
||||||
|
|
|
@ -12,9 +12,7 @@ use super::texture::{AtlasAllocation, TextureAtlas};
|
||||||
use super::Vertex;
|
use super::Vertex;
|
||||||
use collections::hash_map::HashMap;
|
use collections::hash_map::HashMap;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use sixtyfps_corelib::font::Font;
|
use sixtyfps_corelib::font::{Font, FontHandle, FontRequest};
|
||||||
use sixtyfps_corelib::font::FontHandle;
|
|
||||||
use sixtyfps_corelib::SharedString;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::{collections, rc::Rc};
|
use std::{collections, rc::Rc};
|
||||||
|
|
||||||
|
@ -28,13 +26,8 @@ pub(crate) struct GlyphCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlyphCache {
|
impl GlyphCache {
|
||||||
pub fn find_font(
|
pub fn find_font(&self, request: &FontRequest) -> Rc<RefCell<CachedFontGlyphs>> {
|
||||||
&self,
|
let font = sixtyfps_corelib::font::FONT_CACHE.with(|fc| fc.find_font(request));
|
||||||
font_family: &SharedString,
|
|
||||||
pixel_size: f32,
|
|
||||||
) -> Rc<RefCell<CachedFontGlyphs>> {
|
|
||||||
let font =
|
|
||||||
sixtyfps_corelib::font::FONT_CACHE.with(|fc| fc.find_font(font_family, pixel_size));
|
|
||||||
|
|
||||||
let font_handle = font.handle();
|
let font_handle = font.handle();
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ use lyon::tessellation::{
|
||||||
FillAttributes, FillOptions, FillTessellator, StrokeAttributes, StrokeOptions,
|
FillAttributes, FillOptions, FillTessellator, StrokeAttributes, StrokeOptions,
|
||||||
StrokeTessellator,
|
StrokeTessellator,
|
||||||
};
|
};
|
||||||
use sixtyfps_corelib::{eventloop::ComponentWindow, SharedString};
|
use sixtyfps_corelib::{eventloop::ComponentWindow, font::FontRequest};
|
||||||
use sixtyfps_corelib::{
|
use sixtyfps_corelib::{
|
||||||
graphics::{
|
graphics::{
|
||||||
Color, Frame as GraphicsFrame, GraphicsBackend, GraphicsWindow,
|
Color, Frame as GraphicsFrame, GraphicsBackend, GraphicsWindow,
|
||||||
|
@ -532,8 +532,8 @@ impl RenderingPrimitivesBuilder for GLRenderingPrimitivesBuilder {
|
||||||
Resource::None => SmallVec::new(),
|
Resource::None => SmallVec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HighLevelRenderingPrimitive::Text { text, font_family, font_size } => {
|
HighLevelRenderingPrimitive::Text { text, font_request } => {
|
||||||
smallvec![self.create_glyph_runs(text, font_family, *font_size)]
|
smallvec![self.create_glyph_runs(text, font_request)]
|
||||||
}
|
}
|
||||||
HighLevelRenderingPrimitive::Path { width, height, elements, stroke_width } => {
|
HighLevelRenderingPrimitive::Path { width, height, elements, stroke_width } => {
|
||||||
let mut primitives = SmallVec::new();
|
let mut primitives = SmallVec::new();
|
||||||
|
@ -725,10 +725,9 @@ impl GLRenderingPrimitivesBuilder {
|
||||||
fn create_glyph_runs(
|
fn create_glyph_runs(
|
||||||
&mut self,
|
&mut self,
|
||||||
text: &str,
|
text: &str,
|
||||||
font_family: &SharedString,
|
font_request: &FontRequest,
|
||||||
pixel_size: f32,
|
|
||||||
) -> GLRenderingPrimitive {
|
) -> 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 cached_glyphs = cached_glyphs.borrow_mut();
|
||||||
let mut atlas = self.texture_atlas.borrow_mut();
|
let mut atlas = self.texture_atlas.borrow_mut();
|
||||||
let glyphs_runs = cached_glyphs.render_glyphs(&self.context, &mut atlas, text);
|
let glyphs_runs = cached_glyphs.render_glyphs(&self.context, &mut atlas, text);
|
||||||
|
@ -739,11 +738,9 @@ impl GLRenderingPrimitivesBuilder {
|
||||||
fn create_glyph_runs(
|
fn create_glyph_runs(
|
||||||
&mut self,
|
&mut self,
|
||||||
text: &str,
|
text: &str,
|
||||||
font_family: &SharedString,
|
font_request: &FontRequest,
|
||||||
pixel_size: f32,
|
|
||||||
) -> GLRenderingPrimitive {
|
) -> GLRenderingPrimitive {
|
||||||
let font =
|
let font = sixtyfps_corelib::font::FONT_CACHE.with(|fc| fc.find_font(font_request));
|
||||||
sixtyfps_corelib::font::FONT_CACHE.with(|fc| fc.find_font(font_family, pixel_size));
|
|
||||||
let text_canvas = font.render_text(text);
|
let text_canvas = font.render_text(text);
|
||||||
|
|
||||||
let texture = Rc::new(GLTexture::new_from_canvas(&self.context, &text_canvas));
|
let texture = Rc::new(GLTexture::new_from_canvas(&self.context, &text_canvas));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue