2011-11-20 14:44:17 +00:00
|
|
|
//*******************************************************************
|
|
|
|
//glfont2.cpp -- glFont Version 2.0 implementation
|
|
|
|
//Copyright (c) 1998-2002 Brad Fish
|
|
|
|
//See glfont.html for terms of use
|
|
|
|
//May 14, 2002
|
|
|
|
//*******************************************************************
|
|
|
|
|
|
|
|
//STL headers
|
|
|
|
#include <string>
|
2014-04-07 00:10:05 +00:00
|
|
|
#include "ttvfs_stdio.h"
|
2012-06-01 15:26:13 +00:00
|
|
|
#include "ByteBuffer.h"
|
2011-11-20 14:44:17 +00:00
|
|
|
using namespace std;
|
|
|
|
|
2013-06-19 16:35:06 +00:00
|
|
|
|
|
|
|
#ifdef _WIN32 /* Stupid Windows needs to include windows.h before gl.h */
|
|
|
|
#undef FAR
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
|
|
#define NOMINMAX
|
2011-11-20 14:44:17 +00:00
|
|
|
#include <windows.h>
|
2013-06-19 16:35:06 +00:00
|
|
|
#undef GetCharWidth
|
2011-11-20 14:44:17 +00:00
|
|
|
#endif
|
2017-02-09 20:17:21 +00:00
|
|
|
#include <GL/gl.h>
|
2012-05-19 00:41:31 +00:00
|
|
|
|
2011-11-20 14:44:17 +00:00
|
|
|
//glFont header
|
|
|
|
#include "glfont2.h"
|
|
|
|
using namespace glfont;
|
|
|
|
|
|
|
|
//*******************************************************************
|
|
|
|
//GLFont Class Implementation
|
|
|
|
//*******************************************************************
|
|
|
|
GLFont::GLFont ()
|
|
|
|
{
|
|
|
|
//Initialize header to safe state
|
|
|
|
header.tex = -1;
|
|
|
|
header.tex_width = 0;
|
|
|
|
header.tex_height = 0;
|
|
|
|
header.start_char = 0;
|
|
|
|
header.end_char = 0;
|
|
|
|
header.chars = NULL;
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
|
|
|
GLFont::~GLFont ()
|
|
|
|
{
|
|
|
|
//Destroy the font
|
|
|
|
Destroy();
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
|
|
|
bool GLFont::Create (const char *file_name, int tex, bool loadTexture)
|
|
|
|
{
|
2012-07-10 20:18:21 +00:00
|
|
|
ByteBuffer::uint32 num_chars, num_tex_bytes;
|
2011-11-20 14:44:17 +00:00
|
|
|
char *tex_bytes;
|
|
|
|
|
|
|
|
//Destroy the old font if there was one, just to be safe
|
|
|
|
Destroy();
|
|
|
|
|
2022-04-07 00:38:39 +00:00
|
|
|
|
2012-06-01 15:26:13 +00:00
|
|
|
VFILE *fh = vfopen(file_name, "rb");
|
|
|
|
if (!fh)
|
2011-11-20 14:44:17 +00:00
|
|
|
return false;
|
2014-04-07 00:10:05 +00:00
|
|
|
|
|
|
|
size_t sz = 0;
|
|
|
|
if(vfsize(fh, &sz) < 0)
|
|
|
|
{
|
|
|
|
vfclose(fh);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-06-01 15:26:13 +00:00
|
|
|
ByteBuffer bb(sz);
|
|
|
|
bb.resize(sz);
|
|
|
|
vfread(bb.contents(), 1, sz, fh);
|
|
|
|
vfclose(fh);
|
|
|
|
|
2011-11-20 14:44:17 +00:00
|
|
|
// Read the header from file
|
|
|
|
header.tex = tex;
|
2012-06-27 19:51:54 +00:00
|
|
|
bb.skipRead(4); // skip tex field
|
|
|
|
header.tex_width = bb.read<ByteBuffer::uint32>();
|
|
|
|
header.tex_height = bb.read<ByteBuffer::uint32>();
|
|
|
|
header.start_char = bb.read<ByteBuffer::uint32>();
|
|
|
|
header.end_char = bb.read<ByteBuffer::uint32>();
|
|
|
|
bb.skipRead(4); // skip chars field
|
2012-06-01 15:26:13 +00:00
|
|
|
|
2011-11-20 14:44:17 +00:00
|
|
|
//Allocate space for character array
|
|
|
|
num_chars = header.end_char - header.start_char + 1;
|
|
|
|
if ((header.chars = new GLFontChar[num_chars]) == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
//Read character array
|
2012-07-10 20:50:31 +00:00
|
|
|
for (unsigned int i = 0; i < num_chars; i++)
|
2011-11-20 14:44:17 +00:00
|
|
|
{
|
2012-06-01 15:26:13 +00:00
|
|
|
bb >> header.chars[i].dx;
|
|
|
|
bb >> header.chars[i].dy;
|
|
|
|
bb >> header.chars[i].tx1;
|
|
|
|
bb >> header.chars[i].ty1;
|
|
|
|
bb >> header.chars[i].tx2;
|
|
|
|
bb >> header.chars[i].ty2;
|
2011-11-20 14:44:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//Read texture pixel data
|
|
|
|
num_tex_bytes = header.tex_width * header.tex_height * 2;
|
|
|
|
tex_bytes = new char[num_tex_bytes];
|
2012-07-10 20:18:21 +00:00
|
|
|
// HACK: Aquaria uses override textures, so we can live with the truncation.
|
|
|
|
bb.read(tex_bytes, std::min(num_tex_bytes, bb.readable()));
|
2011-11-20 14:44:17 +00:00
|
|
|
|
|
|
|
//Build2DMipmaps(3, header.tex_width, header.tex_height, GL_UNSIGNED_BYTE, tex_bytes, 1);
|
|
|
|
|
|
|
|
if (loadTexture)
|
|
|
|
{
|
2022-04-07 00:38:39 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
2011-11-20 14:44:17 +00:00
|
|
|
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_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
|
|
|
|
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, 2, header.tex_width,
|
|
|
|
header.tex_height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
|
|
|
|
(void *)tex_bytes);
|
|
|
|
//gluBuild2DMipmaps(GL_TEXTURE_2D, 2, header.tex_width, header.tex_height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (void*)tex_bytes);
|
|
|
|
//Build2DMipmaps(3, header.tex_width, header.tex_height, GL_LUMINANCE_ALPHA, tex_bytes, 1);
|
|
|
|
//Create OpenGL texture
|
|
|
|
/*
|
2022-04-07 00:38:39 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
2011-11-20 14:44:17 +00:00
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
|
|
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
//Free texture pixels memory
|
|
|
|
delete[] tex_bytes;
|
|
|
|
|
|
|
|
//Return successfully
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
|
|
|
bool GLFont::Create (const std::string &file_name, int tex, bool loadTexture)
|
|
|
|
{
|
|
|
|
return Create(file_name.c_str(), tex);
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
|
|
|
void GLFont::Destroy (void)
|
|
|
|
{
|
|
|
|
//Delete the character array if necessary
|
|
|
|
if (header.chars)
|
|
|
|
{
|
|
|
|
delete[] header.chars;
|
|
|
|
header.chars = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
2023-05-31 15:08:52 +00:00
|
|
|
void GLFont::GetTexSize (std::pair<int, int> *size) const
|
2011-11-20 14:44:17 +00:00
|
|
|
{
|
|
|
|
//Retrieve texture size
|
|
|
|
size->first = header.tex_width;
|
|
|
|
size->second = header.tex_height;
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
2023-05-31 15:08:52 +00:00
|
|
|
int GLFont::GetTexWidth (void) const
|
2011-11-20 14:44:17 +00:00
|
|
|
{
|
|
|
|
//Return texture width
|
|
|
|
return header.tex_width;
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
2023-05-31 15:08:52 +00:00
|
|
|
int GLFont::GetTexHeight (void) const
|
2011-11-20 14:44:17 +00:00
|
|
|
{
|
|
|
|
//Return texture height
|
|
|
|
return header.tex_height;
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
2023-05-31 15:08:52 +00:00
|
|
|
void GLFont::GetCharInterval (std::pair<int, int> *interval) const
|
2011-11-20 14:44:17 +00:00
|
|
|
{
|
|
|
|
//Retrieve character interval
|
|
|
|
interval->first = header.start_char;
|
|
|
|
interval->second = header.end_char;
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
2023-05-31 15:08:52 +00:00
|
|
|
int GLFont::GetStartChar (void) const
|
2011-11-20 14:44:17 +00:00
|
|
|
{
|
|
|
|
//Return start character
|
|
|
|
return header.start_char;
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
2023-05-31 15:08:52 +00:00
|
|
|
int GLFont::GetEndChar (void) const
|
2011-11-20 14:44:17 +00:00
|
|
|
{
|
|
|
|
//Return end character
|
|
|
|
return header.end_char;
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
2023-05-31 15:08:52 +00:00
|
|
|
void GLFont::GetCharSize (unsigned char c, std::pair<int, int> *size) const
|
2011-11-20 14:44:17 +00:00
|
|
|
{
|
|
|
|
//Make sure character is in range
|
|
|
|
if (c < header.start_char || c > header.end_char)
|
|
|
|
{
|
|
|
|
//Not a valid character, so it obviously has no size
|
|
|
|
size->first = 0;
|
|
|
|
size->second = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GLFontChar *glfont_char;
|
|
|
|
|
|
|
|
//Retrieve character size
|
|
|
|
glfont_char = &header.chars[c - header.start_char];
|
|
|
|
size->first = (int)(glfont_char->dx * header.tex_width);
|
|
|
|
size->second = (int)(glfont_char->dy *
|
|
|
|
header.tex_height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
2023-05-31 15:08:52 +00:00
|
|
|
int GLFont::GetCharWidth (unsigned char c) const
|
2011-11-20 14:44:17 +00:00
|
|
|
{
|
|
|
|
//Make sure in range
|
|
|
|
if (c < header.start_char || c > header.end_char)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GLFontChar *glfont_char;
|
2022-04-07 00:38:39 +00:00
|
|
|
|
2011-11-20 14:44:17 +00:00
|
|
|
//Retrieve character width
|
|
|
|
glfont_char = &header.chars[c - header.start_char];
|
|
|
|
|
|
|
|
// hack to fix empty spaces
|
|
|
|
if (c == ' ' && glfont_char->dx <= 0)
|
|
|
|
{
|
|
|
|
GLFontChar *glfont_a = &header.chars['a' - header.start_char];
|
2013-06-19 16:35:06 +00:00
|
|
|
glfont_char->dx = glfont_a->dx*0.75f;
|
2011-11-20 14:44:17 +00:00
|
|
|
glfont_char->dy = glfont_a->dy;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (int)(glfont_char->dx * header.tex_width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
2023-05-31 15:08:52 +00:00
|
|
|
int GLFont::GetCharHeight (unsigned char c) const
|
2011-11-20 14:44:17 +00:00
|
|
|
{
|
|
|
|
//Make sure in range
|
|
|
|
if (c < header.start_char || c > header.end_char)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GLFontChar *glfont_char;
|
|
|
|
|
|
|
|
//Retrieve character height
|
|
|
|
glfont_char = &header.chars[c - header.start_char];
|
|
|
|
return (int)(glfont_char->dy * header.tex_height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
2023-05-31 15:08:52 +00:00
|
|
|
void GLFont::Begin (void) const
|
2011-11-20 14:44:17 +00:00
|
|
|
{
|
|
|
|
//Bind to font texture
|
|
|
|
glBindTexture(GL_TEXTURE_2D, header.tex);
|
|
|
|
}
|
|
|
|
//*******************************************************************
|
2023-05-31 15:08:52 +00:00
|
|
|
void GLFont::GetStringSize (const std::string &text, std::pair<int, int> *size) const
|
2011-11-20 14:44:17 +00:00
|
|
|
{
|
|
|
|
unsigned int i;
|
2012-07-13 14:03:21 +00:00
|
|
|
unsigned int c;
|
2011-11-20 14:44:17 +00:00
|
|
|
GLFontChar *glfont_char;
|
|
|
|
float width;
|
2022-04-07 00:38:39 +00:00
|
|
|
|
2011-11-20 14:44:17 +00:00
|
|
|
//debugLog("size->second");
|
|
|
|
//Height is the same for now...might change in future
|
|
|
|
size->second = (int)(header.chars[header.start_char].dy *
|
|
|
|
header.tex_height);
|
|
|
|
|
|
|
|
//Calculate width of string
|
|
|
|
width = 0.0F;
|
|
|
|
for (i = 0; i < text.size(); i++)
|
|
|
|
{
|
|
|
|
//Make sure character is in range
|
2012-06-19 00:29:14 +00:00
|
|
|
c = (unsigned char)text[i];
|
2022-04-07 00:38:39 +00:00
|
|
|
|
2011-11-20 14:44:17 +00:00
|
|
|
if (c < header.start_char || c > header.end_char)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
//Get pointer to glFont character
|
|
|
|
glfont_char = &header.chars[c - header.start_char];
|
|
|
|
|
|
|
|
//Get width and height
|
2022-04-07 00:38:39 +00:00
|
|
|
width += glfont_char->dx * header.tex_width;
|
2011-11-20 14:44:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//Save width
|
|
|
|
//debugLog("size first");
|
|
|
|
size->first = (int)width;
|
2022-04-07 00:38:39 +00:00
|
|
|
|
2011-11-20 14:44:17 +00:00
|
|
|
//debugLog("done");
|
|
|
|
}
|
|
|
|
|
|
|
|
//End of file
|
|
|
|
|
|
|
|
|