mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-23 06:48:16 +00:00
feat(core): support old homescreen format
[no changelog]
This commit is contained in:
parent
2388a8edea
commit
dcda5e0142
@ -10,7 +10,7 @@ use crate::{
|
|||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
pub struct Image {
|
pub struct Image {
|
||||||
pub toif: Toif,
|
pub toif: Toif<'static>,
|
||||||
area: Rect,
|
area: Rect,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,12 +52,12 @@ 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.
|
/// 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<'i> {
|
||||||
data: &'static [u8],
|
data: &'i [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Toif {
|
impl<'i> Toif<'i> {
|
||||||
pub const fn new(data: &'static [u8]) -> Option<Self> {
|
pub const fn new(data: &'i [u8]) -> Option<Self> {
|
||||||
if data.len() < TOIF_HEADER_LENGTH || data[0] != b'T' || data[1] != b'O' || data[2] != b'I'
|
if data.len() < TOIF_HEADER_LENGTH || data[0] != b'T' || data[1] != b'O' || data[2] != b'I'
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
@ -91,7 +91,7 @@ impl Toif {
|
|||||||
Offset::new(self.width(), self.height())
|
Offset::new(self.width(), self.height())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zdata(&self) -> &'static [u8] {
|
pub fn zdata(&self) -> &'i [u8] {
|
||||||
&self.data[TOIF_HEADER_LENGTH..]
|
&self.data[TOIF_HEADER_LENGTH..]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ impl Toif {
|
|||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
pub struct Icon {
|
pub struct Icon {
|
||||||
pub toif: Toif,
|
pub toif: Toif<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Icon {
|
impl Icon {
|
||||||
|
@ -14,6 +14,15 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
trezorhal::{display::ToifFormat, uzlib::UZLIB_WINDOW_SIZE},
|
||||||
|
ui::{
|
||||||
|
display::{tjpgd::BufferInput, toif::Toif},
|
||||||
|
model_tt::component::homescreen::render::{
|
||||||
|
HomescreenJpeg, HomescreenToif, HOMESCREEN_TOIF_SIZE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
use render::{
|
use render::{
|
||||||
homescreen, homescreen_blurred, HomescreenNotification, HomescreenText, HOMESCREEN_IMAGE_SIZE,
|
homescreen, homescreen_blurred, HomescreenNotification, HomescreenText, HOMESCREEN_IMAGE_SIZE,
|
||||||
};
|
};
|
||||||
@ -195,16 +204,39 @@ where
|
|||||||
let notification = self.get_notification();
|
let notification = self.get_notification();
|
||||||
|
|
||||||
let res = get_image();
|
let res = get_image();
|
||||||
|
let mut show_default = true;
|
||||||
|
|
||||||
if let Ok(data) = res {
|
if let Ok(data) = res {
|
||||||
|
if is_image_jpeg(data.as_ref()) {
|
||||||
|
let mut input = BufferInput(data.as_ref());
|
||||||
|
let mut hs_img = HomescreenJpeg::new(&mut input);
|
||||||
homescreen(
|
homescreen(
|
||||||
data.as_ref(),
|
&mut hs_img,
|
||||||
&[text],
|
&[text],
|
||||||
notification,
|
notification,
|
||||||
self.paint_notification_only,
|
self.paint_notification_only,
|
||||||
);
|
);
|
||||||
} else {
|
show_default = false;
|
||||||
|
} else if is_image_toif(data.as_ref()) {
|
||||||
|
let input = unwrap!(Toif::new(data.as_ref()));
|
||||||
|
let mut window = [0; UZLIB_WINDOW_SIZE];
|
||||||
|
let mut hs_img =
|
||||||
|
HomescreenToif::new(input.decompression_context(Some(&mut window)));
|
||||||
homescreen(
|
homescreen(
|
||||||
IMAGE_HOMESCREEN,
|
&mut hs_img,
|
||||||
|
&[text],
|
||||||
|
notification,
|
||||||
|
self.paint_notification_only,
|
||||||
|
);
|
||||||
|
show_default = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if show_default {
|
||||||
|
let mut input = BufferInput(IMAGE_HOMESCREEN);
|
||||||
|
let mut hs_img = HomescreenJpeg::new(&mut input);
|
||||||
|
homescreen(
|
||||||
|
&mut hs_img,
|
||||||
&[text],
|
&[text],
|
||||||
notification,
|
notification,
|
||||||
self.paint_notification_only,
|
self.paint_notification_only,
|
||||||
@ -289,10 +321,28 @@ where
|
|||||||
];
|
];
|
||||||
|
|
||||||
let res = get_image();
|
let res = get_image();
|
||||||
|
let mut show_default = true;
|
||||||
|
|
||||||
if let Ok(data) = res {
|
if let Ok(data) = res {
|
||||||
homescreen_blurred(data.as_ref(), &texts);
|
if is_image_jpeg(data.as_ref()) {
|
||||||
} else {
|
let mut input = BufferInput(data.as_ref());
|
||||||
homescreen_blurred(IMAGE_HOMESCREEN, &texts);
|
let mut hs_img = HomescreenJpeg::new(&mut input);
|
||||||
|
homescreen_blurred(&mut hs_img, &texts);
|
||||||
|
show_default = false;
|
||||||
|
} else if is_image_toif(data.as_ref()) {
|
||||||
|
let input = unwrap!(Toif::new(data.as_ref()));
|
||||||
|
let mut window = [0; UZLIB_WINDOW_SIZE];
|
||||||
|
let mut hs_img =
|
||||||
|
HomescreenToif::new(input.decompression_context(Some(&mut window)));
|
||||||
|
homescreen_blurred(&mut hs_img, &texts);
|
||||||
|
show_default = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if show_default {
|
||||||
|
let mut input = BufferInput(IMAGE_HOMESCREEN);
|
||||||
|
let mut hs_img = HomescreenJpeg::new(&mut input);
|
||||||
|
homescreen_blurred(&mut hs_img, &texts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,21 +353,36 @@ fn get_image() -> Result<Gc<[u8]>, ()> {
|
|||||||
if let Ok(mut buffer) = result {
|
if let Ok(mut buffer) = result {
|
||||||
let buf = unsafe { Gc::<[u8]>::as_mut(&mut buffer) };
|
let buf = unsafe { Gc::<[u8]>::as_mut(&mut buffer) };
|
||||||
if get_avatar(buf).is_ok() {
|
if get_avatar(buf).is_ok() {
|
||||||
let jpeg = jpeg_info(buffer.as_ref());
|
|
||||||
if let Some((size, mcu_height)) = jpeg {
|
|
||||||
if size.x == HOMESCREEN_IMAGE_SIZE
|
|
||||||
&& size.y == HOMESCREEN_IMAGE_SIZE
|
|
||||||
&& mcu_height <= 16
|
|
||||||
{
|
|
||||||
return Ok(buffer);
|
return Ok(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_image_jpeg(buffer: &[u8]) -> bool {
|
||||||
|
let jpeg = jpeg_info(buffer);
|
||||||
|
if let Some((size, mcu_height)) = jpeg {
|
||||||
|
if size.x == HOMESCREEN_IMAGE_SIZE && size.y == HOMESCREEN_IMAGE_SIZE && mcu_height <= 16 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_image_toif(buffer: &[u8]) -> bool {
|
||||||
|
let toif = Toif::new(buffer);
|
||||||
|
if let Some(toif) = toif {
|
||||||
|
if toif.size().x == HOMESCREEN_TOIF_SIZE
|
||||||
|
&& toif.size().y == HOMESCREEN_TOIF_SIZE
|
||||||
|
&& toif.format() == ToifFormat::FullColorBE
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<T> crate::trace::Trace for Lockscreen<T> {
|
impl<T> crate::trace::Trace for Lockscreen<T> {
|
||||||
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
|
||||||
|
@ -8,6 +8,7 @@ use crate::{
|
|||||||
buffers::{get_blurring_buffer, get_jpeg_buffer, get_jpeg_work_buffer, BufferJpeg},
|
buffers::{get_blurring_buffer, get_jpeg_buffer, get_jpeg_work_buffer, BufferJpeg},
|
||||||
display,
|
display,
|
||||||
display::bar_radius_buffer,
|
display::bar_radius_buffer,
|
||||||
|
uzlib::UzlibContext,
|
||||||
},
|
},
|
||||||
ui::{
|
ui::{
|
||||||
constant::screen,
|
constant::screen,
|
||||||
@ -51,6 +52,9 @@ struct HomescreenTextInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const HOMESCREEN_IMAGE_SIZE: i16 = 240;
|
pub const HOMESCREEN_IMAGE_SIZE: i16 = 240;
|
||||||
|
pub const HOMESCREEN_TOIF_SIZE: i16 = 144;
|
||||||
|
pub const HOMESCREEN_TOIF_Y_OFFSET: i16 = 27;
|
||||||
|
pub const HOMESCREEN_TOIF_X_OFFSET: usize = ((WIDTH - HOMESCREEN_TOIF_SIZE) / 2) as usize;
|
||||||
|
|
||||||
const HOMESCREEN_MAX_ICON_SIZE: i16 = 20;
|
const HOMESCREEN_MAX_ICON_SIZE: i16 = 20;
|
||||||
const NOTIFICATION_HEIGHT: i16 = 36;
|
const NOTIFICATION_HEIGHT: i16 = 36;
|
||||||
@ -79,6 +83,102 @@ const RED_IDX: usize = 0;
|
|||||||
const GREEN_IDX: usize = 1;
|
const GREEN_IDX: usize = 1;
|
||||||
const BLUE_IDX: usize = 2;
|
const BLUE_IDX: usize = 2;
|
||||||
|
|
||||||
|
pub trait HomescreenDecompressor {
|
||||||
|
fn get_height(&self) -> i16;
|
||||||
|
fn decompress(&mut self);
|
||||||
|
fn get_data(&mut self) -> &mut BufferJpeg;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HomescreenJpeg<'i> {
|
||||||
|
pub output: BufferOutput<'i>,
|
||||||
|
pub jdec: Option<JDEC<'i, 'i>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'i> HomescreenJpeg<'i> {
|
||||||
|
pub fn new(input: &'i mut BufferInput<'i>) -> Self {
|
||||||
|
Self {
|
||||||
|
output: BufferOutput::new(unsafe { get_jpeg_buffer(0, true) }, WIDTH, 16),
|
||||||
|
jdec: JDEC::new(input, unsafe {
|
||||||
|
get_jpeg_work_buffer(0, true).buffer.as_mut_slice()
|
||||||
|
})
|
||||||
|
.ok(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'i> HomescreenDecompressor for HomescreenJpeg<'i> {
|
||||||
|
fn get_height(&self) -> i16 {
|
||||||
|
if let Some(dec) = self.jdec.as_ref() {
|
||||||
|
return dec.mcu_height();
|
||||||
|
}
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decompress(&mut self) {
|
||||||
|
self.jdec.as_mut().map(|dec| dec.decomp(&mut self.output));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_data(&mut self) -> &mut BufferJpeg {
|
||||||
|
self.output.buffer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HomescreenToif<'i> {
|
||||||
|
pub output: BufferOutput<'i>,
|
||||||
|
pub decomp_context: UzlibContext<'i>,
|
||||||
|
line: i16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'i> HomescreenToif<'i> {
|
||||||
|
pub fn new(context: UzlibContext<'i>) -> Self {
|
||||||
|
Self {
|
||||||
|
output: BufferOutput::new(unsafe { get_jpeg_buffer(0, true) }, WIDTH, 16),
|
||||||
|
decomp_context: context,
|
||||||
|
line: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'i> HomescreenDecompressor for HomescreenToif<'i> {
|
||||||
|
fn get_height(&self) -> i16 {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decompress(&mut self) {
|
||||||
|
// SAFETY: Aligning to u8 slice is safe, because the original slice is aligned
|
||||||
|
// to 16 bits, therefore there are also no residuals (prefix/suffix).
|
||||||
|
// The data in the slices are integers, so these are valid for both u16
|
||||||
|
// and u8.
|
||||||
|
if self.line >= HOMESCREEN_TOIF_Y_OFFSET
|
||||||
|
&& self.line < HOMESCREEN_TOIF_Y_OFFSET + HOMESCREEN_TOIF_SIZE
|
||||||
|
{
|
||||||
|
let (_, workbuf, _) = unsafe { self.output.buffer().buffer.align_to_mut::<u8>() };
|
||||||
|
let result = self.decomp_context.uncompress(
|
||||||
|
&mut workbuf[2 * HOMESCREEN_TOIF_X_OFFSET
|
||||||
|
..2 * HOMESCREEN_TOIF_X_OFFSET + 2 * HOMESCREEN_TOIF_SIZE as usize],
|
||||||
|
);
|
||||||
|
|
||||||
|
if result.is_err() {
|
||||||
|
self.output.buffer().buffer.fill(0);
|
||||||
|
} else {
|
||||||
|
for i in 0..HOMESCREEN_TOIF_SIZE as usize {
|
||||||
|
workbuf.swap(
|
||||||
|
2 * HOMESCREEN_TOIF_X_OFFSET + 2 * i,
|
||||||
|
2 * HOMESCREEN_TOIF_X_OFFSET + 2 * i + 1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.output.buffer().buffer.fill(0);
|
||||||
|
}
|
||||||
|
self.line += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_data(&mut self) -> &mut BufferJpeg {
|
||||||
|
self.output.buffer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn homescreen_get_fg_text(
|
fn homescreen_get_fg_text(
|
||||||
y_tmp: i16,
|
y_tmp: i16,
|
||||||
text_info: HomescreenTextInfo,
|
text_info: HomescreenTextInfo,
|
||||||
@ -428,7 +528,7 @@ fn get_data(buffer: &mut BufferJpeg, line_num: i16, mcu_height: i16) -> &mut [u1
|
|||||||
&mut buffer.buffer[data_start..data_end]
|
&mut buffer.buffer[data_start..data_end]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn homescreen_blurred(data: &[u8], texts: &[HomescreenText]) {
|
pub fn homescreen_blurred(data: &mut dyn HomescreenDecompressor, texts: &[HomescreenText]) {
|
||||||
let mut icon_data = [0_u8; (HOMESCREEN_MAX_ICON_SIZE * HOMESCREEN_MAX_ICON_SIZE / 2) as usize];
|
let mut icon_data = [0_u8; (HOMESCREEN_MAX_ICON_SIZE * HOMESCREEN_MAX_ICON_SIZE / 2) as usize];
|
||||||
|
|
||||||
let text_buffer = unsafe { get_text_buffer(0, true) };
|
let text_buffer = unsafe { get_text_buffer(0, true) };
|
||||||
@ -437,27 +537,15 @@ pub fn homescreen_blurred(data: &[u8], texts: &[HomescreenText]) {
|
|||||||
let mut text_info =
|
let mut text_info =
|
||||||
homescreen_position_text(unwrap!(texts.get(0)), text_buffer, &mut icon_data);
|
homescreen_position_text(unwrap!(texts.get(0)), text_buffer, &mut icon_data);
|
||||||
|
|
||||||
let jpeg_pool = unsafe { get_jpeg_work_buffer(0, true).buffer.as_mut_slice() };
|
let mcu_height = data.get_height();
|
||||||
let jpeg_buffer = unsafe { get_jpeg_buffer(0, true) };
|
data.decompress();
|
||||||
let mut jpeg_input = BufferInput(data);
|
|
||||||
let mut jpeg_output = BufferOutput::new(jpeg_buffer, WIDTH, 16);
|
|
||||||
let mut mcu_height = 8;
|
|
||||||
let mut jd: Option<JDEC> = JDEC::new(&mut jpeg_input, jpeg_pool).ok();
|
|
||||||
|
|
||||||
if let Some(dec) = &jd {
|
|
||||||
mcu_height = dec.mcu_height();
|
|
||||||
if !(dec.width() == WIDTH && dec.height() == HEIGHT && mcu_height <= 16) {
|
|
||||||
jd = None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jd.as_mut().map(|dec| dec.decomp(&mut jpeg_output));
|
|
||||||
|
|
||||||
set_window(screen());
|
set_window(screen());
|
||||||
|
|
||||||
let mut blurring = BlurringContext::new();
|
let mut blurring = BlurringContext::new();
|
||||||
|
|
||||||
// handling top edge case: preload the edge value N+1 times
|
// handling top edge case: preload the edge value N+1 times
|
||||||
blurring.compute_line_avgs(jpeg_output.buffer(), mcu_height);
|
blurring.compute_line_avgs(data.get_data(), mcu_height);
|
||||||
|
|
||||||
for _ in 0..=BLUR_RADIUS {
|
for _ in 0..=BLUR_RADIUS {
|
||||||
blurring.vertical_avg_add();
|
blurring.vertical_avg_add();
|
||||||
@ -466,12 +554,12 @@ pub fn homescreen_blurred(data: &[u8], texts: &[HomescreenText]) {
|
|||||||
|
|
||||||
// load enough values to be able to compute first line averages
|
// load enough values to be able to compute first line averages
|
||||||
for _ in 0..BLUR_RADIUS {
|
for _ in 0..BLUR_RADIUS {
|
||||||
blurring.compute_line_avgs(jpeg_output.buffer(), mcu_height);
|
blurring.compute_line_avgs(data.get_data(), mcu_height);
|
||||||
blurring.vertical_avg_add();
|
blurring.vertical_avg_add();
|
||||||
blurring.inc_add();
|
blurring.inc_add();
|
||||||
|
|
||||||
if (blurring.get_line_num() % mcu_height) == 0 {
|
if (blurring.get_line_num() % mcu_height) == 0 {
|
||||||
jd.as_mut().map(|dec| dec.decomp(&mut jpeg_output));
|
data.decompress();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,7 +567,7 @@ pub fn homescreen_blurred(data: &[u8], texts: &[HomescreenText]) {
|
|||||||
// several lines have been already decompressed before this loop, adjust for
|
// several lines have been already decompressed before this loop, adjust for
|
||||||
// that
|
// that
|
||||||
if y < HOMESCREEN_IMAGE_SIZE - (BLUR_RADIUS + 1) {
|
if y < HOMESCREEN_IMAGE_SIZE - (BLUR_RADIUS + 1) {
|
||||||
blurring.compute_line_avgs(jpeg_output.buffer(), mcu_height);
|
blurring.compute_line_avgs(data.get_data(), mcu_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
let done = homescreen_line_blurred(&icon_data, text_buffer, text_info, &blurring, y);
|
let done = homescreen_line_blurred(&icon_data, text_buffer, text_info, &blurring, y);
|
||||||
@ -510,14 +598,14 @@ pub fn homescreen_blurred(data: &[u8], texts: &[HomescreenText]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (blurring.get_line_num() % mcu_height) == 0 && (blurring.get_line_num() < HEIGHT) {
|
if (blurring.get_line_num() % mcu_height) == 0 && (blurring.get_line_num() < HEIGHT) {
|
||||||
jd.as_mut().map(|dec| dec.decomp(&mut jpeg_output));
|
data.decompress();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dma2d_wait_for_transfer();
|
dma2d_wait_for_transfer();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn homescreen(
|
pub fn homescreen(
|
||||||
data: &[u8],
|
data: &mut dyn HomescreenDecompressor,
|
||||||
texts: &[HomescreenText],
|
texts: &[HomescreenText],
|
||||||
notification: Option<HomescreenNotification>,
|
notification: Option<HomescreenNotification>,
|
||||||
notification_only: bool,
|
notification_only: bool,
|
||||||
@ -551,34 +639,20 @@ pub fn homescreen(
|
|||||||
homescreen_position_text(unwrap!(texts.get(0)), text_buffer, &mut icon_data)
|
homescreen_position_text(unwrap!(texts.get(0)), text_buffer, &mut icon_data)
|
||||||
};
|
};
|
||||||
|
|
||||||
let jpeg_pool = unsafe { get_jpeg_work_buffer(0, true).buffer.as_mut_slice() };
|
|
||||||
let jpeg_buffer = unsafe { get_jpeg_buffer(0, true) };
|
|
||||||
let mut jpeg_input = BufferInput(data);
|
|
||||||
let mut jpeg_output = BufferOutput::new(jpeg_buffer, WIDTH, 16);
|
|
||||||
let mut mcu_height = 8;
|
|
||||||
let mut jd: Option<JDEC> = JDEC::new(&mut jpeg_input, jpeg_pool).ok();
|
|
||||||
|
|
||||||
if let Some(dec) = &jd {
|
|
||||||
mcu_height = dec.mcu_height();
|
|
||||||
if !(dec.width() == WIDTH && dec.height() == HEIGHT && mcu_height <= 16) {
|
|
||||||
jd = None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set_window(screen());
|
set_window(screen());
|
||||||
|
|
||||||
let mcu_height = mcu_height as i16;
|
let mcu_height = data.get_height();
|
||||||
|
|
||||||
for y in 0..HEIGHT {
|
for y in 0..HEIGHT {
|
||||||
if (y % mcu_height) == 0 {
|
if (y % mcu_height) == 0 {
|
||||||
jd.as_mut().map(|dec| dec.decomp(&mut jpeg_output));
|
data.decompress();
|
||||||
}
|
}
|
||||||
|
|
||||||
let done = homescreen_line(
|
let done = homescreen_line(
|
||||||
&icon_data,
|
&icon_data,
|
||||||
text_buffer,
|
text_buffer,
|
||||||
text_info,
|
text_info,
|
||||||
jpeg_output.buffer(),
|
data.get_data(),
|
||||||
mcu_height,
|
mcu_height,
|
||||||
y,
|
y,
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user