diff options
-rw-r--r-- | src/fontcache.cpp | 130 |
1 files changed, 49 insertions, 81 deletions
diff --git a/src/fontcache.cpp b/src/fontcache.cpp index ed621cfc1..ae5416dd8 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -140,8 +140,11 @@ bool SpriteFontCache::GetDrawGlyphShadow() /** Font cache for fonts that are based on a freetype font. */ class FreeTypeFontCache : public FontCache { +private: + FT_Face face; ///< The font face associated with this font. public: - FreeTypeFontCache(FontSize fs) : FontCache(fs) {} + FreeTypeFontCache(FontSize fs, FT_Face face, int pixels); + ~FreeTypeFontCache(); virtual SpriteID GetUnicodeGlyph(uint32 key) { return this->parent->GetUnicodeGlyph(key); } virtual void SetUnicodeGlyph(uint32 key, SpriteID sprite) { this->parent->SetUnicodeGlyph(key, sprite); } virtual void InitializeUnicodeGlyphMap() { this->parent->InitializeUnicodeGlyphMap(); } @@ -152,10 +155,6 @@ public: }; FT_Library _library = NULL; -static FT_Face _face_small = NULL; -static FT_Face _face_medium = NULL; -static FT_Face _face_large = NULL; -static FT_Face _face_mono = NULL; static int _ascender[FS_END]; FreeTypeSettings _freetype; @@ -163,40 +162,46 @@ FreeTypeSettings _freetype; static const byte FACE_COLOUR = 1; static const byte SHADOW_COLOUR = 2; -static void SetFontGeometry(FT_Face face, FontSize size, int pixels) +/** + * Create a new FreeTypeFontCache. + * @param fs The font size that is going to be cached. + * @param face The font that has to be loaded. + * @param pixels The number of pixels this font should be high. + */ +FreeTypeFontCache::FreeTypeFontCache(FontSize fs, FT_Face face, int pixels) : FontCache(fs), face(face) { if (pixels == 0) { /* Try to determine a good height based on the minimal height recommended by the font. */ - pixels = _default_font_height[size]; + pixels = _default_font_height[this->fs]; - TT_Header *head = (TT_Header *)FT_Get_Sfnt_Table(face, ft_sfnt_head); + TT_Header *head = (TT_Header *)FT_Get_Sfnt_Table(this->face, ft_sfnt_head); if (head != NULL) { /* Font height is minimum height plus the difference between the default * height for this font size and the small size. */ - int diff = _default_font_height[size] - _default_font_height[FS_SMALL]; - pixels = Clamp(min(head->Lowest_Rec_PPEM, 20) + diff, _default_font_height[size], MAX_FONT_SIZE); + int diff = _default_font_height[this->fs] - _default_font_height[FS_SMALL]; + pixels = Clamp(min(head->Lowest_Rec_PPEM, 20) + diff, _default_font_height[this->fs], MAX_FONT_SIZE); } } - FT_Error err = FT_Set_Pixel_Sizes(face, 0, pixels); + FT_Error err = FT_Set_Pixel_Sizes(this->face, 0, pixels); if (err == FT_Err_Invalid_Pixel_Size) { /* Find nearest size to that requested */ - FT_Bitmap_Size *bs = face->available_sizes; - int i = face->num_fixed_sizes; + FT_Bitmap_Size *bs = this->face->available_sizes; + int i = this->face->num_fixed_sizes; int n = bs->height; for (; --i; bs++) { if (abs(pixels - bs->height) < abs(pixels - n)) n = bs->height; } - FT_Set_Pixel_Sizes(face, 0, n); + FT_Set_Pixel_Sizes(this->face, 0, n); } - int asc = face->size->metrics.ascender >> 6; - int dec = face->size->metrics.descender >> 6; + int asc = this->face->size->metrics.ascender >> 6; + int dec = this->face->size->metrics.descender >> 6; - _ascender[size] = asc; - _font_height[size] = asc - dec; + _ascender[this->fs] = asc; + _font_height[this->fs] = asc - dec; } /** @@ -253,15 +258,11 @@ static void LoadFreeTypeFont(const char *font_name, FT_Face *face, const char *t static void ResetGlyphCache(bool monospace); /** - * Unload a face and set it to NULL. - * @param face the face to unload + * Unload the face */ -static void UnloadFace(FT_Face *face) +FreeTypeFontCache::~FreeTypeFontCache() { - if (*face == NULL) return; - - FT_Done_Face(*face); - *face = NULL; + if (this->face != NULL) FT_Done_Face(this->face); } /** @@ -273,14 +274,6 @@ void InitFreeType(bool monospace) ResetFontSizes(monospace); ResetGlyphCache(monospace); - if (monospace) { - UnloadFace(&_face_mono); - } else { - UnloadFace(&_face_small); - UnloadFace(&_face_medium); - UnloadFace(&_face_large); - } - if (StrEmpty(_freetype.small.font) && StrEmpty(_freetype.medium.font) && StrEmpty(_freetype.large.font) && StrEmpty(_freetype.mono.font)) { DEBUG(freetype, 1, "No font faces specified, using sprite fonts instead"); return; @@ -297,30 +290,23 @@ void InitFreeType(bool monospace) /* Load each font */ if (monospace) { - LoadFreeTypeFont(_freetype.mono.font , &_face_mono, "mono"); + FT_Face mono = NULL; + LoadFreeTypeFont(_freetype.mono.font , &mono, "mono"); - if (_face_mono != NULL) { - new FreeTypeFontCache(FS_MONO); - SetFontGeometry(_face_mono, FS_MONO, _freetype.mono.size); - } + if (mono != NULL) new FreeTypeFontCache(FS_MONO, mono, _freetype.mono.size); } else { - LoadFreeTypeFont(_freetype.small.font, &_face_small, "small"); - LoadFreeTypeFont(_freetype.medium.font, &_face_medium, "medium"); - LoadFreeTypeFont(_freetype.large.font, &_face_large, "large"); + FT_Face small = NULL; + FT_Face medium = NULL; + FT_Face large = NULL; + + LoadFreeTypeFont(_freetype.small.font, &small, "small"); + LoadFreeTypeFont(_freetype.medium.font, &medium, "medium"); + LoadFreeTypeFont(_freetype.large.font, &large, "large"); /* Set each font size */ - if (_face_small != NULL) { - new FreeTypeFontCache(FS_SMALL); - SetFontGeometry(_face_small, FS_SMALL, _freetype.small.size); - } - if (_face_medium != NULL) { - new FreeTypeFontCache(FS_NORMAL); - SetFontGeometry(_face_medium, FS_NORMAL, _freetype.medium.size); - } - if (_face_large != NULL) { - new FreeTypeFontCache(FS_LARGE); - SetFontGeometry(_face_large, FS_LARGE, _freetype.large.size); - } + if (small != NULL) new FreeTypeFontCache(FS_SMALL, small, _freetype.small.size); + if (medium != NULL) new FreeTypeFontCache(FS_NORMAL, medium, _freetype.medium.size); + if (large != NULL) new FreeTypeFontCache(FS_LARGE, large, _freetype.large.size); } } @@ -329,13 +315,9 @@ void InitFreeType(bool monospace) */ void UninitFreeType() { - ResetGlyphCache(true); - ResetGlyphCache(false); - - UnloadFace(&_face_small); - UnloadFace(&_face_medium); - UnloadFace(&_face_large); - UnloadFace(&_face_mono); + ResetFontSizes(true); + ResetFontSizes(false); + ClearFontCache(); for (FontSize fs = FS_BEGIN; fs < FS_END; fs++) { FontCache *fc = FontCache::Get(fs); @@ -355,18 +337,6 @@ void FreeTypeFontCache::ClearFontCache() ResetGlyphCache(false); } -static FT_Face GetFontFace(FontSize size) -{ - switch (size) { - default: NOT_REACHED(); - case FS_NORMAL: return _face_medium; - case FS_SMALL: return _face_small; - case FS_LARGE: return _face_large; - case FS_MONO: return _face_mono; - } -} - - struct GlyphEntry { Sprite *sprite; byte width; @@ -464,7 +434,6 @@ static bool GetFontAAState(FontSize size) const Sprite *FreeTypeFontCache::GetGlyph(WChar key) { - FT_Face face = GetFontFace(this->fs); FT_GlyphSlot slot; GlyphEntry new_glyph; GlyphEntry *glyph; @@ -477,7 +446,7 @@ const Sprite *FreeTypeFontCache::GetGlyph(WChar key) assert(IsPrintable(key)); /* Bail out if no face loaded, or for our special characters */ - if (face == NULL || (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END)) { + if (this->face == NULL || (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END)) { SpriteID sprite = this->GetUnicodeGlyph(key); if (sprite == 0) sprite = this->GetUnicodeGlyph('?'); @@ -485,7 +454,7 @@ const Sprite *FreeTypeFontCache::GetGlyph(WChar key) if (sprite != 0) return GetSprite(sprite, ST_FONT); /* For the 'rare' case there is no font available at all. */ - if (face == NULL) error("No sprite font and no real font either... bailing!"); + if (this->face == NULL) error("No sprite font and no real font either... bailing!"); /* Use the '?' from the freetype font. */ key = '?'; @@ -495,11 +464,11 @@ const Sprite *FreeTypeFontCache::GetGlyph(WChar key) glyph = GetGlyphPtr(this->fs, key); if (glyph != NULL && glyph->sprite != NULL) return glyph->sprite; - slot = face->glyph; + slot = this->face->glyph; bool aa = GetFontAAState(this->fs); - FT_UInt glyph_index = FT_Get_Char_Index(face, key); + FT_UInt glyph_index = FT_Get_Char_Index(this->face, key); if (glyph_index == 0) { if (key == '?') { /* The font misses the '?' character. Use sprite font. */ @@ -518,8 +487,8 @@ const Sprite *FreeTypeFontCache::GetGlyph(WChar key) return glyph->sprite; } } - FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); - FT_Render_Glyph(face->glyph, aa ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); + FT_Load_Glyph(this->face, glyph_index, FT_LOAD_DEFAULT); + FT_Render_Glyph(this->face->glyph, aa ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); /* Despite requesting a normal glyph, FreeType may have returned a bitmap */ aa = (slot->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY); @@ -577,10 +546,9 @@ bool FreeTypeFontCache::GetDrawGlyphShadow() uint FreeTypeFontCache::GetGlyphWidth(WChar key) { - FT_Face face = GetFontFace(this->fs); GlyphEntry *glyph; - if (face == NULL || (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END)) { + if (this->face == NULL || (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END)) { SpriteID sprite = this->GetUnicodeGlyph(key); if (sprite == 0) sprite = this->GetUnicodeGlyph('?'); return SpriteExists(sprite) ? GetSprite(sprite, ST_FONT)->width + (this->fs != FS_NORMAL && this->fs != FS_MONO) : 0; |