#pragma once

#include <efi.h>
#include <common.h>
#include "ttf_math.h"

typedef struct ttf_face ttf_face_t;

typedef struct ttf_face {
    const SUINT8* data;
    UINTN         size;

    // head
    SUINT32 units_per_em;
    SSINT16 index_to_loc_format;  // 0 = short, 1 = long

    // hhea
    SSINT16 hhea_ascender;
    SSINT16 hhea_descender;
    SSINT16 hhea_line_gap;
    SUINT16 num_long_hor_metrics;

    // maxp
    SUINT16 num_glyphs;
    SUINT16 max_points;
    SUINT16 max_contours;

    // os/2
    SSINT16 os2_ascender;
    SSINT16 os2_descender;
    SSINT16 os2_line_gap;

    // Table directory (sorted by tag at open time)
    struct {
        char     tag[4];
        SUINT32  offset;
        SUINT32  length;
    } tables[32];
    SUINT16 num_tables;

    // Cached pointers into data[]
    const SUINT8* loca;   // size depends on num_glyphs and format
    const SUINT8* glyf;
    SUINT32       glyf_len;
    const SUINT8* hmtx;
    SUINT32       hmtx_len;
    const SUINT8* cmap;
} ttf_face_t;

// Decomposed glyph: contours in pixel space (26.6 fp) ready to scan.
typedef struct ttf_outline {
    f26_6   x[1024];
    f26_6   y[1024];
    SUINT8  on_curve[1024];
    SUINT16 first[64];
    SUINT16 last[64];
    SUINT16 num_contours;
    SUINT16 num_points;

    // Bounding box in pixel space (26.6 fp).
    SSINT32 xmin, ymin, xmax, ymax;

    // Pen advance in pixel space (26.6 fp).
    f26_6 advance;
} ttf_outline_t;

typedef struct ttf_seg {
    f26_6 x0, y0, x1, y1;  // line / quad end points
    f26_6 cx, cy;          // quadratic control (set to x0/y0 if is_line)
    SUINT8 is_line;        // 1 = line, 0 = quad
} ttf_seg_t;

// Parse the glyf entry for glyph_id. Fills outline already
// scaled to pixel_size_px. Returns false on composite / parse error.
bool ttf_load_glyph(ttf_face_t* face, SUINT16 glyph_id,
    SUINT32 pixel_size_px, ttf_outline_t* out);

// UTF-8 decoder. *p advances past the codepoint. Returns -1 on error.
SSINT32 ttf_utf8_decode(const char** p);

// cmap lookup — returns glyph_id (0 = notdef).
SUINT16 ttf_cmap_lookup(ttf_face_t* face, SSINT32 cp);

// Decompose outline into a flat array of line/quadratic segments.
//   out must have room for 2*num_points + num_contours entries.
void ttf_outline_to_segments(const ttf_outline_t* outline,
    ttf_seg_t* segs, SUINT32* num_segs);

// Scanline rasterize segments into per-pixel coverage.
//   coverage[w*h] gets values in [0, N] where N = supersample count.
void ttf_rasterize(const ttf_seg_t* segs, SUINT32 num_segs,
    SSINT32 x0, SSINT32 y0, SUINT32 w, SUINT32 h,
    SUINT8* coverage, SUINT32 N);
