4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
10 /** @file fontcache.cpp Cache for characters from fonts. */
13 #include "fontcache.h"
14 #include "fontdetection.h"
15 #include "blitter/factory.hpp"
16 #include "core/math_func.hpp"
17 #include "core/smallmap_type.hpp"
18 #include "strings_func.h"
19 #include "zoom_type.h"
20 #include "gfx_layout.h"
21 #include "zoom_func.h"
23 #include "table/sprites.h"
24 #include "table/control_codes.h"
25 #include "table/unicode.h"
27 #include "safeguards.h"
29 static const int ASCII_LETTERSTART
= 32; ///< First printable ASCII letter.
30 static const int MAX_FONT_SIZE
= 72; ///< Maximum font size.
32 /** Default heights for the different sizes of fonts. */
33 static const int _default_font_height
[FS_END
] = {10, 6, 18, 10};
34 static const int _default_font_ascender
[FS_END
] = { 8, 5, 15, 8};
37 * Create a new font cache.
38 * @param fs The size of the font.
40 FontCache::FontCache(FontSize fs
) : parent(FontCache::Get(fs
)), fs(fs
), height(_default_font_height
[fs
]),
41 ascender(_default_font_ascender
[fs
]), descender(_default_font_ascender
[fs
] - _default_font_height
[fs
]),
44 assert(this->parent
== NULL
|| this->fs
== this->parent
->fs
);
45 FontCache::caches
[this->fs
] = this;
46 Layouter::ResetFontCache(this->fs
);
49 /** Clean everything up. */
50 FontCache::~FontCache()
52 assert(this->fs
== this->parent
->fs
);
53 FontCache::caches
[this->fs
] = this->parent
;
54 Layouter::ResetFontCache(this->fs
);
59 * Get height of a character for a given font size.
60 * @param size Font size to get height of
61 * @return Height of characters in the given font (pixels)
63 int GetCharacterHeight(FontSize size
)
65 return FontCache::Get(size
)->GetHeight();
69 /** Font cache for fonts that are based on a freetype font. */
70 class SpriteFontCache
: public FontCache
{
72 SpriteID
**glyph_to_spriteid_map
; ///< Mapping of glyphs to sprite IDs.
74 void ClearGlyphToSpriteMap();
76 SpriteFontCache(FontSize fs
);
78 virtual SpriteID
GetUnicodeGlyph(WChar key
);
79 virtual void SetUnicodeGlyph(WChar key
, SpriteID sprite
);
80 virtual void InitializeUnicodeGlyphMap();
81 virtual void ClearFontCache();
82 virtual const Sprite
*GetGlyph(GlyphID key
);
83 virtual uint
GetGlyphWidth(GlyphID key
);
84 virtual int GetHeight() const;
85 virtual bool GetDrawGlyphShadow();
86 virtual GlyphID
MapCharToGlyph(WChar key
) { assert(IsPrintable(key
)); return SPRITE_GLYPH
| key
; }
87 virtual const void *GetFontTable(uint32 tag
, size_t &length
) { length
= 0; return NULL
; }
88 virtual const char *GetFontName() { return "sprite"; }
92 * Create a new sprite font cache.
93 * @param fs The font size to create the cache for.
95 SpriteFontCache::SpriteFontCache(FontSize fs
) : FontCache(fs
), glyph_to_spriteid_map(NULL
)
97 this->InitializeUnicodeGlyphMap();
101 * Free everything we allocated.
103 SpriteFontCache::~SpriteFontCache()
105 this->ClearGlyphToSpriteMap();
108 SpriteID
SpriteFontCache::GetUnicodeGlyph(GlyphID key
)
110 if (this->glyph_to_spriteid_map
[GB(key
, 8, 8)] == NULL
) return 0;
111 return this->glyph_to_spriteid_map
[GB(key
, 8, 8)][GB(key
, 0, 8)];
114 void SpriteFontCache::SetUnicodeGlyph(GlyphID key
, SpriteID sprite
)
116 if (this->glyph_to_spriteid_map
== NULL
) this->glyph_to_spriteid_map
= CallocT
<SpriteID
*>(256);
117 if (this->glyph_to_spriteid_map
[GB(key
, 8, 8)] == NULL
) this->glyph_to_spriteid_map
[GB(key
, 8, 8)] = CallocT
<SpriteID
>(256);
118 this->glyph_to_spriteid_map
[GB(key
, 8, 8)][GB(key
, 0, 8)] = sprite
;
121 void SpriteFontCache::InitializeUnicodeGlyphMap()
123 /* Clear out existing glyph map if it exists */
124 this->ClearGlyphToSpriteMap();
128 default: NOT_REACHED();
129 case FS_MONO
: // Use normal as default for mono spaced font
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;
135 for (uint i
= ASCII_LETTERSTART
; i
< 256; i
++) {
136 SpriteID sprite
= base
+ i
- ASCII_LETTERSTART
;
137 if (!SpriteExists(sprite
)) continue;
138 this->SetUnicodeGlyph(i
, sprite
);
139 this->SetUnicodeGlyph(i
+ SCC_SPRITE_START
, sprite
);
142 for (uint i
= 0; i
< lengthof(_default_unicode_map
); i
++) {
143 byte key
= _default_unicode_map
[i
].key
;
145 /* Clear the glyph. This happens if the glyph at this code point
146 * is non-standard and should be accessed by an SCC_xxx enum
148 this->SetUnicodeGlyph(_default_unicode_map
[i
].code
, 0);
150 SpriteID sprite
= base
+ key
- ASCII_LETTERSTART
;
151 this->SetUnicodeGlyph(_default_unicode_map
[i
].code
, sprite
);
157 * Clear the glyph to sprite mapping.
159 void SpriteFontCache::ClearGlyphToSpriteMap()
161 if (this->glyph_to_spriteid_map
== NULL
) return;
163 for (uint i
= 0; i
< 256; i
++) {
164 free(this->glyph_to_spriteid_map
[i
]);
166 free(this->glyph_to_spriteid_map
);
167 this->glyph_to_spriteid_map
= NULL
;
170 void SpriteFontCache::ClearFontCache()
172 Layouter::ResetFontCache(this->fs
);
175 const Sprite
*SpriteFontCache::GetGlyph(GlyphID key
)
177 SpriteID sprite
= this->GetUnicodeGlyph(key
);
178 if (sprite
== 0) sprite
= this->GetUnicodeGlyph('?');
179 return GetSprite(sprite
, ST_FONT
);
182 uint
SpriteFontCache::GetGlyphWidth(GlyphID key
)
184 SpriteID sprite
= this->GetUnicodeGlyph(key
);
185 if (sprite
== 0) sprite
= this->GetUnicodeGlyph('?');
186 return SpriteExists(sprite
) ? GetSprite(sprite
, ST_FONT
)->width
+ ScaleGUITrad(this->fs
!= FS_NORMAL
? 1 : 0) : 0;
189 int SpriteFontCache::GetHeight() const
191 return ScaleGUITrad(this->height
);
194 bool SpriteFontCache::GetDrawGlyphShadow()
199 /* static */ FontCache
*FontCache::caches
[FS_END
] = { new SpriteFontCache(FS_NORMAL
), new SpriteFontCache(FS_SMALL
), new SpriteFontCache(FS_LARGE
), new SpriteFontCache(FS_MONO
) };
202 #include <ft2build.h>
203 #include FT_FREETYPE_H
205 #include FT_TRUETYPE_TABLES_H
207 /** Font cache for fonts that are based on a freetype font. */
208 class FreeTypeFontCache
: public FontCache
{
210 FT_Face face
; ///< The font face associated with this font.
212 typedef SmallMap
<uint32
, SmallPair
<size_t, const void*> > FontTable
; ///< Table with font table cache
213 FontTable font_tables
; ///< Cached font tables.
215 /** Container for information about a glyph. */
217 Sprite
*sprite
; ///< The loaded sprite.
218 byte width
; ///< The width of the glyph.
219 bool duplicate
; ///< Whether this glyph entry is a duplicate, i.e. may this be freed?
223 * The glyph cache. This is structured to reduce memory consumption.
224 * 1) There is a 'segment' table for each font size.
225 * 2) Each segment table is a discrete block of characters.
226 * 3) Each block contains 256 (aligned) characters sequential characters.
228 * The cache is accessed in the following way:
229 * For character 0x0041 ('A'): glyph_to_sprite[0x00][0x41]
230 * For character 0x20AC (Euro): glyph_to_sprite[0x20][0xAC]
232 * Currently only 256 segments are allocated, "limiting" us to 65536 characters.
233 * This can be simply changed in the two functions Get & SetGlyphPtr.
235 GlyphEntry
**glyph_to_sprite
;
237 GlyphEntry
*GetGlyphPtr(GlyphID key
);
238 void SetGlyphPtr(GlyphID key
, const GlyphEntry
*glyph
, bool duplicate
= false);
241 FreeTypeFontCache(FontSize fs
, FT_Face face
, int pixels
);
242 ~FreeTypeFontCache();
243 virtual SpriteID
GetUnicodeGlyph(WChar key
) { return this->parent
->GetUnicodeGlyph(key
); }
244 virtual void SetUnicodeGlyph(WChar key
, SpriteID sprite
) { this->parent
->SetUnicodeGlyph(key
, sprite
); }
245 virtual void InitializeUnicodeGlyphMap() { this->parent
->InitializeUnicodeGlyphMap(); }
246 virtual void ClearFontCache();
247 virtual const Sprite
*GetGlyph(GlyphID key
);
248 virtual uint
GetGlyphWidth(GlyphID key
);
249 virtual bool GetDrawGlyphShadow();
250 virtual GlyphID
MapCharToGlyph(WChar key
);
251 virtual const void *GetFontTable(uint32 tag
, size_t &length
);
252 virtual const char *GetFontName() { return face
->family_name
; }
255 FT_Library _library
= NULL
;
257 FreeTypeSettings _freetype
;
259 static const byte FACE_COLOUR
= 1;
260 static const byte SHADOW_COLOUR
= 2;
263 * Create a new FreeTypeFontCache.
264 * @param fs The font size that is going to be cached.
265 * @param face The font that has to be loaded.
266 * @param pixels The number of pixels this font should be high.
268 FreeTypeFontCache::FreeTypeFontCache(FontSize fs
, FT_Face face
, int pixels
) : FontCache(fs
), face(face
), glyph_to_sprite(NULL
)
270 assert(face
!= NULL
);
273 /* Try to determine a good height based on the minimal height recommended by the font. */
274 pixels
= _default_font_height
[this->fs
];
276 TT_Header
*head
= (TT_Header
*)FT_Get_Sfnt_Table(this->face
, ft_sfnt_head
);
278 /* Font height is minimum height plus the difference between the default
279 * height for this font size and the small size. */
280 int diff
= _default_font_height
[this->fs
] - _default_font_height
[FS_SMALL
];
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
) {
288 /* Find nearest size to that requested */
289 FT_Bitmap_Size
*bs
= this->face
->available_sizes
;
290 int i
= this->face
->num_fixed_sizes
;
291 if (i
> 0) { // In pathetic cases one might get no fixed sizes at all.
295 if (abs(pixels
- bs
->height
) >= abs(pixels
- n
)) continue;
297 chosen
= this->face
->num_fixed_sizes
- i
;
300 /* Don't use FT_Set_Pixel_Sizes here - it might give us another
301 * error, even though the size is available (FS#5885). */
302 err
= FT_Select_Size(this->face
, chosen
);
306 if (err
== FT_Err_Ok
) {
307 this->units_per_em
= this->face
->units_per_EM
;
308 this->ascender
= this->face
->size
->metrics
.ascender
>> 6;
309 this->descender
= this->face
->size
->metrics
.descender
>> 6;
310 this->height
= this->ascender
- this->descender
;
312 /* Both FT_Set_Pixel_Sizes and FT_Select_Size failed. */
313 DEBUG(freetype
, 0, "Font size selection failed. Using FontCache defaults.");
318 * Loads the freetype font.
319 * First type to load the fontname as if it were a path. If that fails,
320 * try to resolve the filename of the font using fontconfig, where the
321 * format is 'font family name' or 'font family name, font style'.
322 * @param fs The font size to load.
324 static void LoadFreeTypeFont(FontSize fs
)
326 FreeTypeSubSetting
*settings
= NULL
;
328 default: NOT_REACHED();
329 case FS_SMALL
: settings
= &_freetype
.small
; break;
330 case FS_NORMAL
: settings
= &_freetype
.medium
; break;
331 case FS_LARGE
: settings
= &_freetype
.large
; break;
332 case FS_MONO
: settings
= &_freetype
.mono
; break;
335 if (StrEmpty(settings
->font
)) return;
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
);
349 if (error
!= FT_Err_Ok
) error
= GetFontByFaceName(settings
->font
, &face
);
351 if (error
== FT_Err_Ok
) {
352 DEBUG(freetype
, 2, "Requested '%s', using '%s %s'", settings
->font
, face
->family_name
, face
->style_name
);
354 /* Attempt to select the unicode character map */
355 error
= FT_Select_Charmap(face
, ft_encoding_unicode
);
356 if (error
== FT_Err_Ok
) goto found_face
; // Success
358 if (error
== FT_Err_Invalid_CharMap_Handle
) {
359 /* Try to pick a different character map instead. We default to
360 * the first map, but platform_id 0 encoding_id 0 should also
361 * be unicode (strange system...) */
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
);
386 new FreeTypeFontCache(fs
, face
, settings
->size
);
391 * Free everything that was allocated for this font cache.
393 FreeTypeFontCache::~FreeTypeFontCache()
395 FT_Done_Face(this->face
);
396 this->ClearFontCache();
398 for (FontTable::iterator iter
= this->font_tables
.Begin(); iter
!= this->font_tables
.End(); iter
++) {
399 free(iter
->second
.second
);
404 * Reset cached glyphs.
406 void FreeTypeFontCache::ClearFontCache()
408 if (this->glyph_to_sprite
== NULL
) return;
410 for (int i
= 0; i
< 256; i
++) {
411 if (this->glyph_to_sprite
[i
] == NULL
) continue;
413 for (int j
= 0; j
< 256; j
++) {
414 if (this->glyph_to_sprite
[i
][j
].duplicate
) continue;
415 free(this->glyph_to_sprite
[i
][j
].sprite
);
418 free(this->glyph_to_sprite
[i
]);
421 free(this->glyph_to_sprite
);
422 this->glyph_to_sprite
= NULL
;
424 Layouter::ResetFontCache(this->fs
);
427 FreeTypeFontCache::GlyphEntry
*FreeTypeFontCache::GetGlyphPtr(GlyphID key
)
429 if (this->glyph_to_sprite
== NULL
) return NULL
;
430 if (this->glyph_to_sprite
[GB(key
, 8, 8)] == NULL
) return NULL
;
431 return &this->glyph_to_sprite
[GB(key
, 8, 8)][GB(key
, 0, 8)];
435 void FreeTypeFontCache::SetGlyphPtr(GlyphID key
, const GlyphEntry
*glyph
, bool duplicate
)
437 if (this->glyph_to_sprite
== NULL
) {
438 DEBUG(freetype
, 3, "Allocating root glyph cache for size %u", this->fs
);
439 this->glyph_to_sprite
= CallocT
<GlyphEntry
*>(256);
442 if (this->glyph_to_sprite
[GB(key
, 8, 8)] == NULL
) {
443 DEBUG(freetype
, 3, "Allocating glyph cache for range 0x%02X00, size %u", GB(key
, 8, 8), this->fs
);
444 this->glyph_to_sprite
[GB(key
, 8, 8)] = CallocT
<GlyphEntry
>(256);
447 DEBUG(freetype
, 4, "Set glyph for unicode character 0x%04X, size %u", key
, this->fs
);
448 this->glyph_to_sprite
[GB(key
, 8, 8)][GB(key
, 0, 8)].sprite
= glyph
->sprite
;
449 this->glyph_to_sprite
[GB(key
, 8, 8)][GB(key
, 0, 8)].width
= glyph
->width
;
450 this->glyph_to_sprite
[GB(key
, 8, 8)][GB(key
, 0, 8)].duplicate
= duplicate
;
453 static void *AllocateFont(size_t size
)
455 return MallocT
<byte
>(size
);
459 /* Check if a glyph should be rendered with antialiasing */
460 static bool GetFontAAState(FontSize size
)
462 /* AA is only supported for 32 bpp */
463 if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 32) return false;
466 default: NOT_REACHED();
467 case FS_NORMAL
: return _freetype
.medium
.aa
;
468 case FS_SMALL
: return _freetype
.small
.aa
;
469 case FS_LARGE
: return _freetype
.large
.aa
;
470 case FS_MONO
: return _freetype
.mono
.aa
;
475 const Sprite
*FreeTypeFontCache::GetGlyph(GlyphID key
)
477 if ((key
& SPRITE_GLYPH
) != 0) return this->parent
->GetGlyph(key
);
479 /* Check for the glyph in our cache */
480 GlyphEntry
*glyph
= this->GetGlyphPtr(key
);
481 if (glyph
!= NULL
&& glyph
->sprite
!= NULL
) return glyph
->sprite
;
483 FT_GlyphSlot slot
= this->face
->glyph
;
485 bool aa
= GetFontAAState(this->fs
);
487 GlyphEntry new_glyph
;
489 GlyphID question_glyph
= this->MapCharToGlyph('?');
490 if (question_glyph
== 0) {
491 /* The font misses the '?' character. Use built-in sprite.
492 * Note: We cannot use the baseset as this also has to work in the bootstrap GUI. */
493 #define CPSET { 0, 0, 0, 0, 1 }
494 #define CP___ { 0, 0, 0, 0, 0 }
495 static SpriteLoader::CommonPixel builtin_questionmark_data
[10 * 8] = {
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___
,
509 static const SpriteLoader::Sprite builtin_questionmark
= {
515 builtin_questionmark_data
518 Sprite
*spr
= BlitterFactory::GetCurrentBlitter()->Encode(&builtin_questionmark
, AllocateFont
);
520 new_glyph
.sprite
= spr
;
521 new_glyph
.width
= spr
->width
+ (this->fs
!= FS_NORMAL
);
522 this->SetGlyphPtr(key
, &new_glyph
, false);
523 return new_glyph
.sprite
;
525 /* Use '?' for missing characters. */
526 this->GetGlyph(question_glyph
);
527 glyph
= this->GetGlyphPtr(question_glyph
);
528 this->SetGlyphPtr(key
, glyph
, true);
529 return glyph
->sprite
;
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
);
535 /* Despite requesting a normal glyph, FreeType may have returned a bitmap */
536 aa
= (slot
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
);
538 /* Add 1 pixel for the shadow on the medium font. Our sprite must be at least 1x1 pixel */
539 uint width
= max(1U, (uint
)slot
->bitmap
.width
+ (this->fs
== FS_NORMAL
));
540 uint height
= max(1U, (uint
)slot
->bitmap
.rows
+ (this->fs
== FS_NORMAL
));
542 /* Limit glyph size to prevent overflows later on. */
543 if (width
> 256 || height
> 256) usererror("Font glyph is too large");
545 /* FreeType has rendered the glyph, now we allocate a sprite and copy the image into it */
546 SpriteLoader::Sprite sprite
;
547 sprite
.AllocateData(ZOOM_LVL_NORMAL
, width
* height
);
548 sprite
.type
= ST_FONT
;
549 sprite
.width
= width
;
550 sprite
.height
= height
;
551 sprite
.x_offs
= slot
->bitmap_left
;
552 sprite
.y_offs
= this->ascender
- slot
->bitmap_top
;
554 /* Draw shadow for medium size */
555 if (this->fs
== FS_NORMAL
&& !aa
) {
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;
575 new_glyph
.sprite
= BlitterFactory::GetCurrentBlitter()->Encode(&sprite
, AllocateFont
);
576 new_glyph
.width
= slot
->advance
.x
>> 6;
578 this->SetGlyphPtr(key
, &new_glyph
);
580 return new_glyph
.sprite
;
584 bool FreeTypeFontCache::GetDrawGlyphShadow()
586 return this->fs
== FS_NORMAL
&& GetFontAAState(FS_NORMAL
);
590 uint
FreeTypeFontCache::GetGlyphWidth(GlyphID key
)
592 if ((key
& SPRITE_GLYPH
) != 0) return this->parent
->GetGlyphWidth(key
);
594 GlyphEntry
*glyph
= this->GetGlyphPtr(key
);
595 if (glyph
== NULL
|| glyph
->sprite
== NULL
) {
597 glyph
= this->GetGlyphPtr(key
);
603 GlyphID
FreeTypeFontCache::MapCharToGlyph(WChar key
)
605 assert(IsPrintable(key
));
607 if (key
>= SCC_SPRITE_START
&& key
<= SCC_SPRITE_END
) {
608 return this->parent
->MapCharToGlyph(key
);
611 return FT_Get_Char_Index(this->face
, key
);
614 const void *FreeTypeFontCache::GetFontTable(uint32 tag
, size_t &length
)
616 const FontTable::iterator iter
= this->font_tables
.Find(tag
);
617 if (iter
!= this->font_tables
.End()) {
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
);
633 this->font_tables
.Insert(tag
, SmallPair
<size_t, const void *>(length
, result
));
637 #endif /* WITH_FREETYPE */
640 * (Re)initialize the freetype related things, i.e. load the non-sprite fonts.
641 * @param monospace Whether to initialise the monospace or regular fonts.
643 void InitFreeType(bool monospace
)
645 for (FontSize fs
= FS_BEGIN
; fs
< FS_END
; fs
++) {
646 if (monospace
!= (fs
== FS_MONO
)) continue;
648 FontCache
*fc
= FontCache::Get(fs
);
649 if (fc
->HasParent()) delete fc
;
652 LoadFreeTypeFont(fs
);
658 * Free everything allocated w.r.t. fonts.
660 void UninitFreeType()
662 for (FontSize fs
= FS_BEGIN
; fs
< FS_END
; fs
++) {
663 FontCache
*fc
= FontCache::Get(fs
);
664 if (fc
->HasParent()) delete fc
;
668 FT_Done_FreeType(_library
);
670 #endif /* WITH_FREETYPE */