use cranpose_ui_graphics::{Brush, Color};
const LUMINANCE_BITS: u32 = 3;
const LUMINANCE_CLASSES: usize = 1 << LUMINANCE_BITS;
type CorrectionTable = [u8; 256];
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct TextLuminance(u8);
impl TextLuminance {
pub fn of_color(color: Color) -> Self {
let channel = |value: f32| u32::from(unit_to_u8(value));
let luminance =
(channel(color.0) * 54 + channel(color.1) * 183 + channel(color.2) * 19) >> 8;
Self((luminance >> (8 - LUMINANCE_BITS)) as u8)
}
pub fn of_brush(brush: &Brush) -> Self {
match brush {
Brush::Solid(color) => Self::of_color(*color),
_ => Self::of_color(Color(0.5, 0.5, 0.5, 1.0)),
}
}
pub fn correction(self) -> MaskGammaCorrection {
MaskGammaCorrection(&CORRECTION_TABLES[usize::from(self.0)])
}
}
#[derive(Clone, Copy)]
pub struct MaskGammaCorrection(&'static CorrectionTable);
impl MaskGammaCorrection {
pub fn apply(self, coverage: u8) -> u8 {
self.0[usize::from(coverage)]
}
pub fn apply_unit(self, coverage: u8) -> f32 {
unit_coverage(self.apply(coverage))
}
}
pub(crate) fn unit_coverage(value: u8) -> f32 {
UNIT_COVERAGE[usize::from(value)]
}
static UNIT_COVERAGE: [f32; 256] = {
let mut table = [0.0; 256];
let mut value = 0;
while value < 256 {
table[value] = value as f32 / 255.0;
value += 1;
}
table
};
pub(crate) fn unit_to_u8(value: f32) -> u8 {
cranpose_ui_graphics::whole::round(value.clamp(0.0, 1.0) * 255.0) as u8
}
static CORRECTION_TABLES: [CorrectionTable; LUMINANCE_CLASSES] =
include!(concat!(env!("OUT_DIR"), "/mask_gamma.rs"));
#[cfg(test)]
#[path = "tests/text_mask_gamma_tests.rs"]
mod tests;