1 #include <amaltheia/Graphics.h>
9 #include <string> // For memset
11 #include <freetype/freetype.h>
12 #include <freetype/ftglyph.h>
13 #include <freetype/ftoutln.h>
14 #include <freetype/fttrigon.h>
16 //#include "FTGLTextureFont.h"
17 //#include "FTTextureGlyph.h"
18 typedef double FTGL_DOUBLE;
19 typedef float FTGL_FLOAT;
21 // Fixes for deprecated identifiers in 2.1.5
22 #ifndef FT_OPEN_MEMORY
23 #define FT_OPEN_MEMORY (FT_Open_Flags)1
26 #ifndef FT_RENDER_MODE_MONO
27 #define FT_RENDER_MODE_MONO ft_render_mode_mono
30 #ifndef FT_RENDER_MODE_NORMAL
31 #define FT_RENDER_MODE_NORMAL ft_render_mode_normal
38 inline unsigned int NextPowerOf2( unsigned int in)
61 FTPoint( const double x, const double y, const double z)
68 FTPoint( const FT_Vector& ft_vector)
70 values[0] = ft_vector.x;
71 values[1] = ft_vector.y;
75 FTPoint& operator += ( const FTPoint& point)
77 values[0] += point.values[0];
78 values[1] += point.values[1];
79 values[2] += point.values[2];
84 FTPoint operator + ( const FTPoint& point)
87 temp.values[0] = values[0] + point.values[0];
88 temp.values[1] = values[1] + point.values[1];
89 temp.values[2] = values[2] + point.values[2];
94 FTPoint operator * ( double multiplier)
97 temp.values[0] = values[0] * multiplier;
98 temp.values[1] = values[1] * multiplier;
99 temp.values[2] = values[2] * multiplier;
105 friend FTPoint operator*( double multiplier, FTPoint& point);
106 friend bool operator == ( const FTPoint &a, const FTPoint &b);
107 friend bool operator != ( const FTPoint &a, const FTPoint &b);
108 operator const double*() const
112 void X( double x) { values[0] = x;};
113 void Y( double y) { values[1] = y;};
114 void Z( double z) { values[2] = z;};
115 double X() const { return values[0];};
116 double Y() const { return values[1];};
117 double Z() const { return values[2];};
123 bool operator == ( const FTPoint &a, const FTPoint &b)
125 return((a.values[0] == b.values[0]) && (a.values[1] == b.values[1]) && (a.values[2] == b.values[2]));
128 bool operator != ( const FTPoint &a, const FTPoint &b)
130 return((a.values[0] != b.values[0]) || (a.values[1] != b.values[1]) || (a.values[2] != b.values[2]));
133 FTPoint operator*( double multiplier, FTPoint& point)
135 return point * multiplier;
152 FTBBox( float lx, float ly, float lz, float ux, float uy, float uz)
162 FTBBox( FT_GlyphSlot glyph)
171 FT_Outline_Get_CBox( &(glyph->outline), &bbox);
173 lowerX = static_cast<float>( bbox.xMin) / 64.0f;
174 lowerY = static_cast<float>( bbox.yMin) / 64.0f;
176 upperX = static_cast<float>( bbox.xMax) / 64.0f;
177 upperY = static_cast<float>( bbox.yMax) / 64.0f;
185 FTBBox& Move( FTPoint distance)
187 lowerX += distance.X();
188 lowerY += distance.Y();
189 lowerZ += distance.Z();
190 upperX += distance.X();
191 upperY += distance.Y();
192 upperZ += distance.Z();
196 FTBBox& operator += ( const FTBBox& bbox)
198 lowerX = bbox.lowerX < lowerX? bbox.lowerX: lowerX;
199 lowerY = bbox.lowerY < lowerY? bbox.lowerY: lowerY;
200 lowerZ = bbox.lowerZ < lowerZ? bbox.lowerZ: lowerZ;
201 upperX = bbox.upperX > upperX? bbox.upperX: upperX;
202 upperY = bbox.upperY > upperY? bbox.upperY: upperY;
203 upperZ = bbox.upperZ > upperZ? bbox.upperZ: upperZ;
208 void SetDepth( float depth)
210 upperZ = lowerZ + depth;
213 float lowerX, lowerY, lowerZ, upperX, upperY, upperZ;
226 FTGlyph( FT_GlyphSlot glyph, bool useList = true)
228 useDisplayList = useList;
232 bBox = FTBBox( glyph);
233 advance = FTPoint( glyph->advance.x / 64.0f, glyph->advance.y / 64.0f, 0.0f);
237 virtual FTGlyph::~FTGlyph()
240 virtual const FTPoint& Render( const FTPoint& pen) = 0;
241 const FTPoint& Advance() const { return advance;}
242 const FTBBox& BBox() const { return bBox;}
243 FT_Error Error() const { return err;}
262 static const FTLibrary& Instance();
263 const FT_Library* const GetLibrary() const { return library;}
264 FT_Error Error() const { return err;}
269 FTLibrary( const FT_Library&){}
270 FTLibrary& operator=( const FT_Library&) { return *this; }
281 const FTLibrary& FTLibrary::Instance()
283 static FTLibrary ftlib;
288 FTLibrary::~FTLibrary()
292 FT_Done_FreeType( *library);
300 // FTC_Manager_Done( manager );
308 FTLibrary::FTLibrary()
316 bool FTLibrary::Initialise()
321 library = new FT_Library;
323 err = FT_Init_FreeType( library);
331 // FTC_Manager* manager;
333 // if( FTC_Manager_New( lib, 0, 0, 0, my_face_requester, 0, manager )
351 bool CharSize( FT_Face* face, unsigned int point_size, unsigned int x_resolution, unsigned int y_resolution);
352 unsigned int CharSize() const;
353 float Ascender() const;
354 float Descender() const;
355 float Height() const;
357 float Underline() const;
358 FT_Error Error() const { return err; }
364 unsigned int xResolution;
365 unsigned int yResolution;
386 bool FTSize::CharSize( FT_Face* face, unsigned int pointSize, unsigned int xRes, unsigned int yRes )
388 if( size != pointSize || xResolution != xRes || yResolution != yRes)
390 err = FT_Set_Char_Size( *face, 0L, pointSize * 64, xResolution, yResolution);
398 ftSize = (*ftFace)->size;
414 unsigned int FTSize::CharSize() const
420 float FTSize::Ascender() const
422 return ftSize == 0 ? 0.0f : static_cast<float>( ftSize->metrics.ascender) / 64.0f;
426 float FTSize::Descender() const
428 return ftSize == 0 ? 0.0f : static_cast<float>( ftSize->metrics.descender) / 64.0f;
432 float FTSize::Height() const
439 if( FT_IS_SCALABLE((*ftFace)))
441 return ( (*ftFace)->bbox.yMax - (*ftFace)->bbox.yMin) * ( (float)ftSize->metrics.y_ppem / (float)(*ftFace)->units_per_EM);
445 return static_cast<float>( ftSize->metrics.height) / 64.0f;
450 float FTSize::Width() const
457 if( FT_IS_SCALABLE((*ftFace)))
459 return ( (*ftFace)->bbox.xMax - (*ftFace)->bbox.xMin) * ( static_cast<float>(ftSize->metrics.x_ppem) / static_cast<float>((*ftFace)->units_per_EM));
463 return static_cast<float>( ftSize->metrics.max_advance) / 64.0f;
468 float FTSize::Underline() const
480 FTFace( const char* fontFilePath);
481 FTFace( const unsigned char *pBufferBytes, size_t bufferSizeInBytes );
484 bool Attach( const char* fontFilePath);
485 bool Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
486 FT_Face* Face() const { return ftFace;}
487 const FTSize& Size( const unsigned int size, const unsigned int res);
488 unsigned int CharMapCount();
489 FT_Encoding* CharMapList();
490 FTPoint KernAdvance( unsigned int index1, unsigned int index2);
491 FT_GlyphSlot Glyph( unsigned int index, FT_Int load_flags);
492 unsigned int GlyphCount() const { return numGlyphs;}
493 FT_Error Error() const { return err; }
499 FT_Encoding* fontEncodingList;
500 bool hasKerningTable;
504 FTFace::FTFace( const char* fontFilePath)
509 const FT_Long DEFAULT_FACE_INDEX = 0;
510 ftFace = new FT_Face;
512 err = FT_New_Face( *FTLibrary::Instance().GetLibrary(), fontFilePath, DEFAULT_FACE_INDEX, ftFace);
521 numGlyphs = (*ftFace)->num_glyphs;
522 hasKerningTable = FT_HAS_KERNING((*ftFace));
527 FTFace::FTFace( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
531 const FT_Long DEFAULT_FACE_INDEX = 0;
532 ftFace = new FT_Face;
534 err = FT_New_Memory_Face( *FTLibrary::Instance().GetLibrary(), (FT_Byte *)pBufferBytes, bufferSizeInBytes, DEFAULT_FACE_INDEX, ftFace);
543 numGlyphs = (*ftFace)->num_glyphs;
552 FT_Done_Face( *ftFace);
559 bool FTFace::Attach( const char* fontFilePath)
561 err = FT_Attach_File( *ftFace, fontFilePath);
566 bool FTFace::Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
570 open.flags = FT_OPEN_MEMORY;
571 open.memory_base = (FT_Byte *)pBufferBytes;
572 open.memory_size = bufferSizeInBytes;
574 err = FT_Attach_Stream( *ftFace, &open);
579 const FTSize& FTFace::Size( const unsigned int size, const unsigned int res)
581 charSize.CharSize( ftFace, size, res, res);
582 err = charSize.Error();
588 unsigned int FTFace::CharMapCount()
590 return (*ftFace)->num_charmaps;
594 FT_Encoding* FTFace::CharMapList()
596 if( 0 == fontEncodingList)
598 fontEncodingList = new FT_Encoding[CharMapCount()];
599 for( size_t encodingIndex = 0; encodingIndex < CharMapCount(); ++encodingIndex)
601 fontEncodingList[encodingIndex] = (*ftFace)->charmaps[encodingIndex]->encoding;
605 return fontEncodingList;
609 FTPoint FTFace::KernAdvance( unsigned int index1, unsigned int index2)
614 if( hasKerningTable && index1 && index2)
616 FT_Vector kernAdvance;
617 kernAdvance.x = kernAdvance.y = 0;
619 err = FT_Get_Kerning( *ftFace, index1, index2, ft_kerning_unfitted, &kernAdvance);
622 x = static_cast<float>( kernAdvance.x) / 64.0f;
623 y = static_cast<float>( kernAdvance.y) / 64.0f;
627 return FTPoint( x, y, 0.0);
631 FT_GlyphSlot FTFace::Glyph( unsigned int index, FT_Int load_flags)
633 err = FT_Load_Glyph( *ftFace, index, load_flags);
639 return (*ftFace)->glyph;
650 template <typename FT_VECTOR_ITEM_TYPE> class FTVector
653 typedef FT_VECTOR_ITEM_TYPE value_type;
654 typedef value_type& reference;
655 typedef const value_type& const_reference;
656 typedef value_type* iterator;
657 typedef const value_type* const_iterator;
658 typedef size_t size_type;
672 FTVector& operator =(const FTVector& v)
674 reserve(v.capacity());
676 iterator ptr = begin();
677 const_iterator vbegin = v.begin();
678 const_iterator vend = v.end();
680 while( vbegin != vend)
689 size_type size() const
694 size_type capacity() const
704 const_iterator begin() const
711 return begin() + size();
714 const_iterator end() const
716 return begin() + size();
724 reference operator [](size_type pos)
726 return( *(begin() + pos));
729 const_reference operator []( size_type pos) const
731 return( *(begin() + pos));
744 void reserve( size_type n)
752 void push_back(const value_type& x)
754 if( size() == capacity())
759 ( *this)[size()] = x;
763 void resize(size_type n, value_type x)
776 end = this->begin() + n;
780 begin = this->begin() + n;
794 void expand(size_type capacity_hint = 0)
796 size_type new_capacity =( capacity() == 0) ? 256 : capacity()* 2;
799 while( new_capacity < capacity_hint)
805 value_type *new_items = new value_type[new_capacity];
807 iterator begin = this->begin();
808 iterator end = this->end();
809 value_type *ptr = new_items;
822 Capacity = new_capacity;
842 class FTCharToGlyphIndexMap
846 typedef unsigned long CharacterCode;
847 typedef signed long GlyphIndex;
851 NumberOfBuckets = 256,
856 FTCharToGlyphIndexMap()
861 virtual ~FTCharToGlyphIndexMap()
868 // Free main structure
869 delete [] this->Indices;
878 for( int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++)
880 if( this->Indices[i])
882 delete [] this->Indices[i];
883 this->Indices[i] = 0;
889 const GlyphIndex find( CharacterCode c)
896 // Find position of char code in buckets
897 div_t pos = div( c, FTCharToGlyphIndexMap::BucketSize);
899 if( !this->Indices[pos.quot])
904 const FTCharToGlyphIndexMap::GlyphIndex *ptr = &this->Indices[pos.quot][pos.rem];
905 if( *ptr == FTCharToGlyphIndexMap::IndexNotFound)
913 void insert( CharacterCode c, GlyphIndex g)
917 this->Indices = new GlyphIndex* [FTCharToGlyphIndexMap::NumberOfBuckets];
918 for( int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++)
920 this->Indices[i] = 0;
924 // Find position of char code in buckets
925 div_t pos = div(c, FTCharToGlyphIndexMap::BucketSize);
927 // Allocate bucket if does not exist yet
928 if( !this->Indices[pos.quot])
930 this->Indices[pos.quot] = new GlyphIndex [FTCharToGlyphIndexMap::BucketSize];
931 for( int i = 0; i < FTCharToGlyphIndexMap::BucketSize; i++)
933 this->Indices[pos.quot][i] = FTCharToGlyphIndexMap::IndexNotFound;
937 this->Indices[pos.quot][pos.rem] = g;
941 GlyphIndex** Indices;
951 FTCharmap( FTFace* face);
952 virtual ~FTCharmap();
954 FT_Encoding Encoding() const { return ftEncoding;}
955 bool CharMap( FT_Encoding encoding);
956 unsigned int GlyphListIndex( const unsigned int characterCode);
957 unsigned int FontIndex( const unsigned int characterCode);
958 void InsertIndex( const unsigned int characterCode, const unsigned int containerIndex);
959 FT_Error Error() const { return err;}
962 FT_Encoding ftEncoding;
963 const FT_Face ftFace;
964 typedef FTCharToGlyphIndexMap CharacterMap;
965 CharacterMap charMap;
975 FTCharmap::FTCharmap( FTFace* face)
976 : ftFace( *(face->Face())),
979 if( !ftFace->charmap)
981 err = FT_Set_Charmap( ftFace, ftFace->charmaps[0]);
984 ftEncoding = ftFace->charmap->encoding;
988 FTCharmap::~FTCharmap()
994 bool FTCharmap::CharMap( FT_Encoding encoding)
996 if( ftEncoding == encoding)
1001 err = FT_Select_Charmap( ftFace, encoding );
1005 ftEncoding = encoding;
1009 ftEncoding = ft_encoding_none;
1017 unsigned int FTCharmap::GlyphListIndex( unsigned int characterCode )
1019 return charMap.find( characterCode);
1023 unsigned int FTCharmap::FontIndex( unsigned int characterCode )
1025 return FT_Get_Char_Index( ftFace, characterCode);
1029 void FTCharmap::InsertIndex( const unsigned int characterCode, const unsigned int containerIndex)
1031 charMap.insert( characterCode, containerIndex);
1037 class FTGlyphContainer
1039 typedef FTVector<FTGlyph*> GlyphVector;
1041 FTGlyphContainer( FTFace* face);
1042 ~FTGlyphContainer();
1043 bool CharMap( FT_Encoding encoding);
1044 unsigned int FontIndex( const unsigned int characterCode ) const;
1045 void Add( FTGlyph* glyph, const unsigned int characterCode);
1046 const FTGlyph* const Glyph( const unsigned int characterCode) const;
1047 FTBBox BBox( const unsigned int characterCode) const;
1048 float Advance( const unsigned int characterCode, const unsigned int nextCharacterCode);
1050 FTPoint Render( const unsigned int characterCode, const unsigned int nextCharacterCode, FTPoint penPosition);
1052 FT_Error Error() const { return err;}
1064 FTGlyphContainer::FTGlyphContainer( FTFace* f)
1068 glyphs.push_back( NULL);
1069 charMap = new FTCharmap( face);
1073 FTGlyphContainer::~FTGlyphContainer()
1075 GlyphVector::iterator glyphIterator;
1076 for( glyphIterator = glyphs.begin(); glyphIterator != glyphs.end(); ++glyphIterator)
1078 delete *glyphIterator;
1086 bool FTGlyphContainer::CharMap( FT_Encoding encoding)
1088 bool result = charMap->CharMap( encoding);
1089 err = charMap->Error();
1094 unsigned int FTGlyphContainer::FontIndex( const unsigned int characterCode) const
1096 return charMap->FontIndex( characterCode);
1100 void FTGlyphContainer::Add( FTGlyph* tempGlyph, const unsigned int characterCode)
1102 charMap->InsertIndex( characterCode, glyphs.size());
1103 glyphs.push_back( tempGlyph);
1107 const FTGlyph* const FTGlyphContainer::Glyph( const unsigned int characterCode) const
1109 signed int index = charMap->GlyphListIndex( characterCode);
1110 return glyphs[index];
1114 FTBBox FTGlyphContainer::BBox( const unsigned int characterCode) const
1116 return glyphs[charMap->GlyphListIndex( characterCode)]->BBox();
1120 float FTGlyphContainer::Advance( const unsigned int characterCode, const unsigned int nextCharacterCode)
1122 unsigned int left = charMap->FontIndex( characterCode);
1123 unsigned int right = charMap->FontIndex( nextCharacterCode);
1125 float width = face->KernAdvance( left, right).X();
1126 width += glyphs[charMap->GlyphListIndex( characterCode)]->Advance().X();
1132 FTPoint FTGlyphContainer::Render( const unsigned int characterCode, const unsigned int nextCharacterCode, FTPoint penPosition)
1134 FTPoint kernAdvance, advance;
1136 unsigned int left = charMap->FontIndex( characterCode);
1137 unsigned int right = charMap->FontIndex( nextCharacterCode);
1139 kernAdvance = face->KernAdvance( left, right);
1143 advance = glyphs[charMap->GlyphListIndex( characterCode)]->Render( penPosition);
1146 kernAdvance += advance;
1162 FTFont( const char* fontFilePath);
1163 FTFont( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
1166 bool Attach( const char* fontFilePath);
1167 bool Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
1168 bool CharMap( FT_Encoding encoding );
1169 unsigned int CharMapCount();
1170 FT_Encoding* CharMapList();
1171 virtual bool FaceSize( const unsigned int size, const unsigned int res = 72);
1172 unsigned int FaceSize() const;
1173 virtual void Depth( float depth){}
1174 void UseDisplayList( bool useList);
1175 float Ascender() const;
1176 float Descender() const;
1177 float LineHeight() const;
1178 void BBox( const char* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
1179 void BBox( const wchar_t* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
1180 float Advance( const wchar_t* string);
1181 float Advance( const char* string);
1182 virtual void Render( const char* string );
1183 virtual void Render( const wchar_t* string );
1184 FT_Error Error() const { return err;}
1187 virtual FTGlyph* MakeGlyph( unsigned int g) = 0;
1190 bool useDisplayLists;
1194 inline bool CheckGlyph( const unsigned int chr);
1195 FTGlyphContainer* glyphList;
1201 FTFont::FTFont( const char* fontFilePath) : face( fontFilePath), useDisplayLists(true), glyphList(0)
1206 glyphList = new FTGlyphContainer( &face);
1213 class FTTextureGlyph : public FTGlyph
1216 FTTextureGlyph( FT_GlyphSlot glyph, int id, int xOffset, int yOffset, int width, int height);
1217 virtual ~FTTextureGlyph();
1218 virtual const FTPoint& Render( const FTPoint& pen);
1219 static void FTTextureGlyph::ResetActiveTexture(){ activeTextureID = 0;}
1228 static int activeTextureID;
1233 int FTTextureGlyph::activeTextureID = 0;
1235 FTTextureGlyph::FTTextureGlyph( FT_GlyphSlot glyph, int id, int xOffset, int yOffset, int width, int height)
1241 err = FT_Render_Glyph( glyph, FT_RENDER_MODE_NORMAL);
1242 if( err || glyph->format != ft_glyph_format_bitmap)
1247 FT_Bitmap bitmap = glyph->bitmap;
1249 destWidth = bitmap.width;
1250 destHeight = bitmap.rows;
1252 if( destWidth && destHeight)
1254 glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT);
1255 glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE);
1256 glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
1257 glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
1259 glBindTexture( GL_TEXTURE_2D, glTextureID);
1260 glTexSubImage2D( GL_TEXTURE_2D, 0, xOffset, yOffset, destWidth, destHeight, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer);
1262 glPopClientAttrib();
1266 uv[0].X( static_cast<float>(xOffset) / static_cast<float>(width));
1267 uv[0].Y( static_cast<float>(yOffset) / static_cast<float>(height));
1268 uv[1].X( static_cast<float>( xOffset + destWidth) / static_cast<float>(width));
1269 uv[1].Y( static_cast<float>( yOffset + destHeight) / static_cast<float>(height));
1271 pos.X( glyph->bitmap_left);
1272 pos.Y( glyph->bitmap_top);
1276 FTTextureGlyph::~FTTextureGlyph()
1280 const FTPoint& FTTextureGlyph::Render( const FTPoint& pen)
1282 if( activeTextureID != glTextureID)
1284 glBindTexture( GL_TEXTURE_2D, (GLuint)glTextureID);
1285 activeTextureID = glTextureID;
1288 glTranslatef( pen.X(), pen.Y(), 0.0f);
1291 glTexCoord2f( uv[0].X(), uv[0].Y());
1292 glVertex2f( pos.X(), pos.Y());
1294 glTexCoord2f( uv[0].X(), uv[1].Y());
1295 glVertex2f( pos.X(), pos.Y() - destHeight);
1297 glTexCoord2f( uv[1].X(), uv[1].Y());
1298 glVertex2f( destWidth + pos.X(), pos.Y() - destHeight);
1300 glTexCoord2f( uv[1].X(), uv[0].Y());
1301 glVertex2f( destWidth + pos.X(), pos.Y());
1311 class myFont : public FTFont
1315 inline virtual FTGlyph* MakeGlyph( unsigned int glyphIndex)
1317 FT_GlyphSlot ftGlyph = face.Glyph( glyphIndex, FT_LOAD_NO_HINTING);
1321 glyphHeight = static_cast<int>( charSize.Height());
1322 glyphWidth = static_cast<int>( charSize.Width());
1324 if( textureIDList.empty())
1326 textureIDList.push_back( CreateTexture());
1327 xOffset = yOffset = padding;
1330 if( xOffset > ( textureWidth - glyphWidth))
1333 yOffset += glyphHeight;
1335 if( yOffset > ( textureHeight - glyphHeight))
1337 textureIDList.push_back( CreateTexture());
1342 FTTextureGlyph* tempGlyph = new FTTextureGlyph( ftGlyph, textureIDList[textureIDList.size() - 1],
1343 xOffset, yOffset, textureWidth, textureHeight);
1344 xOffset += static_cast<int>( tempGlyph->BBox().upperX - tempGlyph->BBox().lowerX + padding);
1354 inline void CalculateTextureSize()
1356 if( !maximumGLTextureSize)
1358 glGetIntegerv( GL_MAX_TEXTURE_SIZE, (int*)&maximumGLTextureSize);
1359 assert(maximumGLTextureSize); // If you hit this then you have an invalid OpenGL context.
1362 textureWidth = NextPowerOf2( (remGlyphs * glyphWidth) + ( padding * 2));
1363 textureWidth = textureWidth > maximumGLTextureSize ? maximumGLTextureSize : textureWidth;
1365 int h = static_cast<int>( (textureWidth - ( padding * 2)) / glyphWidth);
1367 textureHeight = NextPowerOf2( (( numGlyphs / h) + 1) * glyphHeight);
1368 textureHeight = textureHeight > maximumGLTextureSize ? maximumGLTextureSize : textureHeight;
1372 inline uint CreateTexture()
1374 CalculateTextureSize();
1376 int totalMemory = textureWidth * textureHeight;
1377 unsigned char* textureMemory = new unsigned char[totalMemory];
1378 memset( textureMemory, 0, totalMemory);
1380 unsigned int textID;
1381 glGenTextures( 1, (unsigned int*)&textID);
1383 glBindTexture( GL_TEXTURE_2D, textID);
1384 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1385 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1386 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1387 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1389 glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, textureWidth, textureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, textureMemory);
1391 delete [] textureMemory;
1398 int maximumGLTextureSize;
1401 FTVector<GLuint> textureIDList;
1404 unsigned int padding;
1405 unsigned int numGlyphs;
1406 unsigned int remGlyphs;
1414 myFont( const char* fontFilePath) : FTFont( fontFilePath),
1415 maximumGLTextureSize(0),
1424 remGlyphs = numGlyphs = face.GlyphCount();
1429 glDeleteTextures( textureIDList.size(), (const unsigned int*)&textureIDList[0]);
1433 void print( char *str, int x1, int y1, int x2, int y2, colour c )
1436 glColor4f( c.r, c.g, c.b, c.a);
1437 float h= LineHeight()*0.64f; /* factor 0.64*/
1438 glTranslatef(x1, y1 + h, 0);
1439 glScalef(1.0, -1.0, 1.0);
1441 // ft_print( our_font, x1 , g->getHeight() - y1 - fontSize, str);
1447 bool FaceSize( const unsigned int size, const unsigned int res)
1449 if( !textureIDList.empty())
1451 glDeleteTextures( textureIDList.size(), (const uint*)&textureIDList[0]);
1452 textureIDList.clear();
1453 remGlyphs = numGlyphs = face.GlyphCount();
1456 return FTFont::FaceSize( size, res);
1460 void Render( const char* string)
1462 glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
1465 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
1467 FTTextureGlyph::ResetActiveTexture();
1469 FTFont::Render( string);
1475 void Render( const wchar_t* string)
1477 glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
1480 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
1482 FTTextureGlyph::ResetActiveTexture();
1484 FTFont::Render( string);
1498 g = new Graphics(1024, 768); // bring me a 1024x768 resolution
1500 // // g->setBackground(COLOUR_RGBA(0, 255, 0, 0)); //green background
1501 f = new myFont("Test.ttf");
1502 f->FaceSize(16, 72);
1503 f->CharMap(ft_encoding_unicode);
1505 t = new Font(g, "Test.ttf", 16);
1513 f->print("MPLA", 10,10, 200,200, COLOUR_RGBA(255,255,255,255));
1514 // t->print("hello", 10,10, 200,200, COLOUR_RGBA(255,255,255,255));