v1.2.1: text measuring support

several malvim features added, font data caching, taskbar title overflow fix, new background
This commit is contained in:
stjet
2025-09-06 06:23:57 +00:00
parent 08c2358bdc
commit 10daa9982b
12 changed files with 219 additions and 80 deletions

View File

@@ -6,6 +6,7 @@ use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLik
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest, ShortcutType, InfoType, WindowsVec };
use ming_wm_lib::framebuffer_types::Dimensions;
use ming_wm_lib::themes::ThemeInfo;
use ming_wm_lib::fonts::measure_text;
use ming_wm_lib::components::Component;
use ming_wm_lib::components::toggle_button::ToggleButton;
@@ -78,7 +79,25 @@ impl WindowLike for Taskbar {
break;
}
let info = &self.windows_in_workspace[wi];
let name = &info.1;
let max_text_width = META_WIDTH - PADDING * 2;
//horiz_spacing is by default 1 per char, which measure_text doesn't take into account
let to_measure = info.1.clone();
let to_measure_len = to_measure.chars().count();
let name = if measure_text(&["nimbus-roman".to_string()], to_measure).width + to_measure_len > max_text_width {
let mut current = String::new();
for c in info.1.chars() {
//horiz_spacing is 1 by default
let to_measure = current.clone() + &c.to_string() + "...";
let to_measure_len = to_measure.chars().count();
if measure_text(&["nimbus-roman".to_string()], to_measure).width + to_measure_len > max_text_width {
break;
}
current += &c.to_string();
}
current + "..."
} else {
info.1.clone()
};
let mut b = ToggleButton::new(name.to_string() + "-window", [PADDING * 2 + 44 + (META_WIDTH + PADDING) * wi, PADDING], [META_WIDTH, self.dimensions[1] - (PADDING * 2)], name.to_string(), TaskbarMessage::Nothing, TaskbarMessage::Nothing);
b.inverted = info.0 == self.focused_id;
instructions.extend(b.draw(theme_info));
@@ -123,5 +142,3 @@ impl Taskbar {
}
}
}

View File

@@ -4,9 +4,7 @@ use std::vec::Vec;
use bmp_rust::bmp::BMP;
use ming_wm_lib::framebuffer_types::*;
use crate::fs::get_font_char_from_fonts;
type FontChar = (char, Vec<Vec<u8>>, u8);
use ming_wm_lib::fonts::{ CachedFontCharGetter, FontCharInfo };
fn color_with_alpha(color: RGBColor, bg_color: RGBColor, alpha: u8) -> RGBColor {
/*let factor: f32 = alpha as f32 / 255.0;
@@ -47,6 +45,7 @@ pub struct FramebufferInfo {
//currently doesn't check if writing onto next line accidentally
pub struct FramebufferWriter {
info: FramebufferInfo,
fc_getter: CachedFontCharGetter,
buffer: Vec<u8>,
saved_buffer: Option<Vec<u8>>,
rotate_buffer: Option<Vec<u8>>,
@@ -57,6 +56,7 @@ impl FramebufferWriter {
pub fn new(grayscale: bool) -> Self {
Self {
info: Default::default(),
fc_getter: CachedFontCharGetter::new(128), //an arbitrary high-ish number for max cache size
buffer: Vec::new(),
saved_buffer: None,
rotate_buffer: None,
@@ -128,12 +128,11 @@ impl FramebufferWriter {
}
}
pub fn draw_char(&mut self, top_left: Point, char_info: &FontChar, color: RGBColor, bg_color: RGBColor) {
pub fn draw_char(&mut self, top_left: Point, char_info: &FontCharInfo, color: RGBColor, bg_color: RGBColor) {
let mut start_pos;
for row in 0..char_info.1.len() {
//char_info.2 is vertical offset
start_pos = ((top_left[1] + row + char_info.2 as usize) * self.info.stride + top_left[0]) * self.info.bytes_per_pixel;
for col in &char_info.1[row] {
for row in 0..char_info.height {
start_pos = ((top_left[1] + row + char_info.top_offset as usize) * self.info.stride + top_left[0]) * self.info.bytes_per_pixel;
for col in &char_info.data[row] {
if col > &0 {
if start_pos + 3 < self.info.byte_len {
self._draw_pixel(start_pos, color_with_alpha(color, bg_color, *col));
@@ -226,8 +225,8 @@ impl FramebufferWriter {
if c == ' ' {
top_left[0] += mono_width.unwrap_or(5) as usize;
} else {
let char_info = get_font_char_from_fonts(&fonts, c);
let char_width = char_info.1[0].len();
let char_info = self.fc_getter.get(&fonts, c);
let char_width = char_info.width;
let add_after: usize;
if let Some(mono_width) = mono_width {
let mono_width = mono_width as usize;

View File

@@ -1,38 +1,9 @@
use std::fs::{ read_dir, File };
use std::io::Read;
use std::fs::read_dir;
use std::collections::HashMap;
use ming_wm_lib::dirs;
use ming_wm_lib::utils::get_rest_of_split;
fn get_font_char(dir: &str, c: char) -> Option<(char, Vec<Vec<u8>>, u8)> {
let c = if c == '/' { '𐘋' } else if c == '\\' { '𐚆' } else if c == '.' { '𐘅' } else { c };
if let Ok(mut file) = File::open(dir.to_string() + "/" + &c.to_string() + ".alpha") {
let mut ch: Vec<Vec<u8>> = Vec::new();
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
let lines: Vec<&str> = contents.split("\n").collect();
for ln in 1..lines.len() {
//.unwrap_or(0) is important because zeroes are just empty
ch.push(lines[ln].replace(":", ",,,,").replace(";", ",,,").replace(".", ",,").split(",").map(|n| n.parse().unwrap_or(0)).collect());
}
return Some((c, ch, lines[0].parse().unwrap()));
}
None
}
pub fn get_font_char_from_fonts(fonts: &[String], c: char) -> (char, Vec<Vec<u8>>, u8) {
for font in fonts {
let p = dirs::exe_dir(Some(&("ming_bmps/".to_string() + &font))).to_string_lossy().to_string();
if let Some(font_char) = get_font_char(&p, c) {
return font_char;
}
}
let p = dirs::exe_dir(Some(&("ming_bmps/".to_string() + &fonts[0]))).to_string_lossy().to_string();
//so a ? char should be in every font. otherwise will just return blank
get_font_char(&p, '?').unwrap_or(('?', vec![vec![0]], 0))
}
//Category, Vec<Display name, file name>
pub type ExeWindowInfos = HashMap<String, Vec<(String, String)>>;