
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>

#include "PajaTypes.h"
#include "SWFChar.h"
#include "SWFBitmapC.h"

using namespace PajaTypes;

//
// Some helper functions
//

inline
uint32
lowest_bit_mask( uint32 v )
{
	return (v & -v);
}

static
uint32
ceil_power2( uint32 ui32Num )
{
	uint32	i = lowest_bit_mask( ui32Num );
	while( i < ui32Num )
		i <<= 1;
	return i;
}


SWFBitmapC::SWFBitmapC() :
	m_ui32Width( 0 ),
	m_ui32Height( 0 ),
	m_ui32BPP( 0 ),
	m_pData( 0 ),
	m_ui32TexId( 0 )
{
	// empty
}

SWFBitmapC::~SWFBitmapC()
{
	delete [] m_pData;

	if( m_ui32TexId )
		glDeleteTextures( 1, &m_ui32TexId );
}

uint32
SWFBitmapC::get_type() const
{
	return SWF_CHAR_BITMAP;
}


void
SWFBitmapC::set_width( uint32 ui32Width )
{
	m_ui32Width = ui32Width;
}

uint32
SWFBitmapC::get_width() const
{
	return m_ui32Width;
}

void
SWFBitmapC::set_height( uint32 ui32Height )
{
	m_ui32Height = ui32Height;
}

uint32
SWFBitmapC::get_height() const
{
	return m_ui32Height;
}

void
SWFBitmapC::set_bpp( uint32 ui32BPP )
{
	m_ui32BPP = ui32BPP;
}

uint32
SWFBitmapC::get_bpp() const
{
	return m_ui32BPP;
}

void
SWFBitmapC::set_data( uint8* pData )
{
	m_pData = pData;
}

uint8*
SWFBitmapC::get_data() const
{
	return m_pData;
}

uint32
SWFBitmapC::get_texture_id() const
{
	return m_ui32TexId;
}

void
SWFBitmapC::prepare()
{
	if( m_ui32TexId )
		glDeleteTextures( 1, &m_ui32TexId );

	glGenTextures( 1, &m_ui32TexId );

	glBindTexture( GL_TEXTURE_2D, m_ui32TexId );

	uint32	ui32WidthPow2 = ceil_power2( m_ui32Width );
	uint32	ui32HeightPow2 = ceil_power2( m_ui32Height );

	uint8*	pTexData = 0;

	GLenum	eType;
	if( m_ui32BPP == 24 )
		eType = GL_RGB;
	else
		eType = GL_RGBA;

	if( ui32WidthPow2 != m_ui32Width || ui32HeightPow2 != m_ui32Height ) {
		// the bitmap is not power of 2. scale it.
		uint8*	pScaledData = new uint8[ui32WidthPow2 * ui32HeightPow2 * m_ui32BPP / 8];

		gluScaleImage( eType, m_ui32Width, m_ui32Height, GL_UNSIGNED_BYTE, m_pData,
			ui32WidthPow2, ui32HeightPow2, GL_UNSIGNED_BYTE, pScaledData );

		glTexImage2D( GL_TEXTURE_2D, 0, eType, ui32WidthPow2, ui32HeightPow2, 0, eType, GL_UNSIGNED_BYTE, pScaledData );

		delete [] pScaledData;
	}
	else {
		glTexImage2D( GL_TEXTURE_2D, 0, eType, m_ui32Width, m_ui32Height, 0,
			eType, GL_UNSIGNED_BYTE, m_pData );
	}

	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
}

void
SWFBitmapC::unprepare()
{
	if( m_ui32TexId ) {
		glDeleteTextures( 1, &m_ui32TexId );
		m_ui32TexId = 0;
	}
}