diff --git a/textium/src/lib.rs b/textium/src/lib.rs index 1aef7e6..520d45e 100644 --- a/textium/src/lib.rs +++ b/textium/src/lib.rs @@ -8,6 +8,7 @@ mod error; mod texture; mod geometry; mod rasterizer; +mod packer; use std::iter::Iterator; use std::collections::HashMap; diff --git a/textium/src/packer/mod.rs b/textium/src/packer/mod.rs new file mode 100644 index 0000000..4cd53e3 --- /dev/null +++ b/textium/src/packer/mod.rs @@ -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(&mut self, buf: &O) -> Option> + where O: 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(&mut self, buf: &O, resize_fn: F) -> Rect + where O: Buffer2d::Buffer as Buffer2d>::Pixel>, + F: Fn((usize, usize)) -> (usize, usize); +} + +impl GrowingPacker for P + where A: ResizeableBuffer2d, P: Packer +{ + fn pack_resize(&mut self, buf: &O, resize_fn: F) -> Rect + where O: Buffer2d::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) + } + } + } +}