1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-23 06:58:13 +00:00

fixup! feat(core): introduce new drawing library

This commit is contained in:
cepetr 2024-03-07 17:43:47 +01:00
parent 5cb2abd3c8
commit 434b272f44
15 changed files with 78 additions and 164 deletions

View File

@ -1,41 +0,0 @@
use crate::ui::{display::Color, geometry::Offset};
use super::{BasicCanvas, Canvas, Mono8Canvas};
use crate::trezorhal::display;
pub struct MonoDisplay<'a> {
canvas: Mono8Canvas<'a>,
}
impl<'a> MonoDisplay<'a> {
pub fn new(size: Offset, buff: &'a mut [u8]) -> Option<Self> {
Some(Self {
canvas: Mono8Canvas::new(size, None, buff)?,
})
}
pub fn canvas(&mut self) -> &mut Mono8Canvas<'a> {
&mut self.canvas
}
pub fn refresh(&self) {
// TODO:
let w = self.canvas.width() as u16 - 1;
let h = self.canvas.height() as u16 - 1;
display::set_window(0, 0, w, h);
let view = self.canvas.view();
for y in 0..self.canvas.size().y {
let row = unwrap!(view.row(y));
for value in row.iter() {
let c = Color::rgb(*value, *value, *value);
display::pixeldata(c.into());
}
}
display::refresh();
}
}

View File

@ -1,49 +0,0 @@
use crate::ui::{
display::Color,
geometry::{Offset, Rect},
};
use super::{BasicCanvas, BitmapView, Viewport};
use crate::trezorhal::bitmap::Dma2d;
// ==========================================================================
// Display canvas
// ==========================================================================
pub struct Wnd565Display {
size: Offset,
viewport: Viewport,
}
impl Wnd565Display {
pub fn acquire() -> Option<Self> {
let size = Offset::new(240, 240); // TODO
let viewport = Viewport::from_size(size);
Some(Self { size, viewport })
}
}
impl BasicCanvas for Wnd565Display {
fn viewport(&self) -> Viewport {
self.viewport
}
fn set_viewport(&mut self, viewport: Viewport) {
self.viewport = viewport.absolute_clip(self.bounds());
}
fn size(&self) -> Offset {
self.size
}
fn fill_rect(&mut self, r: Rect, color: Color) {
let r = r.translate(self.viewport.origin);
Dma2d::wnd565_fill(r, self.viewport.clip, color);
}
fn draw_bitmap(&mut self, r: Rect, bitmap: BitmapView) {
let r = r.translate(self.viewport.origin);
Dma2d::wnd565_copy(r, self.viewport.clip, &bitmap);
}
}

View File

