1 #include <amaltheia/Graphics.h>
8 #include <string> // For memset
10 #include <freetype/freetype.h>
11 #include <freetype/ftglyph.h>
12 #include <freetype/ftoutln.h>
13 #include <freetype/fttrigon.h>
18 //#include "FTGLTextureFont.h"
19 //#include "FTTextureGlyph.h"
20 typedef double FTGL_DOUBLE;
21 typedef float FTGL_FLOAT;
23 // Fixes for deprecated identifiers in 2.1.5
24 #ifndef FT_OPEN_MEMORY
25 #define FT_OPEN_MEMORY (FT_Open_Flags)1
28 #ifndef FT_RENDER_MODE_MONO
29 #define FT_RENDER_MODE_MONO ft_render_mode_mono
32 #ifndef FT_RENDER_MODE_NORMAL
33 #define FT_RENDER_MODE_NORMAL ft_render_mode_normal
40 inline unsigned int NextPowerOf2( unsigned int in)
63 FTPoint( const double x, const double y, const double z)
70 FTPoint( const FT_Vector& ft_vector)
72 values[0] = ft_vector.x;
73 values[1] = ft_vector.y;
77 FTPoint& operator += ( const FTPoint& point)
79 values[0] += point.values[0];
80 values[1] += point.values[1];
81 values[2] += point.values[2];
86 FTPoint operator + ( const FTPoint& point)
89 temp.values[0] = values[0] + point.values[0];
90 temp.values[1] = values[1] + point.values[1];
91 temp.values[2] = values[2] + point.values[2];
96 FTPoint operator * ( double multiplier)
99 temp.values[0] = values[0] * multiplier;
100 temp.values[1] = values[1] * multiplier;
101 temp.values[2] = values[2] * multiplier;
107 friend FTPoint operator*( double multiplier, FTPoint& point);
108 friend bool operator == ( const FTPoint &a, const FTPoint &b);
109 friend bool operator != ( const FTPoint &a, const FTPoint &b);
110 operator const double*() const
114 void X( double x) { values[0] = x;};
115 void Y( double y) { values[1] = y;};
116 void Z( double z) { values[2] = z;};
117 double X() const { return values[0];};
118 double Y() const { return values[1];};
119 double Z() const { return values[2];};
125 bool operator == ( const FTPoint &a, const FTPoint &b)
127 return((a.values[0] == b.values[0]) && (a.values[1] == b.values[1]) && (a.values[2] == b.values[2]));
130 bool operator != ( const FTPoint &a, const FTPoint &b)
132 return((a.values[0] != b.values[0]) || (a.values[1] != b.values[1]) || (a.values[2] != b.values[2]));
135 FTPoint operator*( double multiplier, FTPoint& point)
137 return point * multiplier;
154 FTBBox( float lx, float ly, float lz, float ux, float uy, float uz)
164 FTBBox( FT_GlyphSlot glyph)
173 FT_Outline_Get_CBox( &(glyph->outline), &bbox);
175 lowerX = static_cast<float>( bbox.xMin) / 64.0f;
176 lowerY = static_cast<float>( bbox.yMin) / 64.0f;
178 upperX = static_cast<float>( bbox.xMax) / 64.0f;
179 upperY = static_cast<float>( bbox.yMax) / 64.0f;
187 FTBBox& Move( FTPoint distance)
189 lowerX += distance.X();
190 lowerY += distance.Y();
191 lowerZ += distance.Z();
192 upperX += distance.X();
193 upperY += distance.Y();
194 upperZ += distance.Z();
198 FTBBox& operator += ( const FTBBox& bbox)
200 lowerX = bbox.lowerX < lowerX? bbox.lowerX: lowerX;
201 lowerY = bbox.lowerY < lowerY? bbox.lowerY: lowerY;
202 lowerZ = bbox.lowerZ < lowerZ? bbox.lowerZ: lowerZ;
203 upperX = bbox.upperX > upperX? bbox.upperX: upperX;
204 upperY = bbox.upperY > upperY? bbox.upperY: upperY;
205 upperZ = bbox.upperZ > upperZ? bbox.upperZ: upperZ;
210 void SetDepth( float depth)
212 upperZ = lowerZ + depth;
215 float lowerX, lowerY, lowerZ, upperX, upperY, upperZ;
228 FTGlyph( FT_GlyphSlot glyph, bool useList = true)
230 useDisplayList = useList;
234 bBox = FTBBox( glyph);
235 advance = FTPoint( glyph->advance.x / 64.0f, glyph->advance.y / 64.0f, 0.0f);
239 virtual FTGlyph::~FTGlyph()
242 virtual const FTPoint& Render( const FTPoint& pen) = 0;
243 const FTPoint& Advance() const { return advance;}
244 const FTBBox& BBox() const { return bBox;}
245 FT_Error Error() const { return err;}
264 static const FTLibrary& Instance();
265 const FT_Library* const GetLibrary() const { return library;}
266 FT_Error Error() const { return err;}
271 FTLibrary( const FT_Library&){}
272 FTLibrary& operator=( const FT_Library&) { return *this; }
283 const FTLibrary& FTLibrary::Instance()
285 static FTLibrary ftlib;
290 FTLibrary::~FTLibrary()
294 FT_Done_FreeType( *library);
302 // FTC_Manager_Done( manager );
310 FTLibrary::FTLibrary()
318 bool FTLibrary::Initialise()
323 library = new FT_Library;
325 err = FT_Init_FreeType( library);
333 // FTC_Manager* manager;
335 // if( FTC_Manager_New( lib, 0, 0, 0, my_face_requester, 0, manager )
353 bool CharSize( FT_Face* face, unsigned int point_size, unsigned int x_resolution, unsigned int y_resolution);
354 unsigned int CharSize() const;
355 float Ascender() const;
356 float Descender() const;
357 float Height() const;
359 float Underline() const;
360 FT_Error Error() const { return err; }
366 unsigned int xResolution;
367 unsigned int yResolution;
388 bool FTSize::CharSize( FT_Face* face, unsigned int pointSize, unsigned int xRes, unsigned int yRes )
390 if( size != pointSize || xResolution != xRes || yResolution != yRes)
392 err = FT_Set_Char_Size( *face, 0L, pointSize * 64, xResolution, yResolution);
400 ftSize = (*ftFace)->size;
416 unsigned int FTSize::CharSize() const
422 float FTSize::Ascender() const
424 return ftSize == 0 ? 0.0f : static_cast<float>( ftSize->metrics.ascender) / 64.0f;
428 float FTSize::Descender() const
430 return ftSize == 0 ? 0.0f : static_cast<float>( ftSize->metrics.descender) / 64.0f;
434 float FTSize::Height() const
441 if( FT_IS_SCALABLE((*ftFace)))
443 return ( (*ftFace)->bbox.yMax - (*ftFace)->bbox.yMin) * ( (float)ftSize->metrics.y_ppem / (float)(*ftFace)->units_per_EM);
447 return static_cast<float>( ftSize->metrics.height) / 64.0f;
452 float FTSize::Width() const
459 if( FT_IS_SCALABLE((*ftFace)))
461 return ( (*ftFace)->bbox.xMax - (*ftFace)->bbox.xMin) * ( static_cast<float>(ftSize->metrics.x_ppem) / static_cast<float>((*ftFace)->units_per_EM));
465 return static_cast<float>( ftSize->metrics.max_advance) / 64.0f;
470 float FTSize::Underline() const
482 FTFace( const char* fontFilePath);
483 FTFace( const unsigned char *pBufferBytes, size_t bufferSizeInBytes );
486 bool Attach( const char* fontFilePath);
487 bool Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
488 FT_Face* Face() const { return ftFace;}
489 const FTSize& Size( const unsigned int size, const unsigned int res);
490 unsigned int CharMapCount();
491 FT_Encoding* CharMapList();
492 FTPoint KernAdvance( unsigned int index1, unsigned int index2);
493 FT_GlyphSlot Glyph( unsigned int index, FT_Int load_flags);
494 unsigned int GlyphCount() const { return numGlyphs;}
495 FT_Error Error() const { return err; }
501 FT_Encoding* fontEncodingList;
502 bool hasKerningTable;
506 FTFace::FTFace( const char* fontFilePath)
511 const FT_Long DEFAULT_FACE_INDEX = 0;
512 ftFace = new FT_Face;
514 err = FT_New_Face( *FTLibrary::Instance().GetLibrary(), fontFilePath, DEFAULT_FACE_INDEX, ftFace);
523 numGlyphs = (*ftFace)->num_glyphs;
524 hasKerningTable = FT_HAS_KERNING((*ftFace));
529 FTFace::FTFace( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
533 const FT_Long DEFAULT_FACE_INDEX = 0;
534 ftFace = new FT_Face;
536 err = FT_New_Memory_Face( *FTLibrary::Instance().GetLibrary(), (FT_Byte *)pBufferBytes, bufferSizeInBytes, DEFAULT_FACE_INDEX, ftFace);
545 numGlyphs = (*ftFace)->num_glyphs;
554 FT_Done_Face( *ftFace);
561 bool FTFace::Attach( const char* fontFilePath)
563 err = FT_Attach_File( *ftFace, fontFilePath);
568 bool FTFace::Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
572 open.flags = FT_OPEN_MEMORY;
573 open.memory_base = (FT_Byte *)pBufferBytes;
574 open.memory_size = bufferSizeInBytes;
576 err = FT_Attach_Stream( *ftFace, &open);
581 const FTSize& FTFace::Size( const unsigned int size, const unsigned int res)
583 charSize.CharSize( ftFace, size, res, res);
584 err = charSize.Error();
590 unsigned int FTFace::CharMapCount()
592 return (*ftFace)->num_charmaps;
596 FT_Encoding* FTFace::CharMapList()
598 if( 0 == fontEncodingList)
600 fontEncodingList = new FT_Encoding[CharMapCount()];
601 for( size_t encodingIndex = 0; encodingIndex < CharMapCount(); ++encodingIndex)
603 fontEncodingList[encodingIndex] = (*ftFace)->charmaps[encodingIndex]->encoding;
607 return fontEncodingList;
611 FTPoint FTFace::KernAdvance( unsigned int index1, unsigned int index2)
616 if( hasKerningTable && index1 && index2)
618 FT_Vector kernAdvance;
619 kernAdvance.x = kernAdvance.y = 0;
621 err = FT_Get_Kerning( *ftFace, index1, index2, ft_kerning_unfitted, &kernAdvance);
624 x = static_cast<float>( kernAdvance.x) / 64.0f;
625 y = static_cast<float>( kernAdvance.y) / 64.0f;
629 return FTPoint( x, y, 0.0);
633 FT_GlyphSlot FTFace::Glyph( unsigned int index, FT_Int load_flags)
635 err = FT_Load_Glyph( *ftFace, index, load_flags);
641 return (*ftFace)->glyph;
652 template <typename FT_VECTOR_ITEM_TYPE> class FTVector
655 typedef FT_VECTOR_ITEM_TYPE value_type;
656 typedef value_type& reference;
657 typedef const value_type& const_reference;
658 typedef value_type* iterator;
659 typedef const value_type* const_iterator;
660 typedef size_t size_type;
674 FTVector& operator =(const FTVector& v)
676 reserve(v.capacity());
678 iterator ptr = begin();
679 const_iterator vbegin = v.begin();
680 const_iterator vend = v.end();
682 while( vbegin != vend)
691 size_type size() const
696 size_type capacity() const
706 const_iterator begin() const
713 return begin() + size();
716 const_iterator end() const
718 return begin() + size();
726 reference operator [](size_type pos)
728 return( *(begin() + pos));
731 const_reference operator []( size_type pos) const
733 return( *(begin() + pos));
746 void reserve( size_type n)
754 void push_back(const value_type& x)
756 if( size() == capacity())
761 ( *this)[size()] = x;
765 void resize(size_type n, value_type x)
778 end = this->begin() + n;
782 begin = this->begin() + n;
796 void expand(size_type capacity_hint = 0)
798 size_type new_capacity =( capacity() == 0) ? 256 : capacity()* 2;
801 while( new_capacity < capacity_hint)
807 value_type *new_items = new value_type[new_capacity];
809 iterator begin = this->begin();
810 iterator end = this->end();
811 value_type *ptr = new_items;
824 Capacity = new_capacity;
844 class FTCharToGlyphIndexMap
848 typedef unsigned long CharacterCode;
849 typedef signed long GlyphIndex;
853 NumberOfBuckets = 256,
858 FTCharToGlyphIndexMap()
863 virtual ~FTCharToGlyphIndexMap()
870 // Free main structure
871 delete [] this->Indices;
880 for( int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++)
882 if( this->Indices[i])
884 delete [] this->Indices[i];
885 this->Indices[i] = 0;
891 const GlyphIndex find( CharacterCode c)
898 // Find position of char code in buckets
899 div_t pos = div( c, FTCharToGlyphIndexMap::BucketSize);
901 if( !this->Indices[pos.quot])
906 const FTCharToGlyphIndexMap::GlyphIndex *ptr = &this->Indices[pos.quot][pos.rem];
907 if( *ptr == FTCharToGlyphIndexMap::IndexNotFound)
915 void insert( CharacterCode c, GlyphIndex g)
919 this->Indices = new GlyphIndex* [FTCharToGlyphIndexMap::NumberOfBuckets];
920 for( int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++)
922 this->Indices[i] = 0;
926 // Find position of char code in buckets
927 div_t pos = div(c, FTCharToGlyphIndexMap::BucketSize);
929 // Allocate bucket if does not exist yet
930 if( !this->Indices[pos.quot])
932 this->Indices[pos.quot] = new GlyphIndex [FTCharToGlyphIndexMap::BucketSize];
933 for( int i = 0; i < FTCharToGlyphIndexMap::BucketSize; i++)
935 this->Indices[pos.quot][i] = FTCharToGlyphIndexMap::IndexNotFound;
939 this->Indices[pos.quot][pos.rem] = g;
943 GlyphIndex** Indices;
953 FTCharmap( FTFace* face);
954 virtual ~FTCharmap();
956 FT_Encoding Encoding() const { return ftEncoding;}
957 bool CharMap( FT_Encoding encoding);
958 unsigned int GlyphListIndex( const unsigned int characterCode);
959 unsigned int FontIndex( const unsigned int characterCode);
960 void InsertIndex( const unsigned int characterCode, const unsigned int containerIndex);
961 FT_Error Error() const { return err;}
964 FT_Encoding ftEncoding;
965 const FT_Face ftFace;
966 typedef FTCharToGlyphIndexMap CharacterMap;
967 CharacterMap charMap;
977 FTCharmap::FTCharmap( FTFace* face)
978 : ftFace( *(face->Face())),
981 if( !ftFace->charmap)
983 err = FT_Set_Charmap( ftFace, ftFace->charmaps[0]);
986 ftEncoding = ftFace->charmap->encoding;
990 FTCharmap::~FTCharmap()
996 bool FTCharmap::CharMap( FT_Encoding encoding)
998 if( ftEncoding == encoding)
1003 err = FT_Select_Charmap( ftFace, encoding );
1007 ftEncoding = encoding;
1011 ftEncoding = ft_encoding_none;
1019 unsigned int FTCharmap::GlyphListIndex( unsigned int characterCode )
1021 return charMap.find( characterCode);
1025 unsigned int FTCharmap::FontIndex( unsigned int characterCode )
1027 return FT_Get_Char_Index( ftFace, characterCode);
1031 void FTCharmap::InsertIndex( const unsigned int characterCode, const unsigned int containerIndex)
1033 charMap.insert( characterCode, containerIndex);
1039 class FTGlyphContainer
1041 typedef FTVector<FTGlyph*> GlyphVector;
1043 FTGlyphContainer( FTFace* face);
1044 ~FTGlyphContainer();
1045 bool CharMap( FT_Encoding encoding);
1046 unsigned int FontIndex( const unsigned int characterCode ) const;
1047 void Add( FTGlyph* glyph, const unsigned int characterCode);
1048 const FTGlyph* const Glyph( const unsigned int characterCode) const;
1049 FTBBox BBox( const unsigned int characterCode) const;
1050 float Advance( const unsigned int characterCode, const unsigned int nextCharacterCode);
1052 FTPoint Render( const unsigned int characterCode, const unsigned int nextCharacterCode, FTPoint penPosition);
1054 FT_Error Error() const { return err;}
1066 FTGlyphContainer::FTGlyphContainer( FTFace* f)
1070 glyphs.push_back( NULL);
1071 charMap = new FTCharmap( face);
1075 FTGlyphContainer::~FTGlyphContainer()
1077 GlyphVector::iterator glyphIterator;
1078 for( glyphIterator = glyphs.begin(); glyphIterator != glyphs.end(); ++glyphIterator)
1080 delete *glyphIterator;
1088 bool FTGlyphContainer::CharMap( FT_Encoding encoding)
1090 bool result = charMap->CharMap( encoding);
1091 err = charMap->Error();
1096 unsigned int FTGlyphContainer::FontIndex( const unsigned int characterCode) const
1098 return charMap->FontIndex( characterCode);
1102 void FTGlyphContainer::Add( FTGlyph* tempGlyph, const unsigned int characterCode)
1104 charMap->InsertIndex( characterCode, glyphs.size());
1105 glyphs.push_back( tempGlyph);
1109 const FTGlyph* const FTGlyphContainer::Glyph( const unsigned int characterCode) const
1111 signed int index = charMap->GlyphListIndex( characterCode);
1112 return glyphs[index];
1116 FTBBox FTGlyphContainer::BBox( const unsigned int characterCode) const
1118 return glyphs[charMap->GlyphListIndex( characterCode)]->BBox();
1122 float FTGlyphContainer::Advance( const unsigned int characterCode, const unsigned int nextCharacterCode)
1124 unsigned int left = charMap->FontIndex( characterCode);
1125 unsigned int right = charMap->FontIndex( nextCharacterCode);
1127 float width = face->KernAdvance( left, right).X();
1128 width += glyphs[charMap->GlyphListIndex( characterCode)]->Advance().X();
1134 FTPoint FTGlyphContainer::Render( const unsigned int characterCode, const unsigned int nextCharacterCode, FTPoint penPosition)
1136 FTPoint kernAdvance, advance;
1138 unsigned int left = charMap->FontIndex( characterCode);
1139 unsigned int right = charMap->FontIndex( nextCharacterCode);
1141 kernAdvance = face->KernAdvance( left, right);
1145 advance = glyphs[charMap->GlyphListIndex( characterCode)]->Render( penPosition);
1148 kernAdvance += advance;
1164 FTFont( const char* fontFilePath);
1165 FTFont( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
1168 bool Attach( const char* fontFilePath);
1169 bool Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
1170 bool CharMap( FT_Encoding encoding );
1171 unsigned int CharMapCount();
1172 FT_Encoding* CharMapList();
1173 virtual bool FaceSize( const unsigned int size, const unsigned int res = 72);
1174 unsigned int FaceSize() const;
1175 virtual void Depth( float depth){}
1176 void UseDisplayList( bool useList);
1177 float Ascender() const;
1178 float Descender() const;
1179 float LineHeight() const;
1180 void BBox( const char* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
1181 void BBox( const wchar_t* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
1182 float Advance( const wchar_t* string);
1183 float Advance( const char* string);
1184 virtual void Render( const char* string );
1185 virtual void Render( const wchar_t* string );
1186 FT_Error Error() const { return err;}
1189 virtual FTGlyph* MakeGlyph( unsigned int g) = 0;
1192 bool useDisplayLists;
1196 inline bool CheckGlyph( const unsigned int chr);
1197 FTGlyphContainer* glyphList;
1203 FTFont::FTFont( const char* fontFilePath) : face(fontFilePath), useDisplayLists(true), glyphList(0)
1208 glyphList = new FTGlyphContainer( &face);
1215 FTFont::FTFont( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
1216 : face( pBufferBytes, bufferSizeInBytes),
1222 glyphList = new FTGlyphContainer( &face);
1233 bool FTFont::Attach( const char* fontFilePath)
1235 if( face.Attach( fontFilePath))
1248 bool FTFont::Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
1250 if( face.Attach( pBufferBytes, bufferSizeInBytes))
1263 bool FTFont::FaceSize( const unsigned int size, const unsigned int res )
1265 charSize = face.Size( size, res);
1273 if( glyphList != NULL)
1278 glyphList = new FTGlyphContainer( &face);
1283 unsigned int FTFont::FaceSize() const
1285 return charSize.CharSize();
1289 bool FTFont::CharMap( FT_Encoding encoding)
1291 bool result = glyphList->CharMap( encoding);
1292 err = glyphList->Error();
1297 unsigned int FTFont::CharMapCount()
1299 return face.CharMapCount();
1303 FT_Encoding* FTFont::CharMapList()
1305 return face.CharMapList();
1309 void FTFont::UseDisplayList( bool useList)
1311 useDisplayLists = useList;
1314 float FTFont::Ascender() const
1316 return charSize.Ascender();
1320 float FTFont::Descender() const
1322 return charSize.Descender();
1325 float FTFont::LineHeight() const
1327 return charSize.Height();
1330 void FTFont::BBox( const char* string,
1331 float& llx, float& lly, float& llz, float& urx, float& ury, float& urz)
1335 if((NULL != string) && ('\0' != *string))
1337 const unsigned char* c = (unsigned char*)string;
1342 totalBBox = glyphList->BBox( *c);
1343 advance = glyphList->Advance( *c, *(c + 1));
1350 FTBBox tempBBox = glyphList->BBox( *c);
1351 tempBBox.Move( FTPoint( advance, 0.0f, 0.0f));
1352 totalBBox += tempBBox;
1353 advance += glyphList->Advance( *c, *(c + 1));
1358 llx = totalBBox.lowerX;
1359 lly = totalBBox.lowerY;
1360 llz = totalBBox.lowerZ;
1361 urx = totalBBox.upperX;
1362 ury = totalBBox.upperY;
1363 urz = totalBBox.upperZ;
1367 void FTFont::BBox( const wchar_t* string,
1368 float& llx, float& lly, float& llz, float& urx, float& ury, float& urz)
1372 if((NULL != string) && ('\0' != *string))
1374 const wchar_t* c = string;
1379 totalBBox = glyphList->BBox( *c);
1380 advance = glyphList->Advance( *c, *(c + 1));
1387 FTBBox tempBBox = glyphList->BBox( *c);
1388 tempBBox.Move( FTPoint( advance, 0.0f, 0.0f));
1389 totalBBox += tempBBox;
1390 advance += glyphList->Advance( *c, *(c + 1));
1395 llx = totalBBox.lowerX;
1396 lly = totalBBox.lowerY;
1397 llz = totalBBox.lowerZ;
1398 urx = totalBBox.upperX;
1399 ury = totalBBox.upperY;
1400 urz = totalBBox.upperZ;
1404 float FTFont::Advance( const wchar_t* string)
1406 const wchar_t* c = string;
1413 width += glyphList->Advance( *c, *(c + 1));
1422 float FTFont::Advance( const char* string)
1424 const unsigned char* c = (unsigned char*)string;
1431 width += glyphList->Advance( *c, *(c + 1));
1440 void FTFont::Render( const char* string )
1442 const unsigned char* c = (unsigned char*)string;
1449 pen = glyphList->Render( *c, *(c + 1), pen);
1456 void FTFont::Render( const wchar_t* string )
1458 const wchar_t* c = string;
1465 pen = glyphList->Render( *c, *(c + 1), pen);
1472 bool FTFont::CheckGlyph( const unsigned int characterCode)
1474 if( NULL == glyphList->Glyph( characterCode))
1476 unsigned int glyphIndex = glyphList->FontIndex( characterCode);
1477 FTGlyph* tempGlyph = MakeGlyph( glyphIndex);
1478 if( NULL == tempGlyph)
1487 glyphList->Add( tempGlyph, characterCode);
1498 class FTTextureGlyph : public FTGlyph
1501 FTTextureGlyph( FT_GlyphSlot glyph, Texture * tid, int xOffset, int yOffset, int width, int height);
1502 virtual ~FTTextureGlyph();
1503 virtual const FTPoint& Render( const FTPoint& pen);
1504 static void FTTextureGlyph::ResetActiveTexture()
1506 activeTextureID = 0;
1517 static int activeTextureID;
1518 static Texture* activeTexture;
1523 int FTTextureGlyph::activeTextureID = 0;
1524 Texture* FTTextureGlyph::activeTexture = 0;
1526 FTTextureGlyph::FTTextureGlyph( FT_GlyphSlot glyph, Texture *tid, int xOffset, int yOffset, int width, int height)
1533 glTextureID = tid->gl_Tex;
1535 err = FT_Render_Glyph( glyph, FT_RENDER_MODE_NORMAL);
1536 if( err || glyph->format != ft_glyph_format_bitmap)
1541 FT_Bitmap bitmap = glyph->bitmap;
1543 destWidth = bitmap.width;
1544 destHeight = bitmap.rows;
1547 if( destWidth && destHeight)
1549 glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT);
1550 glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE);
1551 glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
1552 glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
1556 // glBindTexture( GL_TEXTURE_2D, glTextureID);
1557 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,GL_TEXTURE_WIDTH, &tW);
1558 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,GL_TEXTURE_HEIGHT, &tH);
1559 tid->texSubImage2D(xOffset, yOffset, destWidth, destHeight, AM_ALPHA, AM_UBYTE, bitmap.buffer);
1561 // glTexSubImage2D( GL_TEXTURE_2D, 0, xOffset, yOffset, destWidth, destHeight, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer);
1563 printf("TW=%d tH=%d txoff=%d yoff=%d w=%d h=%d\n", tW, tH, xOffset, yOffset, destWidth, destHeight);
1564 glPopClientAttrib();
1568 uv[0].X( static_cast<float>(xOffset) / static_cast<float>(width));
1569 uv[0].Y( static_cast<float>(yOffset) / static_cast<float>(height));
1570 uv[1].X( static_cast<float>( xOffset + destWidth) / static_cast<float>(width));
1571 uv[1].Y( static_cast<float>( yOffset + destHeight) / static_cast<float>(height));
1573 pos.X( glyph->bitmap_left);
1574 pos.Y( glyph->bitmap_top);
1578 FTTextureGlyph::~FTTextureGlyph()
1582 const FTPoint& FTTextureGlyph::Render( const FTPoint& pen)
1584 if( activeTextureID != glTextureID)
1586 g->setTexture(textureID);
1587 printf("setT = %d\n", textureID->gl_Tex);
1588 activeTexture = textureID;
1589 //activeTextureID = glTextureID;
1590 // glBindTexture( GL_TEXTURE_2D, glTextureID);
1598 //g->setWorld(pen.X(), pen.Y(), 0.0f, 0,0,0, 1,1,1);
1599 glTranslatef( pen.X(), pen.Y(), 0.0f);
1601 array[0].u = uv[0].X();
1602 array[0].v = 1 - uv[0].Y();
1603 array[0].x = pos.X();
1604 array[0].y = pos.Y();
1606 array[0].col = COLOUR_RGBA(255,255,255,255);
1607 array[0].nx = array[0].ny = array[0].nz = 0;
1609 array[1].u = uv[0].X();
1610 array[1].v = 1 - uv[1].Y();
1611 array[1].x = pos.X();
1612 array[1].y = pos.Y() - destHeight;
1614 array[1].col = COLOUR_RGBA(255,255,255,255);
1615 array[1].nx = array[1].ny = array[1].nz = 0;
1617 array[2].u = uv[1].X();
1618 array[2].v = 1 - uv[1].Y();
1619 array[2].x = pos.X() + destWidth;
1620 array[2].y = pos.Y() - destHeight;
1622 array[2].col = COLOUR_RGBA(255,255,255,255);
1623 array[2].nx = array[2].ny = array[2].nz = 0;
1625 array[3].u = uv[1].X();
1626 array[3].v = 1 - uv[0].Y();
1627 array[3].x = pos.X() + destWidth;
1628 array[3].y = pos.Y();
1630 array[3].col = COLOUR_RGBA(255,255,255,255);
1631 array[3].nx = array[3].ny = array[3].nz = 0;
1633 //g->renderVertexArray(array, 4, AM_TRIANGLE_STRIP);
1634 g->addTriangle(array[0], array[1], array[2]);
1635 g->addTriangle(array[2], array[3], array[0]);
1637 /* glBegin( GL_QUADS);
1638 glTexCoord2f( uv[0].X(), uv[0].Y());
1639 glVertex2f( pos.X(), pos.Y());
1641 glTexCoord2f( uv[0].X(), uv[1].Y());
1642 glVertex2f( pos.X(), pos.Y() - destHeight);
1644 glTexCoord2f( uv[1].X(), uv[1].Y());
1645 glVertex2f( destWidth + pos.X(), pos.Y() - destHeight);
1647 glTexCoord2f( uv[1].X(), uv[0].Y());
1648 glVertex2f( destWidth + pos.X(), pos.Y());
1658 class myFont : public FTFont
1662 inline virtual FTGlyph* MakeGlyph( unsigned int glyphIndex)
1664 FT_GlyphSlot ftGlyph = face.Glyph( glyphIndex, FT_LOAD_NO_HINTING);
1668 glyphHeight = static_cast<int>( charSize.Height());
1669 glyphWidth = static_cast<int>( charSize.Width());
1671 if( textureIDList.empty())
1673 textureIDList.push_back( CreateTexture());
1674 xOffset = yOffset = padding;
1677 if( xOffset > ( textureWidth - glyphWidth))
1680 yOffset += glyphHeight;
1682 if( yOffset > ( textureHeight - glyphHeight))
1684 textureIDList.push_back( CreateTexture());
1689 FTTextureGlyph* tempGlyph = new FTTextureGlyph( ftGlyph, textureIDList[textureIDList.size() - 1],
1690 xOffset, yOffset, textureWidth, textureHeight);
1691 xOffset += static_cast<int>( tempGlyph->BBox().upperX - tempGlyph->BBox().lowerX + padding);
1701 inline void CalculateTextureSize()
1704 if( !maximumGLTextureSize)
1706 glGetIntegerv( GL_MAX_TEXTURE_SIZE, (int*)&maximumGLTextureSize);
1707 assert(maximumGLTextureSize); // If you hit this then you have an invalid OpenGL context.
1709 printf("maximumGLTextureSize=%d\n", maximumGLTextureSize);
1710 textureWidth = NextPowerOf2( (remGlyphs * glyphWidth) + ( padding * 2));
1711 textureWidth = textureWidth > maximumGLTextureSize ? maximumGLTextureSize : textureWidth;
1713 int h = static_cast<int>( (textureWidth - ( padding * 2)) / glyphWidth);
1715 textureHeight = NextPowerOf2( (( numGlyphs / h) + 1) * glyphHeight);
1716 textureHeight = textureHeight > maximumGLTextureSize ? maximumGLTextureSize : textureHeight;
1720 inline Texture * CreateTexture()
1723 CalculateTextureSize();
1725 int totalMemory = textureWidth * textureHeight;
1726 unsigned char* textureMemory = new unsigned char[totalMemory];
1727 memset( textureMemory, 0, totalMemory);
1729 Texture *texID = new Texture(textureMemory, textureWidth, textureHeight, AM_ALPHA, AM_UBYTE, g);
1731 delete [] textureMemory;
1733 printf("now returning texID=%p\n", texID);
1736 CalculateTextureSize();
1738 int totalMemory = textureWidth * textureHeight;
1739 unsigned char* textureMemory = new unsigned char[totalMemory];
1740 memset( textureMemory, 0, totalMemory);
1743 /* glGenTextures( 1, (GLuint*)&textID);
1744 glBindTexture( GL_TEXTURE_2D, textID);
1745 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1746 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1747 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1748 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1750 glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, textureWidth, textureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, textureMemory);
1753 Texture *tex = new Texture(textureMemory, textureWidth, textureHeight, AM_ALPHA, AM_UBYTE, g);
1754 // g->setTexture(tex);
1755 textID = tex->gl_Tex;
1756 delete [] textureMemory;
1757 printf("@ createTexture returning %d\n", textID);
1764 int maximumGLTextureSize;
1767 FTVector<Texture *> textureIDList;
1770 unsigned int padding;
1771 unsigned int numGlyphs;
1772 unsigned int remGlyphs;
1779 myFont( const char* fontFilePath) : FTFont( fontFilePath),
1780 maximumGLTextureSize(0),
1789 remGlyphs = numGlyphs = face.GlyphCount();
1794 ;//glDeleteTextures( textureIDList.size(), (const unsigned int*)&textureIDList[0]);
1798 void print( char *str, int x1, int y1, int x2, int y2, colour c )
1801 glColor4f( c.r, c.g, c.b, c.a);
1802 float h= LineHeight()*0.64f; /* factor 0.64*/
1803 glTranslatef(x1, y1 + h, 0);
1804 glScalef(1.0, -1.0, 1.0);
1806 // ft_print( our_font, x1 , g->getHeight() - y1 - fontSize, str);
1812 bool FaceSize( const unsigned int size, const unsigned int res)
1814 if( !textureIDList.empty())
1816 glDeleteTextures( textureIDList.size(), (const uint*)&textureIDList[0]);
1817 textureIDList.clear();
1818 remGlyphs = numGlyphs = face.GlyphCount();
1821 return FTFont::FaceSize( size, res);
1825 void Render( const char* string)
1827 // glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
1828 bool a = g->isAlpha();
1829 g->enableAlpha(true);
1830 // glEnable(GL_BLEND);
1832 // glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
1834 FTTextureGlyph::ResetActiveTexture();
1836 FTFont::Render( string);
1843 void Render( const wchar_t* string)
1845 // glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
1847 //glEnable(GL_BLEND);
1848 //glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
1849 bool a = g->isAlpha();
1850 g->enableAlpha(true);
1852 FTTextureGlyph::ResetActiveTexture();
1854 FTFont::Render( string);
1868 g = new Graphics(1024, 768); // bring me a 1024x768 resolution
1870 g->setBackground(COLOUR_RGBA(155, 155, 155, 255)); //green background
1871 f = new myFont("Test.ttf");
1872 f->FaceSize(16, 72);
1873 f->CharMap(ft_encoding_unicode);
1875 t = new Font(g, "Test.ttf", 16);
1884 f->print("MPLA", 10,10, 200,200, COLOUR_RGBA(255,255,255,255));
1885 // t->print("hello", 10,10, 200,200, COLOUR_RGBA(255,255,255,255));