/*
 * (C) Copyright Ian D. Romanick 2007
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * on the rights to use, copy, modify, merge, publish, distribute, sub
 * license, and/or sell copies of the Software, and to permit persons to whom
 * the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
 * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# define _USE_MATH_DEFINES
# include <windows.h>
#endif

#include <GL/glew.h>
#include <math.h>

#include "SDL_text.h"

static int nextpoweroftwo(int x)
{
    const double logbase2 = log(float(x)) / log(2.0f);
    return 1U << (int) ceil(logbase2);
}

void SDL_GL_BeginText(void)
{
    int vPort[4];

    glGetIntegerv(GL_VIEWPORT, vPort);

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();

    glOrtho(0, vPort[2], 0, vPort[3], -1, 1);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
}

void SDL_GL_EndText(void)
{
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();   
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();	
}

void SDL_GL_RenderText(const char *text, TTF_Font *font, SDL_Color color,
		       SDL_Rect *location)
{
    SDL_Surface *initial;
    SDL_Surface *intermediary;
    int w,h;
    GLuint texture;

    /* Use SDL_TTF to render our text */
    initial = TTF_RenderText_Blended(font, text, color);
	
    /* Convert the rendered text to a known format */
    w = nextpoweroftwo(initial->w);
    h = nextpoweroftwo(initial->h);
	
    intermediary = SDL_CreateRGBSurface(0, w, h, 32, 
					0x00ff0000, 0x0000ff00, 0x000000ff,
					0xff000000);

    SDL_BlitSurface(initial, 0, intermediary, 0);
	
    /* Tell GL about our new texture */
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_BGRA, 
		 GL_UNSIGNED_BYTE, intermediary->pixels);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);


    /* prepare to render our texture */
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture);
    glColor3f(1.0f, 1.0f, 1.0f);

    /* Draw a quad at location */
    glBegin(GL_QUADS);

    /* Recall that the origin is in the lower-left corner.  That is why the
     * TexCoords specify different corners than the Vertex coors seem to. */

    glTexCoord2f(0.0f, 1.0f); 
    glVertex2f(location->x    , location->y);
    glTexCoord2f(1.0f, 1.0f); 
    glVertex2f(location->x + GLfloat(w), location->y);
    glTexCoord2f(1.0f, 0.0f); 
    glVertex2f(location->x + GLfloat(w), location->y + GLfloat(h));
    glTexCoord2f(0.0f, 0.0f); 
    glVertex2f(location->x    , location->y + GLfloat(h));
    glEnd();
	
    /* Bad things happen if we delete the texture before it finishes */
    glFinish();
	
    /* return the deltas in the unused w,h part of the rect */
    location->w = initial->w;
    location->h = initial->h;
	
    /* Clean up */
    SDL_FreeSurface(initial);
    SDL_FreeSurface(intermediary);
    glDeleteTextures(1, &texture);
}
