#include "Glyph.h"

#define round_up_26_6(val) (((val) + 63) >> 6u)

bool Glyph::load(FT_Face face, FT_ULong char_code)
{
    if (FT_Load_Char(face, char_code, FT_LOAD_RENDER) != 0)
        return false;

    m_texture = glcxx::Texture::create();
    m_texture->bind(GL_TEXTURE_2D);
    int width = face->glyph->bitmap.width;
    int rounded_width = glcxx::Texture::next_power_of_2(width);
    int height = face->glyph->bitmap.rows;
    int rounded_height = glcxx::Texture::next_power_of_2(height);
    m_advance = round_up_26_6(face->glyph->advance.x);
    uint8_t * texture = new uint8_t[rounded_width * rounded_height];
    memset(texture, 0, rounded_width * rounded_height);
    for (int i = 0; i < height; i++)
    {
        memcpy(&texture[rounded_width * i],
               &face->glyph->bitmap.buffer[width * (height - i - 1)],
               width);
    }

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, rounded_width, rounded_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texture);
    delete[] texture;

    m_array = glcxx::Array::create();
    m_array->bind();

    int left = face->glyph->bitmap_left;
    int top = face->glyph->bitmap_top;
    float s_max = width / (float)rounded_width;
    float t_max = height / (float)rounded_height;
    m_buffer = glcxx::Buffer::create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, {
        (GLfloat)left, (GLfloat)(top - height),           0.0,   0.0,
        (GLfloat)(left + width), (GLfloat)(top - height), s_max, 0.0,
        (GLfloat)left, (GLfloat)top,                      0.0,   t_max,
        (GLfloat)(left + width), (GLfloat)top,            s_max, t_max,
    });

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);

    return true;
}
