|
@@ -8,7 +8,7 @@ mod helpers;
|
|
|
mod impls;
|
|
|
|
|
|
pub trait Readable<PF: PixelFormat> {
|
|
|
- type ReadResult;
|
|
|
+ type ReadResult: Clone;
|
|
|
fn get_pixel(&self, x: usize, y: usize) -> Self::ReadResult;
|
|
|
}
|
|
|
|
|
@@ -16,7 +16,67 @@ pub trait Writable<PF: PixelFormat>: Readable<PF> {
|
|
|
fn set_pixel(&mut self, x: usize, y: usize, to: Self::ReadResult);
|
|
|
}
|
|
|
|
|
|
+/// Generic image manipulation functionality
|
|
|
+pub trait Paintable<PF: PixelFormat>: BitmapMutAccess<PF> + Writable<PF> {
|
|
|
+ fn fill(&mut self, with: Self::ReadResult) {
|
|
|
+ for y in 0..self.height() {
|
|
|
+ for x in 0..self.width() {
|
|
|
+ self.set_pixel(x, y, with.clone());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Fill a region with a given value.
|
|
|
+ fn fill_region(&mut self, region: &math::PixelBox, with: Self::ReadResult) {
|
|
|
+ let image_box = math::PixelBox::from_size(self.size());
|
|
|
+ let Some(isect) = region.intersection(&image_box) else {
|
|
|
+ // nothing to do
|
|
|
+ return;
|
|
|
+ };
|
|
|
+
|
|
|
+ for y in isect.y_range() {
|
|
|
+ for x in isect.x_range() {
|
|
|
+ self.set_pixel(x as usize, y as usize, with.clone());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Copy image data from another bitmap with the same pixel format.
|
|
|
+ fn copy_from(
|
|
|
+ &mut self,
|
|
|
+ amap: &impl BitmapAccess<PF>,
|
|
|
+ amap_region: &math::PixelBox,
|
|
|
+ dst: &math::PixelPoint,
|
|
|
+ ) {
|
|
|
+ let Some((write_region, read_region)) = helpers::clip_to(
|
|
|
+ self.size(),
|
|
|
+ *dst,
|
|
|
+ amap.size(),
|
|
|
+ amap_region.min,
|
|
|
+ amap_region.size(),
|
|
|
+ ) else {
|
|
|
+ return;
|
|
|
+ };
|
|
|
+
|
|
|
+ let row_width = write_region.width() as usize * PF::PIXEL_WIDTH;
|
|
|
+ for y in 0..write_region.height() {
|
|
|
+ let write_offset = ((y + write_region.min.y) * self.row_stride() as i32) as usize;
|
|
|
+ let read_offset = ((y + read_region.min.y) * amap.row_stride() as i32) as usize;
|
|
|
+
|
|
|
+ let write_offset = write_offset + (write_region.min.x as usize) * PF::PIXEL_WIDTH;
|
|
|
+ let read_offset = read_offset + (read_region.min.x as usize) * PF::PIXEL_WIDTH;
|
|
|
+
|
|
|
+ self.data_mut()[write_offset..(write_offset + row_width)]
|
|
|
+ .copy_from_slice(&amap.data()[read_offset..(read_offset + row_width)]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl<PF: PixelFormat, T: BitmapMutAccess<PF> + Writable<PF>> Paintable<PF> for T {}
|
|
|
+
|
|
|
+/// A8-specific painting trait.
|
|
|
pub trait AlphaPaintable: BitmapMutAccess<A8> + Writable<A8, ReadResult = u8> {
|
|
|
+ /*
|
|
|
fn fill(&mut self, with: u8) {
|
|
|
self.data_mut().fill(with);
|
|
|
}
|
|
@@ -49,39 +109,15 @@ pub trait AlphaPaintable: BitmapMutAccess<A8> + Writable<A8, ReadResult = u8> {
|
|
|
.copy_from_slice(&amap.data()[read_offset..(read_offset + row_width)]);
|
|
|
}
|
|
|
}
|
|
|
+ */
|
|
|
}
|
|
|
|
|
|
impl<T: BitmapMutAccess<A8>> AlphaPaintable for T {}
|
|
|
|
|
|
-/// RGBA32-specific painting struct.
|
|
|
+/// RGBA32-specific painting trait.
|
|
|
pub trait RgbaPaintable:
|
|
|
BitmapAccess<Rgba32> + BitmapMutAccess<Rgba32> + Writable<Rgba32, ReadResult = Colour>
|
|
|
{
|
|
|
- /// Fill the entire image with a given colour.
|
|
|
- fn fill(&mut self, col: Colour) {
|
|
|
- for y in 0..self.height() {
|
|
|
- for x in 0..self.width() {
|
|
|
- self.set_pixel(x, y, col);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// Fill a region with a given colour.
|
|
|
- fn fill_region(&mut self, region: &math::PixelBox, col: Colour) {
|
|
|
- let image_box =
|
|
|
- math::PixelBox::from_origin_and_size(math::PixelPoint::origin(), self.size());
|
|
|
- let Some(isect) = region.intersection(&image_box) else {
|
|
|
- // nothing to do
|
|
|
- return;
|
|
|
- };
|
|
|
-
|
|
|
- for y in isect.y_range() {
|
|
|
- for x in isect.x_range() {
|
|
|
- self.set_pixel(x as usize, y as usize, col);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/// Fill a region with a given colour, using the values from an alphamap as the alpha value.
|
|
|
fn fill_masked(
|
|
|
&mut self,
|