1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
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::path::Path;
use crate::ast::DepthExpr;
type Offset = (u32, u32); // x, y or width, height
const COMPONENT_WIDTH: u32 = 20 * RESOLUTION_MULTIPLIER;
const COMPONENT_HEIGHT: u32 = 20 * RESOLUTION_MULTIPLIER;
const DIRECTION_LINE_THICKNESS: u32 = 1 * RESOLUTION_MULTIPLIER;
const DIRECTION_LINE_LENGTH: u32 = 10 * RESOLUTION_MULTIPLIER;
const DIRECTION_LINE_ARROW_OFFSET: u32 = 3 * RESOLUTION_MULTIPLIER / 2;
const RESOLUTION_MULTIPLIER: u32 = 50;
/*
offset based mutation model, to avoid overflowing on previous image
*/
mod colors {
use image::Rgba;
pub const STARSTOP: Rgba<u8> = Rgba([
63, 122, 86, 255,
]);
pub const PROCESS: Rgba<u8> = Rgba([
0, 104, 124, 255,
]);
pub const IO: Rgba<u8> = Rgba([
149, 30, 88, 255,
]);
pub const DIRECT: Rgba<u8> = Rgba([
31, 133, 53, 255,
]);
pub const BG: Rgba<u8> = 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(w.max(extedw), h.max(extedh), colors::BG);
imageops::overlay(&mut resized, img, 0, 0);
*img = image::DynamicImage::ImageRgba8(resized);
}
// TODO: make draw_rect func
fn draw_process(img: &mut DynamicImage, (curw, curh): &mut Offset) -> Offset {
*curw = curw
.checked_sub(COMPONENT_WIDTH / 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;
(*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;
*orih += DIRECTION_LINE_LENGTH;
// arrow
let x = *oriw as i32;
let y = *orih as i32;
let offset = DIRECTION_LINE_ARROW_OFFSET as i32;
// left
draw_polygon_mut(
img,
&[
Point::new(x, y),
Point::new(x - offset, y - offset),
Point::new(x, y - offset),
],
colors::DIRECT,
);
// right
draw_polygon_mut(
img,
&[
Point::new(x, y),
Point::new(x + offset, y - offset),
Point::new(x, y - offset),
],
colors::DIRECT,
);
(*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();
}
|