v1.2.2: text measuring improvements, minor code clean

fixed some clippy warnings, ignored many that I do not care about. also, added demo video and updated koxinga image
This commit is contained in:
stjet
2025-09-28 04:39:41 +00:00
parent 10daa9982b
commit 40f6795163
24 changed files with 173 additions and 119 deletions

View File

@@ -20,9 +20,9 @@ fn get_font_char(dir: &str, c: char) -> Option<FontCharInfo> {
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() {
for ln in lines.iter().skip(1) {
//.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());
ch.push(ln.replace(":", ",,,,").replace(";", ",,,").replace(".", ",,").split(",").map(|n| n.parse().unwrap_or(0)).collect());
}
return Some(FontCharInfo {
c,
@@ -58,8 +58,7 @@ pub struct MeasureInfo {
pub width: usize,
}
/// Doesn't take into account `horiz_spacing`, which defaults to 1 per character
pub fn measure_text(fonts: &[String], text: String) -> MeasureInfo {
pub fn measure_text(fonts: &[String], text: &str, horiz_spacing: Option<usize>) -> MeasureInfo {
let mut height = 0;
let mut width = 0;
for c in text.chars() {
@@ -68,8 +67,27 @@ pub fn measure_text(fonts: &[String], text: String) -> MeasureInfo {
if c_height > height {
height = c_height;
}
width += i.width;
width += i.width + horiz_spacing.unwrap_or(1);
}
width -= horiz_spacing.unwrap_or(1);
MeasureInfo {
height,
width,
}
}
pub fn measure_text_with_cache(fc_getter: &mut CachedFontCharGetter, fonts: &[String], text: &str, horiz_spacing: Option<usize>) -> MeasureInfo {
let mut height = 0;
let mut width = 0;
for c in text.chars() {
let i = fc_getter.get(fonts, c);
let c_height = i.top_offset as usize + i.height;
if c_height > height {
height = c_height;
}
width += i.width + horiz_spacing.unwrap_or(1);
}
width -= horiz_spacing.unwrap_or(1);
MeasureInfo {
height,
width,
@@ -85,9 +103,10 @@ pub struct CachedFontCharGetter {
impl CachedFontCharGetter {
pub fn new(max_cache_size: usize) -> Self {
let mut s: Self = Default::default();
s.max_cache_size = max_cache_size;
s
Self {
max_cache_size,
..Default::default()
}
}
pub fn get(&mut self, fonts: &[String], c: char) -> FontCharInfo {

View File

@@ -44,11 +44,7 @@ pub enum WindowMessageResponse {
impl WindowMessageResponse {
pub fn is_key_char_request(&self) -> bool {
if let WindowMessageResponse::Request(WindowManagerRequest::DoKeyChar(_)) = self {
true
} else {
false
}
matches!(self, WindowMessageResponse::Request(WindowManagerRequest::DoKeyChar(_)))
}
}

View File

@@ -83,7 +83,7 @@ impl Serializable for ThemeInfo {
}
fn deserialize(serialized: &str) -> Result<Self, ()> {
//strip newline at the end
let serialized = if serialized.ends_with("\n") { &serialized[..serialized.len() - 1] } else { serialized };
let serialized = serialized.strip_suffix("\n").unwrap_or(serialized);
let mut theme_info: ThemeInfo = Default::default();
let arrays = serialized.split(":");
//won't error or panic if less than 9... rest will just be black by default I guess
@@ -162,7 +162,7 @@ impl Serializable for WindowMessageResponse {
}
fn deserialize(serialized: &str) -> Result<Self, ()> {
//strip newline at the end
let serialized = if serialized.ends_with("\n") { &serialized[..serialized.len() - 1] } else { serialized };
let serialized = serialized.strip_suffix("\n").unwrap_or(serialized);
let mut parts = serialized.split("/");
match parts.next().unwrap_or("Invalid") {
"JustRedraw" => Ok(WindowMessageResponse::JustRedraw),
@@ -444,12 +444,12 @@ impl Serializable for DrawInstructionsVec {
if self.len() == 0 {
return "empty".to_string();
}
let collected: Vec<_> = self.into_iter().map(|ins| ins.serialize()).collect();
let collected: Vec<_> = self.iter().map(|ins| ins.serialize()).collect();
collected.join("\x1D")
}
fn deserialize(serialized: &str) -> Result<Self, ()> {
//strip newline at the end
let serialized = if serialized.ends_with("\n") { &serialized[..serialized.len() - 1] } else { serialized };
let serialized = serialized.strip_suffix("\n").unwrap_or(serialized);
if serialized == "empty" {
return Ok(Vec::new());
}
@@ -504,7 +504,7 @@ impl Serializable for WindowLikeType {
}
}
fn deserialize(serialized: &str) -> Result<Self, ()> {
let serialized = if serialized.ends_with("\n") { &serialized[..serialized.len() - 1] } else { serialized };
let serialized = serialized.strip_suffix("\n").unwrap_or(serialized);
match serialized {
"LockScreen" => Ok(WindowLikeType::LockScreen),
"Window" => Ok(WindowLikeType::Window),
@@ -531,7 +531,7 @@ impl Serializable for Dimensions {
}
fn deserialize(serialized: &str) -> Result<Self, ()> {
//strip newline at the end
let serialized = if serialized.ends_with("\n") { &serialized[..serialized.len() - 1] } else { serialized };
let serialized = serialized.strip_suffix("\n").unwrap_or(serialized);
let d = get_two_array(serialized)?;
Ok(d)
}
@@ -592,7 +592,7 @@ impl Serializable for WindowMessage {
}
}
fn deserialize(serialized: &str) -> Result<Self, ()> {
let serialized = if serialized.ends_with("\n") { &serialized[..serialized.len() - 1] } else { serialized };
let serialized = serialized.strip_suffix("\n").unwrap_or(serialized);
let mut parts = serialized.split("/");
match parts.next().unwrap_or("Invalid") {
"Init" => {
@@ -716,9 +716,9 @@ impl Serializable for WindowMessage {
return Err(());
}
if let Ok(n) = arg2.unwrap().parse() {
return Ok(WindowMessage::Info(InfoType::WindowsInWorkspace(w_vec, n)));
Ok(WindowMessage::Info(InfoType::WindowsInWorkspace(w_vec, n)))
} else {
return Err(());
Err(())
}
},
"Focus" => Ok(WindowMessage::Focus),

View File

@@ -11,15 +11,17 @@ pub enum Themes {
//Parchment,
}
impl Themes {
pub fn from_str(name: &str) -> Option<Self> {
impl std::str::FromStr for Themes {
type Err = ();
fn from_str(name: &str) -> Result<Self, Self::Err> {
match name {
"Standard" => Some(Themes::Standard),
"Night" => Some(Themes::Night),
"Industrial" => Some(Themes::Industrial),
"Forest" => Some(Themes::Forest),
"Royal" => Some(Themes::Royal),
_ => None,
"Standard" => Ok(Themes::Standard),
"Night" => Ok(Themes::Night),
"Industrial" => Ok(Themes::Industrial),
"Forest" => Ok(Themes::Forest),
"Royal" => Ok(Themes::Royal),
_ => Err(()),
}
}
}

View File

@@ -1,6 +1,7 @@
use std::path::PathBuf;
use std::fs::read_dir;
use crate::fonts::measure_text;
use crate::framebuffer_types::{ Dimensions, Point };
pub fn min(one: usize, two: usize) -> usize {
@@ -96,6 +97,23 @@ pub fn calc_actual_lines<'a>(lines: impl Iterator<Item = &'a String>, max_chars_
actual_lines
}
/// truncate to ... if too long (uses `measure_text`)
pub fn trunc_words(fonts: &[String], to_measure: String, horiz_spacing: Option<usize>, max_text_width: usize) -> String {
if measure_text(fonts, &to_measure, horiz_spacing).width > max_text_width {
let mut current = String::new();
for c in to_measure.chars() {
let to_measure = current.clone() + &c.to_string() + "...";
if measure_text(fonts, &to_measure, horiz_spacing).width > max_text_width {
break;
}
current += &c.to_string();
}
current + "..."
} else {
to_measure.clone()
}
}
pub fn concat_paths(current_path: &str, add_path: &str) -> Result<PathBuf, ()> {
let mut new_path = PathBuf::from(current_path);
//if current_path is a file, automatically uses it's parent (a directory)