* Add "less" target to view make output through less.
[matthijs/ABM2.git] / ABM2 / Amaltheia / myFont.cpp
diff --git a/ABM2/Amaltheia/myFont.cpp b/ABM2/Amaltheia/myFont.cpp
new file mode 100644 (file)
index 0000000..c054535
--- /dev/null
@@ -0,0 +1,1897 @@
+#include <amaltheia/Graphics.h> 
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+
+#include <cassert>
+#include <string> // For memset
+#include <ft2build.h>
+#include <freetype/freetype.h>
+#include <freetype/ftglyph.h>
+#include <freetype/ftoutln.h>
+#include <freetype/fttrigon.h>
+
+
+Graphics *g;
+
+//#include "FTGLTextureFont.h"
+//#include "FTTextureGlyph.h"
+typedef double   FTGL_DOUBLE;
+typedef float    FTGL_FLOAT;
+
+// Fixes for deprecated identifiers in 2.1.5
+#ifndef FT_OPEN_MEMORY
+#define FT_OPEN_MEMORY (FT_Open_Flags)1
+#endif
+
+#ifndef FT_RENDER_MODE_MONO
+#define FT_RENDER_MODE_MONO ft_render_mode_mono
+#endif
+
+#ifndef FT_RENDER_MODE_NORMAL
+#define FT_RENDER_MODE_NORMAL ft_render_mode_normal
+#endif
+
+
+
+
+
+inline unsigned int NextPowerOf2( unsigned int in)
+{
+       in -= 1;
+
+       in |= in >> 16;
+       in |= in >> 8;
+       in |= in >> 4;
+       in |= in >> 2;
+       in |= in >> 1;
+
+       return in + 1;
+}
+
+
+class FTPoint
+{
+       public:
+               FTPoint()
+               {
+                       values[0] = 0;
+                       values[1] = 0;
+                       values[2] = 0;
+               }
+               FTPoint( const double x, const double y, const double z)
+               {
+                       values[0] = x;
+                       values[1] = y;
+                       values[2] = z;
+               }
+        
+               FTPoint( const FT_Vector& ft_vector)
+               {
+                       values[0] = ft_vector.x;
+                       values[1] = ft_vector.y;
+                       values[2] = 0;
+               }
+        
+               FTPoint& operator += ( const FTPoint& point)
+               {
+                       values[0] += point.values[0];
+                       values[1] += point.values[1];
+                       values[2] += point.values[2];
+
+                       return *this;
+               }
+
+               FTPoint operator + ( const FTPoint& point)
+               {
+                       FTPoint temp;
+                       temp.values[0] = values[0] + point.values[0];
+                       temp.values[1] = values[1] + point.values[1];
+                       temp.values[2] = values[2] + point.values[2];
+
+                       return temp;
+               }
+        
+               FTPoint operator * ( double multiplier)
+               {
+                       FTPoint temp;
+                       temp.values[0] = values[0] * multiplier;
+                       temp.values[1] = values[1] * multiplier;
+                       temp.values[2] = values[2] * multiplier;
+
+                       return temp;
+               }
+        
+        
+               friend FTPoint operator*( double multiplier, FTPoint& point);
+               friend bool operator == ( const FTPoint &a, const FTPoint &b);
+               friend bool operator != ( const FTPoint &a, const FTPoint &b);
+               operator const double*() const
+               {
+                       return values;
+               }
+               void X( double x) { values[0] = x;};
+               void Y( double y) { values[1] = y;};
+               void Z( double z) { values[2] = z;};
+               double X() const { return values[0];};
+               double Y() const { return values[1];};
+               double Z() const { return values[2];};
+        
+       private:
+               double values[3];
+};
+
+bool operator == ( const FTPoint &a, const FTPoint &b) 
+{
+       return((a.values[0] == b.values[0]) && (a.values[1] == b.values[1]) && (a.values[2] == b.values[2]));
+}
+
+bool operator != ( const FTPoint &a, const FTPoint &b) 
+{
+       return((a.values[0] != b.values[0]) || (a.values[1] != b.values[1]) || (a.values[2] != b.values[2]));
+}
+
+FTPoint operator*( double multiplier, FTPoint& point)
+{
+       return point * multiplier;
+}
+
+
+class FTBBox
+{
+       public:
+               
+               FTBBox()
+       :   lowerX(0.0f),
+               lowerY(0.0f),
+               lowerZ(0.0f),
+               upperX(0.0f),
+               upperY(0.0f),
+               upperZ(0.0f)
+               {}
+        
+        FTBBox( float lx, float ly, float lz, float ux, float uy, float uz)
+       :   lowerX(lx),
+               lowerY(ly),
+               lowerZ(lz),
+               upperX(ux),
+               upperY(uy),
+               upperZ(uz)
+               {}
+        
+        
+               FTBBox( FT_GlyphSlot glyph)
+       :   lowerX(0.0f),
+               lowerY(0.0f),
+               lowerZ(0.0f),
+               upperX(0.0f),
+               upperY(0.0f),
+               upperZ(0.0f)
+               {
+                       FT_BBox bbox;
+                       FT_Outline_Get_CBox( &(glyph->outline), &bbox);
+
+                       lowerX = static_cast<float>( bbox.xMin) / 64.0f;
+                       lowerY = static_cast<float>( bbox.yMin) / 64.0f;
+                       lowerZ = 0.0f;
+                       upperX = static_cast<float>( bbox.xMax) / 64.0f;
+                       upperY = static_cast<float>( bbox.yMax) / 64.0f;
+                       upperZ = 0.0f;
+            
+               }       
+
+               ~FTBBox()
+               {}
+        
+               FTBBox& Move( FTPoint distance)
+               {
+                       lowerX += distance.X();
+                       lowerY += distance.Y();
+                       lowerZ += distance.Z();
+                       upperX += distance.X();
+                       upperY += distance.Y();
+                       upperZ += distance.Z();
+                       return *this;
+               }
+
+               FTBBox& operator += ( const FTBBox& bbox) 
+               {
+                       lowerX = bbox.lowerX < lowerX? bbox.lowerX: lowerX; 
+                       lowerY = bbox.lowerY < lowerY? bbox.lowerY: lowerY;
+                       lowerZ = bbox.lowerZ < lowerZ? bbox.lowerZ: lowerZ; 
+                       upperX = bbox.upperX > upperX? bbox.upperX: upperX; 
+                       upperY = bbox.upperY > upperY? bbox.upperY: upperY; 
+                       upperZ = bbox.upperZ > upperZ? bbox.upperZ: upperZ; 
+            
+                       return *this;
+               }
+        
+               void SetDepth( float depth)
+               {
+                       upperZ = lowerZ + depth;
+               }
+        
+               float lowerX, lowerY, lowerZ, upperX, upperY, upperZ;
+       protected:
+    
+       private:
+};
+
+
+
+
+
+class FTGlyph
+{
+       public:
+               FTGlyph( FT_GlyphSlot glyph, bool useList = true)
+               {
+                       useDisplayList = useList;
+                       err = 0;
+                       if( glyph)
+                       {
+                               bBox = FTBBox( glyph);
+                               advance = FTPoint( glyph->advance.x / 64.0f, glyph->advance.y / 64.0f, 0.0f);
+                       }
+               }
+
+               virtual FTGlyph::~FTGlyph()
+               {}
+               
+               virtual const FTPoint& Render( const FTPoint& pen) = 0;
+      const FTPoint& Advance() const { return advance;}
+               const FTBBox& BBox() const { return bBox;}
+               FT_Error Error() const { return err;}
+        
+       protected:
+               FTPoint advance;
+               FTBBox bBox;
+               bool useDisplayList;
+               FT_Error err;
+        
+       private:
+};
+
+
+
+
+
+
+class FTLibrary
+{
+       public:
+               static const FTLibrary& Instance();
+               const FT_Library* const GetLibrary() const { return library;}
+               FT_Error Error() const { return err;}
+               ~FTLibrary();
+        
+       private:
+               FTLibrary();
+               FTLibrary( const FT_Library&){}
+               FTLibrary& operator=( const FT_Library&) { return *this; }
+        
+               bool Initialise();
+               FT_Library* library;
+               FT_Error err;
+        
+};
+
+
+
+
+const FTLibrary&  FTLibrary::Instance()
+{
+       static FTLibrary ftlib;
+       return ftlib;
+}
+
+
+FTLibrary::~FTLibrary()
+{
+       if( library != 0)
+       {
+               FT_Done_FreeType( *library);
+
+               delete library;
+               library= 0;
+       }
+
+//  if( manager != 0)
+//  {
+//      FTC_Manager_Done( manager );
+       //
+//      delete manager;
+//      manager= 0;
+//  }
+}
+
+
+FTLibrary::FTLibrary()
+       :   library(0),
+    err(0)
+{
+       Initialise();
+}
+
+
+bool FTLibrary::Initialise()
+{
+       if( library != 0)
+               return true;
+
+       library = new FT_Library;
+    
+       err = FT_Init_FreeType( library);
+       if( err)
+       {
+               delete library;
+               library = 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;
+}
+
+
+
+
+class FTSize
+{
+       public:
+               FTSize();
+               virtual ~FTSize();
+               bool CharSize( FT_Face* face, unsigned int point_size, unsigned int x_resolution, unsigned int y_resolution);
+               unsigned int CharSize() const;
+               float Ascender() const;
+               float Descender() const;
+               float Height() const;
+               float Width() const;
+               float Underline() const;
+               FT_Error Error() const { return err; }
+        
+       private:
+               FT_Face* ftFace;
+               FT_Size ftSize;
+               unsigned int size;
+               unsigned int xResolution;
+               unsigned int yResolution;
+               FT_Error err;
+        
+};
+
+
+
+FTSize::FTSize()
+       :   ftFace(0),
+    ftSize(0),
+        size(0),
+        xResolution(0),
+        yResolution(0),
+        err(0)
+{}
+
+
+        FTSize::~FTSize()
+        {}
+
+
+        bool FTSize::CharSize( FT_Face* face, unsigned int pointSize, unsigned int xRes, unsigned int yRes )
+        {
+                if( size != pointSize || xResolution != xRes || yResolution != yRes)
+                {
+                        err = FT_Set_Char_Size( *face, 0L, pointSize * 64, xResolution, yResolution);
+
+                        if( !err)
+                        {
+                                ftFace = face;
+                                size = pointSize;
+                                xResolution = xRes;
+                                yResolution = yRes;
+                                ftSize = (*ftFace)->size;
+                        }
+                        else
+                        {
+                                ftFace = 0;
+                                size = 0;
+                                xResolution = 0;
+                                yResolution = 0;
+                                ftSize = 0;
+                        }
+                }
+    
+                return !err;
+        }
+
+
+        unsigned int FTSize::CharSize() const
+        {
+                return size;
+        }
+
+
+        float FTSize::Ascender() const
+        {
+                return ftSize == 0 ? 0.0f : static_cast<float>( ftSize->metrics.ascender) / 64.0f;
+        }
+
+
+        float FTSize::Descender() const
+        {
+                return ftSize == 0 ? 0.0f : static_cast<float>( ftSize->metrics.descender) / 64.0f;
+        }
+
+
+        float FTSize::Height() const
+        {
+                if( 0 == ftSize)
+                {
+                        return 0.0f;
+                }
+    
+                if( FT_IS_SCALABLE((*ftFace)))
+                {
+                        return ( (*ftFace)->bbox.yMax - (*ftFace)->bbox.yMin) * ( (float)ftSize->metrics.y_ppem / (float)(*ftFace)->units_per_EM);
+                }
+                else
+                {
+                        return static_cast<float>( ftSize->metrics.height) / 64.0f;
+                }
+        }
+
+
+        float FTSize::Width() const
+        {
+                if( 0 == ftSize)
+                {
+                        return 0.0f;
+                }
+    
+                if( FT_IS_SCALABLE((*ftFace)))
+                {
+                        return ( (*ftFace)->bbox.xMax - (*ftFace)->bbox.xMin) * ( static_cast<float>(ftSize->metrics.x_ppem) / static_cast<float>((*ftFace)->units_per_EM));
+                }
+                else
+                {
+                        return static_cast<float>( ftSize->metrics.max_advance) / 64.0f;
+                }
+        }
+
+
+        float FTSize::Underline() const
+        {
+                return 0.0f;
+        }
+
+
+
+
+class FTFace
+{
+       public:
+        
+               FTFace( const char* fontFilePath);
+               FTFace( const unsigned char *pBufferBytes, size_t bufferSizeInBytes );
+               virtual ~FTFace();
+
+               bool Attach( const char* fontFilePath);
+               bool Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
+               FT_Face* Face() const { return ftFace;}
+               const FTSize& Size( const unsigned int size, const unsigned int res);
+               unsigned int CharMapCount();
+               FT_Encoding* CharMapList();
+               FTPoint KernAdvance( unsigned int index1, unsigned int index2);
+               FT_GlyphSlot Glyph( unsigned int index, FT_Int load_flags);
+               unsigned int GlyphCount() const { return numGlyphs;}
+               FT_Error Error() const { return err; }
+        
+       private:
+               FT_Face* ftFace;
+               FTSize  charSize;
+               int numGlyphs;
+               FT_Encoding* fontEncodingList;
+               bool hasKerningTable;
+               FT_Error err;
+};
+
+FTFace::FTFace( const char* fontFilePath)
+       :   numGlyphs(0),
+    fontEncodingList(0),
+        err(0)
+{
+       const FT_Long DEFAULT_FACE_INDEX = 0;
+       ftFace = new FT_Face;
+
+       err = FT_New_Face( *FTLibrary::Instance().GetLibrary(), fontFilePath, DEFAULT_FACE_INDEX, ftFace);
+
+       if( err)
+       {
+               delete ftFace;
+               ftFace = 0;
+       }
+       else
+       {
+               numGlyphs = (*ftFace)->num_glyphs;
+               hasKerningTable = FT_HAS_KERNING((*ftFace));
+       }
+}
+
+
+FTFace::FTFace( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
+       :   numGlyphs(0),
+    err(0)
+{
+       const FT_Long DEFAULT_FACE_INDEX = 0;
+       ftFace = new FT_Face;
+
+       err = FT_New_Memory_Face( *FTLibrary::Instance().GetLibrary(), (FT_Byte *)pBufferBytes, bufferSizeInBytes, DEFAULT_FACE_INDEX, ftFace);
+
+       if( err)
+       {
+               delete ftFace;
+               ftFace = 0;
+       }
+       else
+       {
+               numGlyphs = (*ftFace)->num_glyphs;
+       }
+}
+
+
+FTFace::~FTFace()
+{
+       if( ftFace)
+       {
+               FT_Done_Face( *ftFace);
+               delete ftFace;
+               ftFace = 0;
+       }
+}
+
+
+bool FTFace::Attach( const char* fontFilePath)
+{
+       err = FT_Attach_File( *ftFace, fontFilePath);
+       return !err;
+}
+
+
+bool FTFace::Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
+{
+       FT_Open_Args open;
+
+       open.flags = FT_OPEN_MEMORY;
+       open.memory_base = (FT_Byte *)pBufferBytes;
+       open.memory_size = bufferSizeInBytes;
+
+       err = FT_Attach_Stream( *ftFace, &open);
+       return !err;
+}
+
+
+const FTSize& FTFace::Size( const unsigned int size, const unsigned int res)
+{
+       charSize.CharSize( ftFace, size, res, res);
+       err = charSize.Error();
+
+       return charSize;
+}
+
+
+unsigned int FTFace::CharMapCount()
+{
+       return (*ftFace)->num_charmaps;
+}
+
+
+FT_Encoding* FTFace::CharMapList()
+{
+       if( 0 == fontEncodingList)
+       {
+               fontEncodingList = new FT_Encoding[CharMapCount()];
+               for( size_t encodingIndex = 0; encodingIndex < CharMapCount(); ++encodingIndex)
+               {
+                       fontEncodingList[encodingIndex] = (*ftFace)->charmaps[encodingIndex]->encoding;
+               }
+       }
+    
+       return fontEncodingList;
+}
+
+
+FTPoint FTFace::KernAdvance( unsigned int index1, unsigned int index2)
+{
+       float x, y;
+       x = y = 0.0f;
+
+       if( hasKerningTable && index1 && index2)
+       {
+               FT_Vector kernAdvance;
+               kernAdvance.x = kernAdvance.y = 0;
+
+               err = FT_Get_Kerning( *ftFace, index1, index2, ft_kerning_unfitted, &kernAdvance);
+               if( !err)
+               {   
+                       x = static_cast<float>( kernAdvance.x) / 64.0f;
+                       y = static_cast<float>( kernAdvance.y) / 64.0f;
+               }
+       }
+    
+       return FTPoint( x, y, 0.0);
+}
+
+
+FT_GlyphSlot FTFace::Glyph( unsigned int index, FT_Int load_flags)
+{
+       err = FT_Load_Glyph( *ftFace, index, load_flags);
+       if( err)
+       {
+               return NULL;
+       }
+
+       return (*ftFace)->glyph;
+}
+
+
+
+
+
+
+
+
+
+ template <typename FT_VECTOR_ITEM_TYPE>  class FTVector
+{
+       public:
+               typedef FT_VECTOR_ITEM_TYPE value_type;
+               typedef value_type& reference;
+               typedef const value_type& const_reference;
+               typedef value_type* iterator;
+               typedef const value_type* const_iterator;
+               typedef size_t size_type;
+        
+               FTVector()
+               {
+                       Capacity = Size = 0;
+                       Items = 0;
+               }
+
+        
+               virtual ~FTVector()
+               {
+                       clear();
+               }
+        
+               FTVector& operator =(const FTVector& v)
+               {
+                       reserve(v.capacity());
+            
+                       iterator ptr = begin();
+                       const_iterator vbegin = v.begin();
+                       const_iterator vend = v.end();
+            
+                       while( vbegin != vend)
+                       {
+                               *ptr++ = *vbegin++;
+                       }
+            
+                       Size = v.size();
+                       return *this;
+               }
+        
+               size_type size() const
+               {
+                       return Size;
+               }
+        
+               size_type capacity() const
+               {
+                       return Capacity;
+               }
+        
+               iterator begin()
+               {
+                       return Items;
+               }
+        
+               const_iterator begin() const
+               {
+                       return Items;
+               }
+        
+               iterator end()
+               {
+                       return begin() + size(); 
+               }
+        
+               const_iterator end() const
+               {
+                       return begin() + size(); 
+               }
+        
+               bool empty() const 
+               { 
+                       return size() == 0; 
+               }
+
+               reference operator [](size_type pos) 
+               { 
+                       return( *(begin() + pos)); 
+               }
+
+               const_reference operator []( size_type pos) const 
+               { 
+                       return( *(begin() + pos)); 
+               }
+        
+               void clear()
+               {
+                       if( Capacity)
+                       {
+                               delete [] Items;
+                               Capacity = Size = 0;
+                               Items = 0;
+                       }
+               }
+
+               void reserve( size_type n)
+               {
+                       if( capacity() < n)
+                       {
+                               expand(n);
+                       }
+               }
+
+               void push_back(const value_type& x)
+               {
+                       if( size() == capacity())
+                       {
+                               expand();
+                       }
+           
+                       ( *this)[size()] = x;
+                       ++Size;
+               }
+
+               void resize(size_type n, value_type x)
+               {
+                       if( n == size())
+                       {
+                               return;
+                       }
+            
+                       reserve(n);
+                       iterator begin, end;
+            
+                       if( n >= Size)
+                       {
+                               begin = this->end();
+                               end = this->begin() + n;
+                       }
+                       else
+                       {
+                               begin = this->begin() + n;
+                               end = this->end();
+                       }
+        
+                       while( begin != end)
+                       {
+                               *begin++ = x;
+                       }
+        
+                       Size = n;
+               }
+
+        
+       private:
+               void expand(size_type capacity_hint = 0)
+               {
+                       size_type new_capacity =( capacity() == 0) ? 256 : capacity()* 2;
+                       if( capacity_hint)
+                       {
+                               while( new_capacity < capacity_hint)
+                               {
+                                       new_capacity *= 2;
+                               }
+                       }
+            
+                       value_type *new_items = new value_type[new_capacity];
+            
+                       iterator begin = this->begin();
+                       iterator end = this->end();
+                       value_type *ptr = new_items;
+            
+                       while( begin != end)
+                       {
+                               *ptr++ = *begin++;
+                       }
+            
+                       if( Capacity)
+                       {
+                               delete [] Items;
+                       }
+        
+                       Items = new_items;
+                       Capacity = new_capacity;
+               }
+
+               size_type Capacity;
+               size_type Size;
+               value_type* Items;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+class FTCharToGlyphIndexMap
+{
+       public:
+  
+               typedef unsigned long CharacterCode;
+               typedef signed long GlyphIndex;
+        
+               enum 
+               {
+                       NumberOfBuckets = 256,
+                       BucketSize = 256,
+                       IndexNotFound = -1
+               };
+
+               FTCharToGlyphIndexMap()
+               {
+                       this->Indices = 0;
+               }
+
+               virtual ~FTCharToGlyphIndexMap()
+               {
+                       if( this->Indices)
+                       {
+                // Free all buckets
+                               this->clear();
+        
+                // Free main structure
+                               delete [] this->Indices;
+                               this->Indices = 0;
+                       }
+               }
+  
+               void clear()
+               {
+                       if(this->Indices)
+                       {
+                               for( int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++)
+                               {
+                                       if( this->Indices[i])
+                                       {
+                                               delete [] this->Indices[i];
+                                               this->Indices[i] = 0;
+                                       }
+                               }
+                       }
+               }
+
+               const GlyphIndex find( CharacterCode c)
+               {
+                       if( !this->Indices)
+                       {
+                               return 0;
+                       }
+        
+            // Find position of char code in buckets
+                       div_t pos = div( c, FTCharToGlyphIndexMap::BucketSize);
+        
+                       if( !this->Indices[pos.quot])
+                       {
+                               return 0;
+                       }
+        
+                       const FTCharToGlyphIndexMap::GlyphIndex *ptr = &this->Indices[pos.quot][pos.rem];
+                       if( *ptr == FTCharToGlyphIndexMap::IndexNotFound)
+                       {
+                               return 0;
+                       }
+        
+                       return *ptr;
+               }
+
+               void insert( CharacterCode c, GlyphIndex g)
+               {
+                       if( !this->Indices)
+                       {
+                               this->Indices = new GlyphIndex* [FTCharToGlyphIndexMap::NumberOfBuckets];
+                               for( int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++)
+                               {
+                                       this->Indices[i] = 0;
+                               }
+                       }
+        
+            // Find position of char code in buckets
+                       div_t pos = div(c, FTCharToGlyphIndexMap::BucketSize);
+        
+            // Allocate bucket if does not exist yet
+                       if( !this->Indices[pos.quot])
+                       {
+                               this->Indices[pos.quot] = new GlyphIndex [FTCharToGlyphIndexMap::BucketSize];
+                               for( int i = 0; i < FTCharToGlyphIndexMap::BucketSize; i++)
+                               {
+                                       this->Indices[pos.quot][i] = FTCharToGlyphIndexMap::IndexNotFound;
+                               }
+                       }
+          
+                       this->Indices[pos.quot][pos.rem] = g;
+               }
+  
+       private:
+               GlyphIndex** Indices;
+};
+
+
+
+
+
+class FTCharmap
+{
+       public:
+               FTCharmap( FTFace* face);
+               virtual ~FTCharmap();
+
+               FT_Encoding Encoding() const { return ftEncoding;}
+               bool CharMap( FT_Encoding encoding);
+               unsigned int GlyphListIndex( const unsigned int characterCode);
+               unsigned int FontIndex( const unsigned int characterCode);
+               void InsertIndex( const unsigned int characterCode, const unsigned int containerIndex);
+               FT_Error Error() const { return err;}
+        
+       private:
+               FT_Encoding ftEncoding;
+               const FT_Face ftFace;
+               typedef FTCharToGlyphIndexMap CharacterMap;
+               CharacterMap charMap;
+        
+               FT_Error err;
+        
+};
+
+
+
+
+
+FTCharmap::FTCharmap( FTFace* face)
+       :   ftFace( *(face->Face())),
+    err(0)
+{
+       if( !ftFace->charmap)
+       {
+               err = FT_Set_Charmap( ftFace, ftFace->charmaps[0]);
+       }
+    
+       ftEncoding = ftFace->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;
+       }
+       else
+       {
+               ftEncoding = ft_encoding_none;
+       }
+        
+       charMap.clear();
+       return !err;
+}
+
+
+unsigned int FTCharmap::GlyphListIndex( unsigned int characterCode )
+{
+       return charMap.find( characterCode);
+}
+
+
+unsigned int FTCharmap::FontIndex( unsigned int characterCode )
+{
+       return FT_Get_Char_Index( ftFace, characterCode);
+}
+
+
+void FTCharmap::InsertIndex( const unsigned int characterCode, const unsigned int containerIndex)
+{
+       charMap.insert( characterCode, containerIndex);
+}
+
+
+
+
+class FTGlyphContainer
+{
+       typedef FTVector<FTGlyph*> GlyphVector;
+       public:
+               FTGlyphContainer( FTFace* face);
+               ~FTGlyphContainer();
+               bool CharMap( FT_Encoding encoding);
+               unsigned int FontIndex( const unsigned int characterCode ) const;
+               void Add( FTGlyph* glyph, const unsigned int characterCode);
+               const FTGlyph* const Glyph( const unsigned int characterCode) const;
+               FTBBox BBox( const unsigned int characterCode) const;
+               float Advance( const unsigned int characterCode, const unsigned int nextCharacterCode);
+        
+               FTPoint Render( const unsigned int characterCode, const unsigned int nextCharacterCode, FTPoint penPosition);
+        
+               FT_Error Error() const { return err;}
+
+       private:
+               FTFace* face;
+               FTCharmap* charMap;
+
+               GlyphVector glyphs;
+
+               FT_Error err;
+};
+
+
+FTGlyphContainer::FTGlyphContainer( FTFace* f)
+       :   face(f),
+    err(0)
+{
+       glyphs.push_back( NULL);
+       charMap = new FTCharmap( face);
+}
+
+
+FTGlyphContainer::~FTGlyphContainer()
+{
+       GlyphVector::iterator glyphIterator;
+       for( glyphIterator = glyphs.begin(); glyphIterator != glyphs.end(); ++glyphIterator)
+       {
+               delete *glyphIterator;
+       }
+    
+       glyphs.clear();
+       delete charMap;
+}
+
+
+bool FTGlyphContainer::CharMap( FT_Encoding encoding)
+{
+       bool result = charMap->CharMap( encoding);
+       err = charMap->Error();
+       return result;
+}
+
+
+unsigned int FTGlyphContainer::FontIndex( const unsigned int characterCode) const
+{
+       return charMap->FontIndex( characterCode);
+}
+
+
+void FTGlyphContainer::Add( FTGlyph* tempGlyph, const unsigned int characterCode)
+{
+       charMap->InsertIndex( characterCode, glyphs.size());
+       glyphs.push_back( tempGlyph);
+}
+
+
+const FTGlyph* const FTGlyphContainer::Glyph( const unsigned int characterCode) const
+{
+       signed int index = charMap->GlyphListIndex( characterCode);
+       return glyphs[index];
+}
+
+
+FTBBox FTGlyphContainer::BBox( const unsigned int characterCode) const
+{
+       return glyphs[charMap->GlyphListIndex( characterCode)]->BBox();
+}
+
+
+float FTGlyphContainer::Advance( const unsigned int characterCode, const unsigned int nextCharacterCode)
+{
+       unsigned int left = charMap->FontIndex( characterCode);
+       unsigned int right = charMap->FontIndex( nextCharacterCode);
+
+       float width = face->KernAdvance( left, right).X();
+       width += glyphs[charMap->GlyphListIndex( characterCode)]->Advance().X();
+    
+       return width;
+}
+
+
+FTPoint FTGlyphContainer::Render( const unsigned int characterCode, const unsigned int nextCharacterCode, FTPoint penPosition)
+{
+       FTPoint kernAdvance, advance;
+    
+       unsigned int left = charMap->FontIndex( characterCode);
+       unsigned int right = charMap->FontIndex( nextCharacterCode);
+
+       kernAdvance = face->KernAdvance( left, right);
+        
+       if( !face->Error())
+       {
+               advance = glyphs[charMap->GlyphListIndex( characterCode)]->Render( penPosition);
+       }
+    
+       kernAdvance += advance;
+       return kernAdvance;
+}
+
+
+
+
+
+
+
+
+
+class FTFont
+{
+       public:
+               
+               FTFont( const char* fontFilePath);
+      FTFont( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
+               virtual ~FTFont();
+        
+               bool Attach( const char* fontFilePath);
+               bool Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
+               bool CharMap( FT_Encoding encoding );
+               unsigned int CharMapCount();
+               FT_Encoding* CharMapList();
+       virtual bool FaceSize( const unsigned int size, const unsigned int res = 72);
+       unsigned int FaceSize() const;
+       virtual void Depth( float depth){}
+               void UseDisplayList( bool useList);
+       float Ascender() const;
+       float Descender() const;
+       float LineHeight() const;
+       void BBox( const char* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
+               void BBox( const wchar_t* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
+               float Advance( const wchar_t* string);
+               float Advance( const char* string);
+               virtual void Render( const char* string );
+               virtual void Render( const wchar_t* string );
+               FT_Error Error() const { return err;}
+
+       protected:
+               virtual FTGlyph* MakeGlyph( unsigned int g) = 0;
+               FTFace face;
+               FTSize charSize;
+               bool useDisplayLists;
+               FT_Error err;
+        
+       private:        
+               inline bool CheckGlyph( const unsigned int chr);
+               FTGlyphContainer* glyphList;
+               FTPoint pen;
+};
+
+
+
+FTFont::FTFont( const char* fontFilePath) : face(fontFilePath), useDisplayLists(true), glyphList(0)
+{
+       err = face.Error();
+       if( err == 0)
+       {
+               glyphList = new FTGlyphContainer( &face);
+       }
+}
+
+
+
+
+FTFont::FTFont( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
+       :   face( pBufferBytes, bufferSizeInBytes),
+    glyphList(0)
+{
+       err = face.Error();
+       if( err == 0)
+       {
+               glyphList = new FTGlyphContainer( &face);
+       }
+}
+
+
+FTFont::~FTFont()
+{
+       delete glyphList;
+}
+
+
+bool FTFont::Attach( const char* fontFilePath)
+{
+       if( face.Attach( fontFilePath))
+       {
+               err = 0;
+               return true;
+       }
+       else
+       {
+               err = face.Error();
+               return false;
+       }
+}
+
+
+bool FTFont::Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
+{
+       if( face.Attach( pBufferBytes, bufferSizeInBytes))
+       {
+               err = 0;
+               return true;
+       }
+       else
+       {
+               err = face.Error();
+               return false;
+       }
+}
+
+
+bool FTFont::FaceSize( const unsigned int size, const unsigned int res )
+{
+       charSize = face.Size( size, res);
+       err = face.Error();
+    
+       if( err != 0)
+       {
+               return false;
+       }
+    
+       if( glyphList != NULL)
+       {
+               delete glyphList;
+       }
+    
+       glyphList = new FTGlyphContainer( &face);
+       return true;
+}
+
+
+unsigned int FTFont::FaceSize() const
+{
+       return charSize.CharSize();
+}
+
+
+bool FTFont::CharMap( FT_Encoding encoding)
+{
+       bool result = glyphList->CharMap( encoding);
+       err = glyphList->Error();
+       return result;
+}
+
+
+unsigned int FTFont::CharMapCount()
+{
+       return face.CharMapCount();
+}
+
+
+FT_Encoding* FTFont::CharMapList()
+{
+       return face.CharMapList();
+}
+
+
+void FTFont::UseDisplayList( bool useList)
+{
+       useDisplayLists = useList;
+}
+
+float FTFont::Ascender() const
+{
+       return charSize.Ascender();
+}
+
+
+float FTFont::Descender() const
+{
+       return charSize.Descender();
+}
+
+float FTFont::LineHeight() const
+{
+       return charSize.Height();
+}
+
+void FTFont::BBox( const char* string,
+                                                float& llx, float& lly, float& llz, float& urx, float& ury, float& urz)
+{
+       FTBBox totalBBox;
+
+       if((NULL != string) && ('\0' != *string))
+       {
+               const unsigned char* c = (unsigned char*)string;
+               float advance = 0;
+
+               if(CheckGlyph( *c))
+               {
+                       totalBBox = glyphList->BBox( *c);
+                       advance = glyphList->Advance( *c, *(c + 1));
+               }
+                
+               while( *++c)
+               {
+                       if(CheckGlyph( *c))
+                       {
+                               FTBBox tempBBox = glyphList->BBox( *c);
+                               tempBBox.Move( FTPoint( advance, 0.0f, 0.0f));
+                               totalBBox += tempBBox;
+                               advance += glyphList->Advance( *c, *(c + 1));
+                       }
+               }
+       }
+
+       llx = totalBBox.lowerX;
+       lly = totalBBox.lowerY;
+       llz = totalBBox.lowerZ;
+       urx = totalBBox.upperX;
+       ury = totalBBox.upperY;
+       urz = totalBBox.upperZ;
+}
+
+
+void FTFont::BBox( const wchar_t* string,
+                                                float& llx, float& lly, float& llz, float& urx, float& ury, float& urz)
+{
+       FTBBox totalBBox;
+
+       if((NULL != string) && ('\0' != *string))
+       {
+               const wchar_t* c = string;
+               float advance = 0;
+
+               if(CheckGlyph( *c))
+               {
+                       totalBBox = glyphList->BBox( *c);
+                       advance = glyphList->Advance( *c, *(c + 1));
+               }
+        
+               while( *++c)
+               {
+                       if(CheckGlyph( *c))
+                       {
+                               FTBBox tempBBox = glyphList->BBox( *c);
+                               tempBBox.Move( FTPoint( advance, 0.0f, 0.0f));
+                               totalBBox += tempBBox;
+                               advance += glyphList->Advance( *c, *(c + 1));
+                       }
+               }
+       }
+
+       llx = totalBBox.lowerX;
+       lly = totalBBox.lowerY;
+       llz = totalBBox.lowerZ;
+       urx = totalBBox.upperX;
+       ury = totalBBox.upperY;
+       urz = totalBBox.upperZ;
+}
+
+
+float FTFont::Advance( const wchar_t* string)
+{
+       const wchar_t* c = string;
+       float width = 0.0f;
+
+       while( *c)
+       {
+               if(CheckGlyph( *c))
+               {
+                       width += glyphList->Advance( *c, *(c + 1));
+               }
+               ++c;
+       }
+    
+       return width;
+}
+
+
+float FTFont::Advance( const char* string)
+{
+       const unsigned char* c = (unsigned char*)string;
+       float width = 0.0f;
+
+       while( *c)
+       {
+               if(CheckGlyph( *c))
+               {
+                       width += glyphList->Advance( *c, *(c + 1));
+               }
+               ++c;
+       }
+    
+       return width;
+}
+
+
+void FTFont::Render( const char* string )
+{
+       const unsigned char* c = (unsigned char*)string;
+       pen.X(0); pen.Y(0);
+
+       while( *c)
+       {
+               if(CheckGlyph( *c))
+               {
+                       pen = glyphList->Render( *c, *(c + 1), pen);
+               }
+               ++c;
+       }
+}
+
+
+void FTFont::Render( const wchar_t* string )
+{
+       const wchar_t* c = string;
+       pen.X(0); pen.Y(0);
+
+       while( *c)
+       {
+               if(CheckGlyph( *c))
+               {
+                       pen = glyphList->Render( *c, *(c + 1), pen);
+               }
+               ++c;
+       }
+}
+
+
+bool FTFont::CheckGlyph( const unsigned int characterCode)
+{
+       if( NULL == glyphList->Glyph( characterCode))
+       {
+               unsigned int glyphIndex = glyphList->FontIndex( characterCode);
+               FTGlyph* tempGlyph = MakeGlyph( glyphIndex);
+               if( NULL == tempGlyph)
+               {
+                       if( 0 == err)
+                       {
+                               err = 0x13;
+                       }
+            
+                       return false;
+               }
+               glyphList->Add( tempGlyph, characterCode);
+       }
+    
+       return true;
+}
+
+
+
+
+
+
+class FTTextureGlyph : public FTGlyph
+{
+       public:
+               FTTextureGlyph( FT_GlyphSlot glyph, Texture * tid, int xOffset, int yOffset, int width, int height);
+               virtual ~FTTextureGlyph();
+               virtual const FTPoint& Render( const FTPoint& pen);
+               static void FTTextureGlyph::ResetActiveTexture()
+               {
+                       activeTextureID = 0;
+                       activeTexture = 0;
+               }
+        
+       private:
+               int destWidth;
+               int destHeight;
+               FTPoint pos;
+               FTPoint uv[2];
+               int glTextureID;
+               Texture* textureID;
+               static int activeTextureID;
+               static Texture* activeTexture;
+        
+};
+
+
+int FTTextureGlyph::activeTextureID = 0;
+Texture* FTTextureGlyph::activeTexture = 0;
+FTTextureGlyph::FTTextureGlyph( FT_GlyphSlot glyph, Texture *tid, int xOffset, int yOffset, int width, int height)
+       :   FTGlyph(glyph)
+{
+       destWidth = 0;
+       destHeight = 0;
+
+       textureID = tid;
+       glTextureID = tid->gl_Tex;
+               
+       err = FT_Render_Glyph( glyph, FT_RENDER_MODE_NORMAL);
+       if( err || glyph->format != ft_glyph_format_bitmap)
+       {
+               return;
+       }
+
+       FT_Bitmap      bitmap = glyph->bitmap;
+
+       destWidth  = bitmap.width;
+       destHeight = bitmap.rows;
+    
+       int tW=0, tH=0;
+       if( destWidth && destHeight)
+       {
+               glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT);
+               glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE);
+               glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
+               glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
+               
+               
+               g->setTexture(tid);
+//             glBindTexture( GL_TEXTURE_2D, glTextureID);
+               glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,GL_TEXTURE_WIDTH, &tW);
+               glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,GL_TEXTURE_HEIGHT, &tH);
+               tid->texSubImage2D(xOffset, yOffset, destWidth, destHeight, AM_ALPHA, AM_UBYTE, bitmap.buffer);
+
+       //      glTexSubImage2D( GL_TEXTURE_2D, 0, xOffset, yOffset, destWidth, destHeight, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer);
+               
+               printf("TW=%d tH=%d   txoff=%d  yoff=%d w=%d h=%d\n", tW, tH, xOffset, yOffset, destWidth, destHeight);
+               glPopClientAttrib();
+       }
+
+    
+       uv[0].X( static_cast<float>(xOffset) / static_cast<float>(width));
+       uv[0].Y( static_cast<float>(yOffset) / static_cast<float>(height));
+       uv[1].X( static_cast<float>( xOffset + destWidth) / static_cast<float>(width));
+       uv[1].Y( static_cast<float>( yOffset + destHeight) / static_cast<float>(height));
+    
+       pos.X( glyph->bitmap_left);
+       pos.Y( glyph->bitmap_top);
+}
+
+
+FTTextureGlyph::~FTTextureGlyph()
+{ }
+
+
+const FTPoint& FTTextureGlyph::Render( const FTPoint& pen)
+{
+       if( activeTextureID != glTextureID)
+       {
+               g->setTexture(textureID);
+               printf("setT = %d\n", textureID->gl_Tex);
+               activeTexture = textureID;
+               //activeTextureID = glTextureID;
+//             glBindTexture( GL_TEXTURE_2D, glTextureID);
+               
+       }
+
+       vertex array[4];
+
+       
+       //g->setWorld(pen.X(),  pen.Y(), 0.0f, 0,0,0, 1,1,1);
+       glTranslatef( pen.X(),  pen.Y(), 0.0f);
+       
+       array[0].u = uv[0].X();
+       array[0].v = 1 - uv[0].Y();
+       array[0].x = pos.X();
+       array[0].y = pos.Y();
+       array[0].z = 0;
+       array[0].col = COLOUR_RGBA(255,255,255,255);
+       array[0].nx = array[0].ny = array[0].nz = 0;
+
+       array[1].u = uv[0].X();
+       array[1].v = 1 - uv[1].Y();
+       array[1].x = pos.X();
+       array[1].y = pos.Y() - destHeight;
+       array[1].z = 0;
+       array[1].col = COLOUR_RGBA(255,255,255,255);
+       array[1].nx = array[1].ny = array[1].nz = 0;
+
+       array[2].u = uv[1].X();
+       array[2].v = 1 - uv[1].Y();
+       array[2].x = pos.X() + destWidth;
+       array[2].y = pos.Y() - destHeight;
+       array[2].z = 0;
+       array[2].col = COLOUR_RGBA(255,255,255,255);
+       array[2].nx = array[2].ny = array[2].nz = 0;
+
+       array[3].u = uv[1].X();
+       array[3].v = 1 - uv[0].Y();
+       array[3].x = pos.X() + destWidth;
+       array[3].y = pos.Y();
+       array[3].z = 0;
+       array[3].col = COLOUR_RGBA(255,255,255,255);
+       array[3].nx = array[3].ny = array[3].nz = 0;
+       
+       //g->renderVertexArray(array, 4, AM_TRIANGLE_STRIP);
+       g->addTriangle(array[0], array[1], array[2]);
+       g->addTriangle(array[2], array[3], array[0]);
+       
+/*     glBegin( GL_QUADS);
+       glTexCoord2f( uv[0].X(), uv[0].Y());
+       glVertex2f( pos.X(), pos.Y());
+       
+       glTexCoord2f( uv[0].X(), uv[1].Y());
+       glVertex2f( pos.X(), pos.Y() - destHeight);
+
+       glTexCoord2f( uv[1].X(), uv[1].Y());
+       glVertex2f( destWidth + pos.X(), pos.Y() - destHeight);
+        
+       glTexCoord2f( uv[1].X(), uv[0].Y());
+       glVertex2f( destWidth + pos.X(), pos.Y());
+       glEnd();
+       */
+       return advance;
+}
+
+
+
+
+
+class myFont : public FTFont
+{
+
+       private:
+               inline virtual FTGlyph* MakeGlyph( unsigned int glyphIndex)
+               {
+                       FT_GlyphSlot ftGlyph = face.Glyph( glyphIndex, FT_LOAD_NO_HINTING);
+    
+                       if( ftGlyph)
+                       {
+                               glyphHeight = static_cast<int>( charSize.Height());
+                               glyphWidth = static_cast<int>( charSize.Width());
+        
+                               if( textureIDList.empty())
+                               {
+                                       textureIDList.push_back( CreateTexture());
+                                       xOffset = yOffset = padding;
+                               }
+        
+                               if( xOffset > ( textureWidth - glyphWidth))
+                               {
+                                       xOffset = padding;
+                                       yOffset += glyphHeight;
+            
+                                       if( yOffset > ( textureHeight - glyphHeight))
+                                       {
+                                               textureIDList.push_back( CreateTexture());
+                                               yOffset = padding;
+                                       }
+                               }
+        
+                               FTTextureGlyph* tempGlyph = new FTTextureGlyph( ftGlyph, textureIDList[textureIDList.size() - 1],
+                                               xOffset, yOffset, textureWidth, textureHeight);
+                               xOffset += static_cast<int>( tempGlyph->BBox().upperX - tempGlyph->BBox().lowerX + padding);
+        
+                               --remGlyphs;
+                               return tempGlyph;
+                       }
+    
+                       err = face.Error();
+                       return NULL;
+               }
+               
+               inline void CalculateTextureSize()
+               {
+                       
+                       if( !maximumGLTextureSize)
+                       {
+                               glGetIntegerv( GL_MAX_TEXTURE_SIZE, (int*)&maximumGLTextureSize);
+                               assert(maximumGLTextureSize); // If you hit this then you have an invalid OpenGL context.
+                       }
+                       printf("maximumGLTextureSize=%d\n", maximumGLTextureSize);
+                       textureWidth = NextPowerOf2( (remGlyphs * glyphWidth) + ( padding * 2));
+                       textureWidth = textureWidth > maximumGLTextureSize ? maximumGLTextureSize : textureWidth;
+    
+                       int h = static_cast<int>( (textureWidth - ( padding * 2)) / glyphWidth);
+        
+                       textureHeight = NextPowerOf2( (( numGlyphs / h) + 1) * glyphHeight);
+                       textureHeight = textureHeight > maximumGLTextureSize ? maximumGLTextureSize : textureHeight;
+               }
+
+
+               inline Texture * CreateTexture()
+               {
+
+                       CalculateTextureSize();
+    
+                       int totalMemory = textureWidth * textureHeight;
+                       unsigned char* textureMemory = new unsigned char[totalMemory];
+                       memset( textureMemory, 0, totalMemory);
+
+                       Texture *texID = new Texture(textureMemory, textureWidth, textureHeight, AM_ALPHA, AM_UBYTE, g);
+
+                       delete [] textureMemory;
+
+                       printf("now returning texID=%p\n", texID);
+                       return texID;
+                       /*
+                       CalculateTextureSize();
+
+                       int totalMemory = textureWidth * textureHeight;
+                       unsigned char* textureMemory = new unsigned char[totalMemory];
+                       memset( textureMemory, 0, totalMemory);
+
+                       GLuint textID;
+       /*              glGenTextures( 1, (GLuint*)&textID);
+                       glBindTexture( GL_TEXTURE_2D, textID);
+                       glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+                       glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+                       glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+                       glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    
+                       glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, textureWidth, textureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, textureMemory);
+       */
+                       /*      
+                       Texture *tex = new Texture(textureMemory, textureWidth, textureHeight, AM_ALPHA, AM_UBYTE, g);
+//                     g->setTexture(tex);
+                       textID = tex->gl_Tex;
+                       delete [] textureMemory;
+                       printf("@ createTexture returning %d\n", textID);
+                       return textID;*/
+
+               }
+                               
+
+                               
+               int maximumGLTextureSize;
+               int textureWidth;
+               int textureHeight;
+               FTVector<Texture *> textureIDList;
+               int glyphHeight;
+               int glyphWidth;
+               unsigned int padding;
+               unsigned int numGlyphs;
+               unsigned int remGlyphs;
+               int xOffset;
+               int yOffset;
+
+       
+       public:
+
+       myFont( const char* fontFilePath)       :  FTFont( fontFilePath),
+    maximumGLTextureSize(0),
+        textureWidth(0),
+        textureHeight(0),
+        glyphHeight(0),
+        glyphWidth(0),
+        padding(3),
+        xOffset(0),
+        yOffset(0)
+{
+       remGlyphs = numGlyphs = face.GlyphCount();
+}
+
+~myFont()
+{
+       ;//glDeleteTextures( textureIDList.size(), (const unsigned int*)&textureIDList[0]);
+}
+
+
+void print( char *str, int x1, int y1, int x2, int y2, colour c )
+{
+       g->enter2dMode();
+       glColor4f( c.r, c.g, c.b, c.a);
+       float h= LineHeight()*0.64f;    /* factor 0.64*/
+       glTranslatef(x1, y1 + h, 0);
+       glScalef(1.0, -1.0, 1.0);
+       Render(str);
+//     ft_print( our_font, x1 , g->getHeight() - y1 - fontSize, str);
+       g->leave2dMode();
+}
+
+
+
+bool FaceSize( const unsigned int size, const unsigned int res)
+{
+       if( !textureIDList.empty())
+       {
+               glDeleteTextures( textureIDList.size(), (const uint*)&textureIDList[0]);
+               textureIDList.clear();
+               remGlyphs = numGlyphs = face.GlyphCount();
+       }
+
+       return FTFont::FaceSize( size, res);
+}
+
+
+void Render( const char* string)
+{   
+//     glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
+       bool a = g->isAlpha();
+       g->enableAlpha(true);    
+//     glEnable(GL_BLEND);
+       
+//     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
+
+       FTTextureGlyph::ResetActiveTexture();
+    
+       FTFont::Render( string);
+
+//     glPopAttrib();
+       g->enableAlpha(a);    
+}
+
+
+void Render( const wchar_t* string)
+{   
+//     glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
+    
+       //glEnable(GL_BLEND);
+       //glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
+       bool a = g->isAlpha();
+       g->enableAlpha(true);
+
+       FTTextureGlyph::ResetActiveTexture();
+    
+       FTFont::Render( string);
+       g->enableAlpha(a);
+//     glPopAttrib();
+}
+
+};
+
+
+
+myFont *f;
+Font *t;
+
+bool init(void)
+{
+       g = new Graphics(1024, 768); // bring me a 1024x768 resolution
+       g->createDisplay();
+       g->setBackground(COLOUR_RGBA(155, 155, 155, 255)); //green background
+       f = new myFont("Test.ttf");
+       f->FaceSize(16, 72);
+       f->CharMap(ft_encoding_unicode);
+       
+       t = new Font(g, "Test.ttf", 16);
+       return true;
+}
+
+
+bool renderFrame()
+{
+       g->beginScene();
+       
+       f->print("MPLA", 10,10, 200,200, COLOUR_RGBA(255,255,255,255));
+//     t->print("hello", 10,10, 200,200, COLOUR_RGBA(255,255,255,255));
+       g->endScene();
+       
+       sleep(4);
+       return false;   
+}
+
+bool cleanup()
+{
+       delete g;
+       return true;    
+}
+