| @ -0,0 +1,50 @@ | |||||
| use ::texture::{Buffer2d, ResizeableBuffer2d}; | |||||
| use ::geometry::Rect; | |||||
| 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 { | |||||
| 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) | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||