jay-compositor 1.15.0

The Jay compositor
use crate::utils::ordered_float::F64;
use crate::utils::static_text::StaticText;
use crate::utils::str_fmt::StrCtx;
use crate::utils::str_fmt::StrFmt;
use crate::utils::str_fmt::StrFmtFmt;
use jay_proc::StrFmt;
use jay_proc::jay_hash;
use std::fmt::Write as _;
use std::hash::Hash;

#[jay_hash]
#[derive(Copy, Clone, Debug, Eq)]
pub enum NamedPrimaries {
    Srgb,
    PalM,
    Pal,
    Ntsc,
    GenericFilm,
    Bt2020,
    Cie1931Xyz,
    DciP3,
    DisplayP3,
    AdobeRgb,
}

impl StrFmt for NamedPrimaries {
    fn str_fmt(&self, dst: &mut String, ctx: &StrCtx<'_>) {
        self.text().str_fmt(dst, ctx);
    }
}

impl StaticText for NamedPrimaries {
    fn text(&self) -> &'static str {
        match self {
            NamedPrimaries::Srgb => "srgb",
            NamedPrimaries::PalM => "pal_m",
            NamedPrimaries::Pal => "pal",
            NamedPrimaries::Ntsc => "ntsc",
            NamedPrimaries::GenericFilm => "generic_film",
            NamedPrimaries::Bt2020 => "bt2020",
            NamedPrimaries::Cie1931Xyz => "cie1931_xyz",
            NamedPrimaries::DciP3 => "dci_p3",
            NamedPrimaries::DisplayP3 => "display_p3",
            NamedPrimaries::AdobeRgb => "adobe_rgb",
        }
    }
}

#[jay_hash]
#[derive(Copy, Clone, Debug, Eq)]
pub struct Primaries {
    pub r: (F64, F64),
    pub g: (F64, F64),
    pub b: (F64, F64),
    pub wp: (F64, F64),
}

impl Primaries {
    pub const SRGB: Self = Self {
        r: (F64(0.64), F64(0.33)),
        g: (F64(0.3), F64(0.6)),
        b: (F64(0.15), F64(0.06)),
        wp: (F64(0.3127), F64(0.3290)),
    };

    pub const PAL_M: Self = Self {
        r: (F64(0.67), F64(0.33)),
        g: (F64(0.21), F64(0.71)),
        b: (F64(0.14), F64(0.08)),
        wp: (F64(0.310), F64(0.316)),
    };

    pub const PAL: Self = Self {
        r: (F64(0.64), F64(0.33)),
        g: (F64(0.29), F64(0.60)),
        b: (F64(0.15), F64(0.06)),
        wp: (F64(0.3127), F64(0.3290)),
    };

    pub const NTSC: Self = Self {
        r: (F64(0.630), F64(0.340)),
        g: (F64(0.310), F64(0.595)),
        b: (F64(0.155), F64(0.070)),
        wp: (F64(0.3127), F64(0.3290)),
    };

    pub const GENERIC_FILM: Self = Self {
        r: (F64(0.681), F64(0.319)),
        g: (F64(0.243), F64(0.692)),
        b: (F64(0.145), F64(0.049)),
        wp: (F64(0.310), F64(0.316)),
    };

    pub const BT2020: Self = Self {
        r: (F64(0.708), F64(0.292)),
        g: (F64(0.170), F64(0.797)),
        b: (F64(0.131), F64(0.046)),
        wp: (F64(0.3127), F64(0.3290)),
    };

    pub const CIE1931_XYZ: Self = Self {
        r: (F64(1.0), F64(0.0)),
        g: (F64(0.0), F64(1.0)),
        b: (F64(0.0), F64(0.0)),
        wp: (F64(1.0 / 3.0), F64(1.0 / 3.0)),
    };

    pub const DCI_P3: Self = Self {
        r: (F64(0.680), F64(0.320)),
        g: (F64(0.265), F64(0.690)),
        b: (F64(0.150), F64(0.060)),
        wp: (F64(0.314), F64(0.351)),
    };

    pub const DISPLAY_P3: Self = Self {
        r: (F64(0.680), F64(0.320)),
        g: (F64(0.265), F64(0.690)),
        b: (F64(0.150), F64(0.060)),
        wp: (F64(0.3127), F64(0.3290)),
    };

    pub const ADOBE_RGB: Self = Self {
        r: (F64(0.64), F64(0.33)),
        g: (F64(0.21), F64(0.71)),
        b: (F64(0.15), F64(0.06)),
        wp: (F64(0.3127), F64(0.3290)),
    };

    pub fn about_equal(&self, other: &Self) -> bool {
        const EPSILON: f64 = 0.001;
        macro_rules! ae {
            ($field:ident) => {
                (self.$field.0.0 - other.$field.0.0).abs() < EPSILON
                    && (self.$field.1.0 - other.$field.1.0).abs() < EPSILON
            };
        }
        ae!(r) && ae!(g) && ae!(b) && ae!(wp)
    }
}
impl NamedPrimaries {
    pub const fn primaries(self) -> Primaries {
        match self {
            NamedPrimaries::Srgb => Primaries::SRGB,
            NamedPrimaries::PalM => Primaries::PAL_M,
            NamedPrimaries::Pal => Primaries::PAL,
            NamedPrimaries::Ntsc => Primaries::NTSC,
            NamedPrimaries::GenericFilm => Primaries::GENERIC_FILM,
            NamedPrimaries::Bt2020 => Primaries::BT2020,
            NamedPrimaries::Cie1931Xyz => Primaries::CIE1931_XYZ,
            NamedPrimaries::DciP3 => Primaries::DCI_P3,
            NamedPrimaries::DisplayP3 => Primaries::DISPLAY_P3,
            NamedPrimaries::AdobeRgb => Primaries::ADOBE_RGB,
        }
    }
}

impl StrFmt for Primaries {
    fn str_fmt(&self, dst: &mut String, ctx: &StrCtx<'_>) {
        if ctx.fmt == StrFmtFmt::Human {
            let mut first = true;
            for (n, (x, y)) in [
                (" r", self.r),
                (" g", self.g),
                (" b", self.b),
                ("wp", self.wp),
            ] {
                if !first {
                    dst.push_str("\n");
                    dst.push_str(ctx.prefix);
                    dst.push_str(ctx.spaces);
                }
                first = false;
                dst.push_str(n);
                dst.push_str(": ");
                let _ = write!(dst, "{x:.04} {y:.04}");
            }
        } else {
            #[derive(StrFmt)]
            struct F {
                r: (F64, F64),
                g: (F64, F64),
                b: (F64, F64),
                wp: (F64, F64),
            }
            define_ident!(self.@r);
            define_ident!(self.@g);
            define_ident!(self.@b);
            define_ident!(self.@wp);
            let f = F { r, g, b, wp };
            f.str_fmt(dst, ctx);
        }
    }
}