@ -51,12 +51,12 @@ impl Bar {
Self { thickness, ..self } Self { thickness, ..self }
} }
pub fn render(self, renderer: &mut impl Renderer) { pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) {
renderer.render_shape(self); renderer.render_shape(self);
} }
} }
impl Shape for Bar { impl Shape<'_> for Bar {
fn bounds(&self, _cache: &DrawingCache) -> Rect { fn bounds(&self, _cache: &DrawingCache) -> Rect {
self.area self.area
} }
@ -110,8 +110,8 @@ impl Shape for Bar {
} }
} }
impl ShapeClone for Bar { impl<'s> ShapeClone<'s> for Bar {
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape> fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape<'s>>
where where
T: LocalAllocLeakExt<'alloc>, T: LocalAllocLeakExt<'alloc>,
{ {

View File

@ -16,23 +16,23 @@ use without_alloc::alloc::LocalAllocLeakExt;
/// ///
/// `Shape` objects may use `DrawingCache` as a scratch-pad memory or for /// `Shape` objects may use `DrawingCache` as a scratch-pad memory or for
/// caching expensive calculations results. /// caching expensive calculations results.
pub trait Shape { pub trait Shape<'s> {
/// Returns the smallest bounding rectangle containing whole parts of the /// Returns the smallest bounding rectangle containing whole parts of the
/// shape. /// shape.
/// ///
/// The function is used by renderer for optimization if the shape /// The function is used by renderer for optimization if the shape
/// must be renderer or not. /// must be renderer or not.
fn bounds(&self, cache: &DrawingCache) -> Rect; fn bounds(&self, cache: &DrawingCache<'s>) -> Rect;
/// Draws shape on the canvas. /// Draws shape on the canvas.
fn draw(&mut self, canvas: &mut dyn Canvas, cache: &DrawingCache); fn draw(&mut self, canvas: &mut dyn Canvas, cache: &DrawingCache<'s>);
/// The function should release all allocated resources needed /// The function should release all allocated resources needed
/// for shape drawing. /// for shape drawing.
/// ///
/// It's called by renderer if the shape's draw() function won't be called /// It's called by renderer if the shape's draw() function won't be called
/// anymore. /// anymore.
fn cleanup(&mut self, cache: &DrawingCache); fn cleanup(&mut self, cache: &DrawingCache<'s>);
} }
// ========================================================================== // ==========================================================================
@ -41,12 +41,13 @@ pub trait Shape {
/// All shapes (like `Bar`, `Text`, `Circle`, ...) that can be rendered /// All shapes (like `Bar`, `Text`, `Circle`, ...) that can be rendered
/// by `ProgressiveRender` must implement `ShapeClone`. /// by `ProgressiveRender` must implement `ShapeClone`.
pub trait ShapeClone { pub trait ShapeClone<'s> {
/// Clones a shape object at the specified memory bump. /// Clones a shape object at the specified memory bump.
/// ///
/// The method is used by `ProgressiveRenderer` to store shape objects for /// The method is used by `ProgressiveRenderer` to store shape objects for
/// deferred drawing. /// deferred drawing.
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape> fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape<'s>>
where where
T: LocalAllocLeakExt<'alloc>; T: LocalAllocLeakExt<'alloc>,
'alloc: 's;
} }

View File

@ -17,12 +17,12 @@ impl Blurring {
Self { area, radius } Self { area, radius }
} }
pub fn render(self, renderer: &mut impl Renderer) { pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) {
renderer.render_shape(self); renderer.render_shape(self);
} }
} }
impl Shape for Blurring { impl Shape<'_> for Blurring {
fn bounds(&self, _cache: &DrawingCache) -> Rect { fn bounds(&self, _cache: &DrawingCache) -> Rect {
self.area self.area
} }
@ -34,8 +34,8 @@ impl Shape for Blurring {
} }
} }
impl ShapeClone for Blurring { impl<'s> ShapeClone<'s> for Blurring {
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape> fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape<'s>>
where where
T: LocalAllocLeakExt<'alloc>, T: LocalAllocLeakExt<'alloc>,
{ {

View File

@ -160,7 +160,7 @@ impl<'a> JpegCacheSlot<'a> {
} }
let decoder = unwrap!(self.decoder.as_mut()); // should never fail let decoder = unwrap!(self.decoder.as_mut()); // should never fail
let input = unwrap!(self.input.as_mut()); // shoud never fail let input = unwrap!(self.input.as_mut()); // should never fail
let mut output = JpegFnOutput::new(output); let mut output = JpegFnOutput::new(output);
match decoder.decomp2(input, &mut output) { match decoder.decomp2(input, &mut output) {

View File

@ -36,7 +36,7 @@ impl<'a> ZlibCacheSlot<'a> {
} }
/// May be called with zdata == &[] to make the slot free /// May be called with zdata == &[] to make the slot free
fn reset(&mut self, zdata: &'static [u8]) { fn reset(&mut self, zdata: &'a [u8]) {
// Drop the existing decompression context holding // Drop the existing decompression context holding
// a mutable reference to window buffer // a mutable reference to window buffer
self.dc = None; self.dc = None;
@ -133,7 +133,7 @@ impl<'a> ZlibCache<'a> {
pub fn uncompress( pub fn uncompress(
&mut self, &mut self,
zdata: &'static [u8], zdata: &'a [u8],
offset: usize, offset: usize,
dest_buf: &mut [u8], dest_buf: &mut [u8],
) -> Result<bool, ()> { ) -> Result<bool, ()> {
@ -155,7 +155,7 @@ impl<'a> ZlibCache<'a> {
pub fn uncompress_toif( pub fn uncompress_toif(
&mut self, &mut self,
toif: Toif<'static>, toif: Toif<'a>,
from_row: i16, from_row: i16,
dest_buf: &mut [u8], dest_buf: &mut [u8],
) -> Result<(), ()> { ) -> Result<(), ()> {

View File

@ -64,12 +64,12 @@ impl Circle {
} }
} }
pub fn render(self, renderer: &mut impl Renderer) { pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) {
renderer.render_shape(self); renderer.render_shape(self);
} }
} }
impl Shape for Circle { impl Shape<'_> for Circle {
fn bounds(&self, _cache: &DrawingCache) -> Rect { fn bounds(&self, _cache: &DrawingCache) -> Rect {
let c = self.center; let c = self.center;
let r = self.radius; let r = self.radius;
@ -129,8 +129,8 @@ impl Shape for Circle {
} }
} }
impl ShapeClone for Circle { impl<'s> ShapeClone<'s> for Circle {
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape> fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape<'s>>
where where
T: LocalAllocLeakExt<'alloc>, T: LocalAllocLeakExt<'alloc>,
{ {

View File

@ -8,13 +8,13 @@ use super::{DrawingCache, Renderer, Shape, ShapeClone};
use without_alloc::alloc::LocalAllocLeakExt; use without_alloc::alloc::LocalAllocLeakExt;
/// A shape for rendering compressed JPEG images. /// A shape for rendering compressed JPEG images.
pub struct JpegImage { pub struct JpegImage<'a> {
/// Image position /// Image position
pos: Point, pos: Point,
// Image position alignment // Image position alignment
align: Alignment2D, align: Alignment2D,
/// JPEG data /// JPEG data
jpeg: &'static [u8], jpeg: &'a [u8],
/// Scale factor (default 0) /// Scale factor (default 0)
scale: u8, scale: u8,
/// Blurring radius or 0 if no blurring required (default 0) /// Blurring radius or 0 if no blurring required (default 0)
@ -26,8 +26,8 @@ pub struct JpegImage {
blur_tag: Option<u32>, blur_tag: Option<u32>,
} }
impl JpegImage { impl<'a> JpegImage<'a> {
pub fn new(pos: Point, jpeg: &'static [u8]) -> Self { pub fn new(pos: Point, jpeg: &'a [u8]) -> Self {
JpegImage { JpegImage {
pos, pos,
align: Alignment2D::TOP_LEFT, align: Alignment2D::TOP_LEFT,
@ -59,18 +59,18 @@ impl JpegImage {
Self { dim, ..self } Self { dim, ..self }
} }
pub fn render(self, renderer: &mut impl Renderer) { pub fn render(self, renderer: &mut impl Renderer<'a>) {
renderer.render_shape(self); renderer.render_shape(self);
} }
} }
impl Shape for JpegImage { impl<'a> Shape<'a> for JpegImage<'a> {
fn bounds(&self, cache: &DrawingCache) -> Rect { fn bounds(&self, cache: &DrawingCache<'a>) -> Rect {
let size = unwrap!(cache.jpeg().get_size(self.jpeg, self.scale), "Invalid JPEG"); let size = unwrap!(cache.jpeg().get_size(self.jpeg, self.scale), "Invalid JPEG");
Rect::from_top_left_and_size(size.snap(self.pos, self.align), size) Rect::from_top_left_and_size(size.snap(self.pos, self.align), size)
} }
fn cleanup(&mut self, _cache: &DrawingCache) { fn cleanup(&mut self, _cache: &DrawingCache<'a>) {
self.blur_tag = None; self.blur_tag = None;
} }
@ -78,7 +78,7 @@ impl Shape for JpegImage {
// Faster implementation suitable for DirectRenderer without blurring support // Faster implementation suitable for DirectRenderer without blurring support
// (but is terribly slow on ProgressiveRenderer if slices are not aligned // (but is terribly slow on ProgressiveRenderer if slices are not aligned
// to JPEG MCUs ) // to JPEG MCUs )
fn draw(&mut self, canvas: &mut dyn RgbCanvasEx, cache: &DrawingCache) { fn draw(&mut self, canvas: &mut dyn RgbCanvasEx, cache: &DrawingCache<'a>) {
let bounds = self.bounds(cache); let bounds = self.bounds(cache);
let clip = canvas.viewport().relative_clip(bounds).clip; let clip = canvas.viewport().relative_clip(bounds).clip;
@ -103,7 +103,7 @@ impl Shape for JpegImage {
}*/ }*/
// This is a little bit slower implementation suitable for ProgressiveRenderer // This is a little bit slower implementation suitable for ProgressiveRenderer
fn draw(&mut self, canvas: &mut dyn Canvas, cache: &DrawingCache) { fn draw(&mut self, canvas: &mut dyn Canvas, cache: &DrawingCache<'a>) {
let bounds = self.bounds(cache); let bounds = self.bounds(cache);
let clip = canvas.viewport().relative_clip(bounds).clip; let clip = canvas.viewport().relative_clip(bounds).clip;
@ -188,8 +188,8 @@ impl Shape for JpegImage {
} }
} }
impl ShapeClone for JpegImage { impl<'a> ShapeClone<'a> for JpegImage<'a> {
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape> fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape<'a>>
where where
T: LocalAllocLeakExt<'alloc>, T: LocalAllocLeakExt<'alloc>,
{ {

View File

@ -8,9 +8,9 @@ use crate::ui::{
use static_alloc::Bump; use static_alloc::Bump;
pub fn render_on_display<F>(clip: Option<Rect>, bg_color: Option<Color>, mut func: F) pub fn render_on_display<'a, F>(clip: Option<Rect>, bg_color: Option<Color>, func: F)
where where
F: FnMut(&mut DirectRenderer<Mono8Canvas>), F: FnOnce(&mut DirectRenderer<'_, 'a, Mono8Canvas<'a>>),
{ {
// TODO: do not use constants 128 & 64 directly // TODO: do not use constants 128 & 64 directly
@ -22,6 +22,8 @@ where
let bump = unsafe { &mut *core::ptr::addr_of_mut!(BUMP) }; let bump = unsafe { &mut *core::ptr::addr_of_mut!(BUMP) };
{ {
bump.reset();
let cache = DrawingCache::new(bump, bump); let cache = DrawingCache::new(bump, bump);
let mut canvas = unwrap!(Mono8Canvas::new(Offset::new(128, 64), None, fb)); let mut canvas = unwrap!(Mono8Canvas::new(Offset::new(128, 64), None, fb));
@ -35,7 +37,6 @@ where
refresh_display(&canvas); refresh_display(&canvas);
} }
bump.reset();
} }
fn refresh_display(canvas: &Mono8Canvas) { fn refresh_display(canvas: &Mono8Canvas) {

View File

@ -9,9 +9,9 @@ use crate::trezorhal::bitmap::{BitmapView, Dma2d};
use static_alloc::Bump; use static_alloc::Bump;
pub fn render_on_display<F>(clip: Option<Rect>, bg_color: Option<Color>, mut func: F) pub fn render_on_display<'a, F>(clip: Option<Rect>, bg_color: Option<Color>, func: F)
where where
F: FnMut(&mut ProgressiveRenderer<Bump<[u8; 40 * 1024]>, DisplayModelT>), F: FnOnce(&mut ProgressiveRenderer<'_, 'a, Bump<[u8; 40 * 1024]>, DisplayModelT>),
{ {
#[link_section = ".no_dma_buffers"] #[link_section = ".no_dma_buffers"]
static mut BUMP_A: Bump<[u8; 40 * 1024]> = Bump::uninit(); static mut BUMP_A: Bump<[u8; 40 * 1024]> = Bump::uninit();
@ -22,6 +22,9 @@ where
let bump_a = unsafe { &mut *core::ptr::addr_of_mut!(BUMP_A) }; let bump_a = unsafe { &mut *core::ptr::addr_of_mut!(BUMP_A) };
let bump_b = unsafe { &mut *core::ptr::addr_of_mut!(BUMP_B) }; let bump_b = unsafe { &mut *core::ptr::addr_of_mut!(BUMP_B) };
{ {
bump_a.reset();
bump_b.reset();
let cache = DrawingCache::new(bump_a, bump_b); let cache = DrawingCache::new(bump_a, bump_b);
let mut canvas = DisplayModelT::acquire().unwrap(); let mut canvas = DisplayModelT::acquire().unwrap();
@ -35,8 +38,6 @@ where
target.render(16); target.render(16);
} }
bump_a.reset();
bump_b.reset();
} }
pub struct DisplayModelT { pub struct DisplayModelT {

View File

@ -83,7 +83,7 @@ impl QrImage {
} }
} }
pub fn render(self, renderer: &mut impl Renderer) { pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) {
renderer.render_shape(self); renderer.render_shape(self);
} }
@ -107,7 +107,7 @@ impl QrImage {
} }
} }
impl Shape for QrImage { impl Shape<'_> for QrImage {
fn bounds(&self, _cache: &DrawingCache) -> Rect { fn bounds(&self, _cache: &DrawingCache) -> Rect {
self.area self.area
} }
@ -157,8 +157,8 @@ impl Shape for QrImage {
} }
} }
impl ShapeClone for QrImage { impl<'s> ShapeClone<'s> for QrImage {
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape> fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape<'s>>
where where
T: LocalAllocLeakExt<'alloc>, T: LocalAllocLeakExt<'alloc>,
{ {

View File

@ -14,7 +14,7 @@ use without_alloc::{alloc::LocalAllocLeakExt, FixedVec};
/// All renders must implement Renderer trait /// All renders must implement Renderer trait
/// Renderers can immediately use the draw() method of the passed shape or /// Renderers can immediately use the draw() method of the passed shape or
/// may store it (using the boxed() method) and draw it later /// may store it (using the boxed() method) and draw it later
pub trait Renderer { pub trait Renderer<'a> {
fn viewport(&self) -> Viewport; fn viewport(&self) -> Viewport;
fn set_viewport(&mut self, viewport: Viewport); fn set_viewport(&mut self, viewport: Viewport);
@ -33,7 +33,7 @@ pub trait Renderer {
fn render_shape<S>(&mut self, shape: S) fn render_shape<S>(&mut self, shape: S)
where where
S: Shape + ShapeClone; S: Shape<'a> + ShapeClone<'a>;
fn in_window(&mut self, r: Rect, inner: &dyn Fn(&mut Self)) { fn in_window(&mut self, r: Rect, inner: &dyn Fn(&mut Self)) {
let original = self.set_window(r); let original = self.set_window(r);
@ -60,13 +60,13 @@ pub trait Renderer {
// ========================================================================== // ==========================================================================
/// A simple implementation of a Renderer that draws directly onto the CanvasEx /// A simple implementation of a Renderer that draws directly onto the CanvasEx
pub struct DirectRenderer<'a, 'alloc: 'a, C> pub struct DirectRenderer<'a, 'alloc, C>
where where
C: Canvas, C: Canvas,
{ {
/// Target canvas /// Target canvas
canvas: &'a mut C, canvas: &'a mut C,
/// Drawing che (decompression cache, scratch-pad memory) /// Drawing cache (decompression context, scratch-pad memory)
cache: &'a DrawingCache<'alloc>, cache: &'a DrawingCache<'alloc>,
} }
@ -91,7 +91,7 @@ where
} }
} }
impl<'a, 'alloc, C> Renderer for DirectRenderer<'a, 'alloc, C> impl<'a, 'alloc, C> Renderer<'alloc> for DirectRenderer<'a, 'alloc, C>
where where
C: Canvas, C: Canvas,
{ {
@ -105,7 +105,7 @@ where
fn render_shape<S>(&mut self, mut shape: S) fn render_shape<S>(&mut self, mut shape: S)
where where
S: Shape + ShapeClone, S: Shape<'alloc> + ShapeClone<'alloc>,
{ {
if self.canvas.viewport().contains(shape.bounds(self.cache)) { if self.canvas.viewport().contains(shape.bounds(self.cache)) {
shape.draw(self.canvas, self.cache); shape.draw(self.canvas, self.cache);
@ -119,13 +119,14 @@ where
// ========================================================================== // ==========================================================================
struct ShapeHolder<'a> { struct ShapeHolder<'a> {
shape: &'a mut dyn Shape, shape: &'a mut dyn Shape<'a>,
viewport: Viewport, viewport: Viewport,
} }
/// A more advanced Renderer implementation that supports deferred rendering. /// A more advanced Renderer implementation that supports deferred rendering.
pub struct ProgressiveRenderer<'a, 'alloc, T: LocalAllocLeakExt<'alloc>, C> pub struct ProgressiveRenderer<'a, 'alloc, T, C>
where where
T: LocalAllocLeakExt<'alloc>,
C: BasicCanvas, C: BasicCanvas,
{ {
/// Target canvas /// Target canvas
@ -138,7 +139,7 @@ where
viewport: Viewport, viewport: Viewport,
// Default background color // Default background color
bg_color: Option<Color>, bg_color: Option<Color>,
/// Drawing cache (decompression cache, scratch-pad memory) /// Drawing cache (decompression context, scratch-pad memory)
cache: &'a DrawingCache<'alloc>, cache: &'a DrawingCache<'alloc>,
} }
@ -218,7 +219,7 @@ where
} }
} }
impl<'a, 'alloc, T, C> Renderer for ProgressiveRenderer<'a, 'alloc, T, C> impl<'a, 'alloc, T, C> Renderer<'alloc> for ProgressiveRenderer<'a, 'alloc, T, C>
where where
T: LocalAllocLeakExt<'alloc>, T: LocalAllocLeakExt<'alloc>,
C: BasicCanvas, C: BasicCanvas,
@ -233,7 +234,7 @@ where
fn render_shape<S>(&mut self, shape: S) fn render_shape<S>(&mut self, shape: S)
where where
S: Shape + ShapeClone, S: Shape<'alloc> + ShapeClone<'alloc>,
{ {
// Is the shape visible? // Is the shape visible?
if self.viewport.contains(shape.bounds(self.cache)) { if self.viewport.contains(shape.bounds(self.cache)) {

View File

@ -47,7 +47,7 @@ impl<'a> Text<'a> {
Self { align, ..self } Self { align, ..self }
} }
pub fn render(self, renderer: &mut impl Renderer) { pub fn render<'r>(self, renderer: &mut impl Renderer<'r>) {
renderer.render_shape(self); renderer.render_shape(self);
} }
@ -63,7 +63,7 @@ impl<'a> Text<'a> {
} }
} }
impl<'a> Shape for Text<'a> { impl<'a> Shape<'_> for Text<'a> {
fn bounds(&self, _cache: &DrawingCache) -> Rect { fn bounds(&self, _cache: &DrawingCache) -> Rect {
let pos = self.aligned_pos(); let pos = self.aligned_pos();
let max_ascent = self.font.text_max_height() - self.font.text_baseline(); let max_ascent = self.font.text_max_height() - self.font.text_baseline();
@ -105,8 +105,8 @@ impl<'a> Shape for Text<'a> {
} }
} }
impl<'a> ShapeClone for Text<'a> { impl<'a, 's> ShapeClone<'s> for Text<'a> {
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape> fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape<'s>>
where where
T: LocalAllocLeakExt<'alloc>, T: LocalAllocLeakExt<'alloc>,
{ {

View File

@ -9,21 +9,21 @@ use super::{DrawingCache, Renderer, Shape, ShapeClone};
use without_alloc::alloc::LocalAllocLeakExt; use without_alloc::alloc::LocalAllocLeakExt;
/// A shape for rendering compressed TOIF images. /// A shape for rendering compressed TOIF images.
pub struct ToifImage { pub struct ToifImage<'a> {
/// Image position /// Image position
pos: Point, pos: Point,
// Image position alignment // Image position alignment
align: Alignment2D, align: Alignment2D,
// Image data // Image data
toif: Toif<'static>, toif: Toif<'a>,
// Foreground color // Foreground color
fg_color: Color, fg_color: Color,
// Optional background color // Optional background color
bg_color: Option<Color>, bg_color: Option<Color>,
} }
impl ToifImage { impl<'a> ToifImage<'a> {
pub fn new(pos: Point, toif: Toif<'static>) -> Self { pub fn new(pos: Point, toif: Toif<'a>) -> Self {
Self { Self {
pos, pos,
align: Alignment2D::TOP_LEFT, align: Alignment2D::TOP_LEFT,
@ -48,11 +48,11 @@ impl ToifImage {
} }
} }
pub fn render(self, renderer: &mut impl Renderer) { pub fn render(self, renderer: &mut impl Renderer<'a>) {
renderer.render_shape(self); renderer.render_shape(self);
} }
fn draw_grayscale(&self, canvas: &mut dyn Canvas, cache: &DrawingCache) { fn draw_grayscale(&self, canvas: &mut dyn Canvas, cache: &DrawingCache<'a>) {
// TODO: introduce new viewport/shape function for this calculation // TODO: introduce new viewport/shape function for this calculation
let bounds = self.bounds(cache); let bounds = self.bounds(cache);
let viewport = canvas.viewport(); let viewport = canvas.viewport();
@ -100,7 +100,7 @@ impl ToifImage {
} }
} }
fn draw_rgb(&self, canvas: &mut dyn Canvas, cache: &DrawingCache) { fn draw_rgb(&self, canvas: &mut dyn Canvas, cache: &DrawingCache<'a>) {
// TODO: introduce new viewport/shape function for this calculation // TODO: introduce new viewport/shape function for this calculation
let bounds = self.bounds(cache); let bounds = self.bounds(cache);
let viewport = canvas.viewport(); let viewport = canvas.viewport();
@ -145,17 +145,17 @@ impl ToifImage {
} }
} }
impl Shape for ToifImage { impl<'a> Shape<'a> for ToifImage<'a> {
fn bounds(&self, _cache: &DrawingCache) -> Rect { fn bounds(&self, _cache: &DrawingCache<'a>) -> Rect {
let size = Offset::new(self.toif.width(), self.toif.height()); let size = Offset::new(self.toif.width(), self.toif.height());
Rect::from_top_left_and_size(size.snap(self.pos, self.align), size) Rect::from_top_left_and_size(size.snap(self.pos, self.align), size)
} }
fn cleanup(&mut self, _cache: &DrawingCache) { fn cleanup(&mut self, _cache: &DrawingCache<'a>) {
// TODO: inform the cache that we won't use the zlib slot anymore // TODO: inform the cache that we won't use the zlib slot anymore
} }
fn draw(&mut self, canvas: &mut dyn Canvas, cache: &DrawingCache) { fn draw(&mut self, canvas: &mut dyn Canvas, cache: &DrawingCache<'a>) {
if self.toif.is_grayscale() { if self.toif.is_grayscale() {
self.draw_grayscale(canvas, cache); self.draw_grayscale(canvas, cache);
} else { } else {
@ -164,8 +164,8 @@ impl Shape for ToifImage {
} }
} }
impl ShapeClone for ToifImage { impl<'a> ShapeClone<'a> for ToifImage<'a> {
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape> fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape<'a>>
where where
T: LocalAllocLeakExt<'alloc>, T: LocalAllocLeakExt<'alloc>,
{ {