use super::bitmap::BitmapRef;
use crate::capi_state::CApiState;
use crate::ctypes::*;
const PATTERN_SIZE: usize = 8 + 8;
#[derive(Debug)]
pub enum Color<'a> {
Solid(SolidColor),
Pattern(&'a Pattern),
}
impl Color<'_> {
pub(crate) unsafe fn to_c_color(&self) -> usize {
match self {
Color::Solid(solid) => solid.0 as usize,
Color::Pattern(pattern) => pattern.0.as_ptr() as usize,
}
}
}
impl From<SolidColor> for Color<'_> {
fn from(color: SolidColor) -> Self {
Color::Solid(color)
}
}
impl<'a> From<&'a Pattern> for Color<'a> {
fn from(pattern: &'a Pattern) -> Self {
Color::Pattern(&pattern)
}
}
#[derive(Debug)]
#[repr(transparent)]
pub struct Pattern(CLCDPattern);
impl Pattern {
pub fn new_unmasked(colors: [PixelColor; 8 * 8]) -> Self {
let mut arr = [0; PATTERN_SIZE];
let mut bit = 0;
let mut byte = 0;
for color in colors {
let shift = 7 - bit;
arr[byte] |= (color.to_bit() as u8) << shift;
bit = (bit + 1) % 8;
if bit == 0 {
byte += 1;
}
}
debug_assert_eq!(byte, PATTERN_SIZE / 2);
debug_assert_eq!(bit, 0);
for b in &mut arr[PATTERN_SIZE / 2..] {
*b = 0xff
}
Pattern(arr)
}
pub fn new_masked(colors: [Option<PixelColor>; 8 * 8]) -> Self {
let mut arr = [0; PATTERN_SIZE];
let mut bit = 0;
let mut byte = 0;
for c in colors {
if let Some(color) = c {
let shift = 7 - bit;
arr[byte] |= (color.to_bit() as u8) << shift;
arr[byte + PATTERN_SIZE / 2] |= 1 << shift;
}
bit = (bit + 1) % 8;
if bit == 0 {
byte += 1;
}
}
debug_assert_eq!(byte, PATTERN_SIZE / 2);
debug_assert_eq!(bit, 0);
Pattern(arr)
}
pub fn from_raw_array(arr: [u8; PATTERN_SIZE]) -> Self {
Pattern(arr)
}
pub fn from_bitmap(bitmap: &BitmapRef, x: i32, y: i32) -> Pattern {
let mut arr = [0; PATTERN_SIZE];
let mut c_color: CLCDColor = 0;
unsafe {
CApiState::get().cgraphics.setColorToPattern.unwrap()(
&mut c_color,
bitmap.cptr() as *mut _,
x,
y,
);
core::ptr::copy_nonoverlapping(c_color as *const u8, arr.as_mut_ptr(), PATTERN_SIZE);
}
Pattern(arr)
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct PixelColor(bool);
impl PixelColor {
#[inline]
pub const fn to_bit(self) -> bool {
use static_assertions::*;
const_assert_eq!(SolidColor::kColorBlack.0, 0);
const_assert_eq!(SolidColor::kColorWhite.0, 1);
self.0
}
pub const BLACK: PixelColor = PixelColor(false);
pub const WHITE: PixelColor = PixelColor(true);
}
impl From<bool> for PixelColor {
fn from(b: bool) -> Self {
Self(b)
}
}
impl core::fmt::Debug for PixelColor {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let s = if self.0 == false { "BLACK" } else { "WHITE" };
f.debug_tuple("PixelColor").field(&s).finish()
}
}