|
@ -1,16 +1,93 @@ |
|
|
use std::borrow::Cow;
|
|
|
use std::borrow::Cow;
|
|
|
|
|
|
use std::slice::Chunks;
|
|
|
|
|
|
|
|
|
use glium::texture::{RawImage2d, Texture2dDataSource};
|
|
|
use glium::texture::{RawImage2d, Texture2dDataSource};
|
|
|
pub use glium::texture::PixelValue;
|
|
|
pub use glium::texture::PixelValue;
|
|
|
|
|
|
|
|
|
|
|
|
/// A CPU RAM-based 2d buffer.
|
|
|
|
|
|
pub trait Buffer2d: Sized {
|
|
|
|
|
|
type Pixel;
|
|
|
|
|
|
|
|
|
pub struct Texture2dData<T> where T: Clone {
|
|
|
|
|
|
|
|
|
fn width(&self) -> usize;
|
|
|
|
|
|
fn height(&self) -> usize;
|
|
|
|
|
|
fn dimensions(&self) -> (usize, usize) {(self.width(), self.height())}
|
|
|
|
|
|
|
|
|
|
|
|
fn get(&self, x: usize, y: usize) -> Option<Self::Pixel>;
|
|
|
|
|
|
fn set(&mut self, x: usize, y: usize, v: Self::Pixel);
|
|
|
|
|
|
|
|
|
|
|
|
fn patch<B>(&mut self, x: usize, y: usize, buf: &B)
|
|
|
|
|
|
where B: Buffer2d<Pixel=Self::Pixel>
|
|
|
|
|
|
{
|
|
|
|
|
|
let (w, h) = buf.dimensions();
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: can this be optimized by performing an unsafe memcpy of some sort?
|
|
|
|
|
|
for sy in 0..h {
|
|
|
|
|
|
for sx in 0..w {
|
|
|
|
|
|
match buf.get(sx, sy) {
|
|
|
|
|
|
Some(v) => self.set(x+sx, y+sy, v),
|
|
|
|
|
|
_ => (),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub trait ResizeableBuffer2d: Buffer2d {
|
|
|
|
|
|
fn resize(&mut self, width: usize, height: usize);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub struct Bitmap<T> {
|
|
|
pub data: Vec<T>,
|
|
|
pub data: Vec<T>,
|
|
|
pub width: u32,
|
|
|
|
|
|
pub height: u32,
|
|
|
|
|
|
|
|
|
pub width: usize,
|
|
|
|
|
|
pub height: usize,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<T> Bitmap<T> where T: Clone + Default {
|
|
|
|
|
|
pub fn new(w: usize, h: usize) -> Bitmap<T> {
|
|
|
|
|
|
Bitmap {
|
|
|
|
|
|
data: vec![Default::default(); w*h],
|
|
|
|
|
|
width: w,
|
|
|
|
|
|
height: h,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn lines(&self) -> Chunks<T> {
|
|
|
|
|
|
self.data.chunks(self.width)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<T> Buffer2d for Bitmap<T> where T: Clone {
|
|
|
|
|
|
type Pixel = T;
|
|
|
|
|
|
|
|
|
|
|
|
fn width(&self) -> usize {self.width}
|
|
|
|
|
|
fn height(&self) -> usize {self.height}
|
|
|
|
|
|
|
|
|
|
|
|
fn get(&self, x: usize, y: usize) -> Option<Self::Pixel> {
|
|
|
|
|
|
self.data.get(x + self.width * y).cloned()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn set(&mut self, x: usize, y: usize, v: Self::Pixel) {
|
|
|
|
|
|
if let Some(p) = self.data.get_mut(x + self.width * y) {
|
|
|
|
|
|
*p = v;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<T> ResizeableBuffer2d for Bitmap<T> where T: Clone + Default {
|
|
|
|
|
|
fn resize(&mut self, width: usize, height: usize) {
|
|
|
|
|
|
assert!(self.width() <= width && self.height() <= height,
|
|
|
|
|
|
"resizable buffers cannot shrink!");
|
|
|
|
|
|
|
|
|
|
|
|
// create new, larger buffer
|
|
|
|
|
|
let mut new: Bitmap<T> = Bitmap::new(width as usize, height as usize);
|
|
|
|
|
|
// copy the existing buffer into it
|
|
|
|
|
|
new.patch(0, 0, self);
|
|
|
|
|
|
// overwrite the current buffer with the new buffer
|
|
|
|
|
|
*self = new;
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
impl<'a, P> Texture2dDataSource<'a> for &'a Texture2dData<P>
|
|
|
|
|
|
|
|
|
impl<'a, P> Texture2dDataSource<'a> for &'a Bitmap<P>
|
|
|
where P: Clone + PixelValue
|
|
|
where P: Clone + PixelValue
|
|
|
{
|
|
|
{
|
|
|
type Data = P;
|
|
|
type Data = P;
|
|
@ -18,8 +95,8 @@ impl<'a, P> Texture2dDataSource<'a> for &'a Texture2dData<P> |
|
|
fn into_raw(self) -> RawImage2d<'a, P> {
|
|
|
fn into_raw(self) -> RawImage2d<'a, P> {
|
|
|
RawImage2d {
|
|
|
RawImage2d {
|
|
|
data: Cow::Borrowed(&self.data),
|
|
|
data: Cow::Borrowed(&self.data),
|
|
|
width: self.width,
|
|
|
|
|
|
height: self.height,
|
|
|
|
|
|
|
|
|
width: self.width as u32,
|
|
|
|
|
|
height: self.height as u32,
|
|
|
format: <P as PixelValue>::get_format(),
|
|
|
format: <P as PixelValue>::get_format(),
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|