10 #include "../stdafx.h"
12 #include "../fontcache.h"
13 #include "../fontdetection.h"
14 #include "../blitter/factory.hpp"
15 #include "../core/math_func.hpp"
16 #include "../zoom_func.h"
17 #include "../fileio_func.h"
20 #include "../table/control_codes.h"
22 #include "../safeguards.h"
26 #include FT_FREETYPE_H
28 #include FT_TRUETYPE_TABLES_H
36 virtual const void *InternalGetFontTable(uint32 tag,
size_t &length);
48 FT_Library _library =
nullptr;
59 assert(
face !=
nullptr);
61 this->SetFontSize(
fs,
face, pixels);
64 void FreeTypeFontCache::SetFontSize(
FontSize fs, FT_Face face,
int pixels)
68 int scaled_height =
ScaleFontTrad(this->GetDefaultFontHeight(this->fs));
69 pixels = scaled_height;
71 TT_Header *head = (TT_Header *)FT_Get_Sfnt_Table(this->face, ft_sfnt_head);
72 if (head !=
nullptr) {
83 FT_Error err = FT_Set_Pixel_Sizes(this->face, 0, pixels);
84 if (err != FT_Err_Ok) {
87 FT_Bitmap_Size *bs = this->face->available_sizes;
88 int i = this->face->num_fixed_sizes;
93 if (
abs(pixels - bs->height) >=
abs(pixels - n))
continue;
95 chosen = this->face->num_fixed_sizes - i;
100 err = FT_Select_Size(this->face, chosen);
104 if (err == FT_Err_Ok) {
106 this->
ascender = this->face->size->metrics.ascender >> 6;
107 this->
descender = this->face->size->metrics.descender >> 6;
111 Debug(fontcache, 0,
"Font size selection failed. Using FontCache defaults.");
126 default: NOT_REACHED();
135 if (_library ==
nullptr) {
136 if (FT_Init_FreeType(&_library) != FT_Err_Ok) {
137 ShowInfoF(
"Unable to initialize FreeType, using sprite fonts instead");
141 Debug(fontcache, 2,
"Initialized");
144 const char *font_name =
settings->font.c_str();
145 FT_Face face =
nullptr;
148 FT_Error
error = FT_New_Face(_library, font_name, 0, &face);
150 #if defined(WITH_COCOA)
155 if (
error != FT_Err_Ok) {
158 if (!full_font.empty()) {
159 error = FT_New_Face(_library, full_font.c_str(), 0, &face);
160 #if defined(WITH_COCOA)
169 if (
error == FT_Err_Ok) {
170 Debug(fontcache, 2,
"Requested '{}', using '{} {}'", font_name, face->family_name, face->style_name);
173 error = FT_Select_Charmap(face, ft_encoding_unicode);
174 if (
error == FT_Err_Ok)
goto found_face;
176 if (
error == FT_Err_Invalid_CharMap_Handle) {
180 FT_CharMap found = face->charmaps[0];
183 for (i = 0; i < face->num_charmaps; i++) {
184 FT_CharMap charmap = face->charmaps[i];
185 if (charmap->platform_id == 0 && charmap->encoding_id == 0) {
190 if (found !=
nullptr) {
191 error = FT_Set_Charmap(face, found);
192 if (
error == FT_Err_Ok)
goto found_face;
199 static const char *SIZE_TO_NAME[] = {
"medium",
"small",
"large",
"mono" };
200 ShowInfoF(
"Unable to use '%s' for %s font, FreeType reported error 0x%X, using sprite font instead", font_name, SIZE_TO_NAME[fs],
error);
213 FT_Done_Face(this->face);
214 this->face =
nullptr;
224 if (this->face !=
nullptr) this->SetFontSize(this->fs, this->face, this->
req_size);
230 const Sprite *FreeTypeFontCache::InternalGetGlyph(
GlyphID key,
bool aa)
232 FT_GlyphSlot slot = this->face->glyph;
234 FT_Load_Glyph(this->face, key, aa ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO);
235 FT_Render_Glyph(this->face->glyph, aa ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
238 aa = (slot->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);
241 uint width = std::max(1U, (uint)slot->bitmap.width + (this->fs ==
FS_NORMAL));
242 uint
height = std::max(1U, (uint)slot->bitmap.rows + (this->fs ==
FS_NORMAL));
252 sprite.
width = width;
254 sprite.
x_offs = slot->bitmap_left;
259 for (uint y = 0; y < (uint)slot->bitmap.rows; y++) {
260 for (uint x = 0; x < (uint)slot->bitmap.width; x++) {
261 if (
HasBit(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
262 sprite.
data[1 + x + (1 + y) * sprite.
width].
m = SHADOW_COLOUR;
263 sprite.
data[1 + x + (1 + y) * sprite.
width].
a = 0xFF;
269 for (uint y = 0; y < (uint)slot->bitmap.rows; y++) {
270 for (uint x = 0; x < (uint)slot->bitmap.width; x++) {
271 if (aa ? (slot->bitmap.buffer[x + y * slot->bitmap.pitch] > 0) :
HasBit(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
272 sprite.
data[x + y * sprite.
width].
m = FACE_COLOUR;
273 sprite.
data[x + y * sprite.
width].
a = aa ? slot->bitmap.buffer[x + y * slot->bitmap.pitch] : 0xFF;
278 GlyphEntry new_glyph;
280 new_glyph.
width = slot->advance.x >> 6;
282 this->SetGlyphPtr(key, &new_glyph);
284 return new_glyph.sprite;
290 assert(IsPrintable(key));
292 if (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) {
296 return FT_Get_Char_Index(this->face, key);
299 const void *FreeTypeFontCache::InternalGetFontTable(uint32 tag,
size_t &length)
302 FT_Byte *result =
nullptr;
304 FT_Load_Sfnt_Table(this->face, tag, 0,
nullptr, &len);
307 result = MallocT<FT_Byte>(len);
308 FT_Load_Sfnt_Table(this->face, tag, 0, result, &len);
320 FT_Done_FreeType(_library);
324 #if !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) && !defined(WITH_COCOA)
326 FT_Error
GetFontByFaceName(
const char *font_name, FT_Face *face) {
return FT_Err_Cannot_Open_Resource; }