layout_demo/
layout_demo.rs1use hephaestus::backend::vello::VelloRenderer;
9use hephaestus::color::{rgb8, Color};
10use hephaestus::layout::{CellId, Extent, Grid, Inset, Placement, Track};
11use hephaestus::stroke::Stroke;
12use hephaestus::{Affine, Brush, FillRule, Path, PickId, Renderer, SceneBuilder};
13use kurbo::Shape;
14
15fn main() {
16 let (w, h) = (800u32, 600u32);
17 let dpi = 96.0;
18
19 let mut root = Grid::new(vec![Track::Fr(1.0); 5], vec![Track::Fr(1.0); 3]);
21
22 let mut outer_id = 1u64;
24 for r in 1..=3u16 {
25 for c in 1..=5u16 {
26 root.place_mut(Placement::at(r, c), Grid::cell().id(CellId(outer_id)));
27 outer_id += 1;
28 }
29 }
30
31 let mut inner = Grid::new(
33 [Track::Fr(1.0), Track::Fr(1.0)],
34 [Track::Fr(1.0), Track::Fr(1.0)],
35 );
36 for r in 1..=2u16 {
37 for c in 1..=2u16 {
38 inner.place_mut(
39 Placement::at(r, c),
40 Grid::cell().id(CellId(100 + (r as u64) * 2 + c as u64)),
41 );
42 }
43 }
44 root.place_mut(
45 Placement::at(2, 3).span(1, 3).inset(
46 Inset::default()
47 .left(Extent::cm(1.0))
48 .right(Extent::percent(0.25)),
49 ),
50 inner,
51 );
52
53 root.place_mut(
55 Placement::at(1, 1),
56 Grid::new([Track::Fr(2.0)], [Track::Fr(1.0)])
57 .respect()
58 .id(CellId(200)),
59 );
60
61 let layout = root.solve(hephaestus::Size::new(w as f64, h as f64), dpi);
62
63 let mut renderer = VelloRenderer::new().expect("vello renderer init");
65 {
66 let scene = renderer.scene();
67 let outer_brush: Brush = rgb8(80, 90, 110).into();
68 let outer_stroke = Stroke::new(1.0);
69 for id in 1..=15u64 {
70 if let Some(rect) = layout.rect(CellId(id)) {
71 let path: Path = rect.to_path(0.1);
72 scene.stroke(
73 &outer_stroke,
74 Affine::IDENTITY,
75 &outer_brush,
76 None,
77 &path,
78 PickId::Skip,
79 );
80 }
81 }
82
83 let inner_brush: Brush = rgb8(240, 180, 60).into();
84 let inner_stroke = Stroke::new(2.0);
85 for id in [103u64, 104, 105, 106] {
86 if let Some(rect) = layout.rect(CellId(id)) {
87 let path: Path = rect.to_path(0.1);
88 scene.fill(
89 FillRule::NonZero,
90 Affine::IDENTITY,
91 &Brush::Solid(rgb8(245, 220, 160)),
92 None,
93 &path,
94 PickId::Skip,
95 );
96 scene.stroke(
97 &inner_stroke,
98 Affine::IDENTITY,
99 &inner_brush,
100 None,
101 &path,
102 PickId::Skip,
103 );
104 }
105 }
106
107 let aspect_brush: Brush = rgb8(60, 160, 220).into();
108 if let Some(rect) = layout.rect(CellId(200)) {
109 let path: Path = rect.to_path(0.1);
110 scene.fill(
111 FillRule::NonZero,
112 Affine::IDENTITY,
113 &aspect_brush,
114 None,
115 &path,
116 PickId::Skip,
117 );
118 }
119 }
120
121 let mut pixels = vec![0u8; (w * h * 4) as usize];
122 let bg: Color = rgb8(20, 22, 28);
123 renderer
124 .render_to_buffer(w, h, bg, &mut pixels)
125 .expect("render");
126
127 let path = std::env::current_dir()
128 .unwrap()
129 .join("examples/layout_demo.png");
130 hephaestus::image::write_png(&path, w, h, &pixels).expect("write png");
131 println!("wrote {}", path.display());
132}