use hephaestus::backend::vello::VelloRenderer;
use hephaestus::color::{rgb8, Color};
use hephaestus::composition::{beside, Patch, Slot};
use hephaestus::layout::Cell;
use hephaestus::text::{draw_text_in_rect, TextRun, TextStyle};
use hephaestus::{Affine, Brush, FillRule, Path, PickId, Renderer, SceneBuilder};
use kurbo::Shape;
fn text_cell(text: &str, size: f32) -> Cell {
Cell::measured(TextRun::new(text, &TextStyle::new(size), 96.0))
}
fn plain(id: &str) -> Patch {
Patch::new(id).slot(Slot::Panel, Cell::empty())
}
fn color_for_region(region: &str) -> Color {
match region {
"panel" => rgb8(40, 60, 90),
"axis_top" => rgb8(200, 100, 130),
"axis_bottom" => rgb8(160, 100, 130),
_ => rgb8(120, 120, 120),
}
}
fn main() {
let (w, h) = (1400u32, 400u32);
let dpi = 96.0;
let leaf = beside(
Patch::new("leaf_l")
.slot(Slot::AxisTop, text_cell("axis_top from deepest leaf", 14.0))
.slot(Slot::AxisBottom, text_cell("axis_bottom from leaf", 11.0))
.slot(Slot::Panel, Cell::empty()),
plain("leaf_r"),
);
let mid = beside(plain("mid"), leaf);
let composed = beside(plain("root"), mid);
let layout = composed.solve(hephaestus::Size::new(w as f64, h as f64), dpi);
let mut renderer = VelloRenderer::new().expect("vello renderer init");
{
let scene = renderer.scene();
let stroke = hephaestus::stroke::Stroke::new(1.0);
let text_brush: Brush = rgb8(20, 20, 30).into();
for (_id, region, rect) in layout.iter() {
if region == "panel" {
continue;
}
let c = color_for_region(region);
let tint = Color::new([c.components[0], c.components[1], c.components[2], 0.20]);
let path: Path = rect.to_path(0.1);
scene.fill(
FillRule::NonZero,
Affine::IDENTITY,
&Brush::Solid(tint),
None,
&path,
PickId::Skip,
);
scene.stroke(
&stroke,
Affine::IDENTITY,
&Brush::Solid(c),
None,
&path,
PickId::Skip,
);
}
for (_id, region, rect) in layout.iter() {
if region != "panel" {
continue;
}
let path: Path = rect.to_path(0.1);
scene.fill(
FillRule::NonZero,
Affine::IDENTITY,
&Brush::Solid(color_for_region(region)),
None,
&path,
PickId::Skip,
);
scene.stroke(
&stroke,
Affine::IDENTITY,
&Brush::Solid(rgb8(255, 255, 255)),
None,
&path,
PickId::Skip,
);
}
if let Some(rect) = layout.get("leaf_l", Slot::AxisTop) {
let run = TextRun::new("axis_top from deepest leaf", &TextStyle::new(14.0), 96.0);
draw_text_in_rect(scene, &run, rect, &text_brush, PickId::Skip);
}
if let Some(rect) = layout.get("leaf_l", Slot::AxisBottom) {
let run = TextRun::new("axis_bottom from leaf", &TextStyle::new(11.0), 96.0);
draw_text_in_rect(scene, &run, rect, &text_brush, PickId::Skip);
}
}
let mut pixels = vec![0u8; (w * h * 4) as usize];
let bg: Color = rgb8(248, 248, 252);
renderer
.render_to_buffer(w, h, bg, &mut pixels)
.expect("render");
let path = std::env::current_dir()
.unwrap()
.join("examples/nesting_deep.png");
hephaestus::image::write_png(&path, w, h, &pixels).expect("write png");
println!("wrote {}", path.display());
let root_panel = layout.get("root", Slot::Panel).unwrap();
let mid_panel = layout.get("mid", Slot::Panel).unwrap();
let leaf_l_panel = layout.get("leaf_l", Slot::Panel).unwrap();
let leaf_r_panel = layout.get("leaf_r", Slot::Panel).unwrap();
println!(
"panel y0: root={}, mid={}, leaf_l={}, leaf_r={}",
root_panel.y0, mid_panel.y0, leaf_l_panel.y0, leaf_r_panel.y0
);
println!("(all four should be equal — propagation across 3 nesting levels)");
}