2022-10-20 20:29:11 +08:00
|
|
|
/*
|
|
|
|
PLIB - A Suite of Portable Game Libraries
|
|
|
|
Copyright (C) 1998,2002 Steve Baker
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library 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
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
|
|
License along with this library; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
|
|
|
For further information visit http://plib.sourceforge.net
|
|
|
|
|
|
|
|
$Id: fnt.cxx 1939 2004-08-05 00:41:53Z puggles $
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "fntLocal.h"
|
|
|
|
|
|
|
|
#include <simgear/misc/sg_path.hxx>
|
|
|
|
#include <simgear/debug/logstream.hxx>
|
|
|
|
|
|
|
|
fntFont:: fntFont () {}
|
|
|
|
fntFont::~fntFont () {}
|
|
|
|
|
|
|
|
int fntTexFont::load ( const SGPath& path, GLenum mag, GLenum min )
|
|
|
|
{
|
|
|
|
if (path.extension() == "txf") {
|
|
|
|
return loadTXF ( path, mag, min ) ;
|
|
|
|
} else {
|
|
|
|
const auto ps = path.utf8Str();
|
|
|
|
fntSetError ( SG_WARN,
|
|
|
|
"fnt::load: Error - Unrecognised file format for '%s'", ps.c_str() ) ;
|
|
|
|
return FNT_FALSE ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float fntTexFont::low_putch ( sgVec3 curpos, float pointsize,
|
|
|
|
float italic, char c )
|
|
|
|
{
|
|
|
|
unsigned int cc = (unsigned char) c ;
|
|
|
|
|
|
|
|
/* Auto case-convert if character is absent from font. */
|
|
|
|
|
2022-11-21 21:10:07 +08:00
|
|
|
//zhongjin
|
|
|
|
/*
|
2022-10-20 20:29:11 +08:00
|
|
|
if ( ! exists [ cc ] )
|
|
|
|
{
|
|
|
|
if ( cc >= 'A' && cc <= 'Z' )
|
|
|
|
cc = cc - 'A' + 'a' ;
|
|
|
|
else
|
|
|
|
if ( cc >= 'a' && cc <= 'z' )
|
|
|
|
cc = cc - 'a' + 'A' ;
|
|
|
|
|
|
|
|
if ( cc == ' ' )
|
|
|
|
{
|
|
|
|
curpos [ 0 ] += pointsize / 2.0f ;
|
|
|
|
return pointsize / 2.0f ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-21 21:10:07 +08:00
|
|
|
*/
|
|
|
|
|
2022-10-20 20:29:11 +08:00
|
|
|
/*
|
|
|
|
We might want to consider making some absent characters from
|
|
|
|
others (if they exist): lowercase 'l' could be made into digit '1'
|
|
|
|
or letter 'O' into digit '0'...or vice versa. We could also
|
|
|
|
make 'b', 'd', 'p' and 'q' by mirror-imaging - this would
|
|
|
|
save a little more texture memory in some fonts.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ( ! exists [ cc ] )
|
|
|
|
return 0.0f ;
|
|
|
|
|
|
|
|
glBegin ( GL_TRIANGLE_STRIP ) ;
|
|
|
|
glTexCoord2f ( t_left [cc], t_bot[cc] ) ;
|
|
|
|
glVertex3f ( curpos[0] + v_left [cc] * pointsize,
|
|
|
|
curpos[1] + v_bot [cc] * pointsize,
|
|
|
|
curpos[2] ) ;
|
|
|
|
|
|
|
|
glTexCoord2f ( t_left [cc], t_top[cc] ) ;
|
|
|
|
glVertex3f ( curpos[0] + (italic + v_left [cc]) * pointsize,
|
|
|
|
curpos[1] + v_top [cc] * pointsize,
|
|
|
|
curpos[2] ) ;
|
|
|
|
|
|
|
|
glTexCoord2f ( t_right[cc], t_bot[cc] ) ;
|
|
|
|
glVertex3f ( curpos[0] + v_right[cc] * pointsize,
|
|
|
|
curpos[1] + v_bot [cc] * pointsize,
|
|
|
|
curpos[2] ) ;
|
|
|
|
|
|
|
|
glTexCoord2f ( t_right[cc], t_top[cc] ) ;
|
|
|
|
glVertex3f ( curpos[0] + (italic + v_right[cc]) * pointsize,
|
|
|
|
curpos[1] + v_top [cc] * pointsize,
|
|
|
|
curpos[2] ) ;
|
|
|
|
glEnd () ;
|
|
|
|
|
|
|
|
float ww = ( gap + ( fixed_pitch ? width : widths[cc] ) ) * pointsize ;
|
|
|
|
curpos[0] += ww ;
|
|
|
|
return ww ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void fntTexFont::setGlyph ( char c, float wid,
|
|
|
|
float tex_left, float tex_right,
|
|
|
|
float tex_bot , float tex_top ,
|
|
|
|
float vtx_left, float vtx_right,
|
|
|
|
float vtx_bot , float vtx_top )
|
|
|
|
{
|
|
|
|
unsigned int cc = (unsigned char) c ;
|
|
|
|
|
|
|
|
exists[cc] = FNT_TRUE ;
|
|
|
|
|
|
|
|
widths[cc] = wid;
|
|
|
|
|
|
|
|
t_left[cc] = tex_left ; t_right[cc] = tex_right ;
|
|
|
|
t_bot [cc] = tex_bot ; t_top [cc] = tex_top ;
|
|
|
|
|
|
|
|
v_left[cc] = vtx_left ; v_right[cc] = vtx_right ;
|
|
|
|
v_bot [cc] = vtx_bot ; v_top [cc] = vtx_top ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fntTexFont::getGlyph ( char c, float* wid,
|
|
|
|
float *tex_left, float *tex_right,
|
|
|
|
float *tex_bot , float *tex_top ,
|
|
|
|
float *vtx_left, float *vtx_right,
|
|
|
|
float *vtx_bot , float *vtx_top )
|
|
|
|
{
|
|
|
|
unsigned int cc = (unsigned char) c ;
|
|
|
|
|
|
|
|
if ( ! exists[cc] ) return FNT_FALSE ;
|
|
|
|
|
|
|
|
if ( wid != NULL ) *wid = widths [cc] ;
|
|
|
|
|
|
|
|
if ( tex_left != NULL ) *tex_left = t_left [cc] ;
|
|
|
|
if ( tex_right != NULL ) *tex_right = t_right[cc] ;
|
|
|
|
if ( tex_bot != NULL ) *tex_bot = t_bot [cc] ;
|
|
|
|
if ( tex_top != NULL ) *tex_top = t_top [cc] ;
|
|
|
|
|
|
|
|
if ( vtx_left != NULL ) *vtx_left = v_left [cc] ;
|
|
|
|
if ( vtx_right != NULL ) *vtx_right = v_right[cc] ;
|
|
|
|
if ( vtx_bot != NULL ) *vtx_bot = v_bot [cc] ;
|
|
|
|
if ( vtx_top != NULL ) *vtx_top = v_top [cc] ;
|
|
|
|
|
|
|
|
return FNT_TRUE ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void fntTexFont::getBBox ( const char *s,
|
|
|
|
float pointsize, float italic,
|
|
|
|
float *left, float *right,
|
|
|
|
float *bot , float *top )
|
|
|
|
{
|
|
|
|
float h_pos = 0.0f ;
|
|
|
|
float v_pos = 0.0f ;
|
|
|
|
float l, r, b, t ;
|
|
|
|
|
|
|
|
l = r = b = t = 0.0f ;
|
|
|
|
|
|
|
|
while ( *s != '\0' )
|
|
|
|
{
|
|
|
|
if ( *s == '\n' )
|
|
|
|
{
|
|
|
|
h_pos = 0.0f ;
|
|
|
|
v_pos -= 1.333f ;
|
|
|
|
s++ ;
|
|
|
|
continue ;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int cc = (unsigned char) *(s++) ;
|
|
|
|
|
|
|
|
if ( ! exists [ cc ] )
|
|
|
|
{
|
|
|
|
if ( cc >= 'A' && cc <= 'Z' )
|
|
|
|
cc = cc - 'A' + 'a' ;
|
|
|
|
else
|
|
|
|
if ( cc >= 'a' && cc <= 'z' )
|
|
|
|
cc = cc - 'a' + 'A' ;
|
|
|
|
|
|
|
|
if ( cc == ' ' )
|
|
|
|
{
|
|
|
|
r += 0.5f ;
|
|
|
|
h_pos += 0.5f ;
|
|
|
|
|
|
|
|
continue ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ! exists [ cc ] )
|
|
|
|
continue ;
|
|
|
|
|
|
|
|
if ( italic >= 0 )
|
|
|
|
{
|
|
|
|
if ( l > h_pos + v_left [cc] ) l = h_pos + v_left [cc] ;
|
|
|
|
if ( r < gap + h_pos + v_right[cc]+italic ) r = gap + h_pos + v_right[cc] + italic ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( l > h_pos + v_left [cc]+italic ) l = h_pos + v_left [cc] + italic ;
|
|
|
|
if ( r < gap + h_pos + v_right[cc] ) r = gap + h_pos + v_right[cc] ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( b > v_pos + v_bot [cc] ) b = v_pos + v_bot [cc] ;
|
|
|
|
if ( t < v_pos + v_top [cc] ) t = v_pos + v_top [cc] ;
|
|
|
|
|
|
|
|
h_pos += gap + ( fixed_pitch ? width : widths[cc] ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( left != NULL ) *left = l * pointsize ;
|
|
|
|
if ( right != NULL ) *right = r * pointsize ;
|
|
|
|
if ( top != NULL ) *top = t * pointsize ;
|
|
|
|
if ( bot != NULL ) *bot = b * pointsize ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void fntTexFont::puts ( sgVec3 curpos, float pointsize, float italic, const char *s )
|
|
|
|
{
|
|
|
|
SGfloat origx = curpos[0] ;
|
|
|
|
|
|
|
|
if ( ! bound )
|
|
|
|
bind_texture () ;
|
|
|
|
|
|
|
|
while ( *s != '\0' )
|
|
|
|
{
|
|
|
|
if (*s == '\n')
|
|
|
|
{
|
|
|
|
curpos[0] = origx ;
|
|
|
|
curpos[1] -= pointsize ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
low_putch ( curpos, pointsize, italic, *s ) ;
|
|
|
|
|
|
|
|
s++ ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void fntInit ()
|
|
|
|
{
|
|
|
|
/* Empty right now */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void fntSetError(int level, const char* format, ...)
|
|
|
|
{
|
|
|
|
const int bufferLength = 2048;
|
|
|
|
char buffer[2048];
|
|
|
|
va_list args;
|
|
|
|
va_start (args, format);
|
|
|
|
vsnprintf(buffer,bufferLength,format, args);
|
|
|
|
va_end (args);
|
|
|
|
|
|
|
|
SG_LOG(SG_GUI, static_cast<sgDebugPriority>(level), buffer);
|
|
|
|
}
|