diff options
author | Eli Zaretskii <eliz@gnu.org> | 2019-06-01 12:53:41 +0300 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2019-06-01 12:53:41 +0300 |
commit | 4363777d5c60af8bc93b30d4f6c5e12dc2761160 (patch) | |
tree | 2ff9ea97c469140df5630f6ee5c250e745a78dcb /src/w32uniscribe.c | |
parent | b7730c259bc91f030069e408aaddb43f02da3a3a (diff) | |
download | emacs-4363777d5c60af8bc93b30d4f6c5e12dc2761160.tar.gz |
Move common HarfBuzz code to a common file hbfont.c
* src/hbfont.c: New file, with code moved from w32uniscribe.c
and renamed/modified as appropriate.
* src/w32uniscribe.c: Move to hbfont.c DEF_DLL_FN and macro
definitions for HarfBuzz functions used in hbfont.c
(load_harfbuzz_funcs): Move loading of HarfBuzz functions used
by hbfont.c to hbfont.c:hbfont_init_w32_funcs, and call that
function from here.
(syms_of_w32uniscribe_for_pdumper): Fill the 'shape' and
'combining_capability' members with hbfont.c function names.
* src/w32common.h (hbfont_init_w32_funcs) [HAVE_HARFBUZZ]: Add
prototype.
* src/font.h (hbfont_shape, hbfont_combining_capability)
[HAVE_HARFBUZZ]: Add prototypes.
* src/Makefile.in (SOME_MACHINE_OBJECTS): Add hbfont.o.
* configure.ac (FONT_OBJ): Add hbfont.o if HAVE_HARFBUZZ.
Diffstat (limited to 'src/w32uniscribe.c')
-rw-r--r-- | src/w32uniscribe.c | 429 |
1 files changed, 4 insertions, 425 deletions
diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c index f1e69452160..5372eb15252 100644 --- a/src/w32uniscribe.c +++ b/src/w32uniscribe.c @@ -1,4 +1,5 @@ /* Font backend for the Microsoft W32 Uniscribe API. + Windows-specific parts of the HarfBuzz font backend. Copyright (C) 2008-2019 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -85,42 +86,6 @@ DEF_DLL_FN (void, hb_face_destroy, (hb_face_t *)); DEF_DLL_FN (unsigned int, hb_face_get_upem, (hb_face_t *)); DEF_DLL_FN (hb_bool_t, hb_font_get_nominal_glyph, (hb_font_t *, hb_codepoint_t, hb_codepoint_t *)); -DEF_DLL_FN (hb_unicode_funcs_t *, hb_unicode_funcs_create, - (hb_unicode_funcs_t *)); -DEF_DLL_FN (hb_unicode_funcs_t *, hb_unicode_funcs_get_default, (void)); -DEF_DLL_FN (void, hb_unicode_funcs_set_combining_class_func, - (hb_unicode_funcs_t *, hb_unicode_combining_class_func_t, - void *, hb_destroy_func_t)); -DEF_DLL_FN (void, hb_unicode_funcs_set_general_category_func, - (hb_unicode_funcs_t *, hb_unicode_general_category_func_t, - void *, hb_destroy_func_t)); -DEF_DLL_FN (void, hb_unicode_funcs_set_mirroring_func, - (hb_unicode_funcs_t *, hb_unicode_mirroring_func_t, - void *, hb_destroy_func_t)); -DEF_DLL_FN (hb_buffer_t *, hb_buffer_create, (void)); -DEF_DLL_FN (void, hb_buffer_set_unicode_funcs, - (hb_buffer_t *, hb_unicode_funcs_t *)); -DEF_DLL_FN (void, hb_buffer_clear_contents, (hb_buffer_t *)); -DEF_DLL_FN (hb_bool_t, hb_buffer_pre_allocate, (hb_buffer_t *, unsigned int)); -DEF_DLL_FN (void, hb_buffer_add, (hb_buffer_t *, hb_codepoint_t, unsigned int)); -DEF_DLL_FN (void, hb_buffer_set_content_type, - (hb_buffer_t *, hb_buffer_content_type_t)); -DEF_DLL_FN (void, hb_buffer_set_cluster_level, - (hb_buffer_t *, hb_buffer_cluster_level_t)); -DEF_DLL_FN (void, hb_buffer_set_direction, (hb_buffer_t *, hb_direction_t)); -DEF_DLL_FN (void, hb_buffer_set_language, (hb_buffer_t *, hb_language_t)); -DEF_DLL_FN (hb_language_t, hb_language_from_string, (const char *, int)); -DEF_DLL_FN (void, hb_buffer_guess_segment_properties, (hb_buffer_t *)); -DEF_DLL_FN (hb_bool_t, hb_shape_full, - (hb_font_t *, hb_buffer_t *, const hb_feature_t *, - unsigned int, const char * const *)); -DEF_DLL_FN (unsigned int, hb_buffer_get_length, (hb_buffer_t *)); -DEF_DLL_FN (hb_direction_t, hb_buffer_get_direction, (hb_buffer_t *)); -DEF_DLL_FN (void, hb_buffer_reverse_clusters, (hb_buffer_t *)); -DEF_DLL_FN (hb_glyph_info_t *, hb_buffer_get_glyph_infos, - (hb_buffer_t *, unsigned int *)); -DEF_DLL_FN (hb_glyph_position_t *, hb_buffer_get_glyph_positions, - (hb_buffer_t *, unsigned int *)); #define hb_blob_create fn_hb_blob_create #define hb_face_create_for_tables fn_hb_face_create_for_tables @@ -130,28 +95,6 @@ DEF_DLL_FN (hb_glyph_position_t *, hb_buffer_get_glyph_positions, #define hb_face_destroy fn_hb_face_destroy #define hb_face_get_upem fn_hb_face_get_upem #define hb_font_get_nominal_glyph fn_hb_font_get_nominal_glyph -#define hb_unicode_funcs_create fn_hb_unicode_funcs_create -#define hb_unicode_funcs_get_default fn_hb_unicode_funcs_get_default -#define hb_unicode_funcs_set_combining_class_func fn_hb_unicode_funcs_set_combining_class_func -#define hb_unicode_funcs_set_general_category_func fn_hb_unicode_funcs_set_general_category_func -#define hb_unicode_funcs_set_mirroring_func fn_hb_unicode_funcs_set_mirroring_func -#define hb_buffer_create fn_hb_buffer_create -#define hb_buffer_set_unicode_funcs fn_hb_buffer_set_unicode_funcs -#define hb_buffer_clear_contents fn_hb_buffer_clear_contents -#define hb_buffer_pre_allocate fn_hb_buffer_pre_allocate -#define hb_buffer_add fn_hb_buffer_add -#define hb_buffer_set_content_type fn_hb_buffer_set_content_type -#define hb_buffer_set_cluster_level fn_hb_buffer_set_cluster_level -#define hb_buffer_set_direction fn_hb_buffer_set_direction -#define hb_buffer_set_language fn_hb_buffer_set_language -#define hb_language_from_string fn_hb_language_from_string -#define hb_buffer_guess_segment_properties fn_hb_buffer_guess_segment_properties -#define hb_shape_full fn_hb_shape_full -#define hb_buffer_get_length fn_hb_buffer_get_length -#define hb_buffer_get_direction fn_hb_buffer_get_direction -#define hb_buffer_reverse_clusters fn_hb_buffer_reverse_clusters -#define hb_buffer_get_glyph_infos fn_hb_buffer_get_glyph_infos -#define hb_buffer_get_glyph_positions fn_hb_buffer_get_glyph_positions #endif /* Used by uniscribe_otf_capability. */ @@ -1434,348 +1377,6 @@ w32hb_begin_font (struct font *font, double *position_unit) *position_unit = uniscribe_font->scale; return (hb_font_t *) uniscribe_font->cache; } - -static bool combining_class_loaded = false; -static Lisp_Object canonical_combining_class_table; - -static hb_unicode_combining_class_t -w32uni_combining (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data) -{ - /* Load the Unicode table first time it is needed. */ - if (!combining_class_loaded) - { - canonical_combining_class_table = - uniprop_table (intern ("canonical-combining-class")); - if (NILP (canonical_combining_class_table)) - emacs_abort (); - staticpro (&canonical_combining_class_table); - combining_class_loaded = true; - } - - Lisp_Object combining = - get_unicode_property (canonical_combining_class_table, ch); - if (FIXNUMP (combining)) - return (hb_unicode_combining_class_t) XFIXNUM (combining); - - return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED; -} - -static hb_unicode_general_category_t -w32uni_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 -w32uni_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, w32uni_combining, NULL, NULL); - hb_unicode_funcs_set_general_category_func (funcs, w32uni_general, NULL, NULL); - hb_unicode_funcs_set_mirroring_func (funcs, w32uni_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; -} - -/* HarfBuzz implementation of shape for font backend. See the - commentary before uniscribe_shape for the meaning of the - arguments. */ -static Lisp_Object -w32hb_shape (Lisp_Object lgstring, Lisp_Object direction) -{ - struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); - 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); - - /* Copy the characters in their original logical order, so we can - assign them to glyphs correctly after shaping. */ - int *chars = alloca (text_len * sizeof (int)); - 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); - chars[i] = c; - } - - 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_GRAPHEMES); - - /* If the caller didn't provide a meaningful DIRECTION, let HarfBuzz - guess it. */ - if (!NILP (direction)) - { - 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: maybe drop this guessing once script and language handling - is fixed above; but then will need to guess the direction by - ourselves, perhaps by looking at the the characters using - bidi_get_type or somesuch. */ - hb_buffer_guess_segment_properties (hb_buffer); - - double position_unit; - hb_font_t *hb_font - = font->driver->begin_hb_font - ? font->driver->begin_hb_font (font, &position_unit) - : NULL; - 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 grow the lgstring in this case? Giving up is an - * overly heavy handed solution. */ - if (glyph_len > LGSTRING_GLYPH_LEN (lgstring)) - return Qnil; - - /* We need the clusters in logical order. */ - bool buf_reversed = false; - if (HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (hb_buffer))) - { - buf_reversed = true; - hb_buffer_reverse_clusters (hb_buffer); - } - info = hb_buffer_get_glyph_infos (hb_buffer, NULL); - pos = hb_buffer_get_glyph_positions (hb_buffer, NULL); - int from = -1, to, cluster_offset = 0; - int char_idx, incr = buf_reversed ? -1 : 1; - for (i = 0; i < glyph_len; i++) - { - Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i); - struct font_metrics metrics = {.width = 0}; - int xoff, yoff, wadjust; - - if (NILP (lglyph)) - { - lglyph = LGLYPH_NEW (); - LGSTRING_SET_GLYPH (lgstring, i, lglyph); - } - - if (info[i].cluster != from) - { - int j; - /* Found a new cluster. Determine its FROM and TO, and the - offset to the first character of the cluster. */ - /* FROM is the index of the first character that contributed - to this cluster. */ - from = info[i].cluster; - /* TO is the index of the last character that contributed to - this cluster. */ - for (j = i; j < glyph_len && info[j].cluster == from; j++) - ; - to = (j == glyph_len) ? text_len - 1 : info[j].cluster - 1; - cluster_offset = 0; - /* For RTL buffers, HarfBuzz produces glyphs in a cluster in - reverse order, so we need to account for that to record - the correct character in each glyph. - - Implementation note: the character codepoint recorded in - each glyph is not really used, except when we display the - glyphs in descr-text.el. So this is just an aeasthetic - issue. */ - if (buf_reversed) - cluster_offset = to - from; - } - - /* All the glyphs in a cluster have the same values of FROM and TO. */ - LGLYPH_SET_FROM (lglyph, from); - LGLYPH_SET_TO (lglyph, to); - - /* Not every glyph in a cluster maps directly to a single - character; in general, N characters can yield M glyphs, where - M could be smaller or greater than N. However, in many cases - there is a one-to-one correspondence, and it would be a pity - to lose that information, even if it's sometimes inaccurate. */ - char_idx = from + cluster_offset; - cluster_offset += incr; - if (char_idx > to) - char_idx = to; - if (char_idx < from) - char_idx = from; - LGLYPH_SET_CHAR (lglyph, chars[char_idx]); - 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); -} - -static Lisp_Object -w32hb_combining_capability (struct font *font) -{ - return Qt; -} #endif /* HAVE_HARFBUZZ */ #undef OTF_INT16_VAL @@ -1838,29 +1439,7 @@ load_harfbuzz_funcs (HMODULE library) LOAD_DLL_FN (library, hb_face_get_upem); LOAD_DLL_FN (library, hb_face_destroy); LOAD_DLL_FN (library, hb_font_get_nominal_glyph); - LOAD_DLL_FN (library, hb_unicode_funcs_create); - LOAD_DLL_FN (library, hb_unicode_funcs_get_default); - LOAD_DLL_FN (library, hb_unicode_funcs_set_combining_class_func); - LOAD_DLL_FN (library, hb_unicode_funcs_set_general_category_func); - LOAD_DLL_FN (library, hb_unicode_funcs_set_mirroring_func); - LOAD_DLL_FN (library, hb_buffer_create); - LOAD_DLL_FN (library, hb_buffer_set_unicode_funcs); - LOAD_DLL_FN (library, hb_buffer_clear_contents); - LOAD_DLL_FN (library, hb_buffer_pre_allocate); - LOAD_DLL_FN (library, hb_buffer_add); - LOAD_DLL_FN (library, hb_buffer_set_content_type); - LOAD_DLL_FN (library, hb_buffer_set_cluster_level); - LOAD_DLL_FN (library, hb_buffer_set_direction); - LOAD_DLL_FN (library, hb_buffer_set_language); - LOAD_DLL_FN (library, hb_language_from_string); - LOAD_DLL_FN (library, hb_buffer_guess_segment_properties); - LOAD_DLL_FN (library, hb_shape_full); - LOAD_DLL_FN (library, hb_buffer_get_length); - LOAD_DLL_FN (library, hb_buffer_get_direction); - LOAD_DLL_FN (library, hb_buffer_reverse_clusters); - LOAD_DLL_FN (library, hb_buffer_get_glyph_infos); - LOAD_DLL_FN (library, hb_buffer_get_glyph_positions); - return true; + return hbfont_init_w32_funcs (library); } #endif /* HAVE_HARFBUZZ */ @@ -1913,8 +1492,8 @@ syms_of_w32uniscribe_for_pdumper (void) harfbuzz_font_driver.list = w32hb_list; harfbuzz_font_driver.match = w32hb_match; harfbuzz_font_driver.encode_char = w32hb_encode_char; - harfbuzz_font_driver.shape = w32hb_shape; - harfbuzz_font_driver.combining_capability = w32hb_combining_capability; + harfbuzz_font_driver.shape = hbfont_shape; + harfbuzz_font_driver.combining_capability = hbfont_combining_capability; harfbuzz_font_driver.begin_hb_font = w32hb_begin_font; register_font_driver (&harfbuzz_font_driver, NULL); #endif /* HAVE_HARFBUZZ */ |