diff --git a/core/embed/rust/src/ui/display/font.rs b/core/embed/rust/src/ui/display/font.rs index 1de99b6aef..7cdff05d7d 100644 --- a/core/embed/rust/src/ui/display/font.rs +++ b/core/embed/rust/src/ui/display/font.rs @@ -46,6 +46,8 @@ impl<'a> Glyph<'a> { let width = data[0] as i16; let height = data[1] as i16; + let size = calculate_glyph_size(data); + ensure!(data.len() == size, "Invalid glyph data size"); Glyph { width, height, @@ -144,62 +146,70 @@ impl GlyphData { }; let gl_data = self.get_glyph_data(ch as u16); - ensure!(gl_data.is_some(), "Failed to load glyph"); - Glyph::load(gl_data.unwrap()) - } - - fn calculate_glyph_size(header: &[u8]) -> usize { - let width = header[0] as i16; - let height = header[1] as i16; - - let data_bytes = match constant::FONT_BPP { - 1 => (width * height + 7) / 8, // packed bits - 2 => (width * height + 3) / 4, // packed bits - 4 => (width + 1) / 2 * height, // row aligned to bytes - 8 => width * height, - _ => fatal_error!("Unsupported font bpp"), - }; - - 5 + data_bytes as usize // header (5 bytes) + bitmap data + Glyph::load(unwrap!(gl_data, "Failed to load glyph")) } fn get_glyph_data(&self, codepoint: u16) -> Option<&[u8]> { display::get_font_info(self.font.into()).map(|font_info| { if codepoint >= ' ' as u16 && codepoint < 0x7F { // ASCII character + let offset = codepoint - ' ' as u16; unsafe { - let ptr = *font_info - .glyph_data - .offset((codepoint - ' ' as u16) as isize); - let header = slice::from_raw_parts(ptr, 2); - let full_size = Self::calculate_glyph_size(header); - slice::from_raw_parts(ptr, full_size) + let ptr = *font_info.glyph_data.offset(offset as isize); + self.load_glyph_from_ptr(ptr) } } else { #[cfg(feature = "translations")] { if codepoint >= 0x7F { // UTF8 character from embedded blob - if let Some(guard) = &self.translations_guard { - if let Some(translations) = guard.as_ref() { - if let Some(glyph) = - translations.get_utf8_glyph(codepoint, self.font as u16) - { - return glyph; - } - } + if let Some(glyph) = self + .translations_guard + .as_ref() + .and_then(|guard| guard.as_ref()) + .and_then(|translations| { + translations.get_utf8_glyph(codepoint, self.font as u16) + }) + { + return glyph; } } } - unsafe { - let ptr = font_info.glyph_nonprintable; - let header = slice::from_raw_parts(ptr, 2); - let full_size = Self::calculate_glyph_size(header); - slice::from_raw_parts(ptr, full_size) - } + self.glyph_nonprintable() } }) } + + /// Returns glyph data slice from a raw pointer by reading the header and calculating full size. + unsafe fn load_glyph_from_ptr(&self, ptr: *const u8) -> &[u8] { + unsafe { + let header = slice::from_raw_parts(ptr, 2); + let full_size = calculate_glyph_size(header); + slice::from_raw_parts(ptr, full_size) + } + } + + /// Returns glyph data slize for non-printable characters. + fn glyph_nonprintable(&self) -> &[u8] { + display::get_font_info(self.font.into()) + .map(|font_info| unsafe { self.load_glyph_from_ptr(font_info.glyph_nonprintable) }) + .unwrap() + } +} + +fn calculate_glyph_size(header: &[u8]) -> usize { + let width = header[0] as i16; + let height = header[1] as i16; + + let data_bytes = match constant::FONT_BPP { + 1 => (width * height + 7) / 8, // packed bits + 2 => (width * height + 3) / 4, // packed bits + 4 => (width + 1) / 2 * height, // row aligned to bytes + 8 => width * height, + _ => fatal_error!("Unsupported font bpp"), + }; + + 5 + data_bytes as usize // header (5 bytes) + bitmap data } /// Font constants. Keep in sync with `font_id_t` definition in