#include "DrawText.h"
namespace
{
    const float DEFAULT_POINT_SIZE = 20.f;
    const float DEFAULT_GAP = 0.f;
    
    const char * TEXTURE_FILENAME = "FBX_ASCII_TEXTURE";
    const int TEXTURE_WIDTH = 256;
    const int TEXTURE_HEIGHT = 256;
    const char TEXTURE_MIN_GLYPH = 0x20;
    const char TEXTURE_MAX_GLYPH = 0x7E;
    const int TEXTURE_GLYPH_COUNT = TEXTURE_MAX_GLYPH - TEXTURE_MIN_GLYPH + 1;
}
DrawText::DrawText() : mGlyph(
NULL), mTextureName(0), mPointSize(DEFAULT_POINT_SIZE), mGap(DEFAULT_GAP)
{
    Initialize();
}
DrawText::~DrawText()
{
    delete [] mGlyph;
    glDeleteTextures(1, &mTextureName);
}
void DrawText::Display(const char * pText)
{
    if (!mGlyph || mTextureName == 0)
        return;
    
    glPushAttrib(GL_ENABLE_BIT);
    glPushAttrib(GL_COLOR_BUFFER_BIT);
    glPushAttrib(GL_TEXTURE_BIT);
    glBindTexture(GL_TEXTURE_2D, mTextureName);
    glEnable(GL_TEXTURE_2D);
    
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    glDisable(GL_CULL_FACE);
    
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glPushMatrix();
    const char * pCharacter = pText;
    while (*pCharacter != '\0')
    {
        if (*pCharacter == '\n')
        {
            glPopMatrix();
            
            glTranslatef(0, -mPointSize, 0);
            glPushMatrix();
        }
        else
        {
            Glyph * lGlyph = mGlyph + (*pCharacter - TEXTURE_MIN_GLYPH);
            if (lGlyph)
            {
                
                glBegin(GL_POLYGON);
                glTexCoord2f(lGlyph->texture_left, lGlyph->texture_bottom);
                glVertex2f(lGlyph->vertex_left * mPointSize, lGlyph->vertex_bottom * mPointSize);
                glTexCoord2f(lGlyph->texture_right, lGlyph->texture_bottom);
                glVertex2f(lGlyph->vertex_right * mPointSize, lGlyph->vertex_bottom * mPointSize);
                glTexCoord2f(lGlyph->texture_right, lGlyph->texture_top);
                glVertex2f(lGlyph->vertex_right * mPointSize, lGlyph->vertex_top * mPointSize);
                glTexCoord2f(lGlyph->texture_left, lGlyph->texture_top);
                glVertex2f(lGlyph->vertex_left * mPointSize, lGlyph->vertex_top * mPointSize);
                glEnd();
                const float advance = lGlyph->advance * mPointSize + mGap;
                glTranslatef(advance, 0, 0);
            }
            else
            {
                FBXSDK_printf("Invalid character: %c.\n", *pCharacter);
            }
            
        }
        ++pCharacter;
    }
    glPopMatrix();
    
    glPopAttrib();
    glPopAttrib();
    glPopAttrib();
}
void DrawText::Initialize()
{
    FBXSDK_fopen(lFile, TEXTURE_FILENAME, "rb");
    {
        FBXSDK_printf("Warning: Failed to open %s and no text will be displayed.\n", TEXTURE_FILENAME);
        return;
    }
    
    mGlyph = new Glyph[TEXTURE_GLYPH_COUNT];
    fread(mGlyph, sizeof(Glyph), TEXTURE_GLYPH_COUNT, lFile);
    
    
    const int lTextureSize = TEXTURE_WIDTH * TEXTURE_HEIGHT * 2;
    unsigned char * lTextureData = new unsigned char[lTextureSize];
    if (fread(lTextureData, 1, lTextureSize, lFile) == lTextureSize)
    {
        
        glGenTextures(1, &mTextureName);
        glBindTexture(GL_TEXTURE_2D, mTextureName);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
            GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, lTextureData);
        glBindTexture(GL_TEXTURE_2D, 0);
    }
    delete [] lTextureData;
    fclose(lFile);
}