mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-12 18:40:29 +00:00
(svn r25441) -Codechange: move the freetype font allocation into the FreeTypeFontCache
This commit is contained in:
parent
97a42f4b4f
commit
eb4388f4f3
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user