From 42042ec50210573ecd9a447c30d13aacf1cf6f0c Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sun, 6 Jul 2025 20:42:21 +0200 Subject: [PATCH] cache rendered chars --- Cargo.lock | 4 +--- Cargo.toml | 8 +++++--- src/command_executor.rs | 31 +++++++++++++++++++------------ src/font_renderer.rs | 28 +++++++++++++++++++--------- src/gui.rs | 3 ++- 5 files changed, 46 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f3bdf1e..3ab7490 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1521,9 +1521,7 @@ dependencies = [ [[package]] name = "servicepoint" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d1e88713031e003dc3ee708dbb282e36714eee466a12d311d0e2e24c61c7118" +version = "0.16.0" dependencies = [ "bitvec", "bzip2", diff --git a/Cargo.toml b/Cargo.toml index 9dff976..bb37e66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,9 +19,6 @@ env_logger = "0.11" clap = { version = "4.5", features = ["derive"] } thiserror = "2.0" -# package parsing -servicepoint = { features = ["all_compressions"], version = "0.15.2" } - # font rendering font-kit = "0.14.2" # I should not need this as a direct dependency, but then I cannot spell the types needed to use font-kit... @@ -32,6 +29,11 @@ winit = "0.30" # for drawing pixels onto the surface of the window softbuffer = "0.4.6" +[dependencies.servicepoint] +version = "0.16.0" +features = ["all_compressions"] +path = "../servicepoint-uniffi3" + [profile.release] lto = true # Enable link-time optimization codegen-units = 1 # Reduce number of codegen units to increase optimizations diff --git a/src/command_executor.rs b/src/command_executor.rs index f24a5fe..69ae30c 100644 --- a/src/command_executor.rs +++ b/src/command_executor.rs @@ -5,10 +5,11 @@ use crate::{ }; use log::{debug, error, info, trace, warn}; use servicepoint::{ - BinaryOperation, BitVecCommand, Bitmap, BitmapCommand, GlobalBrightnessCommand, - BrightnessGrid, BrightnessGridCommand, CharGridCommand, ClearCommand, - CompressionCode, Cp437GridCommand, FadeOutCommand, Grid, HardResetCommand, - Origin, TypedCommand, PIXEL_COUNT, PIXEL_WIDTH, TILE_SIZE, + BinaryOperation, BitVecCommand, Bitmap, BitmapCommand, BrightnessGrid, + BrightnessGridCommand, CharGridCommand, ClearCommand, CompressionCode, + Cp437GridCommand, FadeOutCommand, GlobalBrightnessCommand, + HardResetCommand, Origin, TypedCommand, PIXEL_COUNT, PIXEL_WIDTH, + TILE_SIZE, }; use std::{ ops::{BitAnd, BitOr, BitXor}, @@ -46,11 +47,11 @@ impl CommandExecute for BitmapCommand { fn execute(&self, context: &CommandExecutionContext) -> ExecutionResult { let Self { origin: - Origin { - x: offset_x, - y: offset_y, - .. - }, + Origin { + x: offset_x, + y: offset_y, + .. + }, bitmap: pixels, .. } = self; @@ -143,7 +144,7 @@ impl CommandExecute for Cp437GridCommand { bitmap: context.cp437_font[char_code].clone(), compression: CompressionCode::default(), } - .execute(context); + .execute(context); match execute_result { Success => {} Failure => { @@ -199,8 +200,14 @@ impl CommandExecute for CharGridCommand { if let Err(e) = context.font_renderer.render( char, - &mut display, - Origin::new(tile_x * TILE_SIZE, tile_y * TILE_SIZE), + &mut display + .window_mut( + tile_x * TILE_SIZE, + tile_y * TILE_SIZE, + TILE_SIZE, + TILE_SIZE, + ) + .unwrap(), ) { error!( "stopping drawing text because char draw failed: {e}" diff --git a/src/font_renderer.rs b/src/font_renderer.rs index d9f5fd7..efe243f 100644 --- a/src/font_renderer.rs +++ b/src/font_renderer.rs @@ -12,8 +12,11 @@ use pathfinder_geometry::{ transform2d::Transform2F, vector::{vec2f, vec2i}, }; -use servicepoint::{Bitmap, Grid, Origin, Pixels, TILE_SIZE}; -use std::sync::{Mutex, MutexGuard}; +use servicepoint::{Bitmap, GridMut, WindowMut, TILE_SIZE}; +use std::{ + collections::HashMap, + sync::{Mutex, MutexGuard}, +}; #[derive(Debug)] struct SendFont(Font); @@ -32,6 +35,7 @@ pub struct FontRenderer8x8 { font: SendFont, canvas: Mutex, fallback_char: Option, + cache: Mutex>, } #[derive(Debug, thiserror::Error)] @@ -56,6 +60,7 @@ impl FontRenderer8x8 { font: SendFont(font), fallback_char, canvas: Mutex::new(canvas), + cache: Mutex::new(HashMap::new()), } } @@ -74,9 +79,13 @@ impl FontRenderer8x8 { pub fn render( &self, char: char, - bitmap: &mut Bitmap, - offset: Origin, + target: &mut WindowMut, ) -> Result<(), RenderError> { + let cache = &mut *self.cache.lock().unwrap(); + if let Some(drawn_char) = cache.get(&char) { + target.deref_assign(drawn_char); + } + let glyph_id = self.get_glyph(char)?; let mut canvas = self.canvas.lock().unwrap(); @@ -91,20 +100,21 @@ impl FontRenderer8x8 { RasterizationOptions::Bilevel, )?; - Self::copy_to_bitmap(canvas, bitmap, offset) + let mut bitmap = Bitmap::new(TILE_SIZE, TILE_SIZE).unwrap(); + Self::copy_to_bitmap(canvas, &mut bitmap)?; + target.deref_assign(&bitmap); + cache.insert(char, bitmap); + Ok(()) } fn copy_to_bitmap( canvas: MutexGuard, bitmap: &mut Bitmap, - offset: Origin, ) -> Result<(), RenderError> { for y in 0..TILE_SIZE { for x in 0..TILE_SIZE { let canvas_val = canvas.pixels[x + y * TILE_SIZE] != 0; - let bitmap_x = offset.x + x; - let bitmap_y = offset.y + y; - if !bitmap.set_optional(bitmap_x, bitmap_y, canvas_val) { + if !bitmap.set_optional(x, y, canvas_val) { return Err(OutOfBounds(x, y)); } } diff --git a/src/gui.rs b/src/gui.rs index e5f08d4..ad3fa26 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -24,6 +24,7 @@ const PIXEL_HEIGHT_WITH_SPACERS: usize = PIXEL_HEIGHT + NUM_SPACERS * SPACER_HEIGHT; const OFF_COLOR: u32 = u32::from_ne_bytes([0u8, 0, 0, 0]); +const SPACER_COLOR: u32 = u32::from_ne_bytes([100u8, 100, 100, 0]); #[derive(Debug)] pub enum AppEvents { @@ -61,7 +62,7 @@ impl<'t> Gui<'t> { if self.options.spacers && tile_y != 0 { // cannot just frame.skip(PIXEL_WIDTH as usize * SPACER_HEIGHT as usize) because of typing for _ in 0..PIXEL_WIDTH * SPACER_HEIGHT { - frame.next().unwrap(); + *frame.next().unwrap() = SPACER_COLOR; } }