From 2e01665a238512beca31d7636f78c1134d74f352 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Mon, 29 Sep 2025 10:48:52 +0800 Subject: image: get system text --- Cargo.lock | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 2 ++ src/image.rs | 38 +++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eaeae7d..30a0b0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "ab_glyph" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e074464580a518d16a7126262fffaaa47af89d4099d4cb403f8ed938ba12ee7d" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -176,6 +176,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "core_maths" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" +dependencies = [ + "libm", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -314,6 +323,29 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fontconfig-parser" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" +dependencies = [ + "roxmltree", +] + +[[package]] +name = "fontdb" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser", +] + [[package]] name = "getrandom" version = "0.2.16" @@ -463,6 +495,8 @@ dependencies = [ name = "java2flowchart" version = "0.1.0" dependencies = [ + "ab_glyph", + "fontdb", "image", "imageproc", "phf", @@ -557,6 +591,15 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +[[package]] +name = "memmap2" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7" +dependencies = [ + "libc", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -986,6 +1029,12 @@ version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + [[package]] name = "rustversion" version = "1.0.22" @@ -1079,6 +1128,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + [[package]] name = "smallvec" version = "1.15.1" @@ -1149,6 +1207,21 @@ dependencies = [ "zune-jpeg", ] +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "toml" version = "0.8.23" @@ -1188,6 +1261,9 @@ name = "ttf-parser" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" +dependencies = [ + "core_maths", +] [[package]] name = "typenum" @@ -1218,6 +1294,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 5613b7a..7880576 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,8 @@ version = "0.1.0" edition = "2024" [dependencies] +ab_glyph = "0.2.32" +fontdb = "0.23.0" image = "0.25.8" imageproc = "0.25.0" phf = { version = "0.13.1", features = ["macros"] } diff --git a/src/image.rs b/src/image.rs index cd76950..d642d32 100644 --- a/src/image.rs +++ b/src/image.rs @@ -1,7 +1,10 @@ +use ab_glyph::FontArc; +use fontdb::{Database, Family, Query, Source}; use image::{ColorType, DynamicImage, ImageBuffer, imageops}; use imageproc::drawing::{Canvas, draw_filled_rect_mut, draw_polygon_mut}; use imageproc::point::Point; use imageproc::rect::Rect; +use std::io; use std::path::Path; use crate::ast::DepthExpr; @@ -49,6 +52,41 @@ mod colors { ]); } +// TODO: store as singleton +fn get_font() -> Result { + let mut db = Database::new(); + db.load_system_fonts(); + + let id = db + .query(&Query { + families: &[Family::SansSerif], + weight: fontdb::Weight::NORMAL, + stretch: fontdb::Stretch::Normal, + style: fontdb::Style::Normal, + }) + .or_else(|| { + db.faces() + .next() + .map(|f| f.id) + }) + .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "no system fonts"))?; + + let face = db + .face(id) + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "face missing"))?; + + match &face.source { + Source::File(path) => std::fs::read(path).and_then(|bytes| FontArc::try_from_vec(bytes).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "parse font failed"))), + Source::Binary(data) => FontArc::try_from_vec( + data.as_ref() + .as_ref() + .to_vec(), + ) + .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "parse font failed")), + _ => Err(io::Error::new(io::ErrorKind::Unsupported, "unsupported font source")), + } +} + fn ext(img: &mut DynamicImage, (curw, curh): &mut Offset, (extw, exth): &mut Offset) { let (w, h) = img.dimensions(); let extedw = *extw + *curw; -- cgit v1.2.3 From efc16196a470e856c8653aeaac3811988c86570d Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Mon, 29 Sep 2025 10:49:12 +0800 Subject: gitignore: *.png --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ea8c4bf..b76f169 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +*.png -- cgit v1.2.3 From 6182dcbe248f5ceb95817317237ff828a8ac61e0 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Mon, 29 Sep 2025 11:18:22 +0800 Subject: image: draw text --- src/image.rs | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/image.rs b/src/image.rs index d642d32..2aea600 100644 --- a/src/image.rs +++ b/src/image.rs @@ -1,7 +1,7 @@ -use ab_glyph::FontArc; +use ab_glyph::{FontArc, PxScale}; use fontdb::{Database, Family, Query, Source}; use image::{ColorType, DynamicImage, ImageBuffer, imageops}; -use imageproc::drawing::{Canvas, draw_filled_rect_mut, draw_polygon_mut}; +use imageproc::drawing::{Canvas, draw_filled_rect_mut, draw_polygon_mut, draw_text_mut}; use imageproc::point::Point; use imageproc::rect::Rect; use std::io; @@ -12,8 +12,9 @@ use crate::ast::DepthExpr; type Offset = (u32, u32); // x, y or width, height // TODO: based on how much text -const COMPONENT_WIDTH: u32 = 20 * RESOLUTION_MULTIPLIER; -const COMPONENT_HEIGHT: u32 = 20 * RESOLUTION_MULTIPLIER; +const COMPONENT_TEXT_PADDING: u32 = 1 * RESOLUTION_MULTIPLIER; + +const TEXT_SCALE: f32 = 12.0 * RESOLUTION_MULTIPLIER as f32; // TODO: LENGTH based on where to where const DIRECTION_LINE_THICKNESS: u32 = 2 * RESOLUTION_MULTIPLIER; @@ -50,6 +51,9 @@ mod colors { pub const BG: Rgba = Rgba([ 0, 0, 0, 0, ]); + pub const FG: Rgba = Rgba([ + 255, 255, 255, 255, + ]); } // TODO: store as singleton @@ -100,14 +104,29 @@ fn ext(img: &mut DynamicImage, (curw, curh): &mut Offset, (extw, exth): &mut Off } // TODO: make draw_rect func -fn draw_process(img: &mut DynamicImage, (curw, curh): &mut Offset) -> Offset { +fn draw_process(img: &mut DynamicImage, txt: &str, (curw, curh): &mut Offset) -> Offset { *curw = curw - .checked_sub(COMPONENT_WIDTH / 2) + .checked_sub(TEXT_SCALE as u32 / 2) .unwrap_or(0); - ext(img, &mut (*curw, *curh), &mut (COMPONENT_WIDTH, COMPONENT_HEIGHT)); - draw_filled_rect_mut(img, Rect::at(*curw as i32, *curh as i32).of_size(COMPONENT_WIDTH, COMPONENT_HEIGHT), colors::PROCESS); - *curw += COMPONENT_WIDTH / 2; - *curh += COMPONENT_HEIGHT; + let w = TEXT_SCALE as u32 + COMPONENT_TEXT_PADDING * 2; + let h = w; + ext(img, &mut (*curw, *curh), &mut (w, h)); + draw_filled_rect_mut(img, Rect::at(*curw as i32, *curh as i32).of_size(w, h), colors::PROCESS); + draw_text_mut( + img, + colors::FG, + (*curw + COMPONENT_TEXT_PADDING) + .try_into() + .unwrap(), + (*curh + COMPONENT_TEXT_PADDING) + .try_into() + .unwrap(), + PxScale::from(TEXT_SCALE / 2.0), + &get_font().unwrap(), + txt, + ); + *curw += w / 2; + *curh += h; (*curw, *curh) } @@ -150,10 +169,11 @@ fn draw_direction(img: &mut DynamicImage, (oriw, orih): &mut Offset) -> Offset { fn build(ast: &[DepthExpr]) -> DynamicImage { let mut img = DynamicImage::new(0, 0, ColorType::Rgba8); + // TODO: move to mutable singleton let mut offset = (0, 0); - draw_process(&mut img, &mut offset); + draw_process(&mut img, "abcdefghijklmnop", &mut offset); draw_direction(&mut img, &mut offset); - draw_process(&mut img, &mut offset); + draw_process(&mut img, "a", &mut offset); img } -- cgit v1.2.3 From 0f140ebc681b7411dd76e110b2fe304f3e583c6c Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Mon, 29 Sep 2025 12:03:12 +0800 Subject: image(text): line wrap --- src/image.rs | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/image.rs b/src/image.rs index 2aea600..76e86ce 100644 --- a/src/image.rs +++ b/src/image.rs @@ -15,6 +15,7 @@ type Offset = (u32, u32); // x, y or width, height const COMPONENT_TEXT_PADDING: u32 = 1 * RESOLUTION_MULTIPLIER; const TEXT_SCALE: f32 = 12.0 * RESOLUTION_MULTIPLIER as f32; +const TEXT_LEN_WRAP: usize = 10; // TODO: LENGTH based on where to where const DIRECTION_LINE_THICKNESS: u32 = 2 * RESOLUTION_MULTIPLIER; @@ -56,6 +57,17 @@ mod colors { ]); } +fn wrap_str(s: &str) -> Vec { + s.chars() + .collect::>() + .chunks(TEXT_LEN_WRAP) + .map(|c| { + c.iter() + .collect() + }) + .collect() +} + // TODO: store as singleton fn get_font() -> Result { let mut db = Database::new(); @@ -106,27 +118,32 @@ fn ext(img: &mut DynamicImage, (curw, curh): &mut Offset, (extw, exth): &mut Off // TODO: make draw_rect func fn draw_process(img: &mut DynamicImage, txt: &str, (curw, curh): &mut Offset) -> Offset { *curw = curw - .checked_sub(TEXT_SCALE as u32 / 2) + .checked_sub(TEXT_SCALE as u32 * COMPONENT_TEXT_PADDING / 2) .unwrap_or(0); - let w = TEXT_SCALE as u32 + COMPONENT_TEXT_PADDING * 2; - let h = w; + let txt = wrap_str(txt); + let w = (TEXT_SCALE as u32 / 5 * TEXT_LEN_WRAP as u32) + (2 * COMPONENT_TEXT_PADDING); + let h = TEXT_SCALE as u32 / 2 * txt.len() as u32 + (2 * COMPONENT_TEXT_PADDING); ext(img, &mut (*curw, *curh), &mut (w, h)); draw_filled_rect_mut(img, Rect::at(*curw as i32, *curh as i32).of_size(w, h), colors::PROCESS); - draw_text_mut( - img, - colors::FG, - (*curw + COMPONENT_TEXT_PADDING) - .try_into() - .unwrap(), - (*curh + COMPONENT_TEXT_PADDING) - .try_into() - .unwrap(), - PxScale::from(TEXT_SCALE / 2.0), - &get_font().unwrap(), - txt, - ); + // TODO: move to draw_text() + for s in txt { + draw_text_mut( + img, + colors::FG, + (*curw + COMPONENT_TEXT_PADDING) + .try_into() + .unwrap(), + (*curh + COMPONENT_TEXT_PADDING) + .try_into() + .unwrap(), + PxScale::from(TEXT_SCALE / 2_f32), + &get_font().unwrap(), + s.as_str(), + ); + *curh += TEXT_SCALE as u32 / 2; + } *curw += w / 2; - *curh += h; + *curh += 2 * COMPONENT_TEXT_PADDING; (*curw, *curh) } -- cgit v1.2.3 From 3e489fefcec38f2a50567159c2e075a99cace3d4 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Mon, 29 Sep 2025 14:14:06 +0800 Subject: image(text): automatically shrinked width based on text --- src/image.rs | 62 ++++++++++++++++++++++++------------------------------------ 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/src/image.rs b/src/image.rs index 76e86ce..c52caba 100644 --- a/src/image.rs +++ b/src/image.rs @@ -9,7 +9,8 @@ use std::path::Path; use crate::ast::DepthExpr; -type Offset = (u32, u32); // x, y or width, height +type Offset = (u32, u32, u32); // x, y or width, height center +type NCOffset = (u32, u32); // TODO: based on how much text const COMPONENT_TEXT_PADDING: u32 = 1 * RESOLUTION_MULTIPLIER; @@ -103,7 +104,7 @@ fn get_font() -> Result { } } -fn ext(img: &mut DynamicImage, (curw, curh): &mut Offset, (extw, exth): &mut Offset) { +fn ext(img: &mut DynamicImage, (curw, curh): &mut NCOffset, (extw, exth): &mut NCOffset) { let (w, h) = img.dimensions(); let extedw = *extw + *curw; let extedh = *exth + *curh; @@ -116,48 +117,37 @@ fn ext(img: &mut DynamicImage, (curw, curh): &mut Offset, (extw, exth): &mut Off } // TODO: make draw_rect func -fn draw_process(img: &mut DynamicImage, txt: &str, (curw, curh): &mut Offset) -> Offset { - *curw = curw - .checked_sub(TEXT_SCALE as u32 * COMPONENT_TEXT_PADDING / 2) +fn draw_process(img: &mut DynamicImage, txt: &str, (curw, curh, c): &mut Offset) { + let wrapped = wrap_str(txt); + let w = (TEXT_SCALE as u32 / 5 + * if wrapped.len() <= 1 { + txt.len() as u32 + } else { + TEXT_LEN_WRAP as u32 + }) + + (2 * COMPONENT_TEXT_PADDING); + let h = TEXT_SCALE as u32 / 2 * wrapped.len() as u32 + (2 * COMPONENT_TEXT_PADDING); + ext(img, &mut (*c, *curh), &mut (w, h)); + let cw = c + .checked_sub(w / 2) .unwrap_or(0); - let txt = wrap_str(txt); - let w = (TEXT_SCALE as u32 / 5 * TEXT_LEN_WRAP as u32) + (2 * COMPONENT_TEXT_PADDING); - let h = TEXT_SCALE as u32 / 2 * txt.len() as u32 + (2 * COMPONENT_TEXT_PADDING); - ext(img, &mut (*curw, *curh), &mut (w, h)); - draw_filled_rect_mut(img, Rect::at(*curw as i32, *curh as i32).of_size(w, h), colors::PROCESS); + draw_filled_rect_mut(img, Rect::at(cw as i32, *curh as i32).of_size(w, h), colors::PROCESS); // TODO: move to draw_text() - for s in txt { - draw_text_mut( - img, - colors::FG, - (*curw + COMPONENT_TEXT_PADDING) - .try_into() - .unwrap(), - (*curh + COMPONENT_TEXT_PADDING) - .try_into() - .unwrap(), - PxScale::from(TEXT_SCALE / 2_f32), - &get_font().unwrap(), - s.as_str(), - ); + for s in wrapped { + draw_text_mut(img, colors::FG, cw as i32 + COMPONENT_TEXT_PADDING as i32, *curh as i32 + COMPONENT_TEXT_PADDING as i32, PxScale::from(TEXT_SCALE / 2_f32), &get_font().unwrap(), s.as_str()); *curh += TEXT_SCALE as u32 / 2; } - *curw += w / 2; + *c = *curw + (w / 2); *curh += 2 * COMPONENT_TEXT_PADDING; - (*curw, *curh) } -fn draw_direction(img: &mut DynamicImage, (oriw, orih): &mut Offset) -> Offset { - *oriw = oriw - .checked_sub(DIRECTION_LINE_THICKNESS / 2) - .unwrap_or(0); - ext(img, &mut (*oriw, *orih), &mut (DIRECTION_LINE_THICKNESS, DIRECTION_LINE_LENGTH)); - draw_filled_rect_mut(img, Rect::at(*oriw as i32, *orih as i32).of_size(DIRECTION_LINE_THICKNESS, DIRECTION_LINE_LENGTH - DIRECTION_LINE_ARROW_OFFSET), colors::DIRECT); - *oriw += DIRECTION_LINE_THICKNESS / 2; +fn draw_direction(img: &mut DynamicImage, (oriw, orih, c): &mut Offset) { + ext(img, &mut (*c, *orih), &mut (DIRECTION_LINE_THICKNESS, DIRECTION_LINE_LENGTH)); + draw_filled_rect_mut(img, Rect::at(*c as i32 - (DIRECTION_LINE_THICKNESS as i32 / 2), *orih as i32).of_size(DIRECTION_LINE_THICKNESS, DIRECTION_LINE_LENGTH - DIRECTION_LINE_ARROW_OFFSET), colors::DIRECT); *orih += DIRECTION_LINE_LENGTH; // arrow - let x = *oriw as i32; + let x = *c as i32; let y = *orih as i32; let offset = DIRECTION_LINE_ARROW_OFFSET as i32; // left @@ -180,14 +170,12 @@ fn draw_direction(img: &mut DynamicImage, (oriw, orih): &mut Offset) -> Offset { ], colors::DIRECT, ); - - (*oriw, *orih) } fn build(ast: &[DepthExpr]) -> DynamicImage { let mut img = DynamicImage::new(0, 0, ColorType::Rgba8); // TODO: move to mutable singleton - let mut offset = (0, 0); + let mut offset: Offset = (0, 0, 0); draw_process(&mut img, "abcdefghijklmnop", &mut offset); draw_direction(&mut img, &mut offset); draw_process(&mut img, "a", &mut offset); -- cgit v1.2.3 From c379eb2216c80cdaf3c6670afbf3fc2269203634 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Mon, 29 Sep 2025 14:23:59 +0800 Subject: format: clippy --- src/image.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/image.rs b/src/image.rs index c52caba..244ce18 100644 --- a/src/image.rs +++ b/src/image.rs @@ -23,7 +23,7 @@ const DIRECTION_LINE_THICKNESS: u32 = 2 * RESOLUTION_MULTIPLIER; const DIRECTION_LINE_LENGTH: u32 = 13 * RESOLUTION_MULTIPLIER; const DIRECTION_LINE_ARROW_OFFSET: u32 = 5 * RESOLUTION_MULTIPLIER / 2; -const RESOLUTION_MULTIPLIER: u32 = 50; +const RESOLUTION_MULTIPLIER: u32 = 5; /* offset based mutation model, to avoid overflowing on previous image @@ -90,7 +90,7 @@ fn get_font() -> Result { let face = db .face(id) - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "face missing"))?; + .ok_or_else(|| io::Error::other("face missing"))?; match &face.source { Source::File(path) => std::fs::read(path).and_then(|bytes| FontArc::try_from_vec(bytes).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "parse font failed"))), @@ -141,7 +141,7 @@ fn draw_process(img: &mut DynamicImage, txt: &str, (curw, curh, c): &mut Offset) *curh += 2 * COMPONENT_TEXT_PADDING; } -fn draw_direction(img: &mut DynamicImage, (oriw, orih, c): &mut Offset) { +fn draw_direction(img: &mut DynamicImage, (_, orih, c): &mut Offset) { ext(img, &mut (*c, *orih), &mut (DIRECTION_LINE_THICKNESS, DIRECTION_LINE_LENGTH)); draw_filled_rect_mut(img, Rect::at(*c as i32 - (DIRECTION_LINE_THICKNESS as i32 / 2), *orih as i32).of_size(DIRECTION_LINE_THICKNESS, DIRECTION_LINE_LENGTH - DIRECTION_LINE_ARROW_OFFSET), colors::DIRECT); *orih += DIRECTION_LINE_LENGTH; -- cgit v1.2.3 From 3f3092856aaf2844a442ef86b0d4cb58acdff345 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Mon, 29 Sep 2025 14:40:12 +0800 Subject: image(text): only update center offset when its nonzero we'll need to manually update them --- src/image.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/image.rs b/src/image.rs index 244ce18..b78dc04 100644 --- a/src/image.rs +++ b/src/image.rs @@ -137,7 +137,9 @@ fn draw_process(img: &mut DynamicImage, txt: &str, (curw, curh, c): &mut Offset) draw_text_mut(img, colors::FG, cw as i32 + COMPONENT_TEXT_PADDING as i32, *curh as i32 + COMPONENT_TEXT_PADDING as i32, PxScale::from(TEXT_SCALE / 2_f32), &get_font().unwrap(), s.as_str()); *curh += TEXT_SCALE as u32 / 2; } - *c = *curw + (w / 2); + if *c == 0 { + *c = *curw + (w / 2); + } *curh += 2 * COMPONENT_TEXT_PADDING; } @@ -179,6 +181,14 @@ fn build(ast: &[DepthExpr]) -> DynamicImage { draw_process(&mut img, "abcdefghijklmnop", &mut offset); draw_direction(&mut img, &mut offset); draw_process(&mut img, "a", &mut offset); + draw_direction(&mut img, &mut offset); + draw_process(&mut img, "a", &mut offset); + draw_direction(&mut img, &mut offset); + draw_process(&mut img, "a", &mut offset); + draw_direction(&mut img, &mut offset); + draw_process(&mut img, "a", &mut offset); + draw_direction(&mut img, &mut offset); + draw_process(&mut img, "a", &mut offset); img } -- cgit v1.2.3