mirror of
https://github.com/mupen64plus/mupen64plus-oldsvn.git
synced 2025-04-02 10:52:35 -04:00
267 lines
7.1 KiB
C++
267 lines
7.1 KiB
C++
/*
|
|
Copyright (C) 2003 Sven Olsen
|
|
Copyright (C) 2008 nmn
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
//Include our header file.
|
|
#include "OGLError.h"
|
|
#include "OGLFreeType.h"
|
|
|
|
//OpenGL Headers
|
|
#include "stdafx.h"
|
|
#include "glh_genext.h"
|
|
#include <GL/glu.h>
|
|
#include "OGLCombiner.h"
|
|
|
|
inline int next_p2 ( int a )
|
|
{
|
|
int rval=1;
|
|
while(rval<a) rval<<=1;
|
|
return rval;
|
|
}
|
|
|
|
void makeDList ( FT_Face face, char ch, GLuint list_base, GLuint * tex_base )
|
|
{
|
|
|
|
if(FT_Load_Glyph( face, FT_Get_Char_Index( face, ch ), FT_LOAD_DEFAULT )) fprintf(stderr, "FT_Load_Glyph failed");
|
|
|
|
FT_Glyph glyph;
|
|
if(FT_Get_Glyph( face->glyph, &glyph )) fprintf(stderr, "FT_Get_Glyph failed");
|
|
|
|
FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 );
|
|
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
|
|
|
|
FT_Bitmap& bitmap=bitmap_glyph->bitmap;
|
|
|
|
int width = next_p2( bitmap.width );
|
|
int height = next_p2( bitmap.rows );
|
|
|
|
//Allocate memory for the texture data.
|
|
GLubyte* expanded_data = new GLubyte[ 2 * width * height];
|
|
|
|
for(int j=0; j <height;j++)
|
|
{
|
|
for(int i=0; i < width; i++)
|
|
{
|
|
expanded_data[2*(i+j*width)]= expanded_data[2*(i+j*width)+1] = (i>=bitmap.width || j>=bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width*j];
|
|
}
|
|
}
|
|
|
|
glBindTexture( GL_TEXTURE_2D, tex_base[ch]);
|
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
|
|
|
|
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height,0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data );
|
|
|
|
delete [] expanded_data;
|
|
|
|
glNewList(list_base+ch,GL_COMPILE);
|
|
|
|
glBindTexture(GL_TEXTURE_2D,tex_base[ch]);
|
|
|
|
glTranslatef(bitmap_glyph->left,0,0);
|
|
|
|
glPushMatrix();
|
|
glTranslatef(0,bitmap_glyph->top-bitmap.rows,0);
|
|
|
|
float x=(float)bitmap.width / (float)width, y=(float)bitmap.rows / (float)height;
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2d(0,0); glVertex2f(0,bitmap.rows);
|
|
glTexCoord2d(0,y); glVertex2f(0,0);
|
|
glTexCoord2d(x,y); glVertex2f(bitmap.width,0);
|
|
glTexCoord2d(x,0); glVertex2f(bitmap.width,bitmap.rows);
|
|
glEnd();
|
|
glPopMatrix();
|
|
glTranslatef(face->glyph->advance.x >> 6 ,0,0);
|
|
|
|
glEndList();
|
|
}
|
|
|
|
Font::Font(const char * fname, unsigned int h)
|
|
{
|
|
fprintf(stderr, "OGLFreeType: Loading Font %s...\n",fname);
|
|
textures = new GLuint[128];
|
|
|
|
this->h=h;
|
|
|
|
FT_Library library;
|
|
if (FT_Init_FreeType( &library )) fprintf(stderr,"FT_Init_FreeType failed\n");
|
|
|
|
FT_Face face;
|
|
|
|
if (FT_New_Face( library, fname, 0, &face )) fprintf(stderr,"FT_New_Face failed (there is probably a problem with your font file)\n");
|
|
|
|
FT_Set_Char_Size( face, h << 6, h << 6, 96, 96);
|
|
|
|
list_base=glGenLists(128);
|
|
OGLCheckErrors();
|
|
glGenTextures( 128, textures );
|
|
OGLCheckErrors();
|
|
|
|
for(unsigned char i=0;i<128;i++) makeDList(face,i,list_base,textures);
|
|
for(unsigned char i=0;i<128;i++)
|
|
{
|
|
if(FT_Load_Glyph( face, FT_Get_Char_Index( face, i ), FT_LOAD_DEFAULT )) fprintf(stderr, "FT_Load_Glyph failed\n");
|
|
w[i] = face->glyph->advance.x;
|
|
}
|
|
|
|
FT_Done_Face(face);
|
|
|
|
FT_Done_FreeType(library);
|
|
}
|
|
|
|
Font::~Font()
|
|
{
|
|
glDeleteLists(list_base,128);
|
|
glDeleteTextures(128,textures);
|
|
delete [] textures;
|
|
}
|
|
|
|
inline void pushProjectionMatrix()
|
|
{
|
|
glPushAttrib(GL_TRANSFORM_BIT);
|
|
GLint viewport[4];
|
|
glGetIntegerv(GL_VIEWPORT, viewport);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
gluOrtho2D(viewport[0],viewport[2],viewport[1],viewport[3]);
|
|
glPopAttrib();
|
|
}
|
|
|
|
inline void PopProjectionMatrix()
|
|
{
|
|
glPushAttrib(GL_TRANSFORM_BIT);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glPopAttrib();
|
|
}
|
|
|
|
OGLFT_Boundary PreflightTextSize(const Font &ft_font, const char *fmt, ...)
|
|
{
|
|
OGLFT_Boundary size;
|
|
char text[256];
|
|
char *pointer = &text[0];
|
|
va_list ap;
|
|
|
|
if (fmt == NULL) *text=0;
|
|
else
|
|
{
|
|
va_start(ap, fmt);
|
|
vsprintf(text, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
size.H = ft_font.h;
|
|
while(*pointer)
|
|
{
|
|
size.W += ft_font.w[*pointer];
|
|
pointer++;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
void glPrint(const Font &ft_font, float x, float y, float color[4], const char *fmt, ...)
|
|
{
|
|
pushProjectionMatrix();
|
|
|
|
GLuint font=ft_font.list_base;
|
|
float h = ft_font.h/.63f;
|
|
|
|
char text[256];
|
|
va_list ap;
|
|
|
|
if (fmt == NULL) *text=0;
|
|
else
|
|
{
|
|
va_start(ap, fmt);
|
|
vsprintf(text, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
const char *start_line=text;
|
|
vector<string> lines;
|
|
|
|
const char * c = text;;
|
|
|
|
for(;*c;c++)
|
|
{
|
|
if(*c=='\n')
|
|
{
|
|
string line;
|
|
for(const char *n=start_line;n<c;n++) line.append(1,*n);
|
|
lines.push_back(line);
|
|
start_line=c+1;
|
|
}
|
|
}
|
|
|
|
if(start_line)
|
|
{
|
|
string line;
|
|
for(const char *n=start_line;n<c;n++) line.append(1,*n);
|
|
lines.push_back(line);
|
|
}
|
|
|
|
CRender::g_pRender->m_pColorCombiner->DisableCombiner();
|
|
glPushClientAttrib(GL_ALL_CLIENT_ATTRIB_BITS);
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
glDisableClientState(GL_EDGE_FLAG_ARRAY);
|
|
glDisableClientState(GL_INDEX_ARRAY);
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glDisableClientState(GL_FOG_COORDINATE_ARRAY_EXT);
|
|
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
|
glDisable(GL_LIGHTING);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDisable(GL_CULL_FACE);
|
|
glDisable(GL_SCISSOR_TEST);
|
|
glDisable(GL_STENCIL_TEST);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glBlendColorEXT(0,0,0,0);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
glActiveTextureARB(GL_TEXTURE0_ARB);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glListBase(font);
|
|
|
|
glColor4fv(color);
|
|
|
|
float modelview_matrix[16];
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glGetFloatv(GL_MODELVIEW_MATRIX, modelview_matrix);
|
|
|
|
for(unsigned int i=0;i<lines.size();i++)
|
|
{
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glTranslatef(x,y-h*i,0);
|
|
glMultMatrixf(modelview_matrix);
|
|
|
|
glCallLists(lines[i].length(), GL_UNSIGNED_BYTE, lines[i].c_str());
|
|
|
|
glPopMatrix();
|
|
}
|
|
|
|
glPopAttrib();
|
|
glPopClientAttrib();
|
|
|
|
PopProjectionMatrix();
|
|
OGLCheckErrors();
|
|
}
|