From ab1d5d400536f83a43b65c9bcc347a900f6008b4 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Mitsuharu Date: Sun, 2 Jun 2019 13:02:09 +0900 Subject: [PATCH] Make fthbfont and derivatives use common HarfBuzz code in hbfont.c * src/font.h (fthbfont_shape, fthbfont_combining_capability) [HAVE_HARFBUZZ]: Remove prototypes. * src/ftfont.c: Don't include math.h. (uni_combining, uni_general, uni_mirroring, get_hb_unicode_funcs) (fthbfont_shape_by_hb, fthbfont_combining_capability, fthbfont_shape) [HAVE_HARFBUZZ]: Remove functions. * src/ftfont.c (syms_of_ftfont_for_pdumper) [HAVE_HARFBUZZ]: * src/xftfont.c (syms_of_xftfont_for_pdumper) [HAVE_HARFBUZZ]: * src/ftcrfont.c (syms_of_ftcrfont_for_pdumper) [HAVE_HARFBUZZ]: Use hbfont_shape and hbfont_combining_capability instead of fthbfont_shape and fthbfont_combining_capability, respectively. --- src/font.h | 2 - src/ftcrfont.c | 4 +- src/ftfont.c | 295 +------------------------------------------------ src/xftfont.c | 4 +- 4 files changed, 6 insertions(+), 299 deletions(-) diff --git a/src/font.h b/src/font.h index 99b95836d7a..1f35744642b 100644 --- a/src/font.h +++ b/src/font.h @@ -928,9 +928,7 @@ extern void ftfont_filter_properties (Lisp_Object, Lisp_Object); extern void ftfont_text_extents (struct font *, const unsigned *, int, struct font_metrics *); #ifdef HAVE_HARFBUZZ -extern Lisp_Object fthbfont_combining_capability (struct font *); extern hb_font_t *fthbfont_begin_hb_font (struct font *, double *); -extern Lisp_Object fthbfont_shape (Lisp_Object, Lisp_Object); #endif /* HAVE_HARFBUZZ */ extern void syms_of_ftfont (void); #endif /* HAVE_FREETYPE */ diff --git a/src/ftcrfont.c b/src/ftcrfont.c index 79bf68141dc..0c3b74ff289 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c @@ -612,8 +612,8 @@ syms_of_ftcrfont_for_pdumper (void) ftcrhbfont_driver.type = Qftcrhb; ftcrhbfont_driver.list = ftcrhbfont_list; ftcrhbfont_driver.match = ftcrhbfont_match; - ftcrhbfont_driver.shape = fthbfont_shape; - ftcrhbfont_driver.combining_capability = fthbfont_combining_capability; + ftcrhbfont_driver.shape = hbfont_shape; + ftcrhbfont_driver.combining_capability = hbfont_combining_capability; ftcrhbfont_driver.begin_hb_font = ftcrhbfont_begin_hb_font; ftcrhbfont_driver.end_hb_font = ftcrhbfont_end_hb_font; register_font_driver (&ftcrhbfont_driver, NULL); diff --git a/src/ftfont.c b/src/ftfont.c index 5694c49aaf9..97ab4d0e377 100644 --- a/src/ftfont.c +++ b/src/ftfont.c @@ -21,7 +21,6 @@ along with GNU Emacs. If not, see . */ #include #include -#include #include #include @@ -2851,296 +2850,6 @@ fthbfont_begin_hb_font (struct font *font, double *position_unit) return ftfont_info->hb_font; } -static hb_unicode_combining_class_t -uni_combining (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data) -{ - Lisp_Object table, combining; - - /* FIXME: Is it efficient to load the table each time? */ - table = Funicode_property_table_internal (intern ("canonical-combining-class")); - combining = Fget_unicode_property_internal (table, make_fixnum (ch)); - - if (INTEGERP (combining)) - return (hb_unicode_combining_class_t) XFIXNUM (combining); - - return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED; -} - -static hb_unicode_general_category_t -uni_general (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data) -{ - Lisp_Object category = CHAR_TABLE_REF (Vunicode_category_table, ch); - - if (INTEGERP (category)) - { - switch (XFIXNUM (category)) - { - case UNICODE_CATEGORY_Cc: - return HB_UNICODE_GENERAL_CATEGORY_CONTROL; - case UNICODE_CATEGORY_Cf: - return HB_UNICODE_GENERAL_CATEGORY_FORMAT; - case UNICODE_CATEGORY_Cn: - return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED; - case UNICODE_CATEGORY_Co: - return HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE; - case UNICODE_CATEGORY_Cs: - return HB_UNICODE_GENERAL_CATEGORY_SURROGATE; - case UNICODE_CATEGORY_Ll: - return HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER; - case UNICODE_CATEGORY_Lm: - return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER; - case UNICODE_CATEGORY_Lo: - return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER; - case UNICODE_CATEGORY_Lt: - return HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER; - case UNICODE_CATEGORY_Lu: - return HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER; - case UNICODE_CATEGORY_Mc: - return HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK; - case UNICODE_CATEGORY_Me: - return HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK; - case UNICODE_CATEGORY_Mn: - return HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK; - case UNICODE_CATEGORY_Nd: - return HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER; - case UNICODE_CATEGORY_Nl: - return HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER; - case UNICODE_CATEGORY_No: - return HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER; - case UNICODE_CATEGORY_Pc: - return HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION; - case UNICODE_CATEGORY_Pd: - return HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION; - case UNICODE_CATEGORY_Pe: - return HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION; - case UNICODE_CATEGORY_Pf: - return HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION; - case UNICODE_CATEGORY_Pi: - return HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION; - case UNICODE_CATEGORY_Po: - return HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION; - case UNICODE_CATEGORY_Ps: - return HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION; - case UNICODE_CATEGORY_Sc: - return HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL; - case UNICODE_CATEGORY_Sk: - return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL; - case UNICODE_CATEGORY_Sm: - return HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL; - case UNICODE_CATEGORY_So: - return HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL; - case UNICODE_CATEGORY_Zl: - return HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR; - case UNICODE_CATEGORY_Zp: - return HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR; - case UNICODE_CATEGORY_Zs: - return HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR; - case UNICODE_CATEGORY_UNKNOWN: - return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED; - } - } - - return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED; -} - -static hb_codepoint_t -uni_mirroring (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data) -{ - return bidi_mirror_char (ch); -} - -static hb_unicode_funcs_t * -get_hb_unicode_funcs (void) -{ - /* Subclass HarfBuzz's default Unicode functions and override functions that - * use data Emacs can provide. This way changing Emacs data is reflected in - * the shaped output. */ - hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (hb_unicode_funcs_get_default ()); - - hb_unicode_funcs_set_combining_class_func (funcs, uni_combining, NULL, NULL); - hb_unicode_funcs_set_general_category_func (funcs, uni_general, NULL, NULL); - hb_unicode_funcs_set_mirroring_func (funcs, uni_mirroring, NULL, NULL); - - /* Use default implmentation for Unicode composition/decomposition, we might - * want to revisit this later. - hb_unicode_funcs_set_compose_func (funcs, uni_compose, NULL, NULL); - hb_unicode_funcs_set_decompose_func (funcs, uni_decompose, NULL, NULL); - */ - - /* Emacs own script mapping for characters differs from Unicode, so we want - * to keep the default HarfBuzz's implementation here. - hb_unicode_funcs_set_script_func (funcs, uni_script, NULL, NULL); - */ - - return funcs; -} - -static Lisp_Object -fthbfont_shape_by_hb (Lisp_Object lgstring, struct font *font, - Lisp_Object direction) -{ - ptrdiff_t glyph_len = 0, text_len = LGSTRING_GLYPH_LEN (lgstring); - ptrdiff_t i; - - hb_glyph_info_t *info; - hb_glyph_position_t *pos; - - /* Cache the HarfBuzz buffer for better performance and less allocations. - * We intentionally never destroy the buffer. */ - static hb_buffer_t *hb_buffer = NULL; - if (! hb_buffer) - { - hb_buffer = hb_buffer_create (); - hb_unicode_funcs_t* ufuncs = get_hb_unicode_funcs(); - hb_buffer_set_unicode_funcs(hb_buffer, ufuncs); - } - - hb_buffer_clear_contents (hb_buffer); - hb_buffer_pre_allocate (hb_buffer, text_len); - - for (i = 0; i < text_len; i++) - { - Lisp_Object g = LGSTRING_GLYPH (lgstring, i); - int c; - - if (NILP (g)) - break; - c = LGLYPH_CHAR (g); - hb_buffer_add (hb_buffer, c, i); - } - - text_len = i; - if (!text_len) - return Qnil; - - hb_buffer_set_content_type (hb_buffer, HB_BUFFER_CONTENT_TYPE_UNICODE); - hb_buffer_set_cluster_level (hb_buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); - - /* If the caller didn't provide a meaningful DIRECTION, default to L2R. */ - hb_direction_t dir = HB_DIRECTION_LTR; - if (EQ (direction, QL2R)) - dir = HB_DIRECTION_LTR; - else if (EQ (direction, QR2L)) - dir = HB_DIRECTION_RTL; - hb_buffer_set_direction (hb_buffer, dir); - - /* Leave the script determination to HarfBuzz, until Emacs has a - better idea of the script of LGSTRING. FIXME. */ -#if 0 - hb_buffer_set_script (hb_buffer, XXX); -#endif - - /* FIXME: This can only handle the single global language, which - normally comes from the locale. In addition, if - current-iso639-language is a list, we arbitrarily use the first - one. We should instead have a notion of the language of the text - being shaped. */ - Lisp_Object lang = Vcurrent_iso639_language; - if (CONSP (Vcurrent_iso639_language)) - lang = XCAR (Vcurrent_iso639_language); - if (SYMBOLP (lang)) - { - Lisp_Object lang_str = SYMBOL_NAME (lang); - hb_buffer_set_language (hb_buffer, - hb_language_from_string (SSDATA (lang_str), - SBYTES (lang_str))); - } - - /* Guess the default properties for when they cannot be determined - above. FIXME: drop once script handling is fixed above. */ - hb_buffer_guess_segment_properties (hb_buffer); - - double position_unit; - hb_font_t *hb_font = font->driver->begin_hb_font (font, &position_unit); - if (!hb_font) - return make_fixnum (0); - - hb_bool_t success = hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL); - if (font->driver->end_hb_font) - font->driver->end_hb_font (font, hb_font); - if (!success) - return Qnil; - - glyph_len = hb_buffer_get_length (hb_buffer); - /* FIXME: can't we just grew the lgstring in this case? Givving up is an - * overly heavy handed solution. */ - if (glyph_len > LGSTRING_GLYPH_LEN (lgstring)) - return Qnil; - - /* Somewhere up the pipeline wants the glyphs in logical order, while keeping - * clusters in visual order. I don't know where exactly, but lets satisfy - * that. */ - if (HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (hb_buffer))) - hb_buffer_reverse_clusters (hb_buffer); - - info = hb_buffer_get_glyph_infos (hb_buffer, NULL); - pos = hb_buffer_get_glyph_positions (hb_buffer, NULL); - for (i = 0; i < glyph_len; i++) - { - Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i); - EMACS_INT from, to; - struct font_metrics metrics = {.width = 0}; - int xoff, yoff, wadjust; - ptrdiff_t j = i; - - if (NILP (lglyph)) - { - lglyph = LGLYPH_NEW (); - LGSTRING_SET_GLYPH (lgstring, i, lglyph); - } - - from = to = info[i].cluster; - /* FIXME: what does “from” mean here? */ - LGLYPH_SET_FROM (lglyph, from); - - /* FIXME: what does “to” mean here? */ - for (j = i; j < glyph_len && info[j].cluster == info[i].cluster; j++) - ; - to = (j == glyph_len) ? text_len - 1 : info[j].cluster - 1; - LGLYPH_SET_TO (lglyph, to); - - /* FIXME: is this really needed? Not all glyphs map directly to a single character */ - LGLYPH_SET_CHAR (lglyph, LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, from))); - LGLYPH_SET_CODE (lglyph, info[i].codepoint); - - unsigned code = info[i].codepoint; - font->driver->text_extents (font, &code, 1, &metrics); - LGLYPH_SET_WIDTH (lglyph, metrics.width); - LGLYPH_SET_LBEARING (lglyph, metrics.lbearing); - LGLYPH_SET_RBEARING (lglyph, metrics.rbearing); - LGLYPH_SET_ASCENT (lglyph, metrics.ascent); - LGLYPH_SET_DESCENT (lglyph, metrics.descent); - - xoff = lround (pos[i].x_offset * position_unit); - yoff = - lround (pos[i].y_offset * position_unit); - wadjust = lround (pos[i].x_advance * position_unit); - if (xoff || yoff || wadjust != metrics.width) - { - Lisp_Object vec = make_uninit_vector (3); - ASET (vec, 0, make_fixnum (xoff)); - ASET (vec, 1, make_fixnum (yoff)); - ASET (vec, 2, make_fixnum (wadjust)); - LGLYPH_SET_ADJUSTMENT (lglyph, vec); - } - } - - return make_fixnum (glyph_len); -} - -Lisp_Object -fthbfont_combining_capability (struct font *font) -{ - return Qt; -} - -Lisp_Object -fthbfont_shape (Lisp_Object lgstring, Lisp_Object direction) -{ - struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); - - return fthbfont_shape_by_hb (lgstring, font, direction); -} - #endif /* HAVE_HARFBUZZ */ static const char *const ftfont_booleans [] = { @@ -3282,8 +2991,8 @@ syms_of_ftfont_for_pdumper (void) #ifdef HAVE_HARFBUZZ fthbfont_driver = ftfont_driver; fthbfont_driver.type = Qfreetypehb; - fthbfont_driver.shape = fthbfont_shape; - fthbfont_driver.combining_capability = fthbfont_combining_capability; + fthbfont_driver.shape = hbfont_shape; + fthbfont_driver.combining_capability = hbfont_combining_capability; fthbfont_driver.begin_hb_font = fthbfont_begin_hb_font; register_font_driver (&fthbfont_driver, NULL); #endif /* HAVE_HARFBUZZ */ diff --git a/src/xftfont.c b/src/xftfont.c index 08e4edb535a..c1b93b76f57 100644 --- a/src/xftfont.c +++ b/src/xftfont.c @@ -699,8 +699,8 @@ syms_of_xftfont_for_pdumper (void) xfthbfont_driver.type = Qxfthb; xfthbfont_driver.list = xfthbfont_list; xfthbfont_driver.match = xfthbfont_match; - xfthbfont_driver.shape = fthbfont_shape; - xfthbfont_driver.combining_capability = fthbfont_combining_capability; + xfthbfont_driver.shape = hbfont_shape; + xfthbfont_driver.combining_capability = hbfont_combining_capability; xfthbfont_driver.begin_hb_font = xfthbfont_begin_hb_font; xfthbfont_driver.end_hb_font = xfthbfont_end_hb_font; register_font_driver (&xfthbfont_driver, NULL); -- 2.39.2