Adding in new .cpp versions of FT font code.
This commit is contained in:
parent
36d206f40f
commit
9d73c2d22d
76
src/osgText/FTBitmapGlyph.cpp
Normal file
76
src/osgText/FTBitmapGlyph.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
#include "GL/gl.h"
|
||||
|
||||
#include "FTBitmapGlyph.h"
|
||||
#include "FTGL.h"
|
||||
|
||||
|
||||
FTBitmapGlyph::FTBitmapGlyph( FT_Glyph glyph)
|
||||
: FTGlyph(),
|
||||
destWidth(0),
|
||||
destHeight(0),
|
||||
data(0)
|
||||
{
|
||||
// This function will always fail if the glyph's format isn't scalable????
|
||||
FT_Error err = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_mono, 0, 1);
|
||||
if( err || ft_glyph_format_bitmap != glyph->format)
|
||||
{return;}
|
||||
|
||||
FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
|
||||
FT_Bitmap* source = &bitmap->bitmap;
|
||||
|
||||
//check the pixel mode
|
||||
//ft_pixel_mode_grays
|
||||
|
||||
int srcWidth = source->width;
|
||||
int srcHeight = source->rows;
|
||||
int srcPitch = source->pitch;
|
||||
|
||||
advance = glyph->advance.x >> 16;
|
||||
|
||||
pos.x = bitmap->left;
|
||||
pos.y = srcHeight - bitmap->top;
|
||||
|
||||
// FIXME What about dest alignment?
|
||||
destWidth = srcWidth;
|
||||
destHeight = srcHeight;
|
||||
|
||||
data = new unsigned char[srcPitch * destHeight];
|
||||
|
||||
for(int y = 0; y < srcHeight; ++y)
|
||||
{
|
||||
--destHeight;
|
||||
for(int x = 0; x < srcPitch; ++x)
|
||||
{
|
||||
*( data + ( destHeight * srcPitch + x)) = *( source->buffer + ( y * srcPitch) + x);
|
||||
}
|
||||
}
|
||||
|
||||
destHeight = srcHeight;
|
||||
|
||||
// discard glyph image (bitmap or not)
|
||||
// Is this the right place to do this?
|
||||
FT_Done_Glyph( glyph );
|
||||
}
|
||||
|
||||
|
||||
FTBitmapGlyph::~FTBitmapGlyph()
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
|
||||
float FTBitmapGlyph::Render( const FT_Vector& pen)
|
||||
{
|
||||
if( data != 0 )
|
||||
{
|
||||
// Move the glyph origin
|
||||
glBitmap( 0, 0, 0.0, 0.0, pen.x + pos.x, pen.y - pos.y, (const GLubyte *)0 );
|
||||
|
||||
glBitmap( destWidth, destHeight, 0.0f, 0.0, 0.0, 0.0, (const GLubyte *)data);
|
||||
|
||||
// Restore the glyph origin
|
||||
glBitmap( 0, 0, 0.0, 0.0, -pen.x - pos.x, -pen.y + pos.y, (const GLubyte *)0 );
|
||||
}
|
||||
|
||||
return advance;
|
||||
}
|
91
src/osgText/FTCharmap.cpp
Normal file
91
src/osgText/FTCharmap.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include "FTCharmap.h"
|
||||
|
||||
|
||||
FTCharmap::FTCharmap( FT_Face face)
|
||||
: err(0),
|
||||
ftFace( face)
|
||||
{
|
||||
ftEncoding = face->charmap->encoding;
|
||||
}
|
||||
|
||||
|
||||
FTCharmap::~FTCharmap()
|
||||
{
|
||||
charMap.clear();
|
||||
}
|
||||
|
||||
|
||||
bool FTCharmap::CharMap( FT_Encoding encoding)
|
||||
{
|
||||
if( ftEncoding == encoding)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
err = FT_Select_Charmap( ftFace, encoding );
|
||||
|
||||
if( !err)
|
||||
{
|
||||
ftEncoding = encoding;
|
||||
charMap.clear();
|
||||
}
|
||||
|
||||
return !err;
|
||||
}
|
||||
|
||||
|
||||
bool FTCharmap::CharMap( FT_UShort platform, FT_UShort encoding)
|
||||
{
|
||||
FT_CharMap found = 0;
|
||||
FT_CharMap charmap;
|
||||
|
||||
for( int n = 0; n < ftFace->num_charmaps; n++ )
|
||||
{
|
||||
charmap = ftFace->charmaps[n];
|
||||
|
||||
if( charmap->platform_id == platform && charmap->encoding_id == encoding)
|
||||
{
|
||||
found = charmap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !found )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( ftEncoding == found->encoding)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* now, select the charmap for the face object */
|
||||
err = FT_Set_Charmap( ftFace, found );
|
||||
|
||||
if( !err)
|
||||
{
|
||||
ftEncoding = found->encoding;
|
||||
charMap.clear();
|
||||
}
|
||||
|
||||
return !err;
|
||||
}
|
||||
|
||||
|
||||
unsigned int FTCharmap::CharIndex( unsigned int index )
|
||||
{
|
||||
CharacterMap::const_iterator result = charMap.find( index);
|
||||
|
||||
if( result == charMap.end())
|
||||
{
|
||||
unsigned int glyph = FT_Get_Char_Index( ftFace, index);
|
||||
charMap.insert( CharacterMap::value_type( index, glyph));
|
||||
return glyph;
|
||||
}
|
||||
else
|
||||
{
|
||||
return result->second;
|
||||
}
|
||||
|
||||
}
|
110
src/osgText/FTFace.cpp
Normal file
110
src/osgText/FTFace.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include "FTFace.h"
|
||||
#include "FTLibrary.h"
|
||||
#include "FTCharmap.h"
|
||||
#include "FTGL.h"
|
||||
|
||||
|
||||
FTFace::FTFace()
|
||||
: ftFace(0),
|
||||
numCharMaps(0),
|
||||
charMap(0),
|
||||
numGlyphs(0),
|
||||
err(0)
|
||||
{}
|
||||
|
||||
|
||||
FTFace::~FTFace()
|
||||
{
|
||||
delete charMap;
|
||||
charMap = 0;
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
bool FTFace::Open( const char* filename)
|
||||
{
|
||||
ftFace = new FT_Face;
|
||||
err = FT_New_Face( *FTLibrary::Instance().GetLibrary(), filename, 0, ftFace);
|
||||
|
||||
if( err)
|
||||
{
|
||||
delete ftFace;
|
||||
ftFace = 0;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
charMap = new FTCharmap( *ftFace);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FTFace::Close()
|
||||
{
|
||||
if( ftFace)
|
||||
{
|
||||
FT_Done_Face( *ftFace);
|
||||
delete ftFace;
|
||||
ftFace = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FTSize& FTFace::Size( const unsigned int size, const unsigned int res)
|
||||
{
|
||||
if( !charSize.CharSize( ftFace, size, res, res))
|
||||
{
|
||||
err = charSize.Error();
|
||||
}
|
||||
|
||||
return charSize;
|
||||
}
|
||||
|
||||
|
||||
bool FTFace::CharMap( FT_Encoding encoding)
|
||||
{
|
||||
return charMap->CharMap( encoding);
|
||||
}
|
||||
|
||||
|
||||
unsigned int FTFace::CharIndex( unsigned int index) const
|
||||
{
|
||||
return charMap->CharIndex( index);
|
||||
}
|
||||
|
||||
|
||||
FT_Vector& FTFace::KernAdvance( unsigned int index1, unsigned int index2)
|
||||
{
|
||||
kernAdvance.x = 0; kernAdvance.y = 0;
|
||||
|
||||
if( FT_HAS_KERNING((*ftFace)) && index1 && index2)
|
||||
{
|
||||
err = FT_Get_Kerning( *ftFace, index1, index2, ft_kerning_unfitted, &kernAdvance);
|
||||
if( !err)
|
||||
{
|
||||
kernAdvance.x /= 64; kernAdvance.y /= 64;
|
||||
}
|
||||
}
|
||||
|
||||
return kernAdvance;
|
||||
}
|
||||
|
||||
|
||||
FT_Glyph* FTFace::Glyph( unsigned int index, FT_Int load_flags)
|
||||
{
|
||||
err = FT_Load_Glyph( *ftFace, index, load_flags);
|
||||
err = FT_Get_Glyph( (*ftFace)->glyph, &ftGlyph);
|
||||
|
||||
if( !err)
|
||||
{
|
||||
return &ftGlyph;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
148
src/osgText/FTFont.cpp
Normal file
148
src/osgText/FTFont.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
#include "FTFace.h"
|
||||
#include "FTFont.h"
|
||||
#include "FTGlyphContainer.h"
|
||||
#include "FTGL.h"
|
||||
|
||||
|
||||
FTFont::FTFont()
|
||||
: numFaces(0),
|
||||
glyphList(0),
|
||||
err(0)
|
||||
{
|
||||
pen.x = 0;
|
||||
pen.y = 0;
|
||||
}
|
||||
|
||||
|
||||
FTFont::~FTFont()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
bool FTFont::Open( const char* fontname )
|
||||
{
|
||||
if( face.Open( fontname))
|
||||
{
|
||||
FT_Face* ftFace = face.Face();
|
||||
numGlyphs = (*ftFace)->num_glyphs;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = face.Error();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FTFont::Close()
|
||||
{
|
||||
delete glyphList;
|
||||
}
|
||||
|
||||
|
||||
bool FTFont::FaceSize( const unsigned int size, const unsigned int res )
|
||||
{
|
||||
charSize = face.Size( size, res);
|
||||
|
||||
if( glyphList)
|
||||
delete glyphList;
|
||||
|
||||
glyphList = new FTGlyphContainer( &face, numGlyphs);
|
||||
|
||||
if( MakeGlyphList())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool FTFont::CharMap( FT_Encoding encoding)
|
||||
{
|
||||
err = face.CharMap( encoding);
|
||||
return !err;
|
||||
}
|
||||
|
||||
|
||||
int FTFont::Ascender() const
|
||||
{
|
||||
return charSize.Ascender();
|
||||
}
|
||||
|
||||
|
||||
int FTFont::Descender() const
|
||||
{
|
||||
return charSize.Descender();
|
||||
}
|
||||
|
||||
|
||||
float FTFont::Advance( const wchar_t* string)
|
||||
{
|
||||
const wchar_t* c = string; // wchar_t IS unsigned?
|
||||
float width = 0;
|
||||
|
||||
while( *c)
|
||||
{
|
||||
width += glyphList->Advance( *c, *(c + 1));
|
||||
++c;
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
float FTFont::Advance( const char* string)
|
||||
{
|
||||
const unsigned char* c = (unsigned char*)string; // This is ugly, what is the c++ way?
|
||||
float width = 0;
|
||||
|
||||
while( *c)
|
||||
{
|
||||
width += glyphList->Advance( *c, *(c + 1));
|
||||
++c;
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
void FTFont::render( const char* string )
|
||||
{
|
||||
const unsigned char* c = (unsigned char*)string; // This is ugly, what is the c++ way?
|
||||
FT_Vector kernAdvance;
|
||||
pen.x = 0; pen.y = 0;
|
||||
|
||||
while( *c)
|
||||
{
|
||||
kernAdvance = glyphList->render( *c, *(c + 1), pen);
|
||||
|
||||
pen.x += kernAdvance.x;
|
||||
pen.y += kernAdvance.y;
|
||||
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FTFont::render( const wchar_t* string )
|
||||
{
|
||||
const wchar_t* c = string; // wchar_t IS unsigned?
|
||||
FT_Vector kernAdvance;
|
||||
pen.x = 0; pen.y = 0;
|
||||
|
||||
while( *c)
|
||||
{
|
||||
kernAdvance = glyphList->render( *c, *(c + 1), pen);
|
||||
|
||||
pen.x += kernAdvance.x;
|
||||
pen.y += kernAdvance.y;
|
||||
|
||||
++c;
|
||||
}
|
||||
}
|
70
src/osgText/FTGLBitmapFont.cpp
Normal file
70
src/osgText/FTGLBitmapFont.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
#include "GL/gl.h"
|
||||
|
||||
#include "FTGLBitmapFont.h"
|
||||
#include "FTGlyphContainer.h"
|
||||
#include "FTBitmapGlyph.h"
|
||||
|
||||
|
||||
FTGLBitmapFont::FTGLBitmapFont()
|
||||
: tempGlyph(0)
|
||||
{}
|
||||
|
||||
|
||||
FTGLBitmapFont::~FTGLBitmapFont()
|
||||
{}
|
||||
|
||||
|
||||
// OPSignature: bool FTGlyphContainer:MakeGlyphList()
|
||||
bool FTGLBitmapFont::MakeGlyphList()
|
||||
{
|
||||
// if( preCache)
|
||||
for( unsigned int c = 0; c < numGlyphs; ++c)
|
||||
{
|
||||
FT_Glyph* ftGlyph = face.Glyph( c, FT_LOAD_DEFAULT);
|
||||
// FT_HAS_VERTICAL(face)
|
||||
|
||||
if( ftGlyph)
|
||||
{
|
||||
tempGlyph = new FTBitmapGlyph( *ftGlyph);
|
||||
glyphList->Add( tempGlyph);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = face.Error();
|
||||
}
|
||||
}
|
||||
|
||||
return !err;
|
||||
}
|
||||
|
||||
|
||||
void FTGLBitmapFont::render( const char* string)
|
||||
{
|
||||
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT);
|
||||
|
||||
// doing this every frame is a bad?
|
||||
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE);
|
||||
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
|
||||
glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
FTFont::render( string);
|
||||
|
||||
glPopClientAttrib();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FTGLBitmapFont::render( const wchar_t* string)
|
||||
{
|
||||
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT);
|
||||
|
||||
// doing this every frame is a bad?
|
||||
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE);
|
||||
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
|
||||
glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
FTFont::render( string);
|
||||
|
||||
glPopClientAttrib();
|
||||
|
||||
}
|
68
src/osgText/FTGLOutlineFont.cpp
Normal file
68
src/osgText/FTGLOutlineFont.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include "GL/gl.h"
|
||||
|
||||
#include "FTGLOutlineFont.h"
|
||||
#include "FTGlyphContainer.h"
|
||||
#include "FTGL.h"
|
||||
#include "FTOutlineGlyph.h"
|
||||
|
||||
|
||||
FTGLOutlineFont::FTGLOutlineFont()
|
||||
: tempGlyph(0)
|
||||
{}
|
||||
|
||||
|
||||
FTGLOutlineFont::~FTGLOutlineFont()
|
||||
{}
|
||||
|
||||
|
||||
bool FTGLOutlineFont::MakeGlyphList()
|
||||
{
|
||||
for( unsigned int n = 0; n < numGlyphs; ++n)
|
||||
{
|
||||
FT_Glyph* ftGlyph = face.Glyph( n, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
|
||||
|
||||
if( ftGlyph)
|
||||
{
|
||||
tempGlyph = new FTOutlineGlyph( *ftGlyph);
|
||||
glyphList->Add( tempGlyph);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = face.Error();
|
||||
}
|
||||
}
|
||||
|
||||
return !err;
|
||||
}
|
||||
|
||||
|
||||
void FTGLOutlineFont::render( const char* string)
|
||||
{
|
||||
glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT);
|
||||
|
||||
glEnable( GL_LINE_SMOOTH);
|
||||
glHint( GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
|
||||
|
||||
FTFont::render( string);
|
||||
|
||||
glPopAttrib();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FTGLOutlineFont::render( const wchar_t* string)
|
||||
{
|
||||
glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT);
|
||||
|
||||
glEnable( GL_LINE_SMOOTH);
|
||||
glHint( GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
|
||||
|
||||
FTFont::render( string);
|
||||
|
||||
glPopAttrib();
|
||||
|
||||
}
|
66
src/osgText/FTGLPixmapFont.cpp
Normal file
66
src/osgText/FTGLPixmapFont.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include "GL/gl.h"
|
||||
|
||||
#include "FTGLPixmapFont.h"
|
||||
#include "FTGlyphContainer.h"
|
||||
#include "FTPixmapGlyph.h"
|
||||
|
||||
|
||||
FTGLPixmapFont::FTGLPixmapFont()
|
||||
: tempGlyph(0)
|
||||
{}
|
||||
|
||||
|
||||
FTGLPixmapFont::~FTGLPixmapFont()
|
||||
{}
|
||||
|
||||
|
||||
// OPSignature: bool FTGlyphContainer:MakeGlyphList()
|
||||
bool FTGLPixmapFont::MakeGlyphList()
|
||||
{
|
||||
// if( preCache)
|
||||
for( unsigned int c = 0; c < numGlyphs; ++c)
|
||||
{
|
||||
FT_Glyph* ftGlyph = face.Glyph( c, FT_LOAD_DEFAULT);
|
||||
// FT_HAS_VERTICAL(face)
|
||||
|
||||
if( ftGlyph)
|
||||
{
|
||||
tempGlyph = new FTPixmapGlyph( *ftGlyph);
|
||||
glyphList->Add( tempGlyph);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = face.Error();
|
||||
}
|
||||
}
|
||||
|
||||
return !err;
|
||||
}
|
||||
|
||||
|
||||
void FTGLPixmapFont::render( const char* string)
|
||||
{
|
||||
glPushAttrib( GL_ENABLE_BIT | GL_PIXEL_MODE_BIT);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
FTFont::render( string);
|
||||
|
||||
glPopAttrib();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FTGLPixmapFont::render( const wchar_t* string)
|
||||
{
|
||||
glPushAttrib( GL_ENABLE_BIT | GL_PIXEL_MODE_BIT);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
FTFont::render( string);
|
||||
|
||||
glPopAttrib();
|
||||
|
||||
}
|
35
src/osgText/FTGLPolygonFont.cpp
Normal file
35
src/osgText/FTGLPolygonFont.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "FTGLPolygonFont.h"
|
||||
#include "FTGlyphContainer.h"
|
||||
#include "FTGL.h"
|
||||
#include "FTPolyGlyph.h"
|
||||
|
||||
|
||||
|
||||
FTGLPolygonFont::FTGLPolygonFont()
|
||||
: tempGlyph(0)
|
||||
{}
|
||||
|
||||
|
||||
FTGLPolygonFont::~FTGLPolygonFont()
|
||||
{}
|
||||
|
||||
|
||||
bool FTGLPolygonFont::MakeGlyphList()
|
||||
{
|
||||
for( unsigned int n = 0; n < numGlyphs; ++n)
|
||||
{
|
||||
FT_Glyph* ftGlyph = face.Glyph( n, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
|
||||
|
||||
if( ftGlyph)
|
||||
{
|
||||
tempGlyph = new FTPolyGlyph( *ftGlyph);
|
||||
glyphList->Add( tempGlyph);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = face.Error();
|
||||
}
|
||||
}
|
||||
|
||||
return !err;
|
||||
}
|
210
src/osgText/FTGLTextureFont.cpp
Normal file
210
src/osgText/FTGLTextureFont.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
#include "GL/gl.h"
|
||||
|
||||
#include "FTGLTextureFont.h"
|
||||
#include "FTGlyphContainer.h"
|
||||
#include "FTGL.h"
|
||||
#include "FTTextureGlyph.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef unsigned long UInt32; // a mac thing?
|
||||
|
||||
inline UInt32 NextPowerOf2( UInt32 in)
|
||||
{
|
||||
in -= 1;
|
||||
|
||||
in |= in >> 16;
|
||||
in |= in >> 8;
|
||||
in |= in >> 4;
|
||||
in |= in >> 2;
|
||||
in |= in >> 1;
|
||||
|
||||
return in + 1;
|
||||
}
|
||||
|
||||
|
||||
FTGLTextureFont::FTGLTextureFont()
|
||||
: numTextures(1),
|
||||
textMem(0),
|
||||
padding(1),
|
||||
tempGlyph(0),
|
||||
maxTextSize(0),
|
||||
textureWidth(0),
|
||||
textureHeight(0),
|
||||
glyphHeight(0),
|
||||
glyphWidth(0)
|
||||
{}
|
||||
|
||||
|
||||
FTGLTextureFont::~FTGLTextureFont()
|
||||
{
|
||||
glDeleteTextures( numTextures, (const GLuint*)glTextureID);
|
||||
}
|
||||
|
||||
|
||||
bool FTGLTextureFont::MakeGlyphList()
|
||||
{
|
||||
if( !maxTextSize)
|
||||
glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&maxTextSize);
|
||||
|
||||
glyphHeight = ( charSize.Height()) + padding;
|
||||
glyphWidth = ( charSize.Width()) + padding;
|
||||
|
||||
GetSize();
|
||||
int totalMem;
|
||||
|
||||
if( textureHeight > maxTextSize)
|
||||
{
|
||||
numTextures = static_cast<int>( textureHeight / maxTextSize) + 1;
|
||||
if( numTextures > 15) // FIXME
|
||||
numTextures = 15;
|
||||
|
||||
int heightRemain = NextPowerOf2( textureHeight % maxTextSize);
|
||||
totalMem = ((maxTextSize * ( numTextures - 1)) + heightRemain) * textureWidth;
|
||||
|
||||
glGenTextures( numTextures, (GLuint*)&glTextureID[0]);
|
||||
|
||||
textMem = new unsigned char[totalMem]; // GL_ALPHA texture;
|
||||
memset( textMem, 0, totalMem);
|
||||
|
||||
unsigned int glyphNum = 0;
|
||||
unsigned char* currTextPtr = textMem;
|
||||
|
||||
for( int x = 0; x < numTextures - 1; ++x)
|
||||
{
|
||||
glyphNum = FillGlyphs( glyphNum, glTextureID[x], textureWidth, maxTextSize, currTextPtr);
|
||||
|
||||
CreateTexture( x, textureWidth, maxTextSize, currTextPtr);
|
||||
|
||||
currTextPtr += ( textureWidth * maxTextSize);
|
||||
++glyphNum;
|
||||
}
|
||||
|
||||
glyphNum = FillGlyphs( glyphNum, glTextureID[numTextures - 1], textureWidth, heightRemain, currTextPtr);
|
||||
CreateTexture( numTextures - 1, textureWidth, heightRemain, currTextPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
textureHeight = NextPowerOf2( textureHeight);
|
||||
totalMem = textureWidth * textureHeight;
|
||||
|
||||
glGenTextures( numTextures, (GLuint*)&glTextureID[0]);
|
||||
|
||||
textMem = new unsigned char[totalMem]; // GL_ALPHA texture;
|
||||
std::memset( textMem, 0, totalMem);
|
||||
|
||||
FillGlyphs( 0, glTextureID[0], textureWidth, textureHeight, textMem);
|
||||
CreateTexture( 0, textureWidth, textureHeight, textMem);
|
||||
}
|
||||
|
||||
delete [] textMem;
|
||||
return !err;
|
||||
}
|
||||
|
||||
|
||||
unsigned int FTGLTextureFont::FillGlyphs( unsigned int glyphStart, int id, int width, int height, unsigned char* textdata)
|
||||
{
|
||||
int currentTextX = padding;
|
||||
int currentTextY = padding;// + padding;
|
||||
|
||||
float currTextU = (float)padding / (float)width;
|
||||
float currTextV = (float)padding / (float)height;
|
||||
|
||||
// numGlyphs = 256; // FIXME hack
|
||||
unsigned int n;
|
||||
|
||||
for( n = glyphStart; n <= numGlyphs; ++n)
|
||||
{
|
||||
FT_Glyph* ftGlyph = face.Glyph( n, FT_LOAD_NO_HINTING);
|
||||
|
||||
if( ftGlyph)
|
||||
{
|
||||
unsigned char* data = textdata + (( currentTextY * width) + currentTextX);
|
||||
|
||||
currTextU = (float)currentTextX / (float)width;
|
||||
|
||||
tempGlyph = new FTTextureGlyph( *ftGlyph, id, data, width, height, currTextU, currTextV);
|
||||
glyphList->Add( tempGlyph);
|
||||
|
||||
currentTextX += glyphWidth;
|
||||
if( currentTextX > ( width - glyphWidth))
|
||||
{
|
||||
currentTextY += glyphHeight;
|
||||
if( currentTextY > ( height - glyphHeight))
|
||||
return n;
|
||||
|
||||
currentTextX = padding;
|
||||
currTextV = (float)currentTextY / (float)height;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err = face.Error();
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
void FTGLTextureFont::GetSize()
|
||||
{
|
||||
//work out the max width. Most likely maxTextSize
|
||||
textureWidth = NextPowerOf2( numGlyphs * glyphWidth);
|
||||
if( textureWidth > maxTextSize)
|
||||
{
|
||||
textureWidth = maxTextSize;
|
||||
}
|
||||
|
||||
int h = static_cast<int>( textureWidth / glyphWidth);
|
||||
textureHeight = (( numGlyphs / h) + 1) * glyphHeight;
|
||||
}
|
||||
|
||||
|
||||
void FTGLTextureFont::CreateTexture( int id, int width, int height, unsigned char* data)
|
||||
{
|
||||
glPixelStorei( GL_UNPACK_ALIGNMENT, 1); //What does this do exactly?
|
||||
glBindTexture( GL_TEXTURE_2D, glTextureID[id]);
|
||||
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);
|
||||
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
|
||||
void FTGLTextureFont::render( const char* string)
|
||||
{
|
||||
glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, (GLuint)FTTextureGlyph::activeTextureID);
|
||||
|
||||
// QUADS are faster!? Less function call overhead?
|
||||
glBegin( GL_QUADS);
|
||||
FTFont::render( string);
|
||||
glEnd();
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
|
||||
void FTGLTextureFont::render( const wchar_t* string)
|
||||
{
|
||||
glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, (GLuint)FTTextureGlyph::activeTextureID);
|
||||
|
||||
// QUADS are faster!? Less function call overhead?
|
||||
glBegin( GL_QUADS);
|
||||
FTFont::render( string);
|
||||
glEnd();
|
||||
|
||||
glPopAttrib();
|
||||
}
|
14
src/osgText/FTGlyph.cpp
Normal file
14
src/osgText/FTGlyph.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "FTGlyph.h"
|
||||
|
||||
|
||||
FTGlyph::FTGlyph()
|
||||
: advance(0),
|
||||
err(0)
|
||||
{
|
||||
pos.x = 0;
|
||||
pos.y = 0;
|
||||
}
|
||||
|
||||
|
||||
FTGlyph::~FTGlyph()
|
||||
{}
|
66
src/osgText/FTGlyphContainer.cpp
Normal file
66
src/osgText/FTGlyphContainer.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include "FTGlyphContainer.h"
|
||||
#include "FTGlyph.h"
|
||||
#include "FTFace.h"
|
||||
|
||||
|
||||
FTGlyphContainer::FTGlyphContainer( FTFace* f, int g, bool p)
|
||||
: preCache( p),
|
||||
numGlyphs( g),
|
||||
face( f),
|
||||
err( 0)
|
||||
{
|
||||
glyphs.reserve( g);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FTGlyphContainer::~FTGlyphContainer()
|
||||
{
|
||||
vector<FTGlyph*>::iterator iter;
|
||||
for( iter = glyphs.begin(); iter != glyphs.end(); ++iter)
|
||||
{
|
||||
delete *iter;
|
||||
}
|
||||
|
||||
glyphs.clear();
|
||||
}
|
||||
|
||||
|
||||
bool FTGlyphContainer::Add( FTGlyph* tempGlyph)
|
||||
{
|
||||
// At the moment we are using a vector. Vectors don't return bool.
|
||||
glyphs.push_back( tempGlyph);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
float FTGlyphContainer::Advance( unsigned int index, unsigned int next)
|
||||
{
|
||||
unsigned int left = face->CharIndex( index);
|
||||
unsigned int right = face->CharIndex( next);
|
||||
|
||||
float width = face->KernAdvance( left, right).x;
|
||||
width += glyphs[left]->Advance();
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
FT_Vector& FTGlyphContainer::render( unsigned int index, unsigned int next, FT_Vector pen)
|
||||
{
|
||||
kernAdvance.x = 0; kernAdvance.y = 0;
|
||||
|
||||
unsigned int left = face->CharIndex( index);
|
||||
unsigned int right = face->CharIndex( next);
|
||||
|
||||
kernAdvance = face->KernAdvance( left, right);
|
||||
|
||||
if( !face->Error())
|
||||
{
|
||||
advance = glyphs[left]->Render( pen);
|
||||
}
|
||||
|
||||
kernAdvance.x = advance + kernAdvance.x; // FIXME float to long
|
||||
// kernAdvance.y = advance.y + kernAdvance.y;
|
||||
return kernAdvance;
|
||||
}
|
65
src/osgText/FTLibrary.cpp
Normal file
65
src/osgText/FTLibrary.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#include "FTLibrary.h"
|
||||
#include "FTGL.h"
|
||||
|
||||
|
||||
FTLibrary& FTLibrary::Instance()
|
||||
{
|
||||
static FTLibrary ftlib;
|
||||
return ftlib;
|
||||
}
|
||||
|
||||
|
||||
FTLibrary::~FTLibrary()
|
||||
{
|
||||
if( lib != 0)
|
||||
{
|
||||
FT_Done_FreeType( *lib);
|
||||
|
||||
delete lib;
|
||||
lib= 0;
|
||||
}
|
||||
|
||||
// if( manager != 0)
|
||||
// {
|
||||
// FTC_Manager_Done( manager );
|
||||
//
|
||||
// delete manager;
|
||||
// manager= 0;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
FTLibrary::FTLibrary()
|
||||
: lib(0),
|
||||
err(0)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
bool FTLibrary::Init()
|
||||
{
|
||||
if( lib != 0 )
|
||||
return true;
|
||||
|
||||
lib = new FT_Library;
|
||||
|
||||
err = FT_Init_FreeType( lib);
|
||||
if( err)
|
||||
{
|
||||
delete lib;
|
||||
lib = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// FTC_Manager* manager;
|
||||
//
|
||||
// if( FTC_Manager_New( lib, 0, 0, 0, my_face_requester, 0, manager )
|
||||
// {
|
||||
// delete manager;
|
||||
// manager= 0;
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
83
src/osgText/FTOutlineGlyph.cpp
Normal file
83
src/osgText/FTOutlineGlyph.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#include "GL/gl.h"
|
||||
|
||||
#include "FTOutlineGlyph.h"
|
||||
#include "FTVectoriser.h"
|
||||
#include "FTGL.h"
|
||||
|
||||
|
||||
|
||||
FTOutlineGlyph::FTOutlineGlyph( FT_Glyph glyph)
|
||||
: FTGlyph(),
|
||||
vectoriser(0),
|
||||
numPoints(0),
|
||||
numContours(0),
|
||||
contourLength(0),
|
||||
data(0),
|
||||
glList(0)
|
||||
{
|
||||
if( ft_glyph_format_outline != glyph->format)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vectoriser = new FTVectoriser( glyph);
|
||||
|
||||
vectoriser->Ingest();
|
||||
numContours = vectoriser->contours();
|
||||
contourLength = new int[ numContours];
|
||||
|
||||
for( int cn = 0; cn < numContours; ++cn)
|
||||
{
|
||||
contourLength[cn] = vectoriser->contourSize( cn);
|
||||
}
|
||||
|
||||
numPoints = vectoriser->points();
|
||||
data = new double[ numPoints * 3];
|
||||
vectoriser->Output( data);
|
||||
|
||||
advance = glyph->advance.x >> 16;
|
||||
|
||||
delete vectoriser;
|
||||
|
||||
if ( ( numContours < 1) || ( numPoints < 3))
|
||||
return;
|
||||
|
||||
glList = glGenLists(1);
|
||||
int d = 0;
|
||||
|
||||
glNewList( glList, GL_COMPILE);
|
||||
for( int c = 0; c < numContours; ++c)
|
||||
{
|
||||
glBegin( GL_LINE_LOOP);
|
||||
for( int p = 0; p < ( contourLength[c]); ++p)
|
||||
{
|
||||
glVertex2dv( data + d);
|
||||
d += 3;
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
glEndList();
|
||||
|
||||
// discard glyph image (bitmap or not)
|
||||
FT_Done_Glyph( glyph); // Why does this have to be HERE
|
||||
}
|
||||
|
||||
|
||||
FTOutlineGlyph::~FTOutlineGlyph()
|
||||
{
|
||||
delete [] data;
|
||||
delete [] contourLength;
|
||||
}
|
||||
|
||||
|
||||
float FTOutlineGlyph::Render( const FT_Vector& pen)
|
||||
{
|
||||
if( glList)
|
||||
{
|
||||
glTranslatef( pen.x, pen.y, 0);
|
||||
glCallList( glList);
|
||||
glTranslatef( -pen.x, -pen.y, 0);
|
||||
}
|
||||
|
||||
return advance;
|
||||
}
|
94
src/osgText/FTPixmapGlyph.cpp
Normal file
94
src/osgText/FTPixmapGlyph.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include "GL/gl.h"
|
||||
|
||||
#include "FTPixmapGlyph.h"
|
||||
#include "FTGL.h"
|
||||
|
||||
|
||||
FTPixmapGlyph::FTPixmapGlyph( FT_Glyph glyph)
|
||||
: FTGlyph(),
|
||||
destWidth(0),
|
||||
destHeight(0),
|
||||
numGreys(0),
|
||||
data(0)
|
||||
{
|
||||
// This function will always fail if the glyph's format isn't scalable????
|
||||
FT_Error err = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1);
|
||||
if( err || ft_glyph_format_bitmap != glyph->format)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
|
||||
FT_Bitmap* source = &bitmap->bitmap;
|
||||
|
||||
//check the pixel mode
|
||||
//ft_pixel_mode_grays
|
||||
|
||||
int srcWidth = source->width;
|
||||
int srcHeight = source->rows;
|
||||
int srcPitch = source->pitch;
|
||||
|
||||
numGreys = source->num_grays;
|
||||
advance = glyph->advance.x >> 16;
|
||||
|
||||
pos.x = bitmap->left;
|
||||
pos.y = srcHeight - bitmap->top;
|
||||
|
||||
// FIXME What about dest alignment?
|
||||
destWidth = srcWidth;
|
||||
destHeight = srcHeight;
|
||||
|
||||
data = new unsigned char[destWidth * destHeight * 4];
|
||||
|
||||
// Get the current glColor.
|
||||
float ftglColour[4];
|
||||
glGetFloatv( GL_CURRENT_COLOR, ftglColour);
|
||||
|
||||
for(int y = 0; y < srcHeight; ++y)
|
||||
{
|
||||
--destHeight;
|
||||
for(int x = 0; x < srcWidth; ++x)
|
||||
{
|
||||
*( data + ( destHeight * destWidth + x) * 4 + 0) = static_cast<unsigned char>( ftglColour[0] * 255.0f);
|
||||
*( data + ( destHeight * destWidth + x) * 4 + 1) = static_cast<unsigned char>( ftglColour[1] * 255.0f);
|
||||
*( data + ( destHeight * destWidth + x) * 4 + 2) = static_cast<unsigned char>( ftglColour[2] * 255.0f);
|
||||
*( data + ( destHeight * destWidth + x) * 4 + 3) = static_cast<unsigned char>( ftglColour[3] * (*( source->buffer + ( y * srcPitch) + x)));
|
||||
}
|
||||
}
|
||||
|
||||
destHeight = srcHeight;
|
||||
|
||||
// discard glyph image (bitmap or not)
|
||||
// Is this the right place to do this?
|
||||
FT_Done_Glyph( glyph );
|
||||
}
|
||||
|
||||
|
||||
FTPixmapGlyph::~FTPixmapGlyph()
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
|
||||
float FTPixmapGlyph::Render( const FT_Vector& pen)
|
||||
{
|
||||
if( data != 0 )
|
||||
{
|
||||
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT);
|
||||
|
||||
// Move the glyph origin
|
||||
glBitmap( 0, 0, 0.0, 0.0, pen.x + pos.x, pen.y - pos.y, (const GLubyte *)0);
|
||||
|
||||
glPixelStorei( GL_UNPACK_ROW_LENGTH, destWidth);
|
||||
|
||||
glDrawPixels( destWidth, destHeight, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)data);
|
||||
|
||||
|
||||
// Restore the glyph origin
|
||||
glBitmap( 0, 0, 0.0, 0.0, -pen.x - pos.x, -pen.y + pos.y, (const GLubyte *)0);
|
||||
|
||||
glPopClientAttrib();
|
||||
}
|
||||
|
||||
return advance;
|
||||
}
|
156
src/osgText/FTPolyGlyph.cpp
Normal file
156
src/osgText/FTPolyGlyph.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
|
||||
#include "FTPolyGlyph.h"
|
||||
#include "FTVectoriser.h"
|
||||
#include "FTGL.h"
|
||||
|
||||
|
||||
#ifndef CALLBACK
|
||||
#define CALLBACK
|
||||
#endif
|
||||
|
||||
|
||||
void CALLBACK ftglError( GLenum errCode)
|
||||
{
|
||||
// const GLubyte* estring;
|
||||
// estring = gluErrorString( errCode);
|
||||
// fprintf( stderr, "ERROR : %s\n", estring);
|
||||
// exit(1);
|
||||
}
|
||||
|
||||
void CALLBACK ftglVertex( void* data)
|
||||
{
|
||||
glVertex3dv( (double*)data);
|
||||
}
|
||||
|
||||
|
||||
void CALLBACK ftglBegin( GLenum type)
|
||||
{
|
||||
glBegin( type);
|
||||
}
|
||||
|
||||
|
||||
void CALLBACK ftglEnd()
|
||||
{
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
void CALLBACK ftglCombine( GLdouble coords[3], void* vertex_data[4], GLfloat weight[4], void** outData)
|
||||
{
|
||||
double* vertex = new double[3]; // FIXME MEM LEAK
|
||||
|
||||
vertex[0] = coords[0];
|
||||
vertex[1] = coords[1];
|
||||
vertex[2] = coords[2];
|
||||
|
||||
*outData = vertex;
|
||||
}
|
||||
|
||||
|
||||
FTPolyGlyph::FTPolyGlyph( FT_Glyph glyph)
|
||||
: FTGlyph(),
|
||||
vectoriser(0),
|
||||
numPoints(0),
|
||||
numContours(0),
|
||||
contourLength(0),
|
||||
data(0),
|
||||
glList(0)
|
||||
{
|
||||
if( ft_glyph_format_outline != glyph->format)
|
||||
{ return;}
|
||||
|
||||
vectoriser = new FTVectoriser( glyph);
|
||||
|
||||
vectoriser->Ingest();
|
||||
numContours = vectoriser->contours();
|
||||
contourLength = new int[ numContours];
|
||||
|
||||
for( int c = 0; c < numContours; ++c)
|
||||
{
|
||||
contourLength[c] = vectoriser->contourSize( c);
|
||||
}
|
||||
|
||||
numPoints = vectoriser->points();
|
||||
data = new double[ numPoints * 3];
|
||||
vectoriser->Output( data);
|
||||
|
||||
contourFlag = vectoriser->ContourFlag();
|
||||
advance = glyph->advance.x >> 16;
|
||||
|
||||
delete vectoriser;
|
||||
|
||||
if ( ( numContours < 1) || ( numPoints < 3))
|
||||
return;
|
||||
|
||||
Tesselate();
|
||||
|
||||
// discard glyph image (bitmap or not)
|
||||
FT_Done_Glyph( glyph); // Why does this have to be HERE
|
||||
}
|
||||
|
||||
|
||||
void FTPolyGlyph::Tesselate()
|
||||
{
|
||||
glList = glGenLists(1);
|
||||
GLUtesselator* tobj = gluNewTess();
|
||||
int d = 0;
|
||||
|
||||
gluTessCallback( tobj, GLU_TESS_BEGIN, (void (CALLBACK*)())ftglBegin);
|
||||
gluTessCallback( tobj, GLU_TESS_VERTEX, (void (CALLBACK*)())ftglVertex);
|
||||
gluTessCallback( tobj, GLU_TESS_COMBINE, (void (CALLBACK*)())ftglCombine);
|
||||
gluTessCallback( tobj, GLU_TESS_END, ftglEnd);
|
||||
gluTessCallback( tobj, GLU_TESS_ERROR, (void (CALLBACK*)())ftglError);
|
||||
|
||||
glNewList( glList, GL_COMPILE);
|
||||
|
||||
if( contourFlag & ft_outline_even_odd_fill) // ft_outline_reverse_fill
|
||||
{
|
||||
gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
|
||||
}
|
||||
else
|
||||
{
|
||||
gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
|
||||
}
|
||||
|
||||
gluTessProperty( tobj, GLU_TESS_TOLERANCE, 0);
|
||||
gluTessBeginPolygon( tobj, NULL);
|
||||
|
||||
for( int c = 0; c < numContours; ++c)
|
||||
{
|
||||
gluTessBeginContour( tobj);
|
||||
for( int p = 0; p < ( contourLength[c]); ++p)
|
||||
{
|
||||
gluTessVertex( tobj, data + d, data + d);
|
||||
d += 3;
|
||||
}
|
||||
gluTessEndContour( tobj);
|
||||
}
|
||||
|
||||
gluTessEndPolygon( tobj);
|
||||
|
||||
glEndList();
|
||||
|
||||
gluDeleteTess( tobj);
|
||||
}
|
||||
|
||||
|
||||
FTPolyGlyph::~FTPolyGlyph()
|
||||
{
|
||||
delete [] data;
|
||||
delete [] contourLength;
|
||||
}
|
||||
|
||||
|
||||
float FTPolyGlyph::Render( const FT_Vector& pen)
|
||||
{
|
||||
if( glList)
|
||||
{
|
||||
glTranslatef( pen.x, pen.y, 0);
|
||||
glCallList( glList);
|
||||
glTranslatef( -pen.x, -pen.y, 0);
|
||||
}
|
||||
|
||||
return advance;
|
||||
}
|
91
src/osgText/FTSize.cpp
Normal file
91
src/osgText/FTSize.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include "FTSize.h"
|
||||
#include "FTGL.h"
|
||||
|
||||
|
||||
FTSize::FTSize()
|
||||
: size(0),
|
||||
ftFace(0),
|
||||
err(0)
|
||||
{}
|
||||
|
||||
|
||||
FTSize::~FTSize()
|
||||
{}
|
||||
|
||||
|
||||
bool FTSize::CharSize( FT_Face* face, unsigned int point_size, unsigned int x_resolution, unsigned int y_resolution )
|
||||
{
|
||||
ftFace = face;
|
||||
size = point_size;
|
||||
err = FT_Set_Char_Size( *ftFace, 0L, point_size * 64, x_resolution, y_resolution);
|
||||
|
||||
ftSize = (*ftFace)->size;
|
||||
|
||||
return !err;
|
||||
}
|
||||
|
||||
|
||||
int FTSize::Ascender() const
|
||||
{
|
||||
return ftSize->metrics.ascender >> 6;
|
||||
}
|
||||
|
||||
|
||||
int FTSize::Descender() const
|
||||
{
|
||||
return ftSize->metrics.descender >> 6;
|
||||
}
|
||||
|
||||
|
||||
int FTSize::Height() const
|
||||
{
|
||||
if( FT_IS_SCALABLE((*ftFace)))
|
||||
{
|
||||
float height;
|
||||
if( FT_IS_SFNT((*ftFace))) // Don't think this is correct
|
||||
{
|
||||
height = (*ftFace)->bbox.yMax - (*ftFace)->bbox.yMin; // bbox.yMax-bbox.yMin
|
||||
}
|
||||
else
|
||||
{
|
||||
height = (*ftFace)->bbox.yMax - (*ftFace)->bbox.yMin >> 16; // bbox.yMax-bbox.yMin
|
||||
}
|
||||
|
||||
height = height * ( (float)ftSize->metrics.y_ppem / (float)(*ftFace)->units_per_EM);
|
||||
return static_cast<int>(height);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ftSize->metrics.height >> 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int FTSize::Width() const
|
||||
{
|
||||
if( FT_IS_SCALABLE((*ftFace)))
|
||||
{
|
||||
float width;
|
||||
if( FT_IS_SFNT((*ftFace))) // Don't think this is correct
|
||||
{
|
||||
width = ((*ftFace)->bbox.xMax - (*ftFace)->bbox.xMin); // bbox.xMax-bbox.xMin
|
||||
}
|
||||
else
|
||||
{
|
||||
width = ((*ftFace)->bbox.xMax - (*ftFace)->bbox.xMin) >> 16; // bbox.xMax-bbox.xMin
|
||||
}
|
||||
|
||||
width = width * ( (float)ftSize->metrics.x_ppem / (float)(*ftFace)->units_per_EM);
|
||||
return static_cast<int>(width);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ftSize->metrics.max_advance >> 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int FTSize::Underline() const
|
||||
{
|
||||
return 0;
|
||||
}
|
92
src/osgText/FTTextureGlyph.cpp
Normal file
92
src/osgText/FTTextureGlyph.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include "GL/gl.h"
|
||||
|
||||
#include "FTTextureGlyph.h"
|
||||
#include "FTGL.h"
|
||||
|
||||
|
||||
int FTTextureGlyph::activeTextureID = 0;
|
||||
|
||||
FTTextureGlyph::FTTextureGlyph( FT_Glyph glyph, int id, unsigned char* data, int stride, int height, float u, float v)
|
||||
: FTGlyph(),
|
||||
destWidth(0),
|
||||
destHeight(0),
|
||||
numGreys(0),
|
||||
glTextureID(id)
|
||||
{
|
||||
// This function will always fail if the glyph's format isn't scalable????
|
||||
err = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1);
|
||||
if( err || glyph->format != ft_glyph_format_bitmap)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FT_BitmapGlyph bitmap = ( FT_BitmapGlyph)glyph;
|
||||
FT_Bitmap* source = &bitmap->bitmap;
|
||||
|
||||
//check the pixel mode
|
||||
//ft_pixel_mode_grays
|
||||
|
||||
int srcWidth = source->width;
|
||||
int srcHeight = source->rows;
|
||||
int srcPitch = source->pitch;
|
||||
|
||||
numGreys = source->num_grays;
|
||||
advance = glyph->advance.x >> 16;
|
||||
|
||||
pos.x = bitmap->left;
|
||||
pos.y = bitmap->top;
|
||||
|
||||
destWidth = srcWidth;
|
||||
destHeight = srcHeight;
|
||||
|
||||
for(int y = 0; y < srcHeight; ++y)
|
||||
{
|
||||
for(int x = 0; x < srcWidth; ++x)
|
||||
{
|
||||
*( data + ( y * stride + x)) = *( source->buffer + ( y * srcPitch) + x);
|
||||
}
|
||||
}
|
||||
|
||||
// 0
|
||||
// +----+
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// +----+
|
||||
// 1
|
||||
|
||||
uv[0].x = u;
|
||||
uv[0].y = v;
|
||||
uv[1].x = uv[0].x + ( (float)destWidth / (float)stride);
|
||||
uv[1].y = uv[0].y + ( (float)destHeight / (float)height);
|
||||
|
||||
// discard glyph image (bitmap or not)
|
||||
// Is this the right place to do this?
|
||||
FT_Done_Glyph( glyph);
|
||||
}
|
||||
|
||||
|
||||
FTTextureGlyph::~FTTextureGlyph()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
float FTTextureGlyph::Render( const FT_Vector& pen)
|
||||
{
|
||||
// This could be really ugly!!
|
||||
if( activeTextureID != glTextureID)
|
||||
{
|
||||
glEnd();
|
||||
glBindTexture( GL_TEXTURE_2D, (GLuint)glTextureID);
|
||||
activeTextureID = glTextureID;
|
||||
glBegin( GL_QUADS);
|
||||
}
|
||||
|
||||
glTexCoord2f( uv[0].x, uv[0].y); glVertex2f( pen.x + pos.x, pen.y + pos.y);
|
||||
glTexCoord2f( uv[1].x, uv[0].y); glVertex2f( pen.x + destWidth + pos.x, pen.y + pos.y);
|
||||
glTexCoord2f( uv[1].x, uv[1].y); glVertex2f( pen.x + destWidth + pos.x, pen.y + pos.y - destHeight);
|
||||
glTexCoord2f( uv[0].x, uv[1].y); glVertex2f( pen.x + pos.x, pen.y + pos.y - destHeight);
|
||||
|
||||
return advance;
|
||||
}
|
227
src/osgText/FTVectoriser.cpp
Normal file
227
src/osgText/FTVectoriser.cpp
Normal file
@ -0,0 +1,227 @@
|
||||
#include "FTVectoriser.h"
|
||||
#include "FTGL.h"
|
||||
|
||||
|
||||
FTContour::FTContour()
|
||||
: kMAXPOINTS( 1000)
|
||||
{
|
||||
pointList.reserve( kMAXPOINTS);
|
||||
}
|
||||
|
||||
|
||||
FTContour::~FTContour()
|
||||
{
|
||||
pointList.clear();
|
||||
}
|
||||
|
||||
|
||||
void FTContour::AddPoint( const float x, const float y)
|
||||
{
|
||||
ftPoint point( x, y, 0.0);
|
||||
|
||||
// Eliminate duplicate points.
|
||||
if( pointList.empty() || ( pointList[pointList.size() - 1] != point && pointList[0] != point))
|
||||
{
|
||||
pointList.push_back( point);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FTVectoriser::FTVectoriser( const FT_Glyph glyph)
|
||||
: contourFlag(0),
|
||||
contour(0),
|
||||
kBSTEPSIZE( 0.2)
|
||||
{
|
||||
FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph;
|
||||
ftOutline = outline->outline;
|
||||
|
||||
contourList.reserve( ftOutline.n_contours);
|
||||
}
|
||||
|
||||
|
||||
FTVectoriser::~FTVectoriser()
|
||||
{
|
||||
for( int c = 0; c < contours(); ++c)
|
||||
{
|
||||
delete contourList[c];
|
||||
}
|
||||
|
||||
contourList.clear();
|
||||
}
|
||||
|
||||
|
||||
int FTVectoriser::points()
|
||||
{
|
||||
int s = 0;
|
||||
for( int c = 0; c < contours(); ++c)
|
||||
{
|
||||
s += contourList[c]->size();
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
bool FTVectoriser::Ingest()
|
||||
{
|
||||
short first = 0;
|
||||
short last;
|
||||
const short cont = ftOutline.n_contours;
|
||||
|
||||
for( short c = 0; c < cont; ++c)
|
||||
{
|
||||
contour = new FTContour;
|
||||
contourFlag = ftOutline.flags;
|
||||
last = ftOutline.contours[c];
|
||||
|
||||
for( short p = first; p <= last; ++p)
|
||||
{
|
||||
switch( ftOutline.tags[p])
|
||||
{
|
||||
case FT_Curve_Tag_Conic:
|
||||
p += Conic( p, first, last);
|
||||
break;
|
||||
case FT_Curve_Tag_Cubic:
|
||||
p += Cubic( p, first, last);
|
||||
break;
|
||||
case FT_Curve_Tag_On:
|
||||
default:
|
||||
contour->AddPoint( ftOutline.points[p].x, ftOutline.points[p].y);
|
||||
}
|
||||
}
|
||||
|
||||
contourList.push_back( contour);
|
||||
first = last + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int FTVectoriser::Conic( const int index, const int first, const int last)
|
||||
{
|
||||
int next = index + 1;
|
||||
int prev = index - 1;
|
||||
|
||||
if( index == last)
|
||||
next = first;
|
||||
|
||||
if( index == first)
|
||||
prev = last;
|
||||
|
||||
if( ftOutline.tags[next] != FT_Curve_Tag_Conic)
|
||||
{
|
||||
ctrlPtArray[0][0] = ftOutline.points[prev].x; ctrlPtArray[0][1] = ftOutline.points[prev].y;
|
||||
ctrlPtArray[1][0] = ftOutline.points[index].x; ctrlPtArray[1][1] = ftOutline.points[index].y;
|
||||
ctrlPtArray[2][0] = ftOutline.points[next].x; ctrlPtArray[2][1] = ftOutline.points[next].y;
|
||||
|
||||
evaluateCurve( 2);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int next2 = next + 1;
|
||||
if( next == last)
|
||||
next2 = first;
|
||||
|
||||
//create a phantom point
|
||||
float x = ( ftOutline.points[index].x + ftOutline.points[next].x) / 2;
|
||||
float y = ( ftOutline.points[index].y + ftOutline.points[next].y) / 2;
|
||||
|
||||
// process first curve
|
||||
ctrlPtArray[0][0] = ftOutline.points[prev].x; ctrlPtArray[0][1] = ftOutline.points[prev].y;
|
||||
ctrlPtArray[1][0] = ftOutline.points[index].x; ctrlPtArray[1][1] = ftOutline.points[index].y;
|
||||
ctrlPtArray[2][0] = x; ctrlPtArray[2][1] = y;
|
||||
|
||||
evaluateCurve( 2);
|
||||
|
||||
// process second curve
|
||||
ctrlPtArray[0][0] = x; ctrlPtArray[0][1] = y;
|
||||
ctrlPtArray[1][0] = ftOutline.points[next].x; ctrlPtArray[1][1] = ftOutline.points[next].y;
|
||||
ctrlPtArray[2][0] = ftOutline.points[next2].x; ctrlPtArray[2][1] = ftOutline.points[next2].y;
|
||||
evaluateCurve( 2);
|
||||
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int FTVectoriser::Cubic( const int index, const int first, const int last)
|
||||
{
|
||||
int next = index + 1;
|
||||
int prev = index - 1;
|
||||
|
||||
if( index == last)
|
||||
next = first;
|
||||
|
||||
int next2 = next + 1;
|
||||
|
||||
if( next == last)
|
||||
next2 = first;
|
||||
|
||||
if( index == first)
|
||||
prev = last;
|
||||
|
||||
ctrlPtArray[0][0] = ftOutline.points[prev].x; ctrlPtArray[0][1] = ftOutline.points[prev].y;
|
||||
ctrlPtArray[1][0] = ftOutline.points[index].x; ctrlPtArray[1][1] = ftOutline.points[index].y;
|
||||
ctrlPtArray[2][0] = ftOutline.points[next].x; ctrlPtArray[2][1] = ftOutline.points[next].y;
|
||||
ctrlPtArray[3][0] = ftOutline.points[next2].x; ctrlPtArray[3][1] = ftOutline.points[next2].y;
|
||||
|
||||
evaluateCurve( 3);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
// De Casteljau algorithm contributed by Jed Soane
|
||||
void FTVectoriser::deCasteljau( const float t, const int n)
|
||||
{
|
||||
//Calculating successive b(i)'s using de Casteljau algorithm.
|
||||
for( int i = 1; i <= n; i++)
|
||||
for( int k = 0; k <= (n - i); k++)
|
||||
{
|
||||
bValues[i][k][0] = (1 - t) * bValues[i - 1][k][0] + t * bValues[i - 1][k + 1][0];
|
||||
bValues[i][k][1] = (1 - t) * bValues[i - 1][k][1] + t * bValues[i - 1][k + 1][1];
|
||||
}
|
||||
|
||||
//Specify next vertex to be included on curve
|
||||
contour->AddPoint( bValues[n][0][0], bValues[n][0][1]);
|
||||
}
|
||||
|
||||
|
||||
// De Casteljau algorithm contributed by Jed Soane
|
||||
void FTVectoriser::evaluateCurve( const int n)
|
||||
{
|
||||
// setting the b(0) equal to the control points
|
||||
for( int i = 0; i <= n; i++)
|
||||
{
|
||||
bValues[0][i][0] = ctrlPtArray[i][0];
|
||||
bValues[0][i][1] = ctrlPtArray[i][1];
|
||||
}
|
||||
|
||||
float t; //parameter for curve point calc. [0.0, 1.0]
|
||||
|
||||
for( int m = 0; m <= ( 1 / kBSTEPSIZE); m++)
|
||||
{
|
||||
t = m * kBSTEPSIZE;
|
||||
deCasteljau( t, n); //calls to evaluate point on curve att.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FTVectoriser::Output( double* data)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for( int c= 0; c < contours(); ++c)
|
||||
{
|
||||
const FTContour* contour = contourList[c];
|
||||
|
||||
for( int p = 0; p < contour->size(); ++p)
|
||||
{
|
||||
data[i] = static_cast<double>(contour->pointList[p].x / 64.0f); // is 64 correct?
|
||||
data[i + 1] = static_cast<double>(contour->pointList[p].y / 64.0f);
|
||||
data[i + 2] = 0.0; // static_cast<double>(contour->pointList[p].z / 64.0f);
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user