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"
18 #include "../error_func.h"
21 #include "../table/control_codes.h"
23 #include "../safeguards.h"
27 #include FT_FREETYPE_H
29 #include FT_TRUETYPE_TABLES_H
36 void SetFontSize(
int pixels);
37 const Sprite *InternalGetGlyph(
GlyphID key,
bool aa)
override;
44 std::string
GetFontName()
override {
return fmt::format(
"{}, {}",
face->family_name,
face->style_name); }
49 FT_Library _library =
nullptr;
60 assert(
face !=
nullptr);
62 this->SetFontSize(pixels);
65 void FreeTypeFontCache::SetFontSize(
int pixels)
69 int scaled_height =
ScaleGUITrad(FontCache::GetDefaultFontHeight(this->
fs));
70 pixels = scaled_height;
72 TT_Header *head = (TT_Header *)FT_Get_Sfnt_Table(this->
face, ft_sfnt_head);
73 if (head !=
nullptr) {
85 FT_Error err = FT_Set_Pixel_Sizes(this->
face, 0, pixels);
86 if (err != FT_Err_Ok) {
89 FT_Bitmap_Size *bs = this->
face->available_sizes;
90 int i = this->
face->num_fixed_sizes;
95 if (
abs(pixels - bs->height) >=
abs(pixels - n))
continue;
97 chosen = this->
face->num_fixed_sizes - i;
102 err = FT_Select_Size(this->
face, chosen);
106 if (err == FT_Err_Ok) {
107 this->
ascender = this->
face->size->metrics.ascender >> 6;
112 Debug(fontcache, 0,
"Font size selection failed. Using FontCache defaults.");
116 static FT_Error LoadFont(
FontSize fs, FT_Face face,
const char *font_name, uint size)
118 Debug(fontcache, 2,
"Requested '{}', using '{} {}'", font_name, face->family_name, face->style_name);
121 FT_Error error = FT_Select_Charmap(face, ft_encoding_unicode);
122 if (error == FT_Err_Ok)
goto found_face;
124 if (error == FT_Err_Invalid_CharMap_Handle) {
128 FT_CharMap found = face->charmaps[0];
131 for (i = 0; i < face->num_charmaps; i++) {
132 FT_CharMap charmap = face->charmaps[i];
133 if (charmap->platform_id == 0 && charmap->encoding_id == 0) {
138 if (found !=
nullptr) {
139 error = FT_Set_Charmap(face, found);
140 if (error == FT_Err_Ok)
goto found_face;
164 if (font.empty())
return;
166 if (_library ==
nullptr) {
167 if (FT_Init_FreeType(&_library) != FT_Err_Ok) {
168 ShowInfo(
"Unable to initialize FreeType, using sprite fonts instead");
172 Debug(fontcache, 2,
"Initialized");
175 const char *font_name = font.c_str();
176 FT_Face face =
nullptr;
180 if (
settings->os_handle !=
nullptr) index = *
static_cast<const int32_t *
>(
settings->os_handle);
181 FT_Error error = FT_New_Face(_library, font_name, index, &face);
183 if (error != FT_Err_Ok) {
186 if (!full_font.empty()) {
187 error = FT_New_Face(_library, full_font.c_str(), 0, &face);
194 if (error == FT_Err_Ok) {
196 if (error != FT_Err_Ok) {
197 ShowInfo(
"Unable to use '{}' for {} font, FreeType reported error 0x{:X}, using sprite font instead", font_name, FontSizeToName(fs), error);
209 FT_Done_Face(this->face);
210 this->face =
nullptr;
220 if (this->face !=
nullptr) this->SetFontSize(this->
req_size);
226 const Sprite *FreeTypeFontCache::InternalGetGlyph(
GlyphID key,
bool aa)
228 FT_GlyphSlot slot = this->face->glyph;
230 FT_Load_Glyph(this->face, key, aa ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO);
231 FT_Render_Glyph(this->face->glyph, aa ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
234 aa = (slot->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);
238 uint width = std::max(1U, (uint)slot->bitmap.width + shadow);
239 uint
height = std::max(1U, (uint)slot->bitmap.rows + shadow);
250 sprite.
width = width;
252 sprite.
x_offs = slot->bitmap_left;
257 for (uint y = 0; y < (uint)slot->bitmap.rows; y++) {
258 for (uint x = 0; x < (uint)slot->bitmap.width; x++) {
259 if (
HasBit(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
260 sprite.
data[shadow + x + (shadow + y) * sprite.
width].
m = SHADOW_COLOUR;
261 sprite.
data[shadow + x + (shadow + y) * sprite.
width].
a = 0xFF;
267 for (uint y = 0; y < (uint)slot->bitmap.rows; y++) {
268 for (uint x = 0; x < (uint)slot->bitmap.width; x++) {
269 if (aa ? (slot->bitmap.buffer[x + y * slot->bitmap.pitch] > 0) :
HasBit(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
270 sprite.
data[x + y * sprite.
width].
m = FACE_COLOUR;
271 sprite.
data[x + y * sprite.
width].
a = aa ? slot->bitmap.buffer[x + y * slot->bitmap.pitch] : 0xFF;
279 GlyphEntry new_glyph;
280 new_glyph.
data = std::move(allocator.data);
281 new_glyph.width = slot->advance.x >> 6;
283 return this->SetGlyphPtr(key, std::move(new_glyph)).GetSprite();
289 assert(IsPrintable(key));
291 FT_UInt glyph = FT_Get_Char_Index(this->face, key);
293 if (glyph == 0 && allow_fallback && key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) {
305 FT_Done_FreeType(_library);
309 #if !defined(WITH_FONTCONFIG)
311 FT_Error
GetFontByFaceName(
const char *font_name, FT_Face *face) {
return FT_Err_Cannot_Open_Resource; }