mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-19 14:08:11 +00:00
perf(core/rust): parse Toif metadata on demand
[no changelog]
This commit is contained in:
parent
194868438a
commit
0df81b18e3
@ -289,7 +289,6 @@ fn generate_trezorhal_bindings() {
|
|||||||
.allowlist_function("display_bar_radius")
|
.allowlist_function("display_bar_radius")
|
||||||
.allowlist_function("display_bar_radius_buffer")
|
.allowlist_function("display_bar_radius_buffer")
|
||||||
.allowlist_function("display_image")
|
.allowlist_function("display_image")
|
||||||
.allowlist_function("display_toif_info")
|
|
||||||
.allowlist_function("display_loader")
|
.allowlist_function("display_loader")
|
||||||
.allowlist_function("display_pixeldata")
|
.allowlist_function("display_pixeldata")
|
||||||
.allowlist_function("display_pixeldata_dirty")
|
.allowlist_function("display_pixeldata_dirty")
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use super::ffi;
|
use super::ffi;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
use cty::c_int;
|
use cty::c_int;
|
||||||
use num_traits::FromPrimitive;
|
|
||||||
|
|
||||||
use crate::trezorhal::buffers::BufferText;
|
use crate::trezorhal::buffers::BufferText;
|
||||||
|
|
||||||
@ -13,12 +12,6 @@ pub enum ToifFormat {
|
|||||||
GrayScaleEH = ffi::toif_format_t_TOIF_GRAYSCALE_EH as _,
|
GrayScaleEH = ffi::toif_format_t_TOIF_GRAYSCALE_EH as _,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ToifInfo {
|
|
||||||
pub width: u16,
|
|
||||||
pub height: u16,
|
|
||||||
pub format: ToifFormat,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn backlight(val: i32) -> i32 {
|
pub fn backlight(val: i32) -> i32 {
|
||||||
unsafe { ffi::display_backlight(val) }
|
unsafe { ffi::display_backlight(val) }
|
||||||
}
|
}
|
||||||
@ -116,31 +109,6 @@ pub fn image(x: i16, y: i16, w: i16, h: i16, data: &[u8]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toif_info(data: &[u8]) -> Result<ToifInfo, ()> {
|
|
||||||
let mut width: cty::uint16_t = 0;
|
|
||||||
let mut height: cty::uint16_t = 0;
|
|
||||||
let mut format: ffi::toif_format_t = ffi::toif_format_t_TOIF_FULL_COLOR_BE;
|
|
||||||
if unsafe {
|
|
||||||
ffi::display_toif_info(
|
|
||||||
data.as_ptr() as _,
|
|
||||||
data.len() as _,
|
|
||||||
&mut width,
|
|
||||||
&mut height,
|
|
||||||
&mut format,
|
|
||||||
)
|
|
||||||
} {
|
|
||||||
let format = ToifFormat::from_usize(format as usize).unwrap_or(ToifFormat::FullColorBE);
|
|
||||||
|
|
||||||
Ok(ToifInfo {
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
format,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn loader(
|
pub fn loader(
|
||||||
progress: u16,
|
progress: u16,
|
||||||
indeterminate: bool,
|
indeterminate: bool,
|
||||||
|
@ -16,8 +16,8 @@ pub struct Image {
|
|||||||
|
|
||||||
impl Image {
|
impl Image {
|
||||||
pub fn new(data: &'static [u8]) -> Self {
|
pub fn new(data: &'static [u8]) -> Self {
|
||||||
let toif = Toif::new(data);
|
let toif = unwrap!(Toif::new(data));
|
||||||
assert!(toif.format == ToifFormat::FullColorLE);
|
assert!(toif.format() == ToifFormat::FullColorLE);
|
||||||
Self {
|
Self {
|
||||||
toif,
|
toif,
|
||||||
area: Rect::zero(),
|
area: Rect::zero(),
|
||||||
@ -27,8 +27,8 @@ impl Image {
|
|||||||
/// Display the icon with baseline Point, aligned according to the
|
/// Display the icon with baseline Point, aligned according to the
|
||||||
/// `alignment` argument.
|
/// `alignment` argument.
|
||||||
pub fn draw(&self, baseline: Point, alignment: Alignment2D) {
|
pub fn draw(&self, baseline: Point, alignment: Alignment2D) {
|
||||||
let r = Rect::snap(baseline, self.toif.size, alignment);
|
let r = Rect::snap(baseline, self.toif.size(), alignment);
|
||||||
image(r.x0, r.y0, r.width(), r.height(), self.toif.data);
|
image(r.x0, r.y0, r.width(), r.height(), self.toif.zdata());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ impl Component for Image {
|
|||||||
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
||||||
sink(Rect::from_center_and_size(
|
sink(Rect::from_center_and_size(
|
||||||
self.area.center(),
|
self.area.center(),
|
||||||
self.toif.size,
|
self.toif.size(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,12 +101,12 @@ impl Component for BlendedImage {
|
|||||||
type Msg = Never;
|
type Msg = Never;
|
||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
self.bg_top_left = self.bg.toif.size.snap(bounds.center(), CENTER);
|
self.bg_top_left = self.bg.toif.size().snap(bounds.center(), CENTER);
|
||||||
|
|
||||||
let ft_top_left = self.fg.toif.size.snap(bounds.center(), CENTER);
|
let ft_top_left = self.fg.toif.size().snap(bounds.center(), CENTER);
|
||||||
self.fg_offset = ft_top_left - self.bg_top_left;
|
self.fg_offset = ft_top_left - self.bg_top_left;
|
||||||
|
|
||||||
Rect::from_top_left_and_size(self.bg_top_left, self.bg.toif.size)
|
Rect::from_top_left_and_size(self.bg_top_left, self.bg.toif.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||||
@ -120,7 +120,7 @@ impl Component for BlendedImage {
|
|||||||
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
||||||
sink(Rect::from_top_left_and_size(
|
sink(Rect::from_top_left_and_size(
|
||||||
self.bg_top_left,
|
self.bg_top_left,
|
||||||
self.bg.toif.size,
|
self.bg.toif.size(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,10 +43,11 @@ pub fn loader_uncompress(
|
|||||||
const ICON_MAX_SIZE: i16 = constant::LOADER_ICON_MAX_SIZE;
|
const ICON_MAX_SIZE: i16 = constant::LOADER_ICON_MAX_SIZE;
|
||||||
|
|
||||||
if let Some((icon, color)) = icon {
|
if let Some((icon, color)) = icon {
|
||||||
if icon.toif.width() <= ICON_MAX_SIZE && icon.toif.height() <= ICON_MAX_SIZE {
|
let toif_size = icon.toif.size();
|
||||||
|
if toif_size.x <= ICON_MAX_SIZE && toif_size.y <= ICON_MAX_SIZE {
|
||||||
let mut icon_data = [0_u8; ((ICON_MAX_SIZE * ICON_MAX_SIZE) / 2) as usize];
|
let mut icon_data = [0_u8; ((ICON_MAX_SIZE * ICON_MAX_SIZE) / 2) as usize];
|
||||||
icon.toif.uncompress(&mut icon_data);
|
icon.toif.uncompress(&mut icon_data);
|
||||||
let i = Some((icon, color, icon.toif.size));
|
let i = Some((icon, color, toif_size));
|
||||||
loader_rust(y_offset, fg_color, bg_color, progress, indeterminate, i);
|
loader_rust(y_offset, fg_color, bg_color, progress, indeterminate, i);
|
||||||
} else {
|
} else {
|
||||||
loader_rust(y_offset, fg_color, bg_color, progress, indeterminate, None);
|
loader_rust(y_offset, fg_color, bg_color, progress, indeterminate, None);
|
||||||
@ -237,7 +238,7 @@ pub fn loader_rust(
|
|||||||
let x_i = x_c - icon_area.x0;
|
let x_i = x_c - icon_area.x0;
|
||||||
let y_i = y_c - icon_area.y0;
|
let y_i = y_c - icon_area.y0;
|
||||||
|
|
||||||
let data = unwrap!(icon_data).data()
|
let data = unwrap!(icon_data).zdata()
|
||||||
[(((x_i & 0xFE) + (y_i * icon_width)) / 2) as usize];
|
[(((x_i & 0xFE) + (y_i * icon_width)) / 2) as usize];
|
||||||
if (x_i & 0x01) == 0 {
|
if (x_i & 0x01) == 0 {
|
||||||
underlying_color = icon_colortable[(data & 0xF) as usize];
|
underlying_color = icon_colortable[(data & 0xF) as usize];
|
||||||
@ -337,7 +338,7 @@ pub fn loader_rust(
|
|||||||
|
|
||||||
icon_buffer_used.buffer[icon_offset as usize..(icon_offset + icon_width / 2) as usize]
|
icon_buffer_used.buffer[icon_offset as usize..(icon_offset + icon_width / 2) as usize]
|
||||||
.copy_from_slice(
|
.copy_from_slice(
|
||||||
&unwrap!(icon_data).toif.data[(y_i * (icon_width / 2)) as usize
|
&unwrap!(icon_data).toif.zdata()[(y_i * (icon_width / 2)) as usize
|
||||||
..((y_i + 1) * (icon_width / 2)) as usize],
|
..((y_i + 1) * (icon_width / 2)) as usize],
|
||||||
);
|
);
|
||||||
icon_buffer = icon_buffer_used;
|
icon_buffer = icon_buffer_used;
|
||||||
|
@ -24,11 +24,10 @@ use crate::{
|
|||||||
error::Error,
|
error::Error,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
trezorhal::{display, qr, time, uzlib::UzlibContext},
|
trezorhal::{display, qr, time, uzlib::UzlibContext},
|
||||||
ui::lerp::Lerp,
|
ui::{component::image::Image, lerp::Lerp},
|
||||||
};
|
};
|
||||||
use core::slice;
|
use core::slice;
|
||||||
|
|
||||||
use crate::ui::component::image::Image;
|
|
||||||
pub use crate::ui::display::toif::Icon;
|
pub use crate::ui::display::toif::Icon;
|
||||||
#[cfg(any(feature = "model_tt", feature = "model_tr"))]
|
#[cfg(any(feature = "model_tt", feature = "model_tr"))]
|
||||||
pub use loader::{loader, loader_indeterminate, LOADER_MAX, LOADER_MIN};
|
pub use loader::{loader, loader_indeterminate, LOADER_MAX, LOADER_MIN};
|
||||||
@ -228,8 +227,9 @@ pub fn rect_rounded2_partial(
|
|||||||
let mut icon_width = 0;
|
let mut icon_width = 0;
|
||||||
|
|
||||||
if let Some((icon, icon_color)) = icon {
|
if let Some((icon, icon_color)) = icon {
|
||||||
if icon.toif.width() <= MAX_ICON_SIZE && icon.toif.height() <= MAX_ICON_SIZE {
|
let icon_size = icon.toif.size();
|
||||||
icon_area = Rect::from_center_and_size(center, icon.toif.size);
|
if icon_size.x <= MAX_ICON_SIZE && icon_size.y <= MAX_ICON_SIZE {
|
||||||
|
icon_area = Rect::from_center_and_size(center, icon_size);
|
||||||
icon_area_clamped = icon_area.clamp(constant::screen());
|
icon_area_clamped = icon_area.clamp(constant::screen());
|
||||||
icon.toif.uncompress(&mut icon_data);
|
icon.toif.uncompress(&mut icon_data);
|
||||||
icon_colortable = get_color_table(icon_color, bg_color);
|
icon_colortable = get_color_table(icon_color, bg_color);
|
||||||
@ -461,10 +461,10 @@ pub fn text_over_image(
|
|||||||
empty_img.buffer.copy_from_slice(&img1.buffer);
|
empty_img.buffer.copy_from_slice(&img1.buffer);
|
||||||
|
|
||||||
area = a;
|
area = a;
|
||||||
r_img = Rect::from_top_left_and_size(a.top_left() + offset_img, image.toif.size);
|
r_img = Rect::from_top_left_and_size(a.top_left() + offset_img, image.toif.size());
|
||||||
offset_img_final = offset_img;
|
offset_img_final = offset_img;
|
||||||
} else {
|
} else {
|
||||||
area = Rect::from_top_left_and_size(offset_img.into(), image.toif.size);
|
area = Rect::from_top_left_and_size(offset_img.into(), image.toif.size());
|
||||||
r_img = area;
|
r_img = area;
|
||||||
offset_img_final = Offset::zero();
|
offset_img_final = Offset::zero();
|
||||||
}
|
}
|
||||||
@ -583,26 +583,26 @@ pub fn icon_over_icon(
|
|||||||
let final_offset_bg;
|
let final_offset_bg;
|
||||||
if let Some(a) = bg_area {
|
if let Some(a) = bg_area {
|
||||||
area = a;
|
area = a;
|
||||||
r_bg = Rect::from_top_left_and_size(a.top_left() + offset_bg, icon_bg.toif.size);
|
r_bg = Rect::from_top_left_and_size(a.top_left() + offset_bg, icon_bg.toif.size());
|
||||||
final_offset_bg = offset_bg;
|
final_offset_bg = offset_bg;
|
||||||
} else {
|
} else {
|
||||||
r_bg =
|
r_bg =
|
||||||
Rect::from_top_left_and_size(Point::new(offset_bg.x, offset_bg.y), icon_bg.toif.size);
|
Rect::from_top_left_and_size(Point::new(offset_bg.x, offset_bg.y), icon_bg.toif.size());
|
||||||
area = r_bg;
|
area = r_bg;
|
||||||
final_offset_bg = Offset::zero();
|
final_offset_bg = Offset::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
let r_fg = Rect::from_top_left_and_size(area.top_left() + offset_fg, icon_fg.toif.size);
|
let r_fg = Rect::from_top_left_and_size(area.top_left() + offset_fg, icon_fg.toif.size());
|
||||||
|
|
||||||
let clamped = area.clamp(constant::screen()).ensure_even_width();
|
let clamped = area.clamp(constant::screen()).ensure_even_width();
|
||||||
|
|
||||||
set_window(clamped);
|
set_window(clamped);
|
||||||
|
|
||||||
let mut window_bg = [0; UZLIB_WINDOW_SIZE];
|
let mut window_bg = [0; UZLIB_WINDOW_SIZE];
|
||||||
let mut ctx_bg = UzlibContext::new(icon_bg.toif.data, Some(&mut window_bg));
|
let mut ctx_bg = UzlibContext::new(icon_bg.toif.zdata(), Some(&mut window_bg));
|
||||||
|
|
||||||
let mut window_fg = [0; UZLIB_WINDOW_SIZE];
|
let mut window_fg = [0; UZLIB_WINDOW_SIZE];
|
||||||
let mut ctx_fg = UzlibContext::new(icon_fg.toif.data, Some(&mut window_fg));
|
let mut ctx_fg = UzlibContext::new(icon_fg.toif.zdata(), Some(&mut window_fg));
|
||||||
|
|
||||||
dma2d_setup_4bpp_over_4bpp(color_icon_bg.into(), bg_color.into(), color_icon_fg.into());
|
dma2d_setup_4bpp_over_4bpp(color_icon_bg.into(), bg_color.into(), color_icon_fg.into());
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
trezorhal,
|
|
||||||
trezorhal::{
|
trezorhal::{
|
||||||
display::ToifFormat,
|
display::ToifFormat,
|
||||||
uzlib::{UzlibContext, UZLIB_WINDOW_SIZE},
|
uzlib::{UzlibContext, UZLIB_WINDOW_SIZE},
|
||||||
@ -15,22 +14,8 @@ use super::Color;
|
|||||||
|
|
||||||
const TOIF_HEADER_LENGTH: usize = 12;
|
const TOIF_HEADER_LENGTH: usize = 12;
|
||||||
|
|
||||||
pub fn toif_info(data: &[u8]) -> Option<(Offset, ToifFormat)> {
|
|
||||||
if let Ok(info) = trezorhal::display::toif_info(data) {
|
|
||||||
Some((
|
|
||||||
Offset::new(
|
|
||||||
unwrap!(info.width.try_into()),
|
|
||||||
unwrap!(info.height.try_into()),
|
|
||||||
),
|
|
||||||
info.format,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn icon(icon: &Icon, center: Point, fg_color: Color, bg_color: Color) {
|
pub fn icon(icon: &Icon, center: Point, fg_color: Color, bg_color: Color) {
|
||||||
let r = Rect::from_center_and_size(center, icon.toif.size);
|
let r = Rect::from_center_and_size(center, icon.toif.size());
|
||||||
let area = r.translate(get_offset());
|
let area = r.translate(get_offset());
|
||||||
let clamped = area.clamp(constant::screen());
|
let clamped = area.clamp(constant::screen());
|
||||||
let colortable = get_color_table(fg_color, bg_color);
|
let colortable = get_color_table(fg_color, bg_color);
|
||||||
@ -65,29 +50,49 @@ pub fn icon(icon: &Icon, center: Point, fg_color: Color, bg_color: Color) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Holding toif data and allowing it to draw itself.
|
/// Holding toif data and allowing it to draw itself.
|
||||||
|
/// See https://docs.trezor.io/trezor-firmware/misc/toif.html for data format.
|
||||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
pub struct Toif {
|
pub struct Toif {
|
||||||
pub data: &'static [u8],
|
data: &'static [u8],
|
||||||
pub size: Offset,
|
|
||||||
pub format: ToifFormat,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Toif {
|
impl Toif {
|
||||||
pub fn new(data: &'static [u8]) -> Self {
|
pub const fn new(data: &'static [u8]) -> Option<Self> {
|
||||||
let info = unwrap!(toif_info(data));
|
if data.len() < TOIF_HEADER_LENGTH || data[0] != b'T' || data[1] != b'O' || data[2] != b'I'
|
||||||
Self {
|
{
|
||||||
data: data[TOIF_HEADER_LENGTH..].as_ref(),
|
return None;
|
||||||
size: info.0,
|
}
|
||||||
format: info.1,
|
let zdatalen = u32::from_le_bytes([data[8], data[9], data[10], data[11]]) as usize;
|
||||||
|
if zdatalen + TOIF_HEADER_LENGTH != data.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(Self { data })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn format(&self) -> ToifFormat {
|
||||||
|
match self.data[3] {
|
||||||
|
b'f' => ToifFormat::FullColorBE,
|
||||||
|
b'g' => ToifFormat::GrayScaleOH,
|
||||||
|
b'F' => ToifFormat::FullColorLE,
|
||||||
|
b'G' => ToifFormat::GrayScaleEH,
|
||||||
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn width(&self) -> i16 {
|
pub const fn width(&self) -> i16 {
|
||||||
self.size.x
|
u16::from_le_bytes([self.data[4], self.data[5]]) as i16
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn height(&self) -> i16 {
|
pub const fn height(&self) -> i16 {
|
||||||
self.size.y
|
u16::from_le_bytes([self.data[6], self.data[7]]) as i16
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn size(&self) -> Offset {
|
||||||
|
Offset::new(self.width(), self.height())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn zdata(&self) -> &'static [u8] {
|
||||||
|
&self.data[TOIF_HEADER_LENGTH..]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uncompress(&self, dest: &mut [u8]) {
|
pub fn uncompress(&self, dest: &mut [u8]) {
|
||||||
@ -99,7 +104,7 @@ impl Toif {
|
|||||||
&'a self,
|
&'a self,
|
||||||
window: Option<&'a mut [u8; UZLIB_WINDOW_SIZE]>,
|
window: Option<&'a mut [u8; UZLIB_WINDOW_SIZE]>,
|
||||||
) -> UzlibContext {
|
) -> UzlibContext {
|
||||||
UzlibContext::new(self.data, window)
|
UzlibContext::new(self.zdata(), window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,15 +115,15 @@ pub struct Icon {
|
|||||||
|
|
||||||
impl Icon {
|
impl Icon {
|
||||||
pub fn new(data: &'static [u8]) -> Self {
|
pub fn new(data: &'static [u8]) -> Self {
|
||||||
let toif = Toif::new(data);
|
let toif = unwrap!(Toif::new(data));
|
||||||
assert!(toif.format == ToifFormat::GrayScaleEH);
|
assert!(toif.format() == ToifFormat::GrayScaleEH);
|
||||||
Self { toif }
|
Self { toif }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Display the icon with baseline Point, aligned according to the
|
/// Display the icon with baseline Point, aligned according to the
|
||||||
/// `alignment` argument.
|
/// `alignment` argument.
|
||||||
pub fn draw(&self, baseline: Point, alignment: Alignment2D, fg_color: Color, bg_color: Color) {
|
pub fn draw(&self, baseline: Point, alignment: Alignment2D, fg_color: Color, bg_color: Color) {
|
||||||
let r = Rect::snap(baseline, self.toif.size, alignment);
|
let r = Rect::snap(baseline, self.toif.size(), alignment);
|
||||||
icon(self, r.center(), fg_color, bg_color);
|
icon(self, r.center(), fg_color, bg_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,10 +131,11 @@ fn homescreen_position_text(
|
|||||||
let text_width_clamped = text_width.clamp(0, screen().width());
|
let text_width_clamped = text_width.clamp(0, screen().width());
|
||||||
|
|
||||||
let icon_size = if let Some(icon) = text.icon {
|
let icon_size = if let Some(icon) = text.icon {
|
||||||
assert!(icon.toif.width() <= HOMESCREEN_MAX_ICON_SIZE);
|
let size = icon.toif.size();
|
||||||
assert!(icon.toif.height() <= HOMESCREEN_MAX_ICON_SIZE);
|
assert!(size.x <= HOMESCREEN_MAX_ICON_SIZE);
|
||||||
|
assert!(size.y <= HOMESCREEN_MAX_ICON_SIZE);
|
||||||
icon.toif.uncompress(icon_buffer);
|
icon.toif.uncompress(icon_buffer);
|
||||||
icon.toif.size
|
size
|
||||||
} else {
|
} else {
|
||||||
Offset::zero()
|
Offset::zero()
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user