///|
fn choose_for_shelf(
rect : Rect,
x : Int,
y : Int,
shelf_h : Int,
options : PackOptions,
) -> (Int, Int)? {
let mut chosen : (Int, Int)? = None
for candidate in orientation_candidates(rect, options.allow_rotate) {
let (w, h) = candidate
if x + w <= right_limit(options) &&
y + shelf_h.max(h) <= bottom_limit(options) {
match chosen {
None => chosen = Some(candidate)
Some(prev) if better_orientation(candidate, prev) =>
chosen = Some(candidate)
_ => ()
}
}
}
chosen
}
///|
fn pack_shelf(rects : ArrayView[Rect], options : PackOptions) -> Layout {
let placements : Array[Placed] = []
let unpacked : Array[Rect] = []
let ordered = sorted_rects(rects, options.sort)
let start_x = options.padding.outer
let mut x = start_x
let mut y = options.padding.outer
let mut shelf_h = 0
for rect in ordered {
let fit_here = choose_for_shelf(rect, x, y, shelf_h, options)
let candidate = match fit_here {
Some(size) => Some((x, y, size))
None => {
if shelf_h > 0 {
y = y + shelf_h + options.padding.inner
x = start_x
shelf_h = 0
}
match choose_for_shelf(rect, x, y, shelf_h, options) {
Some(size) => Some((x, y, size))
None => None
}
}
}
match candidate {
Some((px, py, (w, h))) => {
placements.push(make_placed(rect, px, py, w, h))
x = px + w + options.padding.inner
shelf_h = shelf_h.max(h)
}
None => unpacked.push(rect)
}
}
make_layout(options.bin, placements, unpacked, ShelfFirstFit)
}