//! Device glyph blitter — the firmware equivalent of the web `drawGlyph`.
//!
//! The web draws Bravura as a font; the device blits the SAME glyphs from a pre-rasterized 4-bit
//! alpha atlas (`glyphs.rs`, generated by `rust/glyphgen`). Each glyph's coverage is alpha-blended
//! over a KNOWN solid background (the notation panel is a flat fill, and a write-only DrawTarget
//! can't read back), so blends are computed against `BG`.

use embedded_graphics::{pixelcolor::Rgb565, prelude::*};

use super::glyphs::{Glyph, ATLAS, ATLAS_W, GLYPHS};

/// Alpha-blend `fg` over `bg` by 4-bit coverage `a` (0..15).
#[inline]
fn blend(fg: Rgb565, bg: Rgb565, a: u8) -> Rgb565 {
    let a = a as u32;
    let mix = |f: u8, b: u8, max: u32| -> u8 {
        ((f as u32 * a + b as u32 * (15 - a)) / 15).min(max) as u8
    };
    Rgb565::new(mix(fg.r(), bg.r(), 31), mix(fg.g(), bg.g(), 63), mix(fg.b(), bg.b(), 31))
}

/// Draw a glyph so its SMuFL origin (pen point = on the reference staff line, the baseline) lands at
/// `origin`. `ink` is blended over `bg`. Fully-transparent pixels are skipped (so glyphs overlap
/// cleanly); partial coverage is blended against `bg` — keep `bg` equal to the panel fill behind it.
pub fn draw_glyph<D>(d: &mut D, glyph: Glyph, origin: Point, ink: Rgb565, bg: Rgb565) -> Result<(), D::Error>
where
    D: DrawTarget<Color = Rgb565>,
{
    let m = GLYPHS[glyph as usize];
    // top-left of the bitmap in screen space: pen x + bearing_x ; baseline y - bearing_y (up)
    let ox = origin.x + m.bearing_x as i32;
    let oy = origin.y - m.bearing_y as i32;
    let row_bytes = ATLAS_W / 2;
    for ry in 0..m.h as usize {
        let ay = m.atlas_y as usize + ry;
        for rx in 0..m.w as usize {
            let ax = m.atlas_x as usize + rx;
            let byte = ATLAS[ay * row_bytes + ax / 2];
            let a = if ax & 1 == 0 { byte >> 4 } else { byte & 0x0F };
            if a == 0 {
                continue;
            }
            let c = if a >= 15 { ink } else { blend(ink, bg, a) };
            d.fill_solid(
                &embedded_graphics::primitives::Rectangle::new(
                    Point::new(ox + rx as i32, oy + ry as i32),
                    Size::new(1, 1),
                ),
                c,
            )?;
        }
    }
    Ok(())
}

/// Advance width of a glyph (px) — for laying out time-signature digit runs.
pub fn advance(glyph: Glyph) -> i32 {
    GLYPHS[glyph as usize].advance as i32
}

/// Bitmap width of a glyph (px) — for centering a glyph on a column.
pub fn width(glyph: Glyph) -> i32 {
    GLYPHS[glyph as usize].w as i32
}
