mindustry logic execution, map- and schematic- parsing and rendering
make blend() faster
bendn 2023-10-05
parent 744a897 · commit d7dc1ad
-rw-r--r--mindus/Cargo.toml1
-rw-r--r--mindus/src/data/dynamic.rs7
-rw-r--r--mindus/src/data/schematic.rs3
-rw-r--r--mindus/src/utils/image/holder.rs2
-rw-r--r--mindus/src/utils/image/mod.rs47
5 files changed, 34 insertions, 26 deletions
diff --git a/mindus/Cargo.toml b/mindus/Cargo.toml
index b10ae99..9c77e79 100644
--- a/mindus/Cargo.toml
+++ b/mindus/Cargo.toml
@@ -26,6 +26,7 @@ blurslice = { version = "0.1" }
enum_dispatch = "0.3"
phf = { version = "0.11", features = ["macros"] }
fimg = { version = "0.4.15", default-features = false }
+umath = "0.0.1"
[features]
bin = ["fimg/save"]
diff --git a/mindus/src/data/dynamic.rs b/mindus/src/data/dynamic.rs
index b328f8a..05652ba 100644
--- a/mindus/src/data/dynamic.rs
+++ b/mindus/src/data/dynamic.rs
@@ -141,10 +141,9 @@ impl Serializable for DynData {
let Ok(len) = usize::try_from(len) else {
return Err(ReadError::BoolArrayLen(len));
};
- let mut result = vec![];
- result.reserve(len);
- for _ in 0..len {
- result.push(buff.read_bool()?);
+ let mut result = vec![false; len];
+ for item in result.iter_mut() {
+ *item = buff.read_bool()?;
}
Ok(DynData::from(result))
}
diff --git a/mindus/src/data/schematic.rs b/mindus/src/data/schematic.rs
index 48e388f..78da2bb 100644
--- a/mindus/src/data/schematic.rs
+++ b/mindus/src/data/schematic.rs
@@ -496,8 +496,7 @@ impl Serializable for Schematic {
if num_table < 0 {
return Err(ReadError::TableSize(num_table));
}
- let mut block_table = Vec::new();
- block_table.reserve(num_table as usize);
+ let mut block_table = Vec::with_capacity(num_table as usize);
for _ in 0..num_table {
let name = buff.read_utf()?;
match BLOCK_REGISTRY.get(name) {
diff --git a/mindus/src/utils/image/holder.rs b/mindus/src/utils/image/holder.rs
index 2a8d03b..2e18724 100644
--- a/mindus/src/utils/image/holder.rs
+++ b/mindus/src/utils/image/holder.rs
@@ -21,7 +21,7 @@ impl<const CHANNELS: usize> ImageHolder<CHANNELS> {
pub fn borrow(&self) -> Image<&[u8], CHANNELS> {
match self {
Self::Own(x) => x.as_ref(),
- Self::Borrow(x) => x.clone(),
+ Self::Borrow(x) => *x,
}
}
diff --git a/mindus/src/utils/image/mod.rs b/mindus/src/utils/image/mod.rs
index a9aa76e..f82c2b1 100644
--- a/mindus/src/utils/image/mod.rs
+++ b/mindus/src/utils/image/mod.rs
@@ -62,7 +62,7 @@ impl ImageUtils for Image<&mut [u8], 4> {
self
}
}
-
+use umath::FFloat;
pub fn blend(bg: &mut [u8; 4], fg: [u8; 4]) {
if fg[3] == 0 {
return;
@@ -71,22 +71,31 @@ pub fn blend(bg: &mut [u8; 4], fg: [u8; 4]) {
*bg = fg;
return;
}
- let bg_a = bg[3] as f32 / 255.0;
- let fg_a = fg[3] as f32 / 255.0;
- let a = bg_a + fg_a - bg_a * fg_a;
- if a == 0.0 {
- return;
- };
- *bg = [
- (255.0
- * ((((fg[0] as f32 / 255.0) * fg_a) + ((bg[0] as f32 / 255.0) * bg_a) * (1.0 - fg_a))
- / a)) as u8,
- (255.0
- * ((((fg[1] as f32 / 255.0) * fg_a) + ((bg[1] as f32 / 255.0) * bg_a) * (1.0 - fg_a))
- / a)) as u8,
- (255.0
- * ((((fg[2] as f32 / 255.0) * fg_a) + ((bg[2] as f32 / 255.0) * bg_a) * (1.0 - fg_a))
- / a)) as u8,
- (255.0 * a) as u8,
- ]
+ #[allow(clippy::multiple_unsafe_ops_per_block)]
+ // SAFETY: no u8 can possibly become INF / NAN
+ unsafe {
+ let max = FFloat::new(255.0);
+ let bg_a = FFloat::new(bg[3] as f32) / max;
+ let fg_a = FFloat::new(fg[3] as f32) / max;
+ let a = bg_a + fg_a - bg_a * fg_a;
+ if a == 0.0 {
+ return;
+ };
+ // could turn it into array::map
+ *bg = [
+ *(max
+ * ((((FFloat::new(fg[0] as f32) / max) * fg_a)
+ + ((FFloat::new(bg[0] as f32) / max) * bg_a) * (FFloat::new(1.0) - fg_a))
+ / a)) as u8,
+ *(max
+ * ((((FFloat::new(fg[1] as f32) / max) * fg_a)
+ + ((FFloat::new(bg[1] as f32) / max) * bg_a) * (FFloat::new(1.0) - fg_a))
+ / a)) as u8,
+ *(max
+ * ((((FFloat::new(fg[2] as f32) / max) * fg_a)
+ + ((FFloat::new(bg[2] as f32) / max) * bg_a) * (FFloat::new(1.0) - fg_a))
+ / a)) as u8,
+ *(max * a) as u8,
+ ]
+ }
}