diff --git a/ggdt/src/graphics/color.rs b/ggdt/src/graphics/color.rs index 997f96f..fa18f04 100644 --- a/ggdt/src/graphics/color.rs +++ b/ggdt/src/graphics/color.rs @@ -549,6 +549,16 @@ pub fn tinted_blend_argb_simd(tint: SimdColor4u8, src: SimdColor4u8, dest: SimdC /////////////////////////////////////////////////////////////////////////////// +pub trait BytesAsColors { + unsafe fn as_colors(&self) -> &[T]; + unsafe fn as_colors_mut(&mut self) -> &mut [T]; +} + +pub trait ColorsAsBytes { + fn as_bytes(&self) -> &[u8]; + fn as_bytes_mut(&mut self) -> &mut [u8]; +} + /// Unpacked 32-bit color represented as individual 8-bit color components where the components are in the /// order alpha, red, green, blue. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] @@ -696,6 +706,46 @@ impl From for ARGBu8x4 { } } +impl BytesAsColors for [u8] { + #[inline] + unsafe fn as_colors(&self) -> &[ARGBu8x4] { + std::slice::from_raw_parts( + self.as_ptr() as *const ARGBu8x4, // + self.len() / std::mem::size_of::(), + ) + } + + #[inline] + unsafe fn as_colors_mut(&mut self) -> &mut [ARGBu8x4] { + std::slice::from_raw_parts_mut( + self.as_mut_ptr() as *mut ARGBu8x4, // + self.len() / std::mem::size_of::(), + ) + } +} + +impl ColorsAsBytes for [ARGBu8x4] { + #[inline] + fn as_bytes(&self) -> &[u8] { + unsafe { + std::slice::from_raw_parts( + self.as_ptr() as *const u8, // + std::mem::size_of_val(self), + ) + } + } + + #[inline] + fn as_bytes_mut(&mut self) -> &mut [u8] { + unsafe { + std::slice::from_raw_parts_mut( + self.as_mut_ptr() as *mut u8, // + std::mem::size_of_val(self), + ) + } + } +} + /// Unpacked 32-bit color represented as individual normalized f32 color components (0.0 to 1.0) where the /// components are in the order alpha, red, green, blue. #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] @@ -1038,6 +1088,83 @@ mod tests { assert_eq!([0xff, 0xff, 0xff, 0xff], ARGBu8x4::from(0xffffffff).tint(ARGBu8x4::from(0x00112233)).to_array()); } + #[test] + fn argbu8x4_bytes_to_colors_casting() { + let mut bytes = + [0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff]; + + let colors = unsafe { bytes.as_colors() }; + assert_eq!( + colors, + [ + ARGBu8x4::from_argb([0xff, 0xff, 0x00, 0x00]), + ARGBu8x4::from_argb([0xff, 0x00, 0xff, 0x00]), + ARGBu8x4::from_argb([0xff, 0x00, 0x00, 0xff]), + ARGBu8x4::from_argb([0xff, 0xff, 0x00, 0xff]), + ] + ); + + let colors = unsafe { bytes.as_colors_mut() }; + assert_eq!( + colors, + [ + ARGBu8x4::from_argb([0xff, 0xff, 0x00, 0x00]), + ARGBu8x4::from_argb([0xff, 0x00, 0xff, 0x00]), + ARGBu8x4::from_argb([0xff, 0x00, 0x00, 0xff]), + ARGBu8x4::from_argb([0xff, 0xff, 0x00, 0xff]), + ] + ); + + // bytes slice which is NOT an exact multiple of 4 + let mut bytes = [ + 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x7f, 0x7f, + ]; + + let colors = unsafe { bytes.as_colors() }; + assert_eq!( + colors, + [ + ARGBu8x4::from_argb([0xff, 0xff, 0x00, 0x00]), + ARGBu8x4::from_argb([0xff, 0x00, 0xff, 0x00]), + ARGBu8x4::from_argb([0xff, 0x00, 0x00, 0xff]), + ARGBu8x4::from_argb([0xff, 0xff, 0x00, 0xff]), + ] + ); + + let colors = unsafe { bytes.as_colors_mut() }; + assert_eq!( + colors, + [ + ARGBu8x4::from_argb([0xff, 0xff, 0x00, 0x00]), + ARGBu8x4::from_argb([0xff, 0x00, 0xff, 0x00]), + ARGBu8x4::from_argb([0xff, 0x00, 0x00, 0xff]), + ARGBu8x4::from_argb([0xff, 0xff, 0x00, 0xff]), + ] + ); + } + + #[test] + fn argbu8x4_colors_to_bytes_casting() { + let mut colors = [ + ARGBu8x4::from_argb([0xff, 0xff, 0x00, 0x00]), + ARGBu8x4::from_argb([0xff, 0x00, 0xff, 0x00]), + ARGBu8x4::from_argb([0xff, 0x00, 0x00, 0xff]), + ARGBu8x4::from_argb([0xff, 0xff, 0x00, 0xff]), + ]; + + let bytes = colors.as_bytes(); + assert_eq!( + bytes, + [0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff] + ); + + let bytes = colors.as_bytes_mut(); + assert_eq!( + bytes, + [0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff] + ); + } + #[test] fn argbf32x4() { let mut color = ARGBf32x4(simd::f32x4::from_array([0.5, 0.1, 0.2, 0.3]));