add support for loading fonts with UTF-8 filenames

This commit is contained in:
takase1121 2022-11-14 22:01:24 +08:00
parent 4457f26502
commit 69938c619c
No known key found for this signature in database
GPG Key ID: 60EEFFC68EB3031B
1 changed files with 63 additions and 4 deletions

View File

@ -8,6 +8,10 @@
#include <freetype/ftoutln.h> #include <freetype/ftoutln.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
#ifdef _WIN32
#include "utfconv.h"
#endif
#include "renderer.h" #include "renderer.h"
#include "renwindow.h" #include "renwindow.h"
@ -51,6 +55,7 @@ typedef struct RenFont {
ERenFontHinting hinting; ERenFontHinting hinting;
unsigned char style; unsigned char style;
unsigned short underline_thickness; unsigned short underline_thickness;
unsigned char *file;
char path[]; char path[];
} RenFont; } RenFont;
@ -206,9 +211,48 @@ static void font_clear_glyph_cache(RenFont* font) {
} }
RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style) { RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style) {
FT_Face face; FT_Face face = NULL;
if (FT_New_Face( library, path, 0, &face))
#ifdef _WIN32
HANDLE file = INVALID_HANDLE_VALUE;
DWORD read;
int font_file_len = 0;
unsigned char *font_file = NULL;
wchar_t *wpath = NULL;
if ((wpath = utfconv_utf8towc(path)) == NULL)
return NULL; return NULL;
if ((file = CreateFileW(wpath,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
goto failure;
if ((font_file_len = GetFileSize(file, NULL)) == INVALID_FILE_SIZE)
goto failure;
font_file = check_alloc(malloc(font_file_len * sizeof(unsigned char)));
if (!ReadFile(file, font_file, font_file_len, &read, NULL) || read != font_file_len)
goto failure;
CloseHandle(file);
free(wpath);
if (FT_New_Memory_Face(library, font_file, read, 0, &face))
goto failure;
#else
if (FT_New_Face(library, path, 0, &face))
return NULL;
#endif
const int surface_scale = renwin_surface_scale(&window_renderer); const int surface_scale = renwin_surface_scale(&window_renderer);
if (FT_Set_Pixel_Sizes(face, 0, (int)(size*surface_scale))) if (FT_Set_Pixel_Sizes(face, 0, (int)(size*surface_scale)))
goto failure; goto failure;
@ -223,6 +267,11 @@ RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antial
font->hinting = hinting; font->hinting = hinting;
font->style = style; font->style = style;
#ifdef _WIN32
// we need to keep this for freetype
font->file = font_file;
#endif
if(FT_IS_SCALABLE(face)) if(FT_IS_SCALABLE(face))
font->underline_thickness = (unsigned short)((face->underline_thickness / (float)face->units_per_EM) * font->size); font->underline_thickness = (unsigned short)((face->underline_thickness / (float)face->units_per_EM) * font->size);
if(!font->underline_thickness) font->underline_thickness = ceil((double) font->height / 14.0); if(!font->underline_thickness) font->underline_thickness = ceil((double) font->height / 14.0);
@ -232,8 +281,15 @@ RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antial
font->space_advance = face->glyph->advance.x / 64.0f; font->space_advance = face->glyph->advance.x / 64.0f;
font->tab_advance = font->space_advance * 2; font->tab_advance = font->space_advance * 2;
return font; return font;
failure:
FT_Done_Face(face); failure:
#ifdef _WIN32
free(wpath);
free(font_file);
if (file != INVALID_HANDLE_VALUE) CloseHandle(file);
#endif
if (face != NULL)
FT_Done_Face(face);
return NULL; return NULL;
} }
@ -252,6 +308,9 @@ const char* ren_font_get_path(RenFont *font) {
void ren_font_free(RenFont* font) { void ren_font_free(RenFont* font) {
font_clear_glyph_cache(font); font_clear_glyph_cache(font);
FT_Done_Face(font->face); FT_Done_Face(font->face);
#ifdef _WIN32
free(font->file);
#endif
free(font); free(font);
} }