@ -27,18 +27,11 @@
# include "textures.h"
# include "textures.h"
# include "graphics.h"
# include "graphics.h"
# include <GL/gl.h>
# include <GL/glu.h>
# include <GL/glext.h>
Font : : Font ( ) :
Font : : Font ( ) :
m_lineHeight ( 14 ) ,
m_lineHeight ( 14 ) ,
m_cursorSize ( 14 ) ,
m_cursorSize ( 14 ) ,
m_color ( Color : : white ) ,
m_color ( 0xFFFFFFFF )
m_firstGlyph ( 32 ) ,
m_numHorizontalGlyphs ( 16 )
{
{
bzero ( m_glyphWidths , sizeof ( m_glyphWidths ) ) ;
}
}
bool Font : : load ( const std : : string & file )
bool Font : : load ( const std : : string & file )
@ -57,6 +50,10 @@ bool Font::load(const std::string& file)
std : : istringstream fin ( fileContents ) ;
std : : istringstream fin ( fileContents ) ;
std : : string textureName ;
std : : string textureName ;
int numHorizontalGlyphs ;
int firstGlyph ;
Size glyphSize ;
Size textureSize ;
try {
try {
YAML : : Parser parser ( fin ) ;
YAML : : Parser parser ( fin ) ;
@ -67,101 +64,97 @@ bool Font::load(const std::string& file)
doc [ " line height " ] > > m_lineHeight ;
doc [ " line height " ] > > m_lineHeight ;
doc [ " cursor size " ] > > m_cursorSize ;
doc [ " cursor size " ] > > m_cursorSize ;
doc [ " color " ] > > m_color ;
doc [ " color " ] > > m_color ;
doc [ " first glyph " ] > > m_firstGlyph ;
doc [ " first glyph " ] > > firstGlyph ;
doc [ " image glyph size " ] > > glyphSize ;
doc [ " image " ] > > textureName ;
doc [ " image " ] > > textureName ;
doc [ " image glyph size " ] > > m_glyphSize ;
m_texture = g_textures . get ( " fonts/ " + textureName ) ;
if ( ! m_texture ) {
error ( " Failed to load image for font \" %s \" " , file . c_str ( ) ) ;
return false ;
}
textureSize = m_texture - > getSize ( ) ;
numHorizontalGlyphs = textureSize . width ( ) / glyphSize . width ( ) ;
const YAML : : Node & widthsNode = doc [ " glyph widths " ] ;
const YAML : : Node & widthsNode = doc [ " glyph widths " ] ;
for ( auto it = widthsNode . begin ( ) ; it ! = widthsNode . end ( ) ; + + it ) {
for ( auto it = widthsNode . begin ( ) ; it ! = widthsNode . end ( ) ; + + it ) {
int id , width ;
int glyph , glyphWidth ;
it . first ( ) > > id ;
it . first ( ) > > glyph ;
it . second ( ) > > width ;
it . second ( ) > > glyphWidth ;
m_glyphWidths [ id ] = width ;
// calculate glyph texture coords
m_glyphsTextureCoords [ glyph ] . setRect ( ( ( glyph - firstGlyph ) % numHorizontalGlyphs ) * glyphSize . width ( ) ,
( ( glyph - firstGlyph ) / numHorizontalGlyphs ) * glyphSize . height ( ) ,
glyphWidth ,
glyphSize . height ( ) ) ;
// store glyph size
m_glyphsSize [ glyph ] . setHeight ( glyphSize . height ( ) ) ;
m_glyphsSize [ glyph ] . setWidth ( glyphWidth ) ;
}
}
} catch ( YAML : : ParserException & e ) {
} catch ( YAML : : ParserException & e ) {
error ( " Malformed font file \" %s \" " , file . c_str ( ) ) ;
error ( " Malformed font file \" %s \" " , file . c_str ( ) ) ;
return false ;
return false ;
}
}
m_texture = g_textures . get ( " fonts/ " + textureName ) ;
m_numHorizontalGlyphs = m_texture - > getSize ( ) . width ( ) / m_glyphSize . width ( ) ;
if ( ! m_texture ) {
error ( " Failed to load image for font \" %s \" " , file . c_str ( ) ) ;
return false ;
}
return true ;
return true ;
}
}
void Font : : renderText ( const Point & pos , const std : : string & text )
void Font : : renderText ( const Point & pos , const std : : string & text )
{
{
// bind font texture
// begin texture rendering
glBindTexture ( GL_TEXTURE_2D , m_texture - > getTextureId ( ) ) ;
g_graphics . setColor ( m_color ) ;
g_graphics . _beginTextureRender ( m_texture . get ( ) ) ;
// set font color
glColor4ubv ( m_color . rgbaPtr ( ) ) ;
// begin render
glBegin ( GL_QUADS ) ;
Point currentPos = pos ;
Point currentPos = pos ;
const Size & screenSize = g_graphics . getScreenSize ( ) ;
const Size & screenSize = g_graphics . getScreenSize ( ) ;
const Size & textureSize = m_texture - > getSize ( ) ;
int textLenght = text . length ( ) ;
int textLenght = text . length ( ) ;
for ( int i = 0 ; i < textLenght ; + + i ) {
for ( int i = 0 ; i < textLenght ; + + i ) {
int c = ( int ) text [ i ] ;
int glyph = ( int ) text [ i ] ;
// check if is visible
// break rendering if the Y pos is below the screen
if ( currentPos . x > = screenSize . width ( ) )
continue ;
if ( currentPos . y > = screenSize . height ( ) )
if ( currentPos . y > = screenSize . height ( ) )
break ;
break ;
// new line
// new line
if ( c = = ' \n ' ) {
if ( glyph = = ( uchar ) ' \n ' ) {
currentPos . y + = m_lineHeight ;
currentPos . y + = m_lineHeight ;
currentPos . x = pos . x ;
currentPos . x = pos . x ;
}
}
// text eof
// render only if the glyph is valid and visible
else if ( c = = ' \0 ' ) {
else if ( glyph > = 32 & & currentPos . x < screenSize . width ( ) ) {
break ;
g_graphics . _drawTexturedRect ( Rect ( currentPos , m_glyphsSize [ glyph ] ) ,
}
m_glyphsTextureCoords [ glyph ] ,
// normal glyph
textureSize ) ;
else if ( c > = m_firstGlyph ) {
currentPos . x + = m_glyphsSize [ glyph ] . width ( ) ;
currentPos . x + = renderGlyph ( currentPos , c ) ;
}
}
}
}
// end font render
// end texture redering
glEnd ( ) ;
g_graphics . _endTextureRender ( ) ;
g_graphics . resetColor ( ) ;
}
}
int Font : : renderGlyph ( const Point & pos , int glyph )
Size Font : : calculateTextSize ( const std : : string & text )
{
{
// get glyph width
int textLenght = text . length ( ) ;
int glyphWidth = m_glyphWidths [ glyph ] ;
Size size ;
Point currentPos ;
// calculate glyph coords on texture font
for ( int i = 0 ; i < textLenght ; + + i ) {
const Size & textureSize = m_texture - > getSize ( ) ;
int glyph = ( int ) text [ i ] ;
int glyphTexCoordX = ( ( glyph - m_firstGlyph ) % m_numHorizontalGlyphs ) * m_glyphSize . width ( ) ;
int glyphTexCoordY = ( ( glyph - m_firstGlyph ) / m_numHorizontalGlyphs ) * m_glyphSize . height ( ) ;
if ( glyph = = ( uchar ) ' \n ' ) {
float textureRight = ( float ) ( glyphTexCoordX + glyphWidth ) / textureSize . width ( ) ;
currentPos . y + = m_lineHeight ;
float textureBottom = ( float ) ( glyphTexCoordY + m_glyphSize . height ( ) ) / textureSize . height ( ) ;
size . expandedTo ( currentPos . toSize ( ) ) ;
float textureTop = ( float ) ( glyphTexCoordY ) / textureSize . height ( ) ;
currentPos . x = 0 ;
float textureLeft = ( float ) ( glyphTexCoordX ) / textureSize . width ( ) ;
}
else if ( glyph > 32 ) {
// calculate glyph coords on screen
currentPos . x + = m_glyphsSize [ glyph ] . width ( ) ;
int right = pos . x + glyphWidth ;
}
int bottom = pos . y + m_glyphSize . height ( ) ;
}
int top = pos . y ;
return size ;
int left = pos . x ;
// render glyph
glTexCoord2f ( textureLeft , textureTop ) ; glVertex2i ( left , top ) ;
glTexCoord2f ( textureLeft , textureBottom ) ; glVertex2i ( left , bottom ) ;
glTexCoord2f ( textureRight , textureBottom ) ; glVertex2i ( right , bottom ) ;
glTexCoord2f ( textureRight , textureTop ) ; glVertex2i ( right , top ) ;
return glyphWidth ;
}
}