mindustry logic execution, map- and schematic- parsing and rendering
rework imageholder and use dynimages
bendn 6 months ago
parent e17962e · commit 80eaf5e
-rw-r--r--mindus/Cargo.toml5
-rw-r--r--mindus/build.rs4
-rw-r--r--mindus/src/block/distribution.rs3
-rw-r--r--mindus/src/block/logic.rs15
-rw-r--r--mindus/src/block/mod.rs18
-rw-r--r--mindus/src/data/map.rs20
-rw-r--r--mindus/src/data/renderer.rs83
-rw-r--r--mindus/src/data/schematic.rs4
-rw-r--r--mindus/src/lib.rs1
-rw-r--r--mindus/src/unit.rs2
-rw-r--r--mindus/src/utils/image/holder.rs140
-rw-r--r--mindus/src/utils/image/mod.rs6
-rw-r--r--mindus/src/utils/mod.rs2
13 files changed, 109 insertions, 194 deletions
diff --git a/mindus/Cargo.toml b/mindus/Cargo.toml
index 093008d..c69b6b8 100644
--- a/mindus/Cargo.toml
+++ b/mindus/Cargo.toml
@@ -29,11 +29,12 @@ fimg = { version = "0.4.33", features = [
"scale",
"blur",
"save",
-], default-features = false }
+], default-features = false, path = "../../fimg" }
atools = "0.1.6"
either = "1.15.0"
implicit-fn = "0.1.0"
lower = "0.2.0"
+car = "0.1.3"
[features]
bin = ["fimg/save"]
@@ -45,7 +46,7 @@ fimg = { version = "0.4.33", features = [
"scale",
"blur",
"save",
-], default-features = false }
+], default-features = false, path = "../../fimg" }
walkdir = "2"
[[bin]]
diff --git a/mindus/build.rs b/mindus/build.rs
index b2dc4a2..3494c0d 100644
--- a/mindus/build.rs
+++ b/mindus/build.rs
@@ -1,4 +1,3 @@
-#![feature(let_chains)]
use fimg::DynImage;
use std::fs::File;
use std::io::Write as _;
@@ -81,7 +80,7 @@ fn main() {
{
continue;
}
- let rgb = path.components().any(|c| c.as_os_str() == "floors");
+ // let rgb = path.components().any(|c| c.as_os_str() == "floors");
let env = path.components().any(|c| c.as_os_str() == "environment");
let path = kebab2bigsnek(
path.with_extension("")
@@ -136,6 +135,7 @@ fn main() {
} else {
p.scale::<fimg::scale::Nearest>(mx / $scale, my / $scale)
};
+ let rgb = env && matches!(p, DynImage::Rgb(_));
let x = new.width();
let y = new.height();
if rgb {
diff --git a/mindus/src/block/distribution.rs b/mindus/src/block/distribution.rs
index fd7064e..b2c67f1 100644
--- a/mindus/src/block/distribution.rs
+++ b/mindus/src/block/distribution.rs
@@ -208,7 +208,8 @@ impl BlockLogic for ItemBlock {
unsafe { p.overlay(top.tint(item.color())) };
if name == "duct-unloader" {
unsafe {
- p.overlay(&load!("duct-unloader-arrows", s).rotate(rot.rotated(false).count()));
+ let mut x = load!("duct-unloader-arrows", s);
+ p.overlay(&*x.rotate(rot.rotated(false).count()));
}
}
return p;
diff --git a/mindus/src/block/logic.rs b/mindus/src/block/logic.rs
index 6e4a110..126dfcd 100644
--- a/mindus/src/block/logic.rs
+++ b/mindus/src/block/logic.rs
@@ -4,7 +4,7 @@ use std::string::FromUtf8Error;
use crate::block::simple::*;
use crate::data::dynamic::DynType;
-use crate::{block::*, Serializable};
+use crate::{Serializable, block::*};
use crate::data::{self, CompressError, DataRead, DataWrite};
@@ -143,7 +143,7 @@ impl BlockLogic for CanvasBlock {
(s * self.size as u32) - offset * 2,
);
let mut borders = load!("canvas", s);
- unsafe { borders.overlay_at(&ImageHolder::from(img), offset, offset) };
+ unsafe { borders.overlay_at(&img, offset, offset) };
return borders;
}
@@ -153,7 +153,7 @@ impl BlockLogic for CanvasBlock {
(*r, *g, *b) = PALETTE[0];
*a = 255;
}
- ImageHolder::from(def)
+ unsafe { def.mapped(crate::utils::Cow::Own) }
}
/// format:
@@ -601,14 +601,13 @@ make_simple!(TileableDisplay, |_,
use std::simd::prelude::*;
let mut b = load!("tile-logic-display", s);
unsafe {
- b.overlay(&ImageHolder::from(
- BITMASKS[u8x8::from_array(
+ b.overlay(
+ &BITMASKS[u8x8::from_array(
swizzled.map(|x| x.is_some_and(|x| x.0.name() == "tile-logic-display") as u8),
)
.simd_eq(u8x8::splat(1))
- .to_bitmask() as usize][s as usize]
- .copy(),
- ))
+ .to_bitmask() as usize][s as usize],
+ )
};
b
});
diff --git a/mindus/src/block/mod.rs b/mindus/src/block/mod.rs
index 05fe780..6ebf7a6 100644
--- a/mindus/src/block/mod.rs
+++ b/mindus/src/block/mod.rs
@@ -2,6 +2,7 @@
//!
//! different block types are organized into modules
use bobbin_bits::U4::{self, B0000, B0001, B0010, B0100, B1000};
+use fimg::DynImage;
use std::error::Error;
use std::fmt;
@@ -10,6 +11,7 @@ use crate::data::map::Build;
use crate::data::{self, CompressError, renderer::*};
use crate::data::{DataRead, GridPos, ReadError as DataReadError};
use crate::item::storage::ItemStorage;
+use crate::utils::Cow;
macro_rules! mods {
($($mod:ident)*) => {
@@ -304,7 +306,7 @@ impl SerializeError {
/// a block. put it in stuff!
pub struct Block {
- image: Option<[Image<&'static [u8], 4>; 3]>,
+ image: Option<[DynImage<&'static [u8]>; 3]>,
name: &'static str,
logic: BlockLogicEnum,
}
@@ -322,7 +324,7 @@ impl Block {
pub(crate) const fn new(
name: &'static str,
logic: BlockLogicEnum,
- image: Option<[Image<&'static [u8], 4>; 3]>,
+ image: Option<[DynImage<&'static [u8]>; 3]>,
) -> Self {
Self { image, name, logic }
}
@@ -365,11 +367,11 @@ impl Block {
context: Option<&RenderingContext>,
rot: Rotation,
scale: Scale,
- ) -> ImageHolder<4> {
+ ) -> DynImage<Cow> {
if let Some(imgs) = &self.image {
- return ImageHolder::from((imgs[scale as usize]).copy());
+ return unsafe { imgs[scale as usize].mapped(Cow::Ref) };
}
- self.logic.draw(self.name, state, context, rot, scale)
+ DynImage::Rgba(self.logic.draw(self.name, state, context, rot, scale))
}
/// size.
@@ -617,18 +619,18 @@ macro_rules! make_register {
};
(impl $field: literal -> $logic: expr) => {
paste::paste! { pub static [<$field:snake:upper>]: Block = Block::new(
- $field, <crate::block::BlockLogicEnum as crate::block::ConstFrom<_>>::fro($logic), Some(crate::data::renderer::load!($field))
+ $field, <crate::block::BlockLogicEnum as crate::block::ConstFrom<_>>::fro($logic), Some(car::map!(crate::data::renderer::load!($field), DynImage::from))
); }
};
(impl $field: literal : $size: literal) => {
paste::paste! { pub static [<$field:snake:upper>]: Block = Block::new(
- $field, BlockLogicEnum::BasicBlock(BasicBlock::new($size, true, &[])), Some(crate::data::renderer::load!($field))
+ $field, BlockLogicEnum::BasicBlock(BasicBlock::new($size, true, &[])), Some(car::map!(crate::data::renderer::load!($field), DynImage::from))
); }
};
// floors
(impl $field: literal > $size: literal) => {
paste::paste! { pub static [<$field:snake:upper>]: Block = Block::new(
- $field, BlockLogicEnum::BasicBlock(BasicBlock::new($size, true, &[])), Some(crate::data::renderer::load!("empty4"))
+ $field, BlockLogicEnum::BasicBlock(BasicBlock::new($size, true, &[])), Some(car::map!(crate::data::renderer::load!("empty4"), DynImage::from))
); }
};
}
diff --git a/mindus/src/data/map.rs b/mindus/src/data/map.rs
index 68b5d3b..6550ced 100644
--- a/mindus/src/data/map.rs
+++ b/mindus/src/data/map.rs
@@ -111,7 +111,7 @@ pub struct Tile {
macro_rules! lo {
($v:expr => [$(|)? $($k:literal $(|)?)+], $scale: ident) => { paste::paste! {
match $v {
- $(BlockEnum::[<$k:camel>] => Some(load!(raw $k, $scale)),)+
+ $(BlockEnum::[<$k:camel>] => Some(DynImage::from(load!(raw $k, $scale))),)+
_ => None,
}
} };
@@ -119,7 +119,7 @@ macro_rules! lo {
#[inline]
pub(crate) fn ore(ore: BlockEnum, s: Scale) -> DynImage<&'static [u8]> {
- lo!(ore => ["ore-copper" | "ore-beryllium" | "ore-lead" | "ore-scrap" | "ore-coal" | "ore-thorium" | "ore-titanium" | "ore-tungsten" | "pebbles" | "tendrils" | "ore-wall-tungsten" | "ore-wall-beryllium" | "ore-wall-thorium" | "spawn" | "ore-crystal-thorium"], s).map(DynImage::Rgba).unwrap_or_else(|| floor(ore, s))
+ lo!(ore => ["ore-copper" | "ore-beryllium" | "ore-lead" | "ore-scrap" | "ore-coal" | "ore-thorium" | "ore-titanium" | "ore-tungsten" | "pebbles" | "tendrils" | "ore-wall-tungsten" | "ore-wall-beryllium" | "ore-wall-thorium" | "spawn" | "ore-crystal-thorium"], s).unwrap_or_else(|| floor(ore, s))
}
#[inline]
@@ -127,7 +127,7 @@ pub(crate) fn floor(tile: BlockEnum, s: Scale) -> DynImage<&'static [u8]> {
macro_rules! x {
($($x:literal)+) => { paste::paste! {
match tile {
- $(BlockEnum::[<$x:camel>] => return DynImage::Rgb(load!(raw $x, s)),)+
+ $(BlockEnum::[<$x:camel>] => return DynImage::from(load!(raw $x, s)),)+
_ => {}
}
}};
@@ -168,7 +168,7 @@ pub(crate) fn floor(tile: BlockEnum, s: Scale) -> DynImage<&'static [u8]> {
| "red-stone" | "red-stone-vent" | "dense-red-stone"
| "carbon-stone" | "carbon-vent"
| "crystal-floor" | "crystalline-stone" | "crystalline-vent"
- | "empty"], s).map(DynImage::Rgb).unwrap_or_else(|| ore(tile, s))
+ | "empty"], s).unwrap_or_else(|| ore(tile, s))
}
impl Tile {
@@ -230,7 +230,11 @@ impl Tile {
/// Draw this tiles build.
#[must_use]
#[inline]
- pub fn build_image(&self, context: Option<&RenderingContext>, s: Scale) -> ImageHolder<4> {
+ pub fn build_image(
+ &self,
+ context: Option<&RenderingContext>,
+ s: Scale,
+ ) -> DynImage<image::Cow> {
// building covers floore
let Some(b) = &self.build else {
unreachable!();
@@ -316,7 +320,7 @@ impl Build {
}
}
- fn image(&self, context: Option<&RenderingContext>, s: Scale) -> ImageHolder<4> {
+ fn image(&self, context: Option<&RenderingContext>, s: Scale) -> DynImage<image::Cow> {
self.block
.image(self.state.as_ref(), context, self.rotation, s)
}
@@ -577,8 +581,8 @@ macro_rules! tiles {
while i < $count {
let floor_id = $me.buff.read_u16()?;
let overlay_id = $me.buff.read_u16()?;
- let &(mut floor) = $r.get(floor_id as usize).unwrap_or(&BlockEnum::Stone);
- let &(mut ore) = $r.get(overlay_id as usize).unwrap_or(&BlockEnum::Air);
+ let &floor = $r.get(floor_id as usize).unwrap_or(&BlockEnum::Stone);
+ let &ore = $r.get(overlay_id as usize).unwrap_or(&BlockEnum::Air);
yield $w::Tile { floor, ore };
let consecutives = $me.buff.read_u8()? as usize;
for _ in 0..consecutives {
diff --git a/mindus/src/data/renderer.rs b/mindus/src/data/renderer.rs
index 493500c..0452fa7 100644
--- a/mindus/src/data/renderer.rs
+++ b/mindus/src/data/renderer.rs
@@ -63,11 +63,11 @@ macro_rules! load {
}
} };
($name:literal, $scale:expr) => { paste::paste! {
- $crate::utils::image::ImageHolder::from(match $scale {
+ #[allow(unused_unsafe)] unsafe { match $scale {
$crate::data::renderer::Scale::Quarter => &$crate::data::renderer::quar::[<$name:snake:upper>],
$crate::data::renderer::Scale::Eigth => &$crate::data::renderer::eigh::[<$name:snake:upper>],
$crate::data::renderer::Scale::Full => &$crate::data::renderer::full::[<$name:snake:upper>],
- }.copy())
+ }.mapped($crate::utils::Cow::Ref) }
} };
($name: ident) => { paste::paste! {
[$crate::data::renderer::full::[<$name:snake:upper>].copy(), $crate::data::renderer::quar::[<$name:snake:upper>].copy(), $crate::data::renderer::eigh::[<$name:snake:upper>].copy()]
@@ -91,11 +91,11 @@ macro_rules! load {
(concat $x:literal => $v:ident which is [$($k:literal $(|)?)+], $scale: ident) => { paste::paste! {
match $v {
$($k =>
- ImageHolder::from(match $scale {
+ #[allow(unused_unsafe)] unsafe { (match $scale {
$crate::data::renderer::Scale::Quarter => &$crate::data::renderer::quar::[<$k:snake:upper _ $x:snake:upper>],
$crate::data::renderer::Scale::Eigth => &$crate::data::renderer::eigh::[<$k:snake:upper _ $x:snake:upper>],
$crate::data::renderer::Scale::Full => &$crate::data::renderer::full::[<$k:snake:upper _ $x:snake:upper>],
- }.copy()),
+ }.mapped($crate::utils::Cow::Ref)) },
)+
#[allow(unreachable_patterns)]
n => unreachable!("{n:?}"),
@@ -137,7 +137,7 @@ impl Renderable for Schematic {
* self.width.checked_sub(self.height).unwrap_or(0) as u32
+ 2;
let mut bg = unsafe {
- load!("metal-floor", scale).borrow().repeated(
+ load!("metal-floor", scale).repeated(
scale * (self.width + x_fac as usize) as u32,
scale * (self.height + y_fac as usize) as u32,
)
@@ -161,13 +161,11 @@ impl Renderable for Schematic {
let y = self.height as u32 - y as u32 - ((tile.block.get_size() / 2) + 1) as u32;
unsafe {
canvas.as_mut().overlay_at(
- &tile
- .image(
- ctx.as_ref(),
- tile.get_rotation().unwrap_or(Rotation::Up),
- scale,
- )
- .borrow(),
+ &tile.image(
+ ctx.as_ref(),
+ tile.get_rotation().unwrap_or(Rotation::Up),
+ scale,
+ ),
scale * (x + x_fac / 2),
scale * (y + y_fac / 2),
)
@@ -217,7 +215,8 @@ impl Renderable for Schematic {
*/
if relative.1 != 0 {
// continue;
- bridge = bridge.swap_wh();
+ bridge =
+ Image::build(bridge.height(), bridge.width()).buf(bridge.take_buffer());
}
let arrow = load!(concat "arrow" => n which is ["bridge-conveyor"| "bridge-conduit" | "phase-conveyor" | "phase-conduit" | "duct-bridge" | "reinforced-bridge-conduit"], scale);
/*
@@ -241,7 +240,7 @@ impl Renderable for Schematic {
} {
unsafe {
canvas.overlay_blended_at(
- &bridge.borrow(),
+ &bridge,
(p.0 as i32 * scale.px() as i32 + index) as u32,
scale * (self.height as u32 - p.1 as u32 - 1 + y_fac / 2),
)
@@ -260,25 +259,19 @@ impl Renderable for Schematic {
((self.height as i32 - p.1 as i32 + 1) * scale.px() as i32 + index) as u32;
unsafe {
- canvas.overlay_blended_at(
- &bridge.borrow(),
- scale * (p.0 as u32 + x_fac / 2),
- y,
- )
+ canvas.overlay_blended_at(&bridge, scale * (p.0 as u32 + x_fac / 2), y)
};
}
if relative.0 != 0 {
unsafe {
canvas.overlay_blended_at(
- &arrow
- .rotated(if directional {
- b.rot.rotated(false).count()
- } else if relative.0 < 0 {
- 2
- } else {
- 0
- })
- .borrow(),
+ &arrow.rotated(if directional {
+ b.rot.rotated(false).count()
+ } else if relative.0 < 0 {
+ 2
+ } else {
+ 0
+ }),
scale.px() as u32
+ ((scale * p.0 as u32).cast_signed()
+ (scale.px() as i32 * relative.0 / 2))
@@ -289,15 +282,13 @@ impl Renderable for Schematic {
} else {
unsafe {
canvas.overlay_blended_at(
- &arrow
- .rotated(if directional {
- b.rot.rotated(false).count()
- } else if relative.1 < 0 {
- 1
- } else {
- 3
- })
- .borrow(),
+ &arrow.rotated(if directional {
+ b.rot.rotated(false).count()
+ } else if relative.1 < 0 {
+ 1
+ } else {
+ 3
+ }),
(scale * p.0 as u32) + (x_fac / 2 + scale.px() as u32) - 1,
scale.px() as u32
+ ((scale * (self.height as u32 - p.1 as u32 - 1)).cast_signed()
@@ -310,7 +301,7 @@ impl Renderable for Schematic {
}
if matches!(scale, Scale::Full) {
- canvas.as_mut().shadow();
+ ImageUtils::shadow(&mut canvas);
unsafe { bg.overlay_blended(&canvas) };
} else {
unsafe { bg.overlay(&canvas) };
@@ -401,11 +392,9 @@ impl Renderable for Map {
const LETTERS: [[Image<&[u8], 4>; 3]; 64] = f![0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63];
unsafe {
img.overlay_at(
- &ImageHolder::from(
- LETTERS[(tile.nd[2] & 0x3f) as usize][scale as usize],
- )
- .rotate(tile.nd[2] & 0x3)
- .borrow(),
+ LETTERS[(tile.nd[2] & 0x3f) as usize][scale as usize]
+ .mapped(image::Cow::Ref)
+ .rotate(tile.nd[2] & 0x3),
scale * x as u32,
scale * y as u32,
)
@@ -493,7 +482,7 @@ impl Renderable for Map {
});
unsafe {
img.as_mut().overlay_at(
- &tile.build_image(ctx.as_ref(), scale).borrow(),
+ &tile.build_image(ctx.as_ref(), scale),
scale * x as u32,
scale * y as u32,
)
@@ -513,7 +502,7 @@ impl Renderable for Map {
}
unsafe {
img.as_mut()
- .overlay_at(&entity.draw(scale).borrow(), scale * x, scale * y)
+ .overlay_at(&entity.draw(scale), scale * x, scale * y)
};
}
img
@@ -591,7 +580,7 @@ pub fn draw_units(
}
unsafe {
img.as_mut()
- .overlay_at(&entity.draw(scale).borrow(), scale * x, scale * y)
+ .overlay_at(&entity.draw(scale), scale * x, scale * y)
};
}
Complete(Err(e)) => return Err(e),
@@ -706,7 +695,7 @@ pub fn draw_map_single(
});
unsafe {
img.as_mut().overlay_at(
- &b.image(None, ctx.as_ref(), r, scale).borrow(),
+ &b.image(None, ctx.as_ref(), r, scale),
scale * x as u32,
scale * y as u32,
)
diff --git a/mindus/src/data/schematic.rs b/mindus/src/data/schematic.rs
index 9553d67..aded36b 100644
--- a/mindus/src/data/schematic.rs
+++ b/mindus/src/data/schematic.rs
@@ -1,4 +1,5 @@
//! schematic parsing
+use fimg::DynImage;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::fmt::{self, Write};
@@ -12,6 +13,7 @@ use crate::data::renderer::*;
use crate::data::{self, DataRead, DataWrite, GridPos, Serializable};
use crate::item::storage::ItemStorage;
use crate::utils::array::Array2D;
+use crate::utils::Cow;
/// biggest schematic
pub const MAX_DIMENSION: usize = 1024;
@@ -67,7 +69,7 @@ impl Placement {
context: Option<&RenderingContext>,
rot: Rotation,
s: Scale,
- ) -> ImageHolder<4> {
+ ) -> DynImage<Cow> {
self.block.image(self.get_state(), context, rot, s)
}
diff --git a/mindus/src/lib.rs b/mindus/src/lib.rs
index d4c0abd..db900c2 100644
--- a/mindus/src/lib.rs
+++ b/mindus/src/lib.rs
@@ -9,6 +9,7 @@
likely_unlikely,
portable_simd,
derive_const,
+ const_from,
coroutines
)]
#![allow(clippy::redundant_closure_call, incomplete_features)]
diff --git a/mindus/src/unit.rs b/mindus/src/unit.rs
index 6a27b1d..0343b5b 100644
--- a/mindus/src/unit.rs
+++ b/mindus/src/unit.rs
@@ -1,6 +1,7 @@
//! units
//!
//! [source](https://github.com/Anuken/Mindustry/blob/master/core/src/mindustry/content/UnitTypes.java)
+use crate::Serializable;
use crate::block::payload::read_payload;
use crate::content::content_enum;
use crate::data::command::UnitCommand;
@@ -11,7 +12,6 @@ use crate::item::Type as Item;
use crate::modifier::Type as Status;
use crate::team::Team;
use crate::utils::ImageHolder;
-use crate::Serializable;
macro_rules! units {
($($unit:literal,)+ $(,)?) => { paste::paste! {
diff --git a/mindus/src/utils/image/holder.rs b/mindus/src/utils/image/holder.rs
index 6618009..45aab38 100644
--- a/mindus/src/utils/image/holder.rs
+++ b/mindus/src/utils/image/holder.rs
@@ -1,132 +1,48 @@
-use super::{ClonerOverlay, ClonerOverlayAt, Image, ImageUtils, Overlay, OverlayAt};
+use super::Image;
+
#[derive(Clone, Debug)]
-pub enum ImageHolder<const CHANNELS: usize> {
- Borrow(Image<&'static [u8], CHANNELS>),
- Own(Image<Box<[u8]>, CHANNELS>),
+pub enum Cow {
+ Ref(&'static [u8]),
+ Own(Box<[u8]>),
}
-
-impl<const CHANNELS: usize> ImageHolder<CHANNELS> {
- #[must_use]
- pub fn own(self) -> Image<Box<[u8]>, CHANNELS> {
- match self {
- Self::Own(x) => x,
- Self::Borrow(x) => x.boxed(),
- }
+impl From<&'static [u8]> for Cow {
+ fn from(value: &'static [u8]) -> Self {
+ Self::Ref(value)
}
}
-
-impl<const CHANNELS: usize> ImageHolder<CHANNELS> {
- pub fn swap_wh(self) -> Self {
- match self {
- ImageHolder::Borrow(image) => {
- ImageHolder::Borrow(Image::build(image.height(), image.width()).buf(image.buffer()))
- }
- ImageHolder::Own(image) => ImageHolder::Own(
- Image::build(image.height(), image.width()).buf(image.take_buffer()),
- ),
- }
+impl From<Box<[u8]>> for Cow {
+ fn from(value: Box<[u8]>) -> Self {
+ Self::Own(value)
}
}
-impl<const CHANNELS: usize> ImageHolder<CHANNELS> {
- #[must_use]
- #[inline]
- pub fn borrow(&self) -> Image<&[u8], CHANNELS> {
+impl Cow {
+ pub fn own(self) -> Box<[u8]> {
match self {
- Self::Own(x) => x.as_ref(),
- Self::Borrow(x) => *x,
+ Self::Own(x) => x,
+ Self::Ref(x) => x.into(),
}
}
-
- #[must_use]
- #[inline]
- pub fn borrow_mut(&mut self) -> Image<&mut [u8], CHANNELS> {
+}
+impl AsRef<[u8]> for Cow {
+ fn as_ref(&self) -> &[u8] {
match self {
- Self::Own(x) => x.as_mut(),
- Self::Borrow(x) => {
- *self = Self::from(x.boxed());
- self.borrow_mut()
- }
+ Cow::Ref(x) => x,
+ Cow::Own(x) => &x,
}
}
}
-macro_rules! make {
- ($me: ident . $fn:ident($($argv:expr),*)) => {
- match $me {
- Self::Own(v) => {
- #[allow(unused_unsafe)]
- unsafe { v.as_mut().$fn($($argv,)*) };
- $me
- }
- Self::Borrow(v) => {
- #[allow(unused_unsafe)]
- { *$me = Self::from(unsafe { v.cloner().$fn($($argv,)*).boxed() }) };
- $me
+impl AsMut<[u8]> for Cow {
+ fn as_mut(&mut self) -> &mut [u8] {
+ match self {
+ Cow::Ref(x) => {
+ *self = Self::Own((*x).into());
+ self.as_mut()
}
- }
- };
-}
-
-impl OverlayAt<ImageHolder<4>> for ImageHolder<4> {
- unsafe fn overlay_at(&mut self, with: &ImageHolder<4>, x: u32, y: u32) -> &mut Self {
- make!(self.overlay_at(&with.borrow(), x, y))
- }
-}
-
-impl OverlayAt<Image<&[u8], 3>> for ImageHolder<3> {
- unsafe fn overlay_at(&mut self, with: &Image<&[u8], 3>, x: u32, y: u32) -> &mut Self {
- make!(self.overlay_at(with, x, y))
- }
-}
-
-impl Overlay<Image<&[u8], 4>> for ImageHolder<3> {
- unsafe fn overlay(&mut self, with: &Image<&[u8], 4>) -> &mut Self {
- make!(self.overlay(with))
- }
-}
-
-impl Overlay<ImageHolder<4>> for ImageHolder<3> {
- unsafe fn overlay(&mut self, with: &ImageHolder<4>) -> &mut Self {
- make!(self.overlay(&with.borrow()))
- }
-}
-
-impl Overlay<ImageHolder<4>> for ImageHolder<4> {
- unsafe fn overlay(&mut self, with: &Self) -> &mut Self {
- make!(self.overlay(&with.borrow()))
- }
-}
-
-impl ImageUtils for ImageHolder<4> {
- fn tint(&mut self, color: (u8, u8, u8)) -> &mut Self {
- self.borrow_mut().tint(color);
- self
- }
-
- unsafe fn rotate(&mut self, times: u8) -> &mut Self {
- match times {
- 2 => make!(self.rot_180()),
- 1 => make!(self.rot_90()),
- 3 => make!(self.rot_270()),
- _ => self,
+ Cow::Own(x) => x,
}
}
-
- fn shadow(&mut self) -> &mut Self {
- self.borrow_mut().shadow();
- self
- }
}
-impl<const CHANNELS: usize> From<Image<&'static [u8], CHANNELS>> for ImageHolder<CHANNELS> {
- fn from(value: Image<&'static [u8], CHANNELS>) -> Self {
- Self::Borrow(value)
- }
-}
-
-impl<const CHANNELS: usize> From<Image<Box<[u8]>, CHANNELS>> for ImageHolder<CHANNELS> {
- fn from(value: Image<Box<[u8]>, CHANNELS>) -> Self {
- Self::Own(value)
- }
-}
+pub type ImageHolder<const CHANNELS: usize> = Image<Cow, CHANNELS>;
diff --git a/mindus/src/utils/image/mod.rs b/mindus/src/utils/image/mod.rs
index e9dcc10..c7754c3 100644
--- a/mindus/src/utils/image/mod.rs
+++ b/mindus/src/utils/image/mod.rs
@@ -1,7 +1,7 @@
pub use fimg::*;
mod holder;
-pub use holder::ImageHolder;
+pub use holder::*;
pub trait ImageUtils {
/// Tint this image with the color
@@ -22,7 +22,7 @@ pub trait ImageUtils {
fn shadow(&mut self) -> &mut Self;
}
-impl ImageUtils for Image<&mut [u8], 4> {
+impl<T: AsMut<[u8]> + AsRef<[u8]>> ImageUtils for Image<T, 4> {
unsafe fn rotate(&mut self, times: u8) -> &mut Self {
match times {
2 => self.rot_180(),
@@ -44,7 +44,7 @@ impl ImageUtils for Image<&mut [u8], 4> {
}
fn shadow(&mut self) -> &mut Self {
- let mut shadow = self.to_owned().boxed();
+ let mut shadow = self.as_ref().boxed();
for [r, g, b, a] in shadow.chunked_mut() {
if *a < 128 {
*r /= 10;
diff --git a/mindus/src/utils/mod.rs b/mindus/src/utils/mod.rs
index 3e12541..7183f0e 100644
--- a/mindus/src/utils/mod.rs
+++ b/mindus/src/utils/mod.rs
@@ -1,3 +1,3 @@
pub mod array;
pub mod image;
-pub use self::image::{Image, ImageHolder, ImageUtils, Overlay, OverlayAt};
+pub use self::image::{Cow, Image, ImageHolder, ImageUtils, Overlay, OverlayAt};