00001 #ifndef __FTCharToGlyphIndexMap__ 00002 #define __FTCharToGlyphIndexMap__ 00003 00004 #include <stdlib.h> 00005 00006 #include "FTGL.h" 00007 00008 /** 00009 * Provides a non-STL alternative to the STL map<unsigned long, unsigned long> 00010 * which maps character codes to glyph indices inside FTCharmap. 00011 * 00012 * Implementation: 00013 * - NumberOfBuckets buckets are considered. 00014 * - Each bucket has BucketSize entries. 00015 * - When the glyph index for the character code C has to be stored, the 00016 * bucket this character belongs to is found using 'C div BucketSize'. 00017 * If this bucket has not been allocated yet, do it now. 00018 * The entry in the bucked is found using 'C mod BucketSize'. 00019 * If it is set to IndexNotFound, then the glyph entry has not been set. 00020 * - Try to mimic the calls made to the STL map API. 00021 * 00022 * Caveats: 00023 * - The glyph index is now a signed long instead of unsigned long, so 00024 * the special value IndexNotFound (= -1) can be used to specify that the 00025 * glyph index has not been stored yet. 00026 */ 00027 class FTGL_EXPORT FTCharToGlyphIndexMap 00028 { 00029 public: 00030 00031 typedef unsigned long CharacterCode; 00032 typedef signed long GlyphIndex; 00033 00034 enum 00035 { 00036 NumberOfBuckets = 256, 00037 BucketSize = 256, 00038 IndexNotFound = -1 00039 }; 00040 00041 FTCharToGlyphIndexMap() 00042 { 00043 this->Indices = 0; 00044 } 00045 00046 virtual ~FTCharToGlyphIndexMap() 00047 { 00048 if( this->Indices) 00049 { 00050 // Free all buckets 00051 this->clear(); 00052 00053 // Free main structure 00054 delete [] this->Indices; 00055 this->Indices = 0; 00056 } 00057 } 00058 00059 void clear() 00060 { 00061 if(this->Indices) 00062 { 00063 for( int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++) 00064 { 00065 if( this->Indices[i]) 00066 { 00067 delete [] this->Indices[i]; 00068 this->Indices[i] = 0; 00069 } 00070 } 00071 } 00072 } 00073 00074 GlyphIndex find( CharacterCode c) 00075 { 00076 if( !this->Indices) 00077 { 00078 return 0; 00079 } 00080 00081 // Find position of char code in buckets 00082 div_t pos = div( c, FTCharToGlyphIndexMap::BucketSize); 00083 00084 if( !this->Indices[pos.quot]) 00085 { 00086 return 0; 00087 } 00088 00089 const FTCharToGlyphIndexMap::GlyphIndex *ptr = &this->Indices[pos.quot][pos.rem]; 00090 if( *ptr == FTCharToGlyphIndexMap::IndexNotFound) 00091 { 00092 return 0; 00093 } 00094 00095 return *ptr; 00096 } 00097 00098 void insert( CharacterCode c, GlyphIndex g) 00099 { 00100 if( !this->Indices) 00101 { 00102 this->Indices = new GlyphIndex* [FTCharToGlyphIndexMap::NumberOfBuckets]; 00103 for( int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++) 00104 { 00105 this->Indices[i] = 0; 00106 } 00107 } 00108 00109 // Find position of char code in buckets 00110 div_t pos = div(c, FTCharToGlyphIndexMap::BucketSize); 00111 00112 // Allocate bucket if does not exist yet 00113 if( !this->Indices[pos.quot]) 00114 { 00115 this->Indices[pos.quot] = new GlyphIndex [FTCharToGlyphIndexMap::BucketSize]; 00116 for( int i = 0; i < FTCharToGlyphIndexMap::BucketSize; i++) 00117 { 00118 this->Indices[pos.quot][i] = FTCharToGlyphIndexMap::IndexNotFound; 00119 } 00120 } 00121 00122 this->Indices[pos.quot][pos.rem] = g; 00123 } 00124 00125 private: 00126 GlyphIndex** Indices; 00127 }; 00128 00129 00130 #endif // __FTCharToGlyphIndexMap__