/* date = July 11th 2022 6:13 pm */

#ifndef FONT_TYPES_H
#define FONT_TYPES_H

/* TODO(allen) - font_types.h
** Optimize the structure for packing (codepoint,index) pairs in the
**  loose font.
** Optimize the structure for accelerated (codepoint -> index) mapping
**  in the baked font.
** Provide a CPU side atlas bitmap assembler * test this vs GPU side assembling
*/

////////////////////////////////
// NOTE(allen): Font Loose Types

typedef struct FONT_GlyphLoose{
  struct FONT_GlyphLoose *next;
  U8 *bitmap;
  U32 w;
  U32 h;
  U32 index;
  S32 left_minus_origin;
  S32 bottom_minus_origin;
  U32 advance;
} FONT_GlyphLoose;

// (larger chunks)
typedef struct FONT_CpIndexLoose{
  struct FONT_CpIndexLoose *next;
  U32 cp;
  U32 index;
} FONT_CpIndexLoose;

typedef struct FONT_Loose{
  FONT_CpIndexLoose *first_cp_index;
  FONT_CpIndexLoose *last_cp_index;
  FONT_GlyphLoose *first_glyph;
  FONT_GlyphLoose *last_glyph;
  U32 min_index;
  U32 max_index;
  S32 ascender;
  S32 descender;
  U32 line_height;
} FONT_Loose;

////////////////////////////////
// NOTE(allen): Font Baked Types

typedef struct FONT_CpNode{
  struct FONT_CpNode *next;
  U32 cp;
  U32 index;
} FONT_CpNode;
typedef struct FONT_CpBucket{
  FONT_CpNode *first;
  FONT_CpNode *last;
} FONT_CpBucket;

#define FONT_CP_BUCKET_COUNT 128

typedef struct FONT_GlyphLayout{
  RectF32 xy_off;
  F32 advance;
} FONT_GlyphLayout;
typedef struct FONT_GlyphCoords{
  V2S32 p;
  V2S32 dim;
} FONT_GlyphCoords;
typedef struct FONT_GlyphUVCoords{
  RectF32 uv;
} FONT_GlyphUVCoords;

typedef struct FONT_Baked{
  FONT_CpBucket *buckets;
  
  FONT_GlyphLayout *glyph_layout;
  FONT_GlyphCoords *glyph_coords;
  FONT_GlyphUVCoords *glyph_uv_coords;
  
  U32 atlas_w;
  U32 atlas_h;
  
  U32 min_index;
  U32 max_index;
  S32 ascender;
  S32 descender;
  U32 line_height;
} FONT_Baked;

////////////////////////////////
// NOTE(allen): Font Pack Types

typedef struct FONT_PackParams{
  // glyphs with a width or height larger than this amount
  // are filtered out and logged
  U32 max_glyph_side;
  
  // initial width and height of the atlas, should be power-of-two,
  // should not be smaller than max_glyph_side
  U32 initial_atlas_side;
  
  // how many times the algorithm may double the size of the atlas
  // before stopping
  U32 max_grow_count;
} FONT_PackParams;

typedef struct FONT_PackNode{
  struct FONT_PackNode *next;
  FONT_GlyphLoose *glyph;
  U32 x;
  U32 y;
} FONT_PackNode;

////////////////////////////////
// NOTE(allen): Font Bake Function

function FONT_Baked* font_bake(Arena *arena, FONT_Loose *font,
                               FONT_PackParams *params);

////////////////////////////////
// NOTE(allen): Font Usage Functions

function U32 font_glyph_index_from_codepoint(FONT_Baked *font, U32 cp);

#endif //FONT_TYPES_H
