From c3acd353b55ba19a1d8254b96dd5e5dfe90ebbfd Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Sun, 28 Sep 2025 17:59:00 +0800 Subject: WIP: image --- src/image.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/main.rs | 9 ++++++- 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/image.rs (limited to 'src') diff --git a/src/image.rs b/src/image.rs new file mode 100644 index 0000000..8e57d2f --- /dev/null +++ b/src/image.rs @@ -0,0 +1,80 @@ +use image::{ColorType, DynamicImage, GenericImage, ImageBuffer, imageops}; +use imageproc::drawing::{Canvas, draw_cross_mut, draw_filled_circle_mut, draw_filled_rect_mut, draw_hollow_circle_mut, draw_hollow_rect_mut, draw_line_segment_mut}; +use imageproc::rect::Rect; +use std::path::Path; + +use crate::ast::DepthExpr; + +type Offset = (u32, u32); // x, y or width, height + +const COMPONENT_WIDTH: u32 = 20; +const COMPONENT_HEIGHT: u32 = 20; + +const DIRECTION_LINE_HEIGHT: u32 = 100; +const DIRECTION_LINE_WIDTH: u32 = 20; + +/* +offset based mutation model, to avoid overflowing on previous image +*/ + +mod colors { + use image::Rgba; + pub const STARSTOP: Rgba = Rgba([ + 63, 122, 86, 255, + ]); + pub const PROCESS: Rgba = Rgba([ + 0, 104, 124, 255, + ]); + pub const IO: Rgba = Rgba([ + 149, 30, 88, 255, + ]); + pub const DIRECT: Rgba = Rgba([ + 31, 133, 53, 255, + ]); + pub const BG: Rgba = Rgba([ + 0, 0, 0, 0, + ]); +} + +fn ext(img: &mut DynamicImage, (curw, curh): &mut Offset, (extw, exth): &mut Offset) { + let (w, h) = img.dimensions(); + let extedw = *extw + *curw; + let extedh = *exth + *curh; + if extedw < w || extedh < h { + return; + } + let mut resized = ImageBuffer::from_pixel(extedw, extedh, colors::BG); + imageops::overlay(&mut resized, img, 0, 0); + *img = image::DynamicImage::ImageRgba8(resized); +} + +fn draw_process(img: &mut DynamicImage, (curw, curh): &mut Offset) -> Offset { + 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; + (*curw, *curh) +} + +fn draw_direction(img: &mut DynamicImage, (oriw, orih): &mut Offset) -> Offset { + ext(img, &mut (*oriw, *orih), &mut (DIRECTION_LINE_WIDTH, DIRECTION_LINE_HEIGHT)); + draw_line_segment_mut(img, (*oriw as f32, *orih as f32), ((*oriw + DIRECTION_LINE_WIDTH) as f32, (*orih + DIRECTION_LINE_HEIGHT) as f32), colors::DIRECT); + *orih += DIRECTION_LINE_HEIGHT; + (*oriw, *orih) +} + +fn build(ast: &[DepthExpr]) -> DynamicImage { + let mut img = DynamicImage::new(0, 0, ColorType::Rgba8); + let mut offset = (0, 0); + draw_process(&mut img, &mut offset); + draw_direction(&mut img, &mut offset); + draw_process(&mut img, &mut offset); + + img +} + +pub fn create(ast: &[DepthExpr], path: &Path) { + build(ast) + .save(path) + .unwrap(); +} diff --git a/src/lib.rs b/src/lib.rs index a553e33..05c7525 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ pub mod ast; +pub mod image; pub mod parser; pub mod tokenizer; diff --git a/src/main.rs b/src/main.rs index ab265d5..0fa96b0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,15 @@ +use std::path::Path; + use java2flowchart::ast::parse; +use java2flowchart::image::create; use java2flowchart::parser; fn main() { let test = "if (first) {firstthen; if (firstthenif) {firstthenifthen} else {firstthenelse}} else {firstelse}println('a')"; - println!("{:#?}", parse(&parser::parse(test))); + let ast = parse(&parser::parse(test)); + + println!("{:#?}", ast); + + create(&ast, Path::new("output.png")); } -- cgit v1.2.3