From 814b509b1ddf7863d18f7f443e8d733173904e81 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Mitsuharu Date: Sat, 6 Jul 2019 14:35:00 +0900 Subject: [PATCH] Add HarfBuzz fallbacks for libotf functions used in ftfont_list * src/ftfont.c [!HAVE_LIBOTF && HAVE_HARFBUZZ]: Include hb-ot.h. (OTF, OTF_tag) [!HAVE_LIBOTF && HAVE_HARFBUZZ]: New typedefs. (hbotf_open, hbotf_check_features) [!HAVE_LIBOTF && HAVE_HARFBUZZ]: New functions. (OTF_open, OTF_close, OTF_check_features) [!HAVE_LIBOTF && HAVE_HARFBUZZ]: New macros. (ftfont_list) [!HAVE_LIBOTF && HAVE_HARFBUZZ]: Use them. --- src/ftfont.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 3 deletions(-) diff --git a/src/ftfont.c b/src/ftfont.c index 6f03d966606..74afa2cf5a2 100644 --- a/src/ftfont.c +++ b/src/ftfont.c @@ -552,7 +552,19 @@ struct OpenTypeSpec OTF_TAG_STR (TAG, str); \ (SYM) = font_intern_prop (str, 4, 1); \ } while (0) -#endif +#elif defined HAVE_HARFBUZZ +/* Libotf emulations on HarfBuzz for the functions called from + ftfont_list. They are a bit slower than the original ones, so used + as fallbacks when libotf is not available. */ +typedef hb_face_t OTF; +typedef unsigned int OTF_tag; +static OTF *hbotf_open (const char *); +static int hbotf_check_features (OTF *, int, OTF_tag, OTF_tag, + const OTF_tag *, int); +#define OTF_open hbotf_open +#define OTF_close hb_face_destroy +#define OTF_check_features hbotf_check_features +#endif /* !HAVE_LIBOTF && HAVE_HARFBUZZ */ static struct OpenTypeSpec * @@ -915,7 +927,7 @@ ftfont_list (struct frame *f, Lisp_Object spec) continue; } #endif /* FC_CAPABILITY */ -#ifdef HAVE_LIBOTF +#if defined HAVE_LIBOTF || defined HAVE_HARFBUZZ if (otspec) { FcChar8 *file; @@ -940,7 +952,7 @@ ftfont_list (struct frame *f, Lisp_Object spec) if (!passed) continue; } -#endif /* HAVE_LIBOTF */ +#endif /* HAVE_LIBOTF || HAVE_HARFBUZZ */ if (VECTORP (chars)) { ptrdiff_t j; @@ -2870,6 +2882,91 @@ fthbfont_begin_hb_font (struct font *font, double *position_unit) return ftfont_info->hb_font; } +#ifndef HAVE_LIBOTF +#include + +static OTF * +hbotf_open (const char *name) +{ + FT_Face ft_face; + + if (! ft_library + && FT_Init_FreeType (&ft_library) != 0) + return NULL; + if (FT_New_Face (ft_library, name, 0, &ft_face) + != 0) + return NULL; + + hb_face_t *face = hb_ft_face_create_referenced (ft_face); + FT_Done_Face (ft_face); + + return face; +} + +static int +hbotf_check_features (OTF *otf, int gsubp, + OTF_tag script, OTF_tag language, + const OTF_tag *features, int n_features) +{ + hb_face_t *face = otf; + hb_tag_t table_tag = gsubp ? HB_OT_TAG_GSUB : HB_OT_TAG_GPOS; + hb_tag_t script_tag = script, language_tag = language; + + unsigned int script_count + = hb_ot_layout_table_get_script_tags (face, table_tag, 0, NULL, NULL); + hb_tag_t *script_tags = xnmalloc (script_count, sizeof *script_tags); + hb_ot_layout_table_get_script_tags (face, table_tag, 0, &script_count, + script_tags); + unsigned int script_index; + for (script_index = 0; script_index < script_count; script_index++) + if (script_tags[script_index] == script_tag) + break; + xfree (script_tags); + if (script_index == script_count) + return 0; + + unsigned int language_index; + if (language_tag == 0) + language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX; + else + { + unsigned int language_count + = hb_ot_layout_script_get_language_tags (face, table_tag, script_index, + 0, NULL, NULL); + hb_tag_t *language_tags = xnmalloc (language_count, + sizeof *language_tags); + hb_ot_layout_script_get_language_tags (face, table_tag, script_index, 0, + &language_count, language_tags); + for (language_index = 0; language_index < script_count; language_index++) + if (language_tags[language_index] == language_tag) + break; + xfree (language_tags); + if (language_index == language_count) + return 0; + } + + for (int j = 0; j < n_features; j++) + { + hb_tag_t feature_tag = features[j]; + hb_bool_t negate = 0; + + if (feature_tag == 0) + continue; + if (feature_tag & 0x80000000) + { + feature_tag &= 0x7FFFFFFF; + negate = 1; + } + + unsigned int feature_index; + if (hb_ot_layout_language_find_feature (face, table_tag, script_index, + language_index, feature_tag, + &feature_index) == negate) + return 0; + } + return 1; +} +#endif /* !HAVE_LIBOTF */ #endif /* HAVE_HARFBUZZ */ static const char *const ftfont_booleans [] = { -- 2.39.2