mirror of
https://codeberg.org/Fl1tzi/microdeck.git
synced 2024-05-07 22:20:49 +00:00
implement text color in image rendering, implement wrapping of text, print runtime errors on device
This commit is contained in:
parent
4536e0a8cd
commit
1f1c388eb3
|
@ -46,6 +46,7 @@ pub struct ImageBuilder {
|
|||
scale: f32,
|
||||
font_size: f32,
|
||||
text: Option<String>,
|
||||
text_color: [u8; 3],
|
||||
image: Option<DynamicImage>,
|
||||
}
|
||||
|
||||
|
@ -59,6 +60,8 @@ impl Default for ImageBuilder {
|
|||
scale: 60.0,
|
||||
font_size: 16.0,
|
||||
text: None,
|
||||
// black
|
||||
text_color: [255, 255, 255],
|
||||
image: None,
|
||||
}
|
||||
}
|
||||
|
@ -92,6 +95,12 @@ impl ImageBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn set_text_color(mut self, text_color: [u8; 3]) -> Self {
|
||||
self.text_color = text_color;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn set_image(mut self, image: DynamicImage) -> Self {
|
||||
self.image = Some(image);
|
||||
|
@ -108,6 +117,7 @@ impl ImageBuilder {
|
|||
image: self.image.unwrap(),
|
||||
scale: self.scale,
|
||||
font_size: self.font_size,
|
||||
text_color: self.text_color,
|
||||
text: self.text.unwrap(),
|
||||
};
|
||||
return c.render();
|
||||
|
@ -116,6 +126,7 @@ impl ImageBuilder {
|
|||
height: self.height,
|
||||
width: self.width,
|
||||
font_size: self.font_size,
|
||||
text_color: self.text_color,
|
||||
text,
|
||||
};
|
||||
return c.render();
|
||||
|
@ -170,6 +181,7 @@ struct TextComponent {
|
|||
height: usize,
|
||||
width: usize,
|
||||
font_size: f32,
|
||||
text_color: [u8; 3],
|
||||
text: String,
|
||||
}
|
||||
|
||||
|
@ -177,27 +189,10 @@ impl Component for TextComponent {
|
|||
fn render(&self) -> DynamicImage {
|
||||
let mut image = RgbImage::new(self.width as u32, self.height as u32);
|
||||
|
||||
let scale = Scale::uniform(self.font_size);
|
||||
let font = &GLOBAL_FONT.get().unwrap();
|
||||
let font_scale = Scale::uniform(self.font_size);
|
||||
let text = wrap_text(self.height as u32, font_scale, &self.text);
|
||||
|
||||
let v_metrics = font.v_metrics(scale);
|
||||
let height = (v_metrics.ascent - v_metrics.descent + v_metrics.line_gap).round() as i32;
|
||||
|
||||
// start at y = 10
|
||||
let mut y_pos = 10;
|
||||
|
||||
for line in self.text.split("\n") {
|
||||
draw_text_mut(
|
||||
&mut image,
|
||||
Rgb([255, 255, 255]),
|
||||
10,
|
||||
y_pos,
|
||||
scale,
|
||||
&GLOBAL_FONT.get().unwrap(),
|
||||
&line,
|
||||
);
|
||||
y_pos += height;
|
||||
}
|
||||
draw_text_on_image(&text, &mut image, Rgb(self.text_color), font_scale);
|
||||
|
||||
image::DynamicImage::ImageRgb8(image)
|
||||
}
|
||||
|
@ -210,6 +205,7 @@ struct ImageTextComponent {
|
|||
image: DynamicImage,
|
||||
scale: f32,
|
||||
font_size: f32,
|
||||
text_color: [u8; 3],
|
||||
text: String,
|
||||
}
|
||||
|
||||
|
@ -224,19 +220,9 @@ impl Component for ImageTextComponent {
|
|||
|
||||
let mut base_image = RgbImage::new(self.height as u32, self.width as u32);
|
||||
|
||||
let font = &GLOBAL_FONT.get().unwrap();
|
||||
let font_scale = Scale::uniform(self.font_size);
|
||||
|
||||
// TODO: allow new line
|
||||
draw_text_mut(
|
||||
&mut base_image,
|
||||
Rgb([255, 255, 255]),
|
||||
0,
|
||||
0,
|
||||
font_scale,
|
||||
font,
|
||||
&self.text,
|
||||
);
|
||||
let text = wrap_text(self.height as u32, font_scale, &self.text);
|
||||
draw_text_on_image(&text, &mut base_image, Rgb(self.text_color), font_scale);
|
||||
// position at the middle
|
||||
let free_space = self.width - image.width() as usize;
|
||||
// TODO: allow padding to be manually set
|
||||
|
@ -250,3 +236,37 @@ impl Component for ImageTextComponent {
|
|||
image::DynamicImage::ImageRgb8(base_image)
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_text_on_image(text: &String, image: &mut RgbImage, color: Rgb<u8>, font_scale: Scale) {
|
||||
let font = &GLOBAL_FONT.get().unwrap();
|
||||
let v_metrics = font.v_metrics(font_scale);
|
||||
|
||||
let line_height = (v_metrics.ascent - v_metrics.descent + v_metrics.line_gap).round() as i32;
|
||||
let mut y_pos = 0;
|
||||
|
||||
for line in text.split('\n') {
|
||||
draw_text_mut(image, color, 0, y_pos, font_scale, font, &line);
|
||||
y_pos += line_height
|
||||
}
|
||||
}
|
||||
|
||||
/// This functions adds '\n' to the line endings. It does not wrap
|
||||
/// words but characters.
|
||||
pub fn wrap_text(max_width: u32, font_size: Scale, text: &String) -> String {
|
||||
let font = &GLOBAL_FONT.get().unwrap();
|
||||
|
||||
let mut new_text: Vec<char> = Vec::new();
|
||||
let mut line_size = 0.0;
|
||||
|
||||
for character in text.chars() {
|
||||
let h_size = font.glyph(character).scaled(font_size).h_metrics();
|
||||
let complete_width = h_size.advance_width + h_size.left_side_bearing;
|
||||
if (line_size + complete_width) as u32 > max_width {
|
||||
new_text.push('\n');
|
||||
line_size = 0.0;
|
||||
}
|
||||
new_text.push(character);
|
||||
line_size += h_size.advance_width + h_size.left_side_bearing;
|
||||
}
|
||||
String::from_iter(new_text)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use self::space::Space;
|
|||
// other things
|
||||
use crate::config::{Button, ButtonConfigError};
|
||||
use crate::device::ImageCache;
|
||||
use crate::image_rendering::load_image;
|
||||
use crate::image_rendering::{load_image, ImageBuilder};
|
||||
use ::image::imageops::FilterType;
|
||||
use ::image::DynamicImage;
|
||||
use async_trait::async_trait;
|
||||
|
@ -91,13 +91,13 @@ pub async fn start_module(
|
|||
button.index,
|
||||
device.kind().key_image_format().size,
|
||||
);
|
||||
let da = DeviceAccess::new(device, button.index).await;
|
||||
let da = DeviceAccess::new(device.clone(), button.index).await;
|
||||
|
||||
// init
|
||||
//
|
||||
// This function should be called after the config was checked,
|
||||
// otherwise it will panic and the module wont be started.
|
||||
let mut module = match module_init_function(button, mc).await {
|
||||
let mut module = match module_init_function(button.clone(), mc).await {
|
||||
Ok(m) => m,
|
||||
Err(e) => panic!("{}", e),
|
||||
};
|
||||
|
@ -105,7 +105,19 @@ pub async fn start_module(
|
|||
// then run module
|
||||
match module.run(da, br).await {
|
||||
Ok(_) => debug!("RETURNED"),
|
||||
Err(e) => error!("RETURNED_ERROR: {}", e),
|
||||
// TODO: maybe find calculation for font size
|
||||
// print error on display
|
||||
Err(e) => {
|
||||
error!("{e}");
|
||||
let da = DeviceAccess::new(device, button.index).await;
|
||||
let res = da.resolution();
|
||||
let image = ImageBuilder::new(res.0, res.1)
|
||||
.set_text(format!("E: {}", e))
|
||||
.set_font_size(12.0)
|
||||
.set_text_color([255, 0, 0])
|
||||
.build();
|
||||
da.write_img(image).await.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,8 +248,6 @@ pub trait Module: Sync + Send {
|
|||
Self: Sized;
|
||||
/// Function for actually running the module and interacting with the device. Errors that
|
||||
/// happen here should be mostly prevented.
|
||||
///
|
||||
/// TODO: The return error is not sent anywhere and is just a panic
|
||||
async fn run(
|
||||
&mut self,
|
||||
device: DeviceAccess,
|
||||
|
|
|
@ -7,6 +7,7 @@ use super::{
|
|||
ReturnError,
|
||||
};
|
||||
|
||||
use crate::image_rendering::wrap_text;
|
||||
use crate::GLOBAL_FONT;
|
||||
use image::{DynamicImage, Rgb, RgbImage};
|
||||
use imageproc::drawing::draw_text_mut;
|
||||
|
@ -96,18 +97,19 @@ fn render_text(
|
|||
|
||||
let scale = Scale::uniform(title_size);
|
||||
let font = &GLOBAL_FONT.get().unwrap();
|
||||
|
||||
let v_metrics = font.v_metrics(scale);
|
||||
let height = (v_metrics.ascent - v_metrics.descent + v_metrics.line_gap).round() as i32;
|
||||
|
||||
// start at y = 10
|
||||
let mut y_pos = 10;
|
||||
let text = wrap_text(image.width(), scale, &title);
|
||||
|
||||
for line in title.split("\n") {
|
||||
// start at y = 0
|
||||
let mut y_pos = 0;
|
||||
|
||||
for line in text.split("\n") {
|
||||
draw_text_mut(
|
||||
&mut image,
|
||||
Rgb([255, 255, 255]),
|
||||
10,
|
||||
0,
|
||||
y_pos,
|
||||
Scale::uniform(title_size),
|
||||
&GLOBAL_FONT.get().unwrap(),
|
||||
|
@ -119,7 +121,7 @@ fn render_text(
|
|||
draw_text_mut(
|
||||
&mut image,
|
||||
Rgb([255, 255, 255]),
|
||||
10,
|
||||
0,
|
||||
y_pos,
|
||||
Scale::uniform(number_size),
|
||||
&GLOBAL_FONT.get().unwrap(),
|
||||
|
|
Loading…
Reference in a new issue