///|
fn ceil_div(n : Int, d : Int) -> Int {
(n + d - 1) / d
}
///|
fn label_char(id : String) -> Char {
if id.is_empty() {
'#'
} else {
id.unsafe_get(0).to_int().unsafe_to_char()
}
}
///|
/// Render a coarse ASCII preview of a layout. Each output cell represents
/// `cell_width` by `cell_height` layout units.
pub fn to_ascii_preview(
layout : Layout,
cell_width? : Int = 1,
cell_height? : Int = 1,
) -> Result[String, PackError] {
if cell_width <= 0 || cell_height <= 0 {
return Err(InvalidCellSize(width=cell_width, height=cell_height))
}
match validate_layout(layout) {
Err(err) => return Err(err)
Ok(_) => ()
}
let cols = ceil_div(layout.bin.width, cell_width)
let rows = ceil_div(layout.bin.height, cell_height)
let cells = Array::make(rows * cols, '.')
for placed in layout.placements {
let mark = label_char(placed.id)
let start_col = placed.x / cell_width
let end_col = (placed.x + placed.width - 1) / cell_width
let start_row = placed.y / cell_height
let end_row = (placed.y + placed.height - 1) / cell_height
for row in start_row..<(end_row + 1) {
for col in start_col..<(end_col + 1) {
if row >= 0 && row < rows && col >= 0 && col < cols {
cells[row * cols + col] = mark
}
}
}
}
let out = StringBuilder()
for row in 0..