From 9594f01a4d972dace5bf896a44ef943c67343da5 Mon Sep 17 00:00:00 2001 From: LongHairedHacker Date: Sun, 23 Sep 2018 21:34:23 +0200 Subject: [PATCH] First implementation of font renderer. --- src/main.rs | 1 + src/st7735/fonts.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++ src/st7735/mod.rs | 8 +++- 3 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 src/st7735/fonts.rs diff --git a/src/main.rs b/src/main.rs index ec97873..420989c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,6 +28,7 @@ mod logo; use printer::UsartPrinter; use st7735::gfx::{PrimitveGFX, GFX}; use st7735::bitmaps::BitmapGFX; +use st7735::fonts::FontRenderer; diff --git a/src/st7735/fonts.rs b/src/st7735/fonts.rs new file mode 100644 index 0000000..390abe3 --- /dev/null +++ b/src/st7735/fonts.rs @@ -0,0 +1,99 @@ +use st7735::gfx::PrimitveGFX; + +pub struct FontGlpyh { + pub bitmap_offset: usize, // Offset in glyph bitmap + pub width: u8, // Size of glyph + pub height: u8, + pub x_advance: u8, // Distance to advance along x-axis + pub x_offset: u8, // Distance to upper left coner from cursor pos + pub y_offset: u8, +} + + +pub struct Font { + pub bitmap: &'static [u8], // Glyph bitmaps, concatenated + pub glyphs: &'static [FontGlpyh], // Array of glyph metadata + pub first: u8, // Start of ASCII extend + pub last: u8, // End of ASCII extend + pub y_advance: u8, // Line height +} + + +pub trait FontRenderer: PrimitveGFX { + fn draw_glyph(&mut self, x: u8, y: u8, glyph: &FontGlpyh, font: &Font, size: u8, color: u16) { + if size == 0 { + return; + } + + // Any clipping should be done by draw_rect + + let x = x as i16; + let y = y as i16; + let size = size as i16; + + let mut bo = glyph.bitmap_offset; + let mut set_pixels: i16 = 0; + let mut bits: u8 = 0; + let mut bit: u8 = 0; + + for cur_y in 0..(glyph.height as i16) { + for cur_x in 0..(glyph.width as i16) { + if bit == 0 { + bits = font.bitmap[bo]; + bo += 1; + bit = 0x80; + } + + if bit & bits != 0 { + set_pixels += 1; + } else if set_pixels > 0 { + let start_x = (x + ((glyph.x_offset as i16) + cur_x - set_pixels) * size) as u8; + let start_y = (y + ((glyph.y_offset as i16) + cur_y) * size) as u8; + let w = (set_pixels * size) as u8; + let h = size as u8; + self.fill_rect(start_x, start_y, w, h, color); + + set_pixels = 0; + } + bit >>= 1; + } + + if set_pixels > 0 { + let start_x = (x + + ((glyph.x_offset as i16) + (glyph.width as i16) - + set_pixels) * size) as u8; + let start_y = (y + ((glyph.y_offset as i16) + cur_y) * size) as u8; + let w = (set_pixels * size) as u8; + let h = size as u8; + self.fill_rect(start_x, start_y, w, h, color); + } + } + } + + fn draw_text(&mut self, x: u8, y: u8, text: &str, font: &Font, size: u8, color: u16) { + let mut cursor_x = x; + let mut cursor_y = y; + + for text_char in text.chars() { + let c = if text_char.is_ascii() { + text_char as u8 + } + else { + '?' as u8 + }; + + if c == '\n' as u8 { + cursor_x = x; + cursor_y += font.y_advance * size; + } + else if c >= font.first && c <= font.last && c != '\r' as u8 { + let pos = (c - font.first) as usize; + let glyph = &font.glyphs[pos]; + self.draw_glyph(cursor_x, cursor_y, glyph, &font, size, color); + cursor_x += glyph.x_advance * size; + } + + } + + } +} diff --git a/src/st7735/mod.rs b/src/st7735/mod.rs index 4887744..7609e9e 100644 --- a/src/st7735/mod.rs +++ b/src/st7735/mod.rs @@ -9,6 +9,7 @@ mod commands; mod init; pub mod gfx; pub mod bitmaps; +pub mod fonts; use st7735::commands::*; @@ -591,6 +592,9 @@ impl bitmaps::BitmapGFX for St7735IO self.set_cs(); } - - } + + +impl fonts::FontRenderer for St7735IO + where SPIAddr: Location, + GPIOAddr: Location {}