34 static const int _default_font_ascender[FS_END] = { 8, 5, 15,  8};
 
   41     ascender(_default_font_ascender[fs]), descender(_default_font_ascender[fs] - 
_default_font_height[fs]),
 
   87   virtual const void *
GetFontTable(uint32 tag, 
size_t &length) { length = 0; 
return NULL; }
 
  128     default: NOT_REACHED();
 
  130     case FS_NORMAL: base = SPR_ASCII_SPACE;       
break;
 
  131     case FS_SMALL:  base = SPR_ASCII_SPACE_SMALL; 
break;
 
  132     case FS_LARGE:  base = SPR_ASCII_SPACE_BIG;   
break;
 
  137     if (!SpriteExists(sprite)) 
continue;
 
  142   for (uint i = 0; i < 
lengthof(_default_unicode_map); i++) {
 
  143     byte key = _default_unicode_map[i].key;
 
  163   for (uint i = 0; i < 256; i++) {
 
  179   return GetSprite(sprite, 
ST_FONT);
 
  202 #include <ft2build.h> 
  203 #include FT_FREETYPE_H 
  205 #include FT_TRUETYPE_TABLES_H 
  251   virtual const void *
GetFontTable(uint32 tag, 
size_t &length);
 
  255 FT_Library _library = NULL;
 
  259 static const byte FACE_COLOUR   = 1;
 
  260 static const byte SHADOW_COLOUR = 2;
 
  270   assert(face != NULL);
 
  276     TT_Header *head = (TT_Header *)FT_Get_Sfnt_Table(this->face, ft_sfnt_head);
 
  281       pixels = 
Clamp(
min(head->Lowest_Rec_PPEM, 20) + diff, _default_font_height[this->fs], 
MAX_FONT_SIZE);
 
  285   FT_Error err = FT_Set_Pixel_Sizes(this->face, 0, pixels);
 
  286   if (err != FT_Err_Ok) {
 
  289     FT_Bitmap_Size *bs = this->face->available_sizes;
 
  290     int i = this->face->num_fixed_sizes;
 
  295         if (
abs(pixels - bs->height) >= 
abs(pixels - n)) 
continue;
 
  297         chosen = this->face->num_fixed_sizes - i;
 
  302       err = FT_Select_Size(this->face, chosen);
 
  306   if (err == FT_Err_Ok) {
 
  308     this->
ascender     = this->face->size->metrics.ascender >> 6;
 
  309     this->
descender    = this->face->size->metrics.descender >> 6;
 
  313     DEBUG(freetype, 0, 
"Font size selection failed. Using FontCache defaults.");
 
  328     default: NOT_REACHED();
 
  337   if (_library == NULL) {
 
  338     if (FT_Init_FreeType(&_library) != FT_Err_Ok) {
 
  339       ShowInfoF(
"Unable to initialize FreeType, using sprite fonts instead");
 
  343     DEBUG(freetype, 2, 
"Initialized");
 
  347   FT_Error 
error = FT_New_Face(_library, settings->
font, 0, &face);
 
  351   if (error == FT_Err_Ok) {
 
  352     DEBUG(freetype, 2, 
"Requested '%s', using '%s %s'", settings->
font, face->family_name, face->style_name);
 
  355     error = FT_Select_Charmap(face, ft_encoding_unicode);
 
  356     if (error == FT_Err_Ok) 
goto found_face; 
 
  358     if (error == FT_Err_Invalid_CharMap_Handle) {
 
  362       FT_CharMap found = face->charmaps[0];
 
  365       for (i = 0; i < face->num_charmaps; i++) {
 
  366         FT_CharMap charmap = face->charmaps[i];
 
  367         if (charmap->platform_id == 0 && charmap->encoding_id == 0) {
 
  373         error = FT_Set_Charmap(face, found);
 
  374         if (error == FT_Err_Ok) 
goto found_face;
 
  381   static const char *SIZE_TO_NAME[] = { 
"medium", 
"small", 
"large", 
"mono" };
 
  382   ShowInfoF(
"Unable to use '%s' for %s font, FreeType reported error 0x%X, using sprite font instead", settings->
font, SIZE_TO_NAME[fs], error);
 
  395   FT_Done_Face(this->
face);
 
  399     free(iter->second.second);
 
  410   for (
int i = 0; i < 256; i++) {
 
  413     for (
int j = 0; j < 256; j++) {
 
  435 void FreeTypeFontCache::SetGlyphPtr(
GlyphID key, 
const GlyphEntry *glyph, 
bool duplicate)
 
  438     DEBUG(freetype, 3, 
"Allocating root glyph cache for size %u", this->
fs);
 
  443     DEBUG(freetype, 3, 
"Allocating glyph cache for range 0x%02X00, size %u", 
GB(key, 8, 8), this->
fs);
 
  447   DEBUG(freetype, 4, 
"Set glyph for unicode character 0x%04X, size %u", key, this->
fs);
 
  453 static void *AllocateFont(
size_t size)
 
  455   return MallocT<byte>(size);
 
  460 static bool GetFontAAState(
FontSize size)
 
  466     default: NOT_REACHED();
 
  481   if (glyph != NULL && glyph->
sprite != NULL) 
return glyph->
sprite;
 
  483   FT_GlyphSlot slot = this->
face->glyph;
 
  485   bool aa = GetFontAAState(this->
fs);
 
  490     if (question_glyph == 0) {
 
  493 #define CPSET { 0, 0, 0, 0, 1 } 
  494 #define CP___ { 0, 0, 0, 0, 0 } 
  496         CP___, CP___, CPSET, CPSET, CPSET, CPSET, CP___, CP___,
 
  497         CP___, CPSET, CPSET, CP___, CP___, CPSET, CPSET, CP___,
 
  498         CP___, CP___, CP___, CP___, CP___, CPSET, CPSET, CP___,
 
  499         CP___, CP___, CP___, CP___, CPSET, CPSET, CP___, CP___,
 
  500         CP___, CP___, CP___, CPSET, CPSET, CP___, CP___, CP___,
 
  501         CP___, CP___, CP___, CPSET, CPSET, CP___, CP___, CP___,
 
  502         CP___, CP___, CP___, CPSET, CPSET, CP___, CP___, CP___,
 
  503         CP___, CP___, CP___, CP___, CP___, CP___, CP___, CP___,
 
  504         CP___, CP___, CP___, CPSET, CPSET, CP___, CP___, CP___,
 
  505         CP___, CP___, CP___, CPSET, CPSET, CP___, CP___, CP___,
 
  515         builtin_questionmark_data
 
  522       this->SetGlyphPtr(key, &new_glyph, 
false);
 
  527       glyph = this->GetGlyphPtr(question_glyph);
 
  528       this->SetGlyphPtr(key, glyph, 
true);
 
  532   FT_Load_Glyph(this->
face, key, FT_LOAD_DEFAULT);
 
  533   FT_Render_Glyph(this->
face->glyph, aa ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
 
  536   aa = (slot->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);
 
  539   uint width  = 
max(1U, (uint)slot->bitmap.width + (this->fs == 
FS_NORMAL));
 
  543   if (width > 256 || height > 256) 
usererror(
"Font glyph is too large");
 
  549   sprite.
width = width;
 
  551   sprite.
x_offs = slot->bitmap_left;
 
  556     for (uint y = 0; y < (uint)slot->bitmap.rows; y++) {
 
  557       for (uint x = 0; x < (uint)slot->bitmap.width; x++) {
 
  558         if (aa ? (slot->bitmap.buffer[x + y * slot->bitmap.pitch] > 0) : 
HasBit(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
 
  559           sprite.
data[1 + x + (1 + y) * sprite.
width].
m = SHADOW_COLOUR;
 
  560           sprite.
data[1 + x + (1 + y) * sprite.
width].
a = aa ? slot->bitmap.buffer[x + y * slot->bitmap.pitch] : 0xFF;
 
  566   for (uint y = 0; y < (uint)slot->bitmap.rows; y++) {
 
  567     for (uint x = 0; x < (uint)slot->bitmap.width; x++) {
 
  568       if (aa ? (slot->bitmap.buffer[x + y * slot->bitmap.pitch] > 0) : 
HasBit(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
 
  569         sprite.
data[x + y * sprite.
width].
m = FACE_COLOUR;
 
  570         sprite.
data[x + y * sprite.
width].
a = aa ? slot->bitmap.buffer[x + y * slot->bitmap.pitch] : 0xFF;
 
  576   new_glyph.
width  = slot->advance.x >> 6;
 
  578   this->SetGlyphPtr(key, &new_glyph);
 
  595   if (glyph == NULL || glyph->
sprite == NULL) {
 
  597     glyph = this->GetGlyphPtr(key);
 
  605   assert(IsPrintable(key));
 
  607   if (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) {
 
  611   return FT_Get_Char_Index(this->
face, key);
 
  618     length = iter->second.first;
 
  619     return iter->second.second;
 
  623   FT_Byte *result = NULL;
 
  625   FT_Load_Sfnt_Table(this->
face, tag, 0, NULL, &len);
 
  628     result = MallocT<FT_Byte>(len);
 
  629     FT_Load_Sfnt_Table(this->
face, tag, 0, result, &len);
 
  646     if (monospace != (fs == 
FS_MONO)) 
continue;
 
  668   FT_Done_FreeType(_library);