mod skyline;
|
|
|
|
use ::texture::{Buffer2d, ResizeableBuffer2d};
|
|
use ::geometry::Rect;
|
|
|
|
pub use self::skyline::SkylinePacker;
|
|
|
|
pub trait Packer {
|
|
type Buffer: Buffer2d;
|
|
|
|
fn new(b: Self::Buffer) -> Self;
|
|
fn pack<O>(&mut self, buf: &O) -> Option<Rect<usize>>
|
|
where O: Buffer2d<Pixel=<Self::Buffer as Buffer2d>::Pixel>; // buffer with same pixel type as this atlas
|
|
|
|
fn set_margin(&mut self, margin: usize);
|
|
fn buf(&self) -> &Self::Buffer;
|
|
fn buf_mut(&mut self) -> &mut Self::Buffer;
|
|
fn into_buf(self) -> Self::Buffer; // TODO: consider actually implementing Into?
|
|
|
|
fn dimensions(&self) -> (usize, usize);
|
|
fn set_dimensions(&mut self, w: usize, h: usize);
|
|
}
|
|
|
|
pub trait GrowingPacker: Packer {
|
|
/// `resize_fn` should describe a strategy for growing the atlas buffer based on the current size.
|
|
fn pack_resize<F, O>(&mut self, buf: &O, resize_fn: F) -> Rect<usize>
|
|
where O: Buffer2d<Pixel=<<Self as Packer>::Buffer as Buffer2d>::Pixel>,
|
|
F: Fn((usize, usize)) -> (usize, usize);
|
|
}
|
|
|
|
impl <A, P> GrowingPacker for P
|
|
where A: ResizeableBuffer2d, P: Packer<Buffer = A>
|
|
{
|
|
fn pack_resize<F, O>(&mut self, buf: &O, resize_fn: F) -> Rect<usize>
|
|
where O: Buffer2d<Pixel=<<Self as Packer>::Buffer as Buffer2d>::Pixel>,
|
|
F: Fn((usize, usize)) -> (usize, usize)
|
|
{
|
|
match self.pack(buf) {
|
|
Some(p) => p,
|
|
None => {
|
|
let (w, h) = self.dimensions();
|
|
let (w_, h_) = resize_fn((w, h));
|
|
if w_ <= w || h_ <= h {
|
|
panic!("Resize functions must make the buffer larger!");
|
|
}
|
|
|
|
self.buf_mut().resize(w_, h_);
|
|
self.set_dimensions(w_, h_);
|
|
|
|
// recurse, trying this new size
|
|
self.pack_resize(buf, resize_fn)
|
|
}
|
|
}
|
|
}
|
|
}
|