diff --git a/kitty/fontconfig.c b/kitty/fontconfig.c index e931d3d46..5a8689219 100644 --- a/kitty/fontconfig.c +++ b/kitty/fontconfig.c @@ -149,7 +149,7 @@ end: return ans; } -static Py_UCS4 char_buf[1024]; +static char_type char_buf[1024]; static inline void add_charset(FcPattern *pat, size_t num) { @@ -169,16 +169,10 @@ end: if (charset != NULL) FcCharSetDestroy(charset); } -bool -information_for_font_family(const char *family, bool bold, bool italic, FontConfigFace *ans) { - memset(ans, 0, sizeof(FontConfigFace)); - FcPattern *match = NULL; - FcPattern *pat = FcPatternCreate(); +static inline bool +_native_fc_match(FcPattern *pat, FontConfigFace *ans) { bool ok = false; - if (pat == NULL) { PyErr_NoMemory(); return ok; } - if (family && strlen(family) > 0) AP(FcPatternAddString, FC_FAMILY, (const FcChar8*)family, "family"); - if (bold) { AP(FcPatternAddInteger, FC_WEIGHT, FC_WEIGHT_BOLD, "weight"); } - if (italic) { AP(FcPatternAddInteger, FC_SLANT, FC_SLANT_ITALIC, "slant"); } + FcPattern *match = NULL; FcResult result; FcConfigSubstitute(NULL, pat, FcMatchPattern); FcDefaultSubstitute(pat); @@ -197,6 +191,21 @@ information_for_font_family(const char *family, bool bold, bool italic, FontConf ok = true; end: if (match != NULL) FcPatternDestroy(match); + return ok; +} + + +bool +information_for_font_family(const char *family, bool bold, bool italic, FontConfigFace *ans) { + memset(ans, 0, sizeof(FontConfigFace)); + FcPattern *pat = FcPatternCreate(); + bool ok = false; + if (pat == NULL) { PyErr_NoMemory(); return ok; } + if (family && strlen(family) > 0) AP(FcPatternAddString, FC_FAMILY, (const FcChar8*)family, "family"); + if (bold) { AP(FcPatternAddInteger, FC_WEIGHT, FC_WEIGHT_BOLD, "weight"); } + if (italic) { AP(FcPatternAddInteger, FC_SLANT, FC_SLANT_ITALIC, "slant"); } + ok = _native_fc_match(pat, ans); +end: if (pat != NULL) FcPatternDestroy(pat); return ok; } @@ -280,6 +289,23 @@ end: return ans; } +bool +fallback_font(char_type ch, const char *family, bool bold, bool italic, FontConfigFace *ans) { + memset(ans, 0, sizeof(FontConfigFace)); + bool ok = false; + FcPattern *pat = FcPatternCreate(); + if (pat == NULL) { PyErr_NoMemory(); return ok; } + if (family) AP(FcPatternAddString, FC_FAMILY, (const FcChar8*)family, "family"); + if (bold) { AP(FcPatternAddInteger, FC_WEIGHT, FC_WEIGHT_BOLD, "weight"); } + if (italic) { AP(FcPatternAddInteger, FC_SLANT, FC_SLANT_ITALIC, "slant"); } + char_buf[0] = ch; + add_charset(pat, 1); + ok = _native_fc_match(pat, ans); +end: + if (pat != NULL) FcPatternDestroy(pat); + return ok; +} + PyObject* create_fallback_face(PyObject UNUSED *base_face, CPUCell* cell, bool bold, bool italic, bool emoji_presentation, FONTS_DATA_HANDLE fg) { PyObject *ans = NULL; diff --git a/kitty/freetype.c b/kitty/freetype.c index df214847f..c47902679 100644 --- a/kitty/freetype.c +++ b/kitty/freetype.c @@ -20,7 +20,6 @@ #define FT_Bitmap_Init FT_Bitmap_New #endif -#include FT_FREETYPE_H #include FT_BITMAP_H #include FT_TRUETYPE_TABLES_H typedef struct { diff --git a/kitty/freetype_render_ui_text.c b/kitty/freetype_render_ui_text.c index d1565b31a..c03f34b1f 100644 --- a/kitty/freetype_render_ui_text.c +++ b/kitty/freetype_render_ui_text.c @@ -18,6 +18,10 @@ FT_Face main_face = NULL; FontConfigFace main_face_information = {0}; FamilyInformation main_face_family = {0}; +static inline FT_UInt +glyph_id_for_codepoint(FT_Face face, char_type cp) { + return FT_Get_Char_Index(face, cp); +} static void cleanup(void) { @@ -35,7 +39,7 @@ set_main_face_family(const char *family, bool bold, bool italic) { main_face_family.bold = bold; main_face_family.italic = italic; } -static bool +static inline bool ensure_state(void) { if (main_face) return false; if (!information_for_font_family(main_face_family.name, main_face_family.bold, main_face_family.italic, &main_face_information)) return false; @@ -45,7 +49,6 @@ ensure_state(void) { static PyObject* path_for_font(PyObject *self UNUSED, PyObject *args) { - (void)ensure_state; const char *family = NULL; int bold = 0, italic = 0; if (!PyArg_ParseTuple(args, "|zpp", &family, &bold, &italic)) return NULL; FontConfigFace f; @@ -55,8 +58,21 @@ path_for_font(PyObject *self UNUSED, PyObject *args) { return ret; } +static PyObject* +fallback_for_char(PyObject *self UNUSED, PyObject *args) { + const char *family = NULL; int bold = 0, italic = 0; + unsigned int ch; + if (!PyArg_ParseTuple(args, "I|zpp", &ch, &family, &bold, &italic)) return NULL; + FontConfigFace f; + if (!fallback_font(ch, family, bold, italic, &f)) return NULL; + PyObject *ret = Py_BuildValue("{ss si si si}", "path", f.path, "index", f.index, "hinting", f.hinting, "hintstyle", f.hintstyle); + free(f.path); + return ret; +} + static PyMethodDef module_methods[] = { METHODB(path_for_font, METH_VARARGS), + METHODB(fallback_for_char, METH_VARARGS), {NULL, NULL, 0, NULL} /* Sentinel */ }; diff --git a/kitty/freetype_render_ui_text.h b/kitty/freetype_render_ui_text.h index c8277a29a..4c49eba45 100644 --- a/kitty/freetype_render_ui_text.h +++ b/kitty/freetype_render_ui_text.h @@ -18,6 +18,6 @@ typedef struct FontConfigFace { bool information_for_font_family(const char *family, bool bold, bool italic, FontConfigFace *ans); FT_Face native_face_from_path(const char *path, int index); - +bool fallback_font(char_type ch, const char *family, bool bold, bool italic, FontConfigFace *ans); void set_main_face_family(const char *family, bool bold, bool italic);