mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-31 15:47:26 +00:00
Clean up MCU font handling code a little
Dedicated a PixelFont struct to the combo of generic font and pixel-size matched glyphs.
This commit is contained in:
parent
1a73460a6a
commit
b27dc9109a
2 changed files with 62 additions and 36 deletions
|
@ -45,7 +45,7 @@ impl Glyph {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait FontMetrics {
|
||||
trait FontMetrics {
|
||||
fn ascent(&self, font: &BitmapFont) -> PhysicalLength;
|
||||
fn height(&self, font: &BitmapFont) -> PhysicalLength;
|
||||
fn pixel_size(&self) -> PhysicalLength;
|
||||
|
@ -68,10 +68,52 @@ impl FontMetrics for BitmapGlyphs {
|
|||
|
||||
pub const DEFAULT_FONT_SIZE: f32 = 12.0;
|
||||
|
||||
pub fn match_font(
|
||||
request: &FontRequest,
|
||||
scale_factor: ScaleFactor,
|
||||
) -> (&'static BitmapFont, &'static BitmapGlyphs) {
|
||||
// A font that is resolved to a specific pixel size.
|
||||
pub struct PixelFont {
|
||||
bitmap_font: &'static BitmapFont,
|
||||
glyphs: &'static BitmapGlyphs,
|
||||
//letter_spacing: PhysicalLength,
|
||||
}
|
||||
|
||||
impl PixelFont {
|
||||
pub fn ascent(&self) -> PhysicalLength {
|
||||
self.glyphs.ascent(self.bitmap_font)
|
||||
}
|
||||
|
||||
pub fn height(&self) -> PhysicalLength {
|
||||
self.glyphs.height(self.bitmap_font)
|
||||
}
|
||||
|
||||
pub fn pixel_size(&self) -> PhysicalLength {
|
||||
self.glyphs.pixel_size()
|
||||
}
|
||||
|
||||
pub fn glyphs_for_text<'a>(
|
||||
&'a self,
|
||||
text: &'a str,
|
||||
) -> impl Iterator<Item = (PhysicalLength, Glyph)> + 'a {
|
||||
let mut x: PhysicalLength = PhysicalLength::zero();
|
||||
text.chars().filter_map(move |char| {
|
||||
if let Some(glyph_index) = self
|
||||
.bitmap_font
|
||||
.character_map
|
||||
.binary_search_by_key(&char, |char_map_entry| char_map_entry.code_point)
|
||||
.ok()
|
||||
.map(|char_map_index| self.bitmap_font.character_map[char_map_index].glyph_index)
|
||||
{
|
||||
let glyph = Glyph(&self.glyphs.glyph_data[glyph_index as usize]);
|
||||
let glyph_x = x;
|
||||
x += glyph.x_advance();
|
||||
Some((glyph_x, glyph))
|
||||
} else {
|
||||
x += self.pixel_size();
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn match_font(request: &FontRequest, scale_factor: ScaleFactor) -> PixelFont {
|
||||
let font = FONTS.with(|fonts| {
|
||||
let fonts = fonts.borrow();
|
||||
let fallback_font =
|
||||
|
@ -98,48 +140,32 @@ pub fn match_font(
|
|||
|
||||
let matching_glyphs = &font.glyphs[nearest_pixel_size];
|
||||
|
||||
(font, matching_glyphs)
|
||||
PixelFont {
|
||||
bitmap_font: font,
|
||||
glyphs: matching_glyphs,
|
||||
/*letter_spacing: (LogicalLength::new(request.letter_spacing.unwrap_or_default())
|
||||
* scale_factor)
|
||||
.cast(),
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_bitmap_font(font_data: &'static BitmapFont) {
|
||||
FONTS.with(|fonts| fonts.borrow_mut().push(font_data))
|
||||
}
|
||||
|
||||
pub fn glyphs_for_text<'a>(
|
||||
font: &'static BitmapFont,
|
||||
glyphs: &'static BitmapGlyphs,
|
||||
text: &'a str,
|
||||
) -> impl Iterator<Item = (PhysicalLength, Glyph)> + 'a {
|
||||
let mut x: PhysicalLength = PhysicalLength::zero();
|
||||
text.chars().filter_map(move |char| {
|
||||
if let Some(glyph_index) = font
|
||||
.character_map
|
||||
.binary_search_by_key(&char, |char_map_entry| char_map_entry.code_point)
|
||||
.ok()
|
||||
.map(|char_map_index| font.character_map[char_map_index].glyph_index)
|
||||
{
|
||||
let glyph = Glyph(&glyphs.glyph_data[glyph_index as usize]);
|
||||
let glyph_x = x;
|
||||
x += glyph.x_advance();
|
||||
Some((glyph_x, glyph))
|
||||
} else {
|
||||
x += glyphs.pixel_size();
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn text_size(
|
||||
font_request: FontRequest,
|
||||
text: &str,
|
||||
_max_width: Option<f32>,
|
||||
scale_factor: ScaleFactor,
|
||||
) -> LogicalSize {
|
||||
let (font, glyphs) = match_font(&font_request, scale_factor);
|
||||
let font = match_font(&font_request, scale_factor);
|
||||
|
||||
let width = glyphs_for_text(font, glyphs, text)
|
||||
let width = font
|
||||
.glyphs_for_text(text)
|
||||
.last()
|
||||
.map_or(PhysicalLength::zero(), |(last_x, last_glyph)| last_x + last_glyph.x_advance());
|
||||
|
||||
PhysicalSize::from_lengths(width, glyphs.height(font)).cast() / scale_factor
|
||||
PhysicalSize::from_lengths(width, font.height()).cast() / scale_factor
|
||||
}
|
||||
|
|
|
@ -537,13 +537,13 @@ impl i_slint_core::item_rendering::ItemRenderer for PrepareScene {
|
|||
|
||||
fn draw_text(&mut self, text: Pin<&i_slint_core::items::Text>) {
|
||||
let font_request = text.unresolved_font_request().merge(&self.default_font);
|
||||
let (font, glyphs) = crate::fonts::match_font(&font_request, self.scale_factor);
|
||||
let font = crate::fonts::match_font(&font_request, self.scale_factor);
|
||||
|
||||
let color = text.color().color();
|
||||
|
||||
let baseline_y = glyphs.ascent(font);
|
||||
let baseline_y = font.ascent();
|
||||
|
||||
for (glyph_baseline_x, glyph) in crate::fonts::glyphs_for_text(font, glyphs, &text.text()) {
|
||||
for (glyph_baseline_x, glyph) in font.glyphs_for_text(&text.text()) {
|
||||
if let Some(dest_rect) = (PhysicalRect::new(
|
||||
PhysicalPoint::from_lengths(
|
||||
glyph_baseline_x + glyph.x(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue