use qcell::{QCell, QCellOwner};
use std::rc::Rc;
use std::sync::OnceLock;
use crate::core::palette::Palette;
static PALETTE_TOKEN: OnceLock<QCellOwner> = OnceLock::new();
pub fn palette_token() -> &'static QCellOwner {
PALETTE_TOKEN.get_or_init(QCellOwner::new)
}
#[derive(Clone)]
pub struct PaletteChainNode {
inner: Rc<QCell<PaletteChainData>>,
}
impl std::fmt::Debug for PaletteChainNode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PaletteChainNode").finish_non_exhaustive()
}
}
struct PaletteChainData {
palette: Option<Palette>,
parent: Option<PaletteChainNode>,
}
impl PaletteChainNode {
pub fn new(
palette: Option<Palette>,
parent: Option<PaletteChainNode>,
) -> Self {
Self {
inner: Rc::new(QCell::new(palette_token(), PaletteChainData { palette, parent })),
}
}
pub fn remap_color(&self, mut color: u8) -> u8 {
let token = palette_token();
let data = self.inner.ro(token);
if let Some(ref palette) = data.palette {
if !palette.is_empty() && (color as usize) <= palette.len() {
let remapped = palette.get(color as usize);
if remapped == 0 {
return 0; }
color = remapped;
}
}
if let Some(ref parent) = data.parent {
parent.remap_color(color)
} else {
color
}
}
}