1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-10 15:30:55 +00:00

perf(core/rust/ui): use 16-bit coordinates

[no changelog]
This commit is contained in:
Martin Milata 2022-09-06 15:29:12 +02:00
parent dd168d2893
commit ef504d40fc
30 changed files with 285 additions and 266 deletions

View File

@ -12,11 +12,11 @@ pub fn backlight(val: i32) -> i32 {
unsafe { ffi::display_backlight(val) } unsafe { ffi::display_backlight(val) }
} }
pub fn text(baseline_x: i32, baseline_y: i32, text: &str, font: i32, fgcolor: u16, bgcolor: u16) { pub fn text(baseline_x: i16, baseline_y: i16, text: &str, font: i32, fgcolor: u16, bgcolor: u16) {
unsafe { unsafe {
ffi::display_text( ffi::display_text(
baseline_x, baseline_x.into(),
baseline_y, baseline_y.into(),
text.as_ptr() as _, text.as_ptr() as _,
text.len() as _, text.len() as _,
font, font,
@ -26,11 +26,15 @@ pub fn text(baseline_x: i32, baseline_y: i32, text: &str, font: i32, fgcolor: u1
} }
} }
pub fn text_width(text: &str, font: i32) -> i32 { pub fn text_width(text: &str, font: i32) -> i16 {
unsafe { ffi::display_text_width(text.as_ptr() as _, text.len() as _, font) } unsafe {
ffi::display_text_width(text.as_ptr() as _, text.len() as _, font)
.try_into()
.unwrap_or(i16::MAX)
}
} }
pub fn char_width(ch: char, font: i32) -> i32 { pub fn char_width(ch: char, font: i32) -> i16 {
let mut buf = [0u8; 4]; let mut buf = [0u8; 4];
let encoding = ch.encode_utf8(&mut buf); let encoding = ch.encode_utf8(&mut buf);
text_width(encoding, font) text_width(encoding, font)
@ -40,25 +44,39 @@ pub fn get_char_glyph(ch: u8, font: i32) -> *const u8 {
unsafe { ffi::display_get_glyph(font, ch) } unsafe { ffi::display_get_glyph(font, ch) }
} }
pub fn text_height(font: i32) -> i32 { pub fn text_height(font: i32) -> i16 {
unsafe { ffi::display_text_height(font) } unsafe {
ffi::display_text_height(font)
.try_into()
.unwrap_or(i16::MAX)
}
} }
pub fn bar(x: i32, y: i32, w: i32, h: i32, fgcolor: u16) { pub fn bar(x: i16, y: i16, w: i16, h: i16, fgcolor: u16) {
unsafe { ffi::display_bar(x, y, w, h, fgcolor) } unsafe { ffi::display_bar(x.into(), y.into(), w.into(), h.into(), fgcolor) }
} }
pub fn bar_radius(x: i32, y: i32, w: i32, h: i32, fgcolor: u16, bgcolor: u16, radius: u8) { pub fn bar_radius(x: i16, y: i16, w: i16, h: i16, fgcolor: u16, bgcolor: u16, radius: u8) {
unsafe { ffi::display_bar_radius(x, y, w, h, fgcolor, bgcolor, radius) } unsafe {
ffi::display_bar_radius(
x.into(),
y.into(),
w.into(),
h.into(),
fgcolor,
bgcolor,
radius,
)
}
} }
pub fn icon(x: i32, y: i32, w: i32, h: i32, data: &[u8], fgcolor: u16, bgcolor: u16) { pub fn icon(x: i16, y: i16, w: i16, h: i16, data: &[u8], fgcolor: u16, bgcolor: u16) {
unsafe { unsafe {
ffi::display_icon( ffi::display_icon(
x, x.into(),
y, y.into(),
w, w.into(),
h, h.into(),
data.as_ptr() as _, data.as_ptr() as _,
data.len() as _, data.len() as _,
fgcolor, fgcolor,
@ -67,8 +85,17 @@ pub fn icon(x: i32, y: i32, w: i32, h: i32, data: &[u8], fgcolor: u16, bgcolor:
} }
} }
pub fn image(x: i32, y: i32, w: i32, h: i32, data: &[u8]) { pub fn image(x: i16, y: i16, w: i16, h: i16, data: &[u8]) {
unsafe { ffi::display_image(x, y, w, h, data.as_ptr() as _, data.len() as _) } unsafe {
ffi::display_image(
x.into(),
y.into(),
w.into(),
h.into(),
data.as_ptr() as _,
data.len() as _,
)
}
} }
pub fn toif_info(data: &[u8]) -> Result<ToifInfo, ()> { pub fn toif_info(data: &[u8]) -> Result<ToifInfo, ()> {
@ -97,7 +124,7 @@ pub fn toif_info(data: &[u8]) -> Result<ToifInfo, ()> {
pub fn loader( pub fn loader(
progress: u16, progress: u16,
indeterminate: bool, indeterminate: bool,
yoffset: i32, yoffset: i16,
fgcolor: u16, fgcolor: u16,
bgcolor: u16, bgcolor: u16,
icon: Option<&[u8]>, icon: Option<&[u8]>,
@ -107,7 +134,7 @@ pub fn loader(
ffi::display_loader( ffi::display_loader(
progress, progress,
indeterminate, indeterminate,
yoffset, yoffset.into(),
fgcolor, fgcolor,
bgcolor, bgcolor,
icon.map(|i| i.as_ptr()).unwrap_or(ptr::null()), icon.map(|i| i.as_ptr()).unwrap_or(ptr::null()),
@ -146,11 +173,11 @@ pub fn set_window(x0: u16, y0: u16, x1: u16, y1: u16) {
} }
} }
pub fn get_offset() -> (i32, i32) { pub fn get_offset() -> (i16, i16) {
unsafe { unsafe {
let mut x: c_int = 0; let mut x: c_int = 0;
let mut y: c_int = 0; let mut y: c_int = 0;
ffi::display_offset(ptr::null_mut(), &mut x, &mut y); ffi::display_offset(ptr::null_mut(), &mut x, &mut y);
(x as i32, y as i32) (x as i16, y as i16)
} }
} }

View File

@ -33,8 +33,8 @@ fn qr_version_index(data: &str, thresholds: &[usize]) -> Option<usize> {
} }
pub fn render_qrcode( pub fn render_qrcode(
x: i32, x: i16,
y: i32, y: i16,
data: &str, data: &str,
max_size: u32, max_size: u32,
case_sensitive: bool, case_sensitive: bool,
@ -69,7 +69,7 @@ pub fn render_qrcode(
buffer[data_len] = 0u8; buffer[data_len] = 0u8;
let cstr = CStr::from_bytes_with_nul_unchecked(&buffer[..data_len + 1]); let cstr = CStr::from_bytes_with_nul_unchecked(&buffer[..data_len + 1]);
display_qrcode(x, y, cstr.as_ptr() as _, scale as u8); display_qrcode(x.into(), y.into(), cstr.as_ptr() as _, scale as u8);
Ok(()) Ok(())
} }
} }

View File

@ -27,7 +27,7 @@ impl<T> GridPlaced<T> {
self self
} }
pub fn with_spacing(mut self, spacing: i32) -> Self { pub fn with_spacing(mut self, spacing: i16) -> Self {
self.grid.spacing = spacing; self.grid.spacing = spacing;
self self
} }
@ -80,11 +80,11 @@ where
pub struct FixedHeightBar<T> { pub struct FixedHeightBar<T> {
inner: T, inner: T,
height: i32, height: i16,
} }
impl<T> FixedHeightBar<T> { impl<T> FixedHeightBar<T> {
pub const fn bottom(inner: T, height: i32) -> Self { pub const fn bottom(inner: T, height: i16) -> Self {
Self { inner, height } Self { inner, height }
} }
} }

View File

@ -6,7 +6,7 @@ struct LineBreak {
/// Index of character **after** the line-break. /// Index of character **after** the line-break.
offset: usize, offset: usize,
/// Distance from the last line-break of the sequence, in pixels. /// Distance from the last line-break of the sequence, in pixels.
width: i32, width: i16,
style: BreakStyle, style: BreakStyle,
} }
@ -19,8 +19,8 @@ enum BreakStyle {
fn limit_line_breaks( fn limit_line_breaks(
breaks: impl Iterator<Item = LineBreak>, breaks: impl Iterator<Item = LineBreak>,
line_height: i32, line_height: i16,
available_height: i32, available_height: i16,
) -> impl Iterator<Item = LineBreak> { ) -> impl Iterator<Item = LineBreak> {
breaks.take(available_height as usize / line_height as usize) breaks.take(available_height as usize / line_height as usize)
} }
@ -42,7 +42,7 @@ fn break_text_to_spans(
text_font: impl GlyphMetrics, text_font: impl GlyphMetrics,
hyphen_font: impl GlyphMetrics, hyphen_font: impl GlyphMetrics,
breaking: LineBreaking, breaking: LineBreaking,
available_width: i32, available_width: i16,
) -> impl Iterator<Item = Span> { ) -> impl Iterator<Item = Span> {
let mut finished = false; let mut finished = false;
let mut last_break = LineBreak { let mut last_break = LineBreak {
@ -89,7 +89,7 @@ fn select_line_breaks(
text_font: impl GlyphMetrics, text_font: impl GlyphMetrics,
hyphen_font: impl GlyphMetrics, hyphen_font: impl GlyphMetrics,
breaking: LineBreaking, breaking: LineBreaking,
available_width: i32, available_width: i16,
) -> impl Iterator<Item = LineBreak> { ) -> impl Iterator<Item = LineBreak> {
let hyphen_width = hyphen_font.char_width('-'); let hyphen_width = hyphen_font.char_width('-');
@ -159,16 +159,16 @@ fn select_line_breaks(
} }
pub trait GlyphMetrics { pub trait GlyphMetrics {
fn char_width(&self, ch: char) -> i32; fn char_width(&self, ch: char) -> i16;
fn line_height(&self) -> i32; fn line_height(&self) -> i16;
} }
impl GlyphMetrics for Font { impl GlyphMetrics for Font {
fn char_width(&self, ch: char) -> i32 { fn char_width(&self, ch: char) -> i16 {
Font::char_width(*self, ch) Font::char_width(*self, ch)
} }
fn line_height(&self) -> i32 { fn line_height(&self) -> i16 {
Font::line_height(*self) Font::line_height(*self)
} }
} }
@ -205,21 +205,21 @@ mod tests {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
struct Fixed { struct Fixed {
width: i32, width: i16,
height: i32, height: i16,
} }
impl GlyphMetrics for Fixed { impl GlyphMetrics for Fixed {
fn char_width(&self, _ch: char) -> i32 { fn char_width(&self, _ch: char) -> i16 {
self.width self.width
} }
fn line_height(&self) -> i32 { fn line_height(&self) -> i16 {
self.height self.height
} }
} }
fn break_text(s: &str, w: i32) -> Vec<Span> { fn break_text(s: &str, w: i16) -> Vec<Span> {
break_text_to_spans( break_text_to_spans(
s, s,
Fixed { Fixed {
@ -236,7 +236,7 @@ mod tests {
.collect::<Vec<_>>() .collect::<Vec<_>>()
} }
fn line_breaks(s: &str, w: i32) -> Vec<LineBreak> { fn line_breaks(s: &str, w: i16) -> Vec<LineBreak> {
select_line_breaks( select_line_breaks(
s.char_indices(), s.char_indices(),
Fixed { Fixed {
@ -253,7 +253,7 @@ mod tests {
.collect::<Vec<_>>() .collect::<Vec<_>>()
} }
fn hard(offset: usize, width: i32) -> LineBreak { fn hard(offset: usize, width: i16) -> LineBreak {
LineBreak { LineBreak {
offset, offset,
width, width,
@ -261,7 +261,7 @@ mod tests {
} }
} }
fn whitespace(offset: usize, width: i32) -> LineBreak { fn whitespace(offset: usize, width: i16) -> LineBreak {
LineBreak { LineBreak {
offset, offset,
width, width,
@ -269,7 +269,7 @@ mod tests {
} }
} }
fn inside_word(offset: usize, width: i32) -> LineBreak { fn inside_word(offset: usize, width: i16) -> LineBreak {
LineBreak { LineBreak {
offset, offset,
width, width,

View File

@ -32,10 +32,10 @@ pub struct TextLayout {
/// Additional space before beginning of text, can be negative to shift text /// Additional space before beginning of text, can be negative to shift text
/// upwards. /// upwards.
pub padding_top: i32, pub padding_top: i16,
/// Additional space between end of text and bottom of bounding box, can be /// Additional space between end of text and bottom of bounding box, can be
/// negative. /// negative.
pub padding_bottom: i32, pub padding_bottom: i16,
/// Fonts, colors, line/page breaking behavior. /// Fonts, colors, line/page breaking behavior.
pub style: TextStyle, pub style: TextStyle,
@ -252,7 +252,7 @@ impl TextLayout {
} }
} }
fn layout_height(&self, init_cursor: Point, end_cursor: Point) -> i32 { fn layout_height(&self, init_cursor: Point, end_cursor: Point) -> i16 {
self.padding_top self.padding_top
+ self.style.text_font.text_height() + self.style.text_font.text_height()
+ (end_cursor.y - init_cursor.y) + (end_cursor.y - init_cursor.y)
@ -262,13 +262,13 @@ impl TextLayout {
pub enum LayoutFit { pub enum LayoutFit {
/// Entire content fits. Vertical size is returned in `height`. /// Entire content fits. Vertical size is returned in `height`.
Fitting { processed_chars: usize, height: i32 }, Fitting { processed_chars: usize, height: i16 },
/// Content fits partially or not at all. /// Content fits partially or not at all.
OutOfBounds { processed_chars: usize, height: i32 }, OutOfBounds { processed_chars: usize, height: i16 },
} }
impl LayoutFit { impl LayoutFit {
pub fn height(&self) -> i32 { pub fn height(&self) -> i16 {
match self { match self {
LayoutFit::Fitting { height, .. } => *height, LayoutFit::Fitting { height, .. } => *height,
LayoutFit::OutOfBounds { height, .. } => *height, LayoutFit::OutOfBounds { height, .. } => *height,
@ -400,7 +400,7 @@ struct Span {
impl Span { impl Span {
fn fit_horizontally( fn fit_horizontally(
text: &str, text: &str,
max_width: i32, max_width: i16,
text_font: impl GlyphMetrics, text_font: impl GlyphMetrics,
breaking: LineBreaking, breaking: LineBreaking,
) -> Self { ) -> Self {
@ -489,16 +489,16 @@ mod tests {
use super::*; use super::*;
pub struct Fixed { pub struct Fixed {
pub width: i32, pub width: i16,
pub height: i32, pub height: i16,
} }
impl GlyphMetrics for Fixed { impl GlyphMetrics for Fixed {
fn char_width(&self, _ch: char) -> i32 { fn char_width(&self, _ch: char) -> i16 {
self.width self.width
} }
fn line_height(&self) -> i32 { fn line_height(&self) -> i16 {
self.height self.height
} }
} }
@ -555,7 +555,7 @@ mod tests {
); );
} }
fn spans_from(text: &str, max_width: i32) -> Vec<(&str, bool)> { fn spans_from(text: &str, max_width: i16) -> Vec<(&str, bool)> {
let mut spans = vec![]; let mut spans = vec![];
let mut remaining_text = text; let mut remaining_text = text;
loop { loop {

View File

@ -11,13 +11,13 @@ use super::layout::{LayoutFit, TextLayout, TextStyle};
pub const MAX_PARAGRAPHS: usize = 9; pub const MAX_PARAGRAPHS: usize = 9;
/// Maximum space between paragraphs. Actual result may be smaller (even 0) if /// Maximum space between paragraphs. Actual result may be smaller (even 0) if
/// it would make paragraphs overflow the bounding box. /// it would make paragraphs overflow the bounding box.
pub const DEFAULT_SPACING: i32 = 0; pub const DEFAULT_SPACING: i16 = 0;
/// Offset of paragraph text from the top of the paragraph bounding box. Tweak /// Offset of paragraph text from the top of the paragraph bounding box. Tweak
/// these values to get nice alignment of baselines relative to the surrounding /// these values to get nice alignment of baselines relative to the surrounding
/// components. /// components.
pub const PARAGRAPH_TOP_SPACE: i32 = -1; pub const PARAGRAPH_TOP_SPACE: i16 = -1;
/// Offset of paragraph bounding box bottom relative to bottom of its text. /// Offset of paragraph bounding box bottom relative to bottom of its text.
pub const PARAGRAPH_BOTTOM_SPACE: i32 = 5; pub const PARAGRAPH_BOTTOM_SPACE: i16 = 5;
pub struct Paragraphs<T> { pub struct Paragraphs<T> {
area: Rect, area: Rect,
@ -48,7 +48,7 @@ where
self self
} }
pub fn with_spacing(mut self, spacing: i32) -> Self { pub fn with_spacing(mut self, spacing: i16) -> Self {
self.placement = self.placement.with_spacing(spacing); self.placement = self.placement.with_spacing(spacing);
self self
} }
@ -352,7 +352,7 @@ impl<T> Checklist<T>
where where
T: AsRef<str>, T: AsRef<str>,
{ {
const CHECK_WIDTH: i32 = 16; const CHECK_WIDTH: i16 = 16;
const DONE_OFFSET: Offset = Offset::new(-2, 6); const DONE_OFFSET: Offset = Offset::new(-2, 6);
const CURRENT_OFFSET: Offset = Offset::new(2, 3); const CURRENT_OFFSET: Offset = Offset::new(2, 3);

View File

@ -66,46 +66,35 @@ pub fn rect_fill_rounded(r: Rect, fg_color: Color, bg_color: Color, radius: u8)
/// NOTE: Cannot start at odd x-coordinate. In this case icon is shifted 1px /// NOTE: Cannot start at odd x-coordinate. In this case icon is shifted 1px
/// left. /// left.
pub fn icon_top_left(top_left: Point, data: &[u8], fg_color: Color, bg_color: Color) { pub fn icon_top_left(top_left: Point, data: &[u8], fg_color: Color, bg_color: Color) {
let toif_info = unwrap!(display::toif_info(data), "Invalid TOIF data"); let (toif_size, toif_data) = toif_info_ensure(data, true);
assert!(toif_info.grayscale);
display::icon( display::icon(
top_left.x, top_left.x,
top_left.y, top_left.y,
toif_info.width.into(), toif_size.x,
toif_info.height.into(), toif_size.y,
&data[12..], // Skip TOIF header. toif_data,
fg_color.into(), fg_color.into(),
bg_color.into(), bg_color.into(),
); );
} }
pub fn icon(center: Point, data: &[u8], fg_color: Color, bg_color: Color) { pub fn icon(center: Point, data: &[u8], fg_color: Color, bg_color: Color) {
let toif_info = unwrap!(display::toif_info(data), "Invalid TOIF data"); let (toif_size, toif_data) = toif_info_ensure(data, true);
assert!(toif_info.grayscale); let r = Rect::from_center_and_size(center, toif_size);
let r = Rect::from_center_and_size(
center,
Offset::new(toif_info.width.into(), toif_info.height.into()),
);
display::icon( display::icon(
r.x0, r.x0,
r.y0, r.y0,
r.width(), r.width(),
r.height(), r.height(),
&data[12..], // Skip TOIF header. toif_data,
fg_color.into(), fg_color.into(),
bg_color.into(), bg_color.into(),
); );
} }
pub fn icon_rust(center: Point, data: &[u8], fg_color: Color, bg_color: Color) { pub fn icon_rust(center: Point, data: &[u8], fg_color: Color, bg_color: Color) {
let toif_info = unwrap!(display::toif_info(data), "Invalid TOIF data"); let (toif_size, toif_data) = toif_info_ensure(data, true);
assert!(toif_info.grayscale); let r = Rect::from_center_and_size(center, toif_size);
let r = Rect::from_center_and_size(
center,
Offset::new(toif_info.width.into(), toif_info.height.into()),
);
let area = r.translate(get_offset()); let area = r.translate(get_offset());
let clamped = area.clamp(constant::screen()); let clamped = area.clamp(constant::screen());
@ -116,7 +105,7 @@ pub fn icon_rust(center: Point, data: &[u8], fg_color: Color, bg_color: Color) {
let mut dest = [0_u8; 1]; let mut dest = [0_u8; 1];
let mut window = [0; UZLIB_WINDOW_SIZE]; let mut window = [0; UZLIB_WINDOW_SIZE];
let mut ctx = UzlibContext::new(&data[12..], Some(&mut window)); let mut ctx = UzlibContext::new(toif_data, Some(&mut window));
for py in area.y0..area.y1 { for py in area.y0..area.y1 {
for px in area.x0..area.x1 { for px in area.x0..area.x1 {
@ -141,26 +130,19 @@ pub fn icon_rust(center: Point, data: &[u8], fg_color: Color, bg_color: Color) {
} }
pub fn image(center: Point, data: &[u8]) { pub fn image(center: Point, data: &[u8]) {
let toif_info = unwrap!(display::toif_info(data), "Invalid TOIF data"); let (toif_size, toif_data) = toif_info_ensure(data, false);
assert!(!toif_info.grayscale);
let r = Rect::from_center_and_size( let r = Rect::from_center_and_size(center, toif_size);
center, display::image(r.x0, r.y0, r.width(), r.height(), toif_data);
Offset::new(toif_info.width.into(), toif_info.height.into()),
);
display::image(
r.x0,
r.y0,
r.width(),
r.height(),
&data[12..], // Skip TOIF header.
);
} }
pub fn toif_info(data: &[u8]) -> Option<(Offset, bool)> { pub fn toif_info(data: &[u8]) -> Option<(Offset, bool)> {
if let Ok(info) = display::toif_info(data) { if let Ok(info) = display::toif_info(data) {
Some(( Some((
Offset::new(info.width.into(), info.height.into()), Offset::new(
unwrap!(info.width.try_into()),
unwrap!(info.height.try_into()),
),
info.grayscale, info.grayscale,
)) ))
} else { } else {
@ -168,6 +150,19 @@ pub fn toif_info(data: &[u8]) -> Option<(Offset, bool)> {
} }
} }
/// Aborts if the TOIF file does not have the correct grayscale flag, do not use
/// with user-supplied inputs.
fn toif_info_ensure(data: &[u8], grayscale: bool) -> (Offset, &[u8]) {
let info = unwrap!(display::toif_info(data), "Invalid TOIF data");
assert_eq!(grayscale, info.grayscale);
let size = Offset::new(
unwrap!(info.width.try_into()),
unwrap!(info.height.try_into()),
);
let payload = &data[12..]; // Skip TOIF header.
(size, payload)
}
// Used on T1 only. // Used on T1 only.
pub fn rect_fill_rounded1(r: Rect, fg_color: Color, bg_color: Color) { pub fn rect_fill_rounded1(r: Rect, fg_color: Color, bg_color: Color) {
display::bar(r.x0, r.y0, r.width(), r.height(), fg_color.into()); display::bar(r.x0, r.y0, r.width(), r.height(), fg_color.into());
@ -243,7 +238,7 @@ impl<'a> TextOverlay<'a> {
/// The implementation could be replaced by (cos(`angle`), sin(`angle`)), /// The implementation could be replaced by (cos(`angle`), sin(`angle`)),
/// if we allow trigonometric functions. /// if we allow trigonometric functions.
/// In the meantime, approximate this with predefined octagon /// In the meantime, approximate this with predefined octagon
fn get_vector(angle: i32) -> Point { fn get_vector(angle: i16) -> Point {
//octagon vertices //octagon vertices
let v = [ let v = [
Point::new(0, 1000), Point::new(0, 1000),
@ -257,7 +252,7 @@ fn get_vector(angle: i32) -> Point {
]; ];
let angle = angle % 360; let angle = angle % 360;
let vertices = v.len() as i32; let vertices = v.len() as i16;
let sector_length = 360 / vertices; // only works if 360 is divisible by vertices let sector_length = 360 / vertices; // only works if 360 is divisible by vertices
let sector = angle / sector_length; let sector = angle / sector_length;
let sector_angle = (angle % sector_length) as f32; let sector_angle = (angle % sector_length) as f32;
@ -285,17 +280,17 @@ fn is_clockwise_or_equal_inc(n_v1: Point, v2: Point) -> bool {
} }
/// Draw a rounded rectangle with corner radius 2 /// Draw a rounded rectangle with corner radius 2
/// Draws only a part (sector of a corresponding circe) /// Draws only a part (sector of a corresponding circle)
/// of the rectangle according to `show_percent` argument, /// of the rectangle according to `show_percent` argument,
/// and optionally draw an `icon` inside /// and optionally draw an `icon` inside
pub fn rect_rounded2_partial( pub fn rect_rounded2_partial(
area: Rect, area: Rect,
fg_color: Color, fg_color: Color,
bg_color: Color, bg_color: Color,
show_percent: i32, show_percent: i16,
icon: Option<(&[u8], Color)>, icon: Option<(&[u8], Color)>,
) { ) {
const MAX_ICON_SIZE: u16 = 64; const MAX_ICON_SIZE: i16 = 64;
let r = area.translate(get_offset()); let r = area.translate(get_offset());
let clamped = r.clamp(constant::screen()); let clamped = r.clamp(constant::screen());
@ -313,20 +308,16 @@ pub fn rect_rounded2_partial(
let mut icon_width = 0; let mut icon_width = 0;
if let Some((icon_bytes, icon_color)) = icon { if let Some((icon_bytes, icon_color)) = icon {
let toif_info = unwrap!(display::toif_info(icon_bytes), "Invalid TOIF data"); let (toif_size, toif_data) = toif_info_ensure(icon_bytes, true);
assert!(toif_info.grayscale);
if toif_info.width <= MAX_ICON_SIZE && toif_info.height <= MAX_ICON_SIZE { if toif_size.x <= MAX_ICON_SIZE && toif_size.y <= MAX_ICON_SIZE {
icon_area = Rect::from_center_and_size( icon_area = Rect::from_center_and_size(center, toif_size);
center,
Offset::new(toif_info.width.into(), toif_info.height.into()),
);
icon_area_clamped = icon_area.clamp(constant::screen()); icon_area_clamped = icon_area.clamp(constant::screen());
let mut ctx = UzlibContext::new(&icon_bytes[12..], None); let mut ctx = UzlibContext::new(toif_data, None);
unwrap!(ctx.uncompress(&mut icon_data), "Decompression failed"); unwrap!(ctx.uncompress(&mut icon_data), "Decompression failed");
icon_colortable = get_color_table(icon_color, bg_color); icon_colortable = get_color_table(icon_color, bg_color);
icon_width = toif_info.width.into(); icon_width = toif_size.x;
use_icon = true; use_icon = true;
} }
} }
@ -409,7 +400,7 @@ fn rect_rounded2_get_pixel(
size: Offset, size: Offset,
colortable: [Color; 16], colortable: [Color; 16],
fill: bool, fill: bool,
line_width: i32, line_width: i16,
) -> Color { ) -> Color {
let border = (p.x >= 0 && p.x < line_width) let border = (p.x >= 0 && p.x < line_width)
|| ((p.x >= size.x - line_width) && p.x <= (size.x - 1)) || ((p.x >= size.x - line_width) && p.x <= (size.x - 1))
@ -447,8 +438,8 @@ pub fn bar_with_text_and_fill(
overlay: Option<TextOverlay>, overlay: Option<TextOverlay>,
fg_color: Color, fg_color: Color,
bg_color: Color, bg_color: Color,
fill_from: i32, fill_from: i16,
fill_to: i32, fill_to: i16,
) { ) {
let r = area.translate(get_offset()); let r = area.translate(get_offset());
let clamped = r.clamp(constant::screen()); let clamped = r.clamp(constant::screen());
@ -481,7 +472,7 @@ pub fn bar_with_text_and_fill(
} }
// Used on T1 only. // Used on T1 only.
pub fn dotted_line(start: Point, width: i32, color: Color) { pub fn dotted_line(start: Point, width: i16, color: Color) {
for x in (start.x..width).step_by(2) { for x in (start.x..width).step_by(2) {
display::bar(x, start.y, 1, 1, color.into()); display::bar(x, start.y, 1, 1, color.into());
} }
@ -492,7 +483,7 @@ pub const LOADER_MAX: u16 = 1000;
pub fn loader( pub fn loader(
progress: u16, progress: u16,
y_offset: i32, y_offset: i16,
fg_color: Color, fg_color: Color,
bg_color: Color, bg_color: Color,
icon: Option<(&[u8], Color)>, icon: Option<(&[u8], Color)>,
@ -510,7 +501,7 @@ pub fn loader(
pub fn loader_indeterminate( pub fn loader_indeterminate(
progress: u16, progress: u16,
y_offset: i32, y_offset: i16,
fg_color: Color, fg_color: Color,
bg_color: Color, bg_color: Color,
icon: Option<(&[u8], Color)>, icon: Option<(&[u8], Color)>,
@ -599,11 +590,11 @@ pub fn get_color_table(fg_color: Color, bg_color: Color) -> [Color; 16] {
} }
pub struct Glyph { pub struct Glyph {
pub width: i32, pub width: i16,
pub height: i32, pub height: i16,
pub adv: i32, pub adv: i16,
pub bearing_x: i32, pub bearing_x: i16,
pub bearing_y: i32, pub bearing_y: i16,
data: &'static [u8], data: &'static [u8],
} }
@ -619,8 +610,8 @@ impl Glyph {
/// - data must have static lifetime /// - data must have static lifetime
pub unsafe fn load(data: *const u8) -> Self { pub unsafe fn load(data: *const u8) -> Self {
unsafe { unsafe {
let width = *data.offset(0) as i32; let width = *data.offset(0) as i16;
let height = *data.offset(1) as i32; let height = *data.offset(1) as i16;
let data_bits = constant::FONT_BPP * width * height; let data_bits = constant::FONT_BPP * width * height;
@ -633,15 +624,15 @@ impl Glyph {
Glyph { Glyph {
width, width,
height, height,
adv: *data.offset(2) as i32, adv: *data.offset(2) as i16,
bearing_x: *data.offset(3) as i32, bearing_x: *data.offset(3) as i16,
bearing_y: *data.offset(4) as i32, bearing_y: *data.offset(4) as i16,
data: slice::from_raw_parts(data.offset(5), data_bytes as usize), data: slice::from_raw_parts(data.offset(5), data_bytes as usize),
} }
} }
} }
pub fn print(&self, pos: Point, colortable: [Color; 16]) -> i32 { pub fn print(&self, pos: Point, colortable: [Color; 16]) -> i16 {
let bearing = Offset::new(self.bearing_x, -self.bearing_y); let bearing = Offset::new(self.bearing_x, -self.bearing_y);
let size = Offset::new(self.width, self.height); let size = Offset::new(self.width, self.height);
let pos_adj = pos + bearing; let pos_adj = pos + bearing;
@ -663,22 +654,22 @@ impl Glyph {
self.adv self.adv
} }
pub fn unpack_bpp1(&self, a: i32) -> u8 { pub fn unpack_bpp1(&self, a: i16) -> u8 {
let c_data = self.data[(a / 8) as usize]; let c_data = self.data[(a / 8) as usize];
((c_data >> (7 - (a % 8))) & 0x01) * 15 ((c_data >> (7 - (a % 8))) & 0x01) * 15
} }
pub fn unpack_bpp2(&self, a: i32) -> u8 { pub fn unpack_bpp2(&self, a: i16) -> u8 {
let c_data = self.data[(a / 4) as usize]; let c_data = self.data[(a / 4) as usize];
((c_data >> (6 - (a % 4) * 2)) & 0x03) * 5 ((c_data >> (6 - (a % 4) * 2)) & 0x03) * 5
} }
pub fn unpack_bpp4(&self, a: i32) -> u8 { pub fn unpack_bpp4(&self, a: i16) -> u8 {
let c_data = self.data[(a / 2) as usize]; let c_data = self.data[(a / 2) as usize];
(c_data >> (4 - (a % 2) * 4)) & 0x0F (c_data >> (4 - (a % 2) * 4)) & 0x0F
} }
pub fn unpack_bpp8(&self, a: i32) -> u8 { pub fn unpack_bpp8(&self, a: i16) -> u8 {
let c_data = self.data[a as usize]; let c_data = self.data[a as usize];
c_data >> 4 c_data >> 4
} }
@ -704,19 +695,19 @@ impl Font {
Self(id) Self(id)
} }
pub fn text_width(self, text: &str) -> i32 { pub fn text_width(self, text: &str) -> i16 {
display::text_width(text, self.0) display::text_width(text, self.0) as i16
} }
pub fn char_width(self, ch: char) -> i32 { pub fn char_width(self, ch: char) -> i16 {
display::char_width(ch, self.0) display::char_width(ch, self.0) as i16
} }
pub fn text_height(self) -> i32 { pub fn text_height(self) -> i16 {
display::text_height(self.0) display::text_height(self.0) as i16
} }
pub fn line_height(self) -> i32 { pub fn line_height(self) -> i16 {
constant::LINE_SPACE + self.text_height() constant::LINE_SPACE + self.text_height()
} }

View File

@ -1,7 +1,7 @@
use crate::ui::lerp::Lerp; use crate::ui::lerp::Lerp;
use core::ops::{Add, Neg, Sub}; use core::ops::{Add, Neg, Sub};
const fn min(a: i32, b: i32) -> i32 { const fn min(a: i16, b: i16) -> i16 {
if a < b { if a < b {
a a
} else { } else {
@ -9,7 +9,7 @@ const fn min(a: i32, b: i32) -> i32 {
} }
} }
const fn max(a: i32, b: i32) -> i32 { const fn max(a: i16, b: i16) -> i16 {
if a > b { if a > b {
a a
} else { } else {
@ -17,7 +17,7 @@ const fn max(a: i32, b: i32) -> i32 {
} }
} }
const fn clamp(x: i32, min: i32, max: i32) -> i32 { const fn clamp(x: i16, min: i16, max: i16) -> i16 {
if x < min { if x < min {
min min
} else if x > max { } else if x > max {
@ -32,16 +32,16 @@ const fn clamp(x: i32, min: i32, max: i32) -> i32 {
/// the `Point` type. /// the `Point` type.
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Offset { pub struct Offset {
pub x: i32, pub x: i16,
pub y: i32, pub y: i16,
} }
impl Offset { impl Offset {
pub const fn new(x: i32, y: i32) -> Self { pub const fn new(x: i16, y: i16) -> Self {
Self { x, y } Self { x, y }
} }
pub const fn uniform(a: i32) -> Self { pub const fn uniform(a: i16) -> Self {
Self::new(a, a) Self::new(a, a)
} }
@ -49,22 +49,22 @@ impl Offset {
Self::new(0, 0) Self::new(0, 0)
} }
pub const fn x(x: i32) -> Self { pub const fn x(x: i16) -> Self {
Self::new(x, 0) Self::new(x, 0)
} }
pub const fn y(y: i32) -> Self { pub const fn y(y: i16) -> Self {
Self::new(0, y) Self::new(0, y)
} }
pub const fn on_axis(axis: Axis, a: i32) -> Self { pub const fn on_axis(axis: Axis, a: i16) -> Self {
match axis { match axis {
Axis::Horizontal => Self::new(a, 0), Axis::Horizontal => Self::new(a, 0),
Axis::Vertical => Self::new(0, a), Axis::Vertical => Self::new(0, a),
} }
} }
pub const fn axis(&self, axis: Axis) -> i32 { pub const fn axis(&self, axis: Axis) -> i16 {
match axis { match axis {
Axis::Horizontal => self.x, Axis::Horizontal => self.x,
Axis::Vertical => self.y, Axis::Vertical => self.y,
@ -132,12 +132,12 @@ impl Sub<Offset> for Offset {
/// coordinates, vectors, and offsets are represented by the `Offset` type. /// coordinates, vectors, and offsets are represented by the `Offset` type.
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct Point { pub struct Point {
pub x: i32, pub x: i16,
pub y: i32, pub y: i16,
} }
impl Point { impl Point {
pub const fn new(x: i32, y: i32) -> Self { pub const fn new(x: i16, y: i16) -> Self {
Self { x, y } Self { x, y }
} }
@ -184,7 +184,7 @@ impl Sub<Point> for Point {
impl Lerp for Point { impl Lerp for Point {
fn lerp(a: Self, b: Self, t: f32) -> Self { fn lerp(a: Self, b: Self, t: f32) -> Self {
Point::new(i32::lerp(a.x, b.x, t), i32::lerp(a.y, b.y, t)) Point::new(i16::lerp(a.x, b.x, t), i16::lerp(a.y, b.y, t))
} }
} }
@ -192,10 +192,10 @@ impl Lerp for Point {
/// bottom-right point `x1`,`y1`. /// bottom-right point `x1`,`y1`.
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct Rect { pub struct Rect {
pub x0: i32, pub x0: i16,
pub y0: i32, pub y0: i16,
pub x1: i32, pub x1: i16,
pub y1: i32, pub y1: i16,
} }
impl Rect { impl Rect {
@ -238,19 +238,19 @@ impl Rect {
Self::from_top_left_and_size(self.top_left(), size) Self::from_top_left_and_size(self.top_left(), size)
} }
pub const fn with_width(self, width: i32) -> Self { pub const fn with_width(self, width: i16) -> Self {
self.with_size(Offset::new(width, self.height())) self.with_size(Offset::new(width, self.height()))
} }
pub const fn with_height(self, height: i32) -> Self { pub const fn with_height(self, height: i16) -> Self {
self.with_size(Offset::new(self.width(), height)) self.with_size(Offset::new(self.width(), height))
} }
pub const fn width(&self) -> i32 { pub const fn width(&self) -> i16 {
self.x1 - self.x0 self.x1 - self.x0
} }
pub const fn height(&self) -> i32 { pub const fn height(&self) -> i16 {
self.y1 - self.y0 self.y1 - self.y0
} }
@ -304,7 +304,7 @@ impl Rect {
} }
} }
pub const fn cut_from_left(&self, width: i32) -> Self { pub const fn cut_from_left(&self, width: i16) -> Self {
Self { Self {
x0: self.x0, x0: self.x0,
y0: self.y0, y0: self.y0,
@ -313,7 +313,7 @@ impl Rect {
} }
} }
pub const fn cut_from_right(&self, width: i32) -> Self { pub const fn cut_from_right(&self, width: i16) -> Self {
Self { Self {
x0: self.x1 - width, x0: self.x1 - width,
y0: self.y0, y0: self.y0,
@ -322,7 +322,7 @@ impl Rect {
} }
} }
pub const fn split_top(self, height: i32) -> (Self, Self) { pub const fn split_top(self, height: i16) -> (Self, Self) {
let height = clamp(height, 0, self.height()); let height = clamp(height, 0, self.height());
let top = Self { let top = Self {
@ -336,11 +336,11 @@ impl Rect {
(top, bottom) (top, bottom)
} }
pub const fn split_bottom(self, height: i32) -> (Self, Self) { pub const fn split_bottom(self, height: i16) -> (Self, Self) {
self.split_top(self.height() - height) self.split_top(self.height() - height)
} }
pub const fn split_left(self, width: i32) -> (Self, Self) { pub const fn split_left(self, width: i16) -> (Self, Self) {
let width = clamp(width, 0, self.width()); let width = clamp(width, 0, self.width());
let left = Self { let left = Self {
@ -354,7 +354,7 @@ impl Rect {
(left, right) (left, right)
} }
pub const fn split_right(self, width: i32) -> (Self, Self) { pub const fn split_right(self, width: i16) -> (Self, Self) {
self.split_left(self.width() - width) self.split_left(self.width() - width)
} }
@ -379,14 +379,14 @@ impl Rect {
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct Insets { pub struct Insets {
pub top: i32, pub top: i16,
pub right: i32, pub right: i16,
pub bottom: i32, pub bottom: i16,
pub left: i32, pub left: i16,
} }
impl Insets { impl Insets {
pub const fn new(top: i32, right: i32, bottom: i32, left: i32) -> Self { pub const fn new(top: i16, right: i16, bottom: i16, left: i16) -> Self {
Self { Self {
top, top,
right, right,
@ -395,27 +395,27 @@ impl Insets {
} }
} }
pub const fn uniform(d: i32) -> Self { pub const fn uniform(d: i16) -> Self {
Self::new(d, d, d, d) Self::new(d, d, d, d)
} }
pub const fn top(d: i32) -> Self { pub const fn top(d: i16) -> Self {
Self::new(d, 0, 0, 0) Self::new(d, 0, 0, 0)
} }
pub const fn right(d: i32) -> Self { pub const fn right(d: i16) -> Self {
Self::new(0, d, 0, 0) Self::new(0, d, 0, 0)
} }
pub const fn bottom(d: i32) -> Self { pub const fn bottom(d: i16) -> Self {
Self::new(0, 0, d, 0) Self::new(0, 0, d, 0)
} }
pub const fn left(d: i32) -> Self { pub const fn left(d: i16) -> Self {
Self::new(0, 0, 0, d) Self::new(0, 0, 0, d)
} }
pub const fn sides(d: i32) -> Self { pub const fn sides(d: i16) -> Self {
Self::new(0, d, 0, d) Self::new(0, d, 0, d)
} }
} }
@ -455,7 +455,7 @@ pub struct Grid {
/// Number of columns (cells on the x-axis) in the grid. /// Number of columns (cells on the x-axis) in the grid.
pub cols: usize, pub cols: usize,
/// Padding between cells. /// Padding between cells.
pub spacing: i32, pub spacing: i16,
/// Total area covered by this grid. /// Total area covered by this grid.
pub area: Rect, pub area: Rect,
} }
@ -470,15 +470,15 @@ impl Grid {
} }
} }
pub const fn with_spacing(self, spacing: i32) -> Self { pub const fn with_spacing(self, spacing: i16) -> Self {
Self { spacing, ..self } Self { spacing, ..self }
} }
pub const fn row_col(&self, row: usize, col: usize) -> Rect { pub const fn row_col(&self, row: usize, col: usize) -> Rect {
let ncols = self.cols as i32; let ncols = self.cols as i16;
let nrows = self.rows as i32; let nrows = self.rows as i16;
let col = min(col as i32, ncols - 1); let col = min(col as i16, ncols - 1);
let row = min(row as i32, nrows - 1); let row = min(row as i16, nrows - 1);
// Total number of horizontal pixels used for spacing. // Total number of horizontal pixels used for spacing.
let spacing_width = self.spacing * (ncols - 1); let spacing_width = self.spacing * (ncols - 1);
@ -535,7 +535,7 @@ pub struct GridCellSpan {
pub struct LinearPlacement { pub struct LinearPlacement {
pub axis: Axis, pub axis: Axis,
pub align: Alignment, pub align: Alignment,
pub spacing: i32, pub spacing: i16,
} }
impl LinearPlacement { impl LinearPlacement {
@ -576,14 +576,14 @@ impl LinearPlacement {
} }
} }
pub const fn with_spacing(self, spacing: i32) -> Self { pub const fn with_spacing(self, spacing: i16) -> Self {
Self { spacing, ..self } Self { spacing, ..self }
} }
/// Arranges all `items` by parameters configured in `self` into `area`. /// Arranges all `items` by parameters configured in `self` into `area`.
/// Does not change the size of the items (only the position). /// Does not change the size of the items (only the position).
pub fn arrange(&self, area: Rect, items: &mut [impl Dimensions]) { pub fn arrange(&self, area: Rect, items: &mut [impl Dimensions]) {
let size_sum: i32 = items let size_sum: i16 = items
.iter_mut() .iter_mut()
.map(|i| i.area().size().axis(self.axis)) .map(|i| i.area().size().axis(self.axis))
.sum(); .sum();
@ -609,7 +609,7 @@ impl LinearPlacement {
sink: &mut dyn FnMut(Point), sink: &mut dyn FnMut(Point),
) { ) {
let item_size = size.axis(self.axis); let item_size = size.axis(self.axis);
let (mut cursor, spacing) = self.compute_spacing(area, count, (count as i32) * item_size); let (mut cursor, spacing) = self.compute_spacing(area, count, (count as i16) * item_size);
let cross_coord = let cross_coord =
area.size().axis(self.axis.cross()) / 2 - size.axis(self.axis.cross()) / 2; area.size().axis(self.axis.cross()) / 2 - size.axis(self.axis.cross()) / 2;
@ -623,15 +623,15 @@ impl LinearPlacement {
} }
} }
const fn compute_spacing(&self, area: Rect, count: usize, size_sum: i32) -> (i32, i32) { const fn compute_spacing(&self, area: Rect, count: usize, size_sum: i16) -> (i16, i16) {
let spacing_count = count.saturating_sub(1); let spacing_count = count.saturating_sub(1);
let spacing_sum = spacing_count as i32 * self.spacing; let spacing_sum = spacing_count as i16 * self.spacing;
let naive_size = size_sum + spacing_sum; let naive_size = size_sum + spacing_sum;
let available_space = area.size().axis(self.axis); let available_space = area.size().axis(self.axis);
// scale down spacing to fit everything into area // scale down spacing to fit everything into area
let (total_size, spacing) = if naive_size > available_space { let (total_size, spacing) = if naive_size > available_space {
let scaled_space = (available_space - size_sum) / max(spacing_count as i32, 1); let scaled_space = (available_space - size_sum) / max(spacing_count as i16, 1);
// forbid negative spacing // forbid negative spacing
(available_space, max(scaled_space, 0)) (available_space, max(scaled_space, 0))
} else { } else {

View File

@ -65,6 +65,7 @@ macro_rules! impl_lerp_for_uint {
}; };
} }
impl_lerp_for_int!(i16);
impl_lerp_for_int!(i32); impl_lerp_for_int!(i32);
impl_lerp_for_uint!(u8); impl_lerp_for_uint!(u8);
impl_lerp_for_uint!(u16); impl_lerp_for_uint!(u16);

View File

@ -37,7 +37,7 @@ where
type Msg = T::Msg; type Msg = T::Msg;
fn place(&mut self, bounds: Rect) -> Rect { fn place(&mut self, bounds: Rect) -> Rect {
const TITLE_SPACE: i32 = 4; const TITLE_SPACE: i16 = 4;
let (title_area, content_area) = bounds.split_top(theme::FONT_BOLD.line_height()); let (title_area, content_area) = bounds.split_top(theme::FONT_BOLD.line_height());
let content_area = content_area.inset(Insets::top(TITLE_SPACE)); let content_area = content_area.inset(Insets::top(TITLE_SPACE));

View File

@ -134,9 +134,9 @@ pub struct ScrollBar {
} }
impl ScrollBar { impl ScrollBar {
pub const WIDTH: i32 = 8; pub const WIDTH: i16 = 8;
pub const DOT_SIZE: Offset = Offset::new(4, 4); pub const DOT_SIZE: Offset = Offset::new(4, 4);
pub const DOT_INTERVAL: i32 = 6; pub const DOT_INTERVAL: i16 = 6;
pub fn vertical() -> Self { pub fn vertical() -> Self {
Self { Self {
@ -205,7 +205,7 @@ impl Component for ScrollBar {
} }
fn paint(&mut self) { fn paint(&mut self) {
let count = self.page_count as i32; let count = self.page_count as i16;
let interval = { let interval = {
let available_height = self.area.height(); let available_height = self.area.height();
let naive_height = count * Self::DOT_INTERVAL; let naive_height = count * Self::DOT_INTERVAL;

View File

@ -1,9 +1,9 @@
use crate::ui::geometry::{Offset, Point, Rect}; use crate::ui::geometry::{Offset, Point, Rect};
pub const WIDTH: i32 = 128; pub const WIDTH: i16 = 128;
pub const HEIGHT: i32 = 64; pub const HEIGHT: i16 = 64;
pub const LINE_SPACE: i32 = 1; pub const LINE_SPACE: i16 = 1;
pub const FONT_BPP: i32 = 1; pub const FONT_BPP: i16 = 1;
pub const fn size() -> Offset { pub const fn size() -> Offset {
Offset::new(WIDTH, HEIGHT) Offset::new(WIDTH, HEIGHT)

View File

@ -18,7 +18,7 @@ pub struct HoldToConfirm {
pos: ButtonPos, pos: ButtonPos,
loader: Loader, loader: Loader,
baseline: Point, baseline: Point,
text_width: i32, text_width: i16,
} }
impl HoldToConfirm { impl HoldToConfirm {

View File

@ -37,7 +37,7 @@ where
type Msg = T::Msg; type Msg = T::Msg;
fn place(&mut self, bounds: Rect) -> Rect { fn place(&mut self, bounds: Rect) -> Rect {
const TITLE_SPACE: i32 = 4; const TITLE_SPACE: i16 = 4;
let (title_area, content_area) = bounds.split_top(theme::FONT_BOLD.line_height()); let (title_area, content_area) = bounds.split_top(theme::FONT_BOLD.line_height());
let content_area = content_area.inset(Insets::top(TITLE_SPACE)); let content_area = content_area.inset(Insets::top(TITLE_SPACE));

View File

@ -111,8 +111,8 @@ impl Loader {
matches!(self.progress(now), Some(display::LOADER_MIN)) matches!(self.progress(now), Some(display::LOADER_MIN))
} }
pub fn paint_loader(&mut self, style: &LoaderStyle, done: i32) { pub fn paint_loader(&mut self, style: &LoaderStyle, done: i16) {
let invert_from = ((self.area.width() + 1) * done) / (display::LOADER_MAX as i32); let invert_from = ((self.area.width() + 1) * done) / (display::LOADER_MAX as i16);
display::bar_with_text_and_fill( display::bar_with_text_and_fill(
self.area, self.area,
@ -169,11 +169,11 @@ impl Component for Loader {
if let State::Initial = self.state { if let State::Initial = self.state {
self.paint_loader(self.styles.normal, 0); self.paint_loader(self.styles.normal, 0);
} else if let State::Grown = self.state { } else if let State::Grown = self.state {
self.paint_loader(self.styles.normal, display::LOADER_MAX as i32); self.paint_loader(self.styles.normal, display::LOADER_MAX as i16);
} else { } else {
let progress = self.progress(now); let progress = self.progress(now);
if let Some(done) = progress { if let Some(done) = progress {
self.paint_loader(self.styles.normal, done as i32); self.paint_loader(self.styles.normal, done as i16);
} else { } else {
self.paint_loader(self.styles.normal, 0); self.paint_loader(self.styles.normal, 0);
} }

View File

@ -134,9 +134,9 @@ pub struct ScrollBar {
} }
impl ScrollBar { impl ScrollBar {
pub const WIDTH: i32 = 8; pub const WIDTH: i16 = 8;
pub const DOT_SIZE: Offset = Offset::new(4, 4); pub const DOT_SIZE: Offset = Offset::new(4, 4);
pub const DOT_INTERVAL: i32 = 6; pub const DOT_INTERVAL: i16 = 6;
pub fn vertical() -> Self { pub fn vertical() -> Self {
Self { Self {
@ -205,7 +205,7 @@ impl Component for ScrollBar {
} }
fn paint(&mut self) { fn paint(&mut self) {
let count = self.page_count as i32; let count = self.page_count as i16;
let interval = { let interval = {
let available_height = self.area.height(); let available_height = self.area.height();
let naive_height = count * Self::DOT_INTERVAL; let naive_height = count * Self::DOT_INTERVAL;

View File

@ -78,7 +78,7 @@ impl ResultAnim {
matches!(self.progress(now), Some(display::LOADER_MAX)) matches!(self.progress(now), Some(display::LOADER_MAX))
} }
pub fn paint_anim(&mut self, done: i32) { pub fn paint_anim(&mut self, done: i16) {
display::rect_rounded2_partial( display::rect_rounded2_partial(
self.area, self.area,
theme::FG, theme::FG,
@ -128,11 +128,11 @@ impl Component for ResultAnim {
if let State::Initial = self.state { if let State::Initial = self.state {
self.paint_anim(0); self.paint_anim(0);
} else if let State::Grown = self.state { } else if let State::Grown = self.state {
self.paint_anim(display::LOADER_MAX as i32); self.paint_anim(display::LOADER_MAX as i16);
} else { } else {
let progress = self.progress(now); let progress = self.progress(now);
if let Some(done) = progress { if let Some(done) = progress {
self.paint_anim(done as i32); self.paint_anim(done as i16);
} else { } else {
self.paint_anim(0); self.paint_anim(0);
} }

View File

@ -29,12 +29,12 @@ pub struct ResultPopup {
autoclose: bool, autoclose: bool,
} }
const ANIM_SIZE: i32 = 18; const ANIM_SIZE: i16 = 18;
const BUTTON_HEIGHT: i32 = 13; const BUTTON_HEIGHT: i16 = 13;
const ANIM_SPACE: i32 = 11; const ANIM_SPACE: i16 = 11;
const ANIM_POS: i32 = 32; const ANIM_POS: i16 = 32;
const ANIM_POS_ADJ_HEADLINE: i32 = 10; const ANIM_POS_ADJ_HEADLINE: i16 = 10;
const ANIM_POS_ADJ_BUTTON: i32 = 6; const ANIM_POS_ADJ_BUTTON: i16 = 6;
impl ResultPopup { impl ResultPopup {
pub fn new( pub fn new(

View File

@ -1,9 +1,9 @@
use crate::ui::geometry::{Offset, Point, Rect}; use crate::ui::geometry::{Offset, Point, Rect};
pub const WIDTH: i32 = 128; pub const WIDTH: i16 = 128;
pub const HEIGHT: i32 = 128; pub const HEIGHT: i16 = 128;
pub const LINE_SPACE: i32 = 1; pub const LINE_SPACE: i16 = 1;
pub const FONT_BPP: i32 = 1; pub const FONT_BPP: i16 = 1;
pub const fn size() -> Offset { pub const fn size() -> Offset {
Offset::new(WIDTH, HEIGHT) Offset::new(WIDTH, HEIGHT)

View File

@ -31,7 +31,7 @@ pub struct Button<T> {
impl<T> Button<T> { impl<T> Button<T> {
/// Offsets the baseline of the button text either up (negative) or down /// Offsets the baseline of the button text either up (negative) or down
/// (positive). /// (positive).
pub const BASELINE_OFFSET: i32 = -3; pub const BASELINE_OFFSET: i16 = -3;
pub fn new(content: ButtonContent<T>) -> Self { pub fn new(content: ButtonContent<T>) -> Self {
Self { Self {
@ -335,7 +335,7 @@ pub struct ButtonStyle {
pub background_color: Color, pub background_color: Color,
pub border_color: Color, pub border_color: Color,
pub border_radius: u8, pub border_radius: u8,
pub border_width: i32, pub border_width: i16,
} }
impl<T> Button<T> { impl<T> Button<T> {

View File

@ -135,9 +135,9 @@ where
} }
} }
pub const ICON_AREA_PADDING: i32 = 2; pub const ICON_AREA_PADDING: i16 = 2;
pub const ICON_AREA_HEIGHT: i32 = 60; pub const ICON_AREA_HEIGHT: i16 = 60;
pub const VALUE_SPACE: i32 = 5; pub const VALUE_SPACE: i16 = 5;
} }
impl<T, U> Component for IconDialog<T, U> impl<T, U> Component for IconDialog<T, U>

View File

@ -44,7 +44,7 @@ where
type Msg = T::Msg; type Msg = T::Msg;
fn place(&mut self, bounds: Rect) -> Rect { fn place(&mut self, bounds: Rect) -> Rect {
const TITLE_SPACE: i32 = theme::BUTTON_SPACING; const TITLE_SPACE: i16 = theme::BUTTON_SPACING;
let (title_area, content_area) = bounds let (title_area, content_area) = bounds
.inset(self.border) .inset(self.border)
@ -105,11 +105,11 @@ where
T: Component, T: Component,
U: AsRef<str>, U: AsRef<str>,
{ {
const HEIGHT: i32 = 42; const HEIGHT: i16 = 42;
const COLOR: Color = theme::YELLOW; const COLOR: Color = theme::YELLOW;
const FONT: Font = theme::FONT_BOLD; const FONT: Font = theme::FONT_BOLD;
const TEXT_OFFSET: Offset = Offset::new(1, -2); const TEXT_OFFSET: Offset = Offset::new(1, -2);
const ICON_SPACE: i32 = 8; const ICON_SPACE: i16 = 8;
pub fn new(icon: &'static [u8], title: U, content: T) -> Self { pub fn new(icon: &'static [u8], title: U, content: T) -> Self {
Self { Self {

View File

@ -10,9 +10,9 @@ use crate::{
}, },
}; };
pub const HEADER_HEIGHT: i32 = 25; pub const HEADER_HEIGHT: i16 = 25;
pub const HEADER_PADDING_SIDE: i32 = 5; pub const HEADER_PADDING_SIDE: i16 = 5;
pub const HEADER_PADDING_BOTTOM: i32 = 12; pub const HEADER_PADDING_BOTTOM: i16 = 12;
/// Contains state commonly used in implementations multi-tap keyboards. /// Contains state commonly used in implementations multi-tap keyboards.
pub struct MultiTapKeyboard { pub struct MultiTapKeyboard {

View File

@ -30,9 +30,9 @@ const MAX_VISIBLE_DIGITS: usize = 16;
const DIGIT_COUNT: usize = 10; // 0..10 const DIGIT_COUNT: usize = 10; // 0..10
const ERASE_HOLD_DURATION: Duration = Duration::from_secs(2); const ERASE_HOLD_DURATION: Duration = Duration::from_secs(2);
const HEADER_HEIGHT: i32 = 25; const HEADER_HEIGHT: i16 = 25;
const HEADER_PADDING_SIDE: i32 = 5; const HEADER_PADDING_SIDE: i16 = 5;
const HEADER_PADDING_BOTTOM: i32 = 12; const HEADER_PADDING_BOTTOM: i16 = 12;
const HEADER_PADDING: Insets = Insets::new( const HEADER_PADDING: Insets = Insets::new(
theme::borders().top, theme::borders().top,
@ -269,9 +269,9 @@ struct PinDots {
} }
impl PinDots { impl PinDots {
const DOT: i32 = 6; const DOT: i16 = 6;
const PADDING: i32 = 6; const PADDING: i16 = 6;
const TWITCH: i32 = 4; const TWITCH: i16 = 4;
fn new(style: LabelStyle) -> Self { fn new(style: LabelStyle) -> Self {
Self { Self {
@ -289,8 +289,8 @@ impl PinDots {
fn size(&self) -> Offset { fn size(&self) -> Offset {
let ndots = self.digits.len().min(MAX_VISIBLE_DOTS); let ndots = self.digits.len().min(MAX_VISIBLE_DOTS);
let mut width = Self::DOT * (ndots as i32); let mut width = Self::DOT * (ndots as i16);
width += Self::PADDING * (ndots.saturating_sub(1) as i32); width += Self::PADDING * (ndots.saturating_sub(1) as i16);
Offset::new(width, Self::DOT) Offset::new(width, Self::DOT)
} }
@ -328,7 +328,7 @@ impl PinDots {
fn paint_digits(&self, area: Rect) { fn paint_digits(&self, area: Rect) {
let center = area.center() + Offset::y(theme::FONT_MONO.text_height() / 2); let center = area.center() + Offset::y(theme::FONT_MONO.text_height() / 2);
let right = let right =
center + Offset::x(theme::FONT_MONO.text_width("0") * (MAX_VISIBLE_DOTS as i32) / 2); center + Offset::x(theme::FONT_MONO.text_width("0") * (MAX_VISIBLE_DOTS as i16) / 2);
let digits = self.digits.len(); let digits = self.digits.len();
if digits <= MAX_VISIBLE_DOTS { if digits <= MAX_VISIBLE_DOTS {

View File

@ -23,7 +23,7 @@ enum State {
} }
pub struct Loader { pub struct Loader {
offset_y: i32, offset_y: i16,
state: State, state: State,
growing_duration: Duration, growing_duration: Duration,
shrinking_duration: Duration, shrinking_duration: Duration,

View File

@ -194,9 +194,9 @@ pub struct PageLayout {
} }
impl PageLayout { impl PageLayout {
const SCROLLBAR_WIDTH: i32 = 10; const SCROLLBAR_WIDTH: i16 = 10;
const SCROLLBAR_SPACE: i32 = 10; const SCROLLBAR_SPACE: i16 = 10;
const HINT_OFF: i32 = 19; const HINT_OFF: i16 = 19;
pub fn new(area: Rect) -> Self { pub fn new(area: Rect) -> Self {
let (_, hint) = area.split_bottom(Self::HINT_OFF); let (_, hint) = area.split_bottom(Self::HINT_OFF);
@ -339,7 +339,7 @@ mod tests {
String::from_utf8(t).unwrap() String::from_utf8(t).unwrap()
} }
fn swipe(component: &mut impl Component, points: &[(i32, i32)]) { fn swipe(component: &mut impl Component, points: &[(i16, i16)]) {
let last = points.len().saturating_sub(1); let last = points.len().saturating_sub(1);
let mut first = true; let mut first = true;
let mut ctx = EventCtx::new(); let mut ctx = EventCtx::new();

View File

@ -15,11 +15,11 @@ pub struct ScrollBar {
} }
impl ScrollBar { impl ScrollBar {
pub const DOT_SIZE: i32 = 6; pub const DOT_SIZE: i16 = 6;
/// Edge to edge. /// Edge to edge.
const DOT_INTERVAL: i32 = 6; const DOT_INTERVAL: i16 = 6;
/// Edge of last dot to center of arrow icon. /// Edge of last dot to center of arrow icon.
const ARROW_SPACE: i32 = 26; const ARROW_SPACE: i16 = 26;
const ICON_UP: &'static [u8] = include_res!("model_tt/res/scroll-up.toif"); const ICON_UP: &'static [u8] = include_res!("model_tt/res/scroll-up.toif");
const ICON_DOWN: &'static [u8] = include_res!("model_tt/res/scroll-down.toif"); const ICON_DOWN: &'static [u8] = include_res!("model_tt/res/scroll-down.toif");

View File

@ -74,7 +74,7 @@ impl Swipe {
self.allow_up || self.allow_down || self.allow_left || self.allow_right self.allow_up || self.allow_down || self.allow_left || self.allow_right
} }
fn ratio(&self, dist: i32) -> f32 { fn ratio(&self, dist: i16) -> f32 {
(dist as f32 / Self::DISTANCE as f32).min(1.0) (dist as f32 / Self::DISTANCE as f32).min(1.0)
} }

View File

@ -1,9 +1,9 @@
use crate::ui::geometry::{Offset, Point, Rect}; use crate::ui::geometry::{Offset, Point, Rect};
pub const WIDTH: i32 = 240; pub const WIDTH: i16 = 240;
pub const HEIGHT: i32 = 240; pub const HEIGHT: i16 = 240;
pub const LINE_SPACE: i32 = 4; pub const LINE_SPACE: i16 = 4;
pub const FONT_BPP: i32 = 4; pub const FONT_BPP: i16 = 4;
pub const fn size() -> Offset { pub const fn size() -> Offset {
Offset::new(WIDTH, HEIGHT) Offset::new(WIDTH, HEIGHT)

View File

@ -48,7 +48,7 @@ pub const RADIUS: u8 = 2;
pub const QR_SIDE_MAX: u32 = 140; pub const QR_SIDE_MAX: u32 = 140;
// Size of icons in the UI (i.e. inside buttons). // Size of icons in the UI (i.e. inside buttons).
pub const ICON_SIZE: i32 = 16; pub const ICON_SIZE: i16 = 16;
// UI icons (greyscale). // UI icons (greyscale).
pub const ICON_CANCEL: &[u8] = include_res!("model_tt/res/cancel.toif"); pub const ICON_CANCEL: &[u8] = include_res!("model_tt/res/cancel.toif");
@ -423,16 +423,16 @@ pub const FORMATTED: FormattedFonts = FormattedFonts {
mono: FONT_MONO, mono: FONT_MONO,
}; };
pub const CONTENT_BORDER: i32 = 5; pub const CONTENT_BORDER: i16 = 5;
pub const KEYBOARD_SPACING: i32 = 8; pub const KEYBOARD_SPACING: i16 = 8;
pub const BUTTON_HEIGHT: i32 = 38; pub const BUTTON_HEIGHT: i16 = 38;
pub const BUTTON_SPACING: i32 = 6; pub const BUTTON_SPACING: i16 = 6;
pub const CHECKLIST_SPACING: i32 = 10; pub const CHECKLIST_SPACING: i16 = 10;
pub const RECOVERY_SPACING: i32 = 18; pub const RECOVERY_SPACING: i16 = 18;
/// Standard button height in pixels. /// Standard button height in pixels.
pub const fn button_rows(count: usize) -> i32 { pub const fn button_rows(count: usize) -> i16 {
let count = count as i32; let count = count as i16;
BUTTON_HEIGHT * count + BUTTON_SPACING * count.saturating_sub(1) BUTTON_HEIGHT * count + BUTTON_SPACING * count.saturating_sub(1)
} }