From f208d5ae77cf381c6f1db9b1aef76d5e9805a106 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Mitsuharu Date: Sun, 5 May 2019 08:21:49 +0900 Subject: [PATCH] Add new font backend drivers for text shaping by HarfBuzz * etc/NEWS: Mention new font backend drivers xfthb and ftcrhb. * src/font.h [HAVE_HARFBUZZ]: Include hb.h. (struct font_driver) [HAVE_HARFBUZZ]: New members begin_hb_font and end_hb_font. (ftfont_match, ftfont_list): Remove externs. (ftfont_match2, ftfont_list2): (fthbfont_combining_capability, fthbfont_begin_hb_font) (fthbfont_shape) [HAVE_HARFBUZZ]: (xfthbfont_driver) [HAVE_XFT && HAVE_HARFBUZZ]: (ftcrhbfont_driver) [USE_CAIRO && HAVE_HARFBUZZ]: Add externs. * src/ftcrfont.c (ftcrfont_list): Use ftfont_list2. (ftcrfont_match): Use ftfont_match2. (ftcrfont_open): Get font type from entity. (ftcrfont_open) [HAVE_HARFBUZZ]: Use HarfBuzz version of driver if specified. (ftcrfont_shape) [HAVE_HARFBUZZ]: Make shaping fail. (ftcrhbfont_list, ftcrhbfont_match) (ftcrhbfont_begin_hb_font) [HAVE_HARFBUZZ]: New functions. (ftcrhbfont_driver) [HAVE_HARFBUZZ]: New variable. (syms_of_ftcrfont_for_pdumper) [HAVE_HARFBUZZ]: Initialize and register it. (syms_of_ftcrfont) [HAVE_HARFBUZZ]: New symbol Qftcrhb. * src/ftfont.c: Include math.h for lround. (fthbfont_driver) [HAVE_HARFBUZZ]: New variable. (ftfont_get_hb_font) [HAVE_HARFBUZZ]: Remove function. (ftfont_list, ftfont_match): Make static. (ftfont_list2, ftfont_match2): New functions. (ftfont_open2) [HAVE_HARFBUZZ]: Use HarfBuzz version of driver if specified. (ftfont_open): Get font type from entity. (ftfont_shape, ftfont_combining_capability, ftfont_driver) [HAVE_HARFBUZZ]: Move HarfBuzz specific part from here ... (fthbfont_shape, fthbfont_combining_capability) (fthbfont_driver) [HAVE_HARFBUZZ]: ... to here. New functions and variable. (fthbfont_begin_hb_font) [HAVE_HARFBUZZ]: New function. (fthbfont_shape_by_hb) [HAVE_HARFBUZZ]: Rename from ftfont_shape_by_hb. Don't take FreeType specific arguments ft_face and matrix. Use begin_hb_font and end_hb_font font driver functions. Use text_extents font driver functions instead of ftfont_glyph_metrics. (syms_of_ftfont) [HAVE_HARFBUZZ]: New symbol Qfreetypehb. (syms_of_ftfont_for_pdumper) [HAVE_HARFBUZZ]: Initialize and register fthbfont_drivert. * src/ftxfont.c (ftxfont_list): Use ftfont_list2. (ftxfont_match): Use ftfont_match2. (ftxfont_driver) [HAVE_HARFBUZZ]: Don't initialize shape member explicitly. * src/xfns.c (Fx_create_frame) [USE_CAIRO && HAVE_HARFBUZZ]: (Fx_create_frame) [HAVE_XFT && HAVE_HARFBUZZ]: Register HarfBuzz versions of font drivers. * src/xftfont.c (xftfont_list): Use ftfont_list2. (xftfont_match): Use ftfont_match2. (xftfont_open): Get font type from entity. (xftfont_open) [HAVE_HARFBUZZ]: Use HarfBuzz version of driver if specified. (xftfont_shape) [HAVE_HARFBUZZ]: Make shaping fail. (xfthbfont_list, xfthbfont_match, xfthbfont_begin_hb_font) (xfthbfont_end_hb_font) [HAVE_HARFBUZZ]: New functions. (xftfont_driver) [HAVE_HARFBUZZ]: Don't initialize shape member explicitly. (xfthbfont_driver) [HAVE_HARFBUZZ]: New variable. (syms_of_xftfont_for_pdumper) [HAVE_HARFBUZZ]: Initialize and register it. (syms_of_xftfont) [HAVE_HARFBUZZ]: New symbol Qxfthb. --- etc/NEWS | 4 +- src/font.h | 34 +++++++++- src/ftcrfont.c | 71 ++++++++++++++++---- src/ftfont.c | 174 +++++++++++++++++++++++++++++++------------------ src/ftxfont.c | 14 +--- src/xfns.c | 6 ++ src/xftfont.c | 76 +++++++++++++++++---- 7 files changed, 277 insertions(+), 102 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 7f66d1d57cc..091f958112f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -32,7 +32,9 @@ suitable libgmp is available. ** The new configure option '--with-harfbuzz' adds support for the HarfBuzz text shaping engine. It is on by default; use './configure ---without-harfbuzz' to build without it. +--without-harfbuzz' to build without it. The HarfBuzz text shaping is +available via new font backend drivers 'xfthb' and 'ftcrhb' for Xft +and Cairo drawings, respectively. ** The new configure option '--with-json' adds support for JSON using the Jansson library. It is on by default; use './configure diff --git a/src/font.h b/src/font.h index 3540a8dba22..1f62a61f0be 100644 --- a/src/font.h +++ b/src/font.h @@ -22,6 +22,10 @@ along with GNU Emacs. If not, see . */ #ifndef EMACS_FONT_H #define EMACS_FONT_H +#ifdef HAVE_HARFBUZZ +#include +#endif /* HAVE_HARFBUZZ */ + struct composition_it; struct face; struct glyph_string; @@ -780,6 +784,21 @@ struct font_driver relies on this hook to throw away its old XftDraw (which won't work after the size change) and get a new one. */ void (*drop_xrender_surfaces) (struct frame *f); + +#ifdef HAVE_HARFBUZZ + /* Optional. + Return a HarfBuzz font object for FONT and store to + *POSITION_UNIT the scale factor to convert a hb_position_t value + to the number of pixels. Return NULL if HarfBuzz font object is + not available for FONT. */ + hb_font_t *(*begin_hb_font) (struct font *font, double *position_unit); + + /* Optional. + Called when the return value (passed as HB_FONT) of begin_hb_font + above is no longer used. Not called if the return value of + begin_hb_font was NULL. */ + void (*end_hb_font) (struct font *font, hb_font_t *hb_font); +#endif /* HAVE_HARFBUZZ */ }; @@ -892,9 +911,9 @@ extern int ftfont_has_char (Lisp_Object, int); extern int ftfont_variation_glyphs (struct font *, int, unsigned[256]); extern Lisp_Object ftfont_combining_capability (struct font *); extern Lisp_Object ftfont_get_cache (struct frame *); -extern Lisp_Object ftfont_list (struct frame *, Lisp_Object); +extern Lisp_Object ftfont_list2 (struct frame *, Lisp_Object, Lisp_Object); extern Lisp_Object ftfont_list_family (struct frame *); -extern Lisp_Object ftfont_match (struct frame *, Lisp_Object); +extern Lisp_Object ftfont_match2 (struct frame *, Lisp_Object, Lisp_Object); extern Lisp_Object ftfont_open (struct frame *, Lisp_Object, int); extern Lisp_Object ftfont_otf_capability (struct font *); extern Lisp_Object ftfont_shape (Lisp_Object, Lisp_Object); @@ -903,6 +922,11 @@ extern void ftfont_close (struct font *); extern void ftfont_filter_properties (Lisp_Object, Lisp_Object); extern void ftfont_text_extents (struct font *, 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 */ #ifdef HAVE_X_WINDOWS @@ -912,6 +936,9 @@ extern void syms_of_xfont (void); extern void syms_of_ftxfont (void); #ifdef HAVE_XFT extern struct font_driver const xftfont_driver; +#ifdef HAVE_HARFBUZZ +extern struct font_driver xfthbfont_driver; +#endif /* HAVE_HARFBUZZ */ #endif #if defined HAVE_FREETYPE || defined HAVE_XFT extern struct font_driver const ftxfont_driver; @@ -933,6 +960,9 @@ extern void syms_of_macfont (void); #endif /* HAVE_NS */ #ifdef USE_CAIRO extern struct font_driver const ftcrfont_driver; +#ifdef HAVE_HARFBUZZ +extern struct font_driver ftcrhbfont_driver; +#endif /* HAVE_HARFBUZZ */ extern void syms_of_ftcrfont (void); #endif diff --git a/src/ftcrfont.c b/src/ftcrfont.c index c0f62e0418e..dc59c2bcadc 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c @@ -98,21 +98,13 @@ ftcrfont_glyph_extents (struct font *font, static Lisp_Object ftcrfont_list (struct frame *f, Lisp_Object spec) { - Lisp_Object list = ftfont_list (f, spec), tail; - - for (tail = list; CONSP (tail); tail = XCDR (tail)) - ASET (XCAR (tail), FONT_TYPE_INDEX, Qftcr); - return list; + return ftfont_list2 (f, spec, Qftcr); } static Lisp_Object ftcrfont_match (struct frame *f, Lisp_Object spec) { - Lisp_Object entity = ftfont_match (f, spec); - - if (VECTORP (entity)) - ASET (entity, FONT_TYPE_INDEX, Qftcr); - return entity; + return ftfont_match2 (f, spec, Qftcr); } static Lisp_Object @@ -124,7 +116,8 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) if (size == 0) size = pixel_size; font_object = font_build_object (VECSIZE (struct font_info), - Qftcr, entity, size); + AREF (entity, FONT_TYPE_INDEX), + entity, size); block_input (); font_object = ftfont_open2 (f, entity, pixel_size, font_object); if (FONT_OBJECT_P (font_object)) @@ -133,6 +126,11 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) struct font_info *ftcrfont_info = (struct font_info *) font; FT_Face ft_face = ftcrfont_info->ft_size->face; +#ifdef HAVE_HARFBUZZ + if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qftcrhb)) + font->driver = &ftcrhbfont_driver; + else +#endif /* HAVE_HARFBUZZ */ font->driver = &ftcrfont_driver; FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw); FT_Activate_Size (ftcrfont_info->ft_size_draw); @@ -291,7 +289,7 @@ ftcrfont_anchor_point (struct font *font, unsigned int code, int idx, static Lisp_Object ftcrfont_shape (Lisp_Object lgstring, Lisp_Object direction) { -#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ +#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); struct font_info *ftcrfont_info = (struct font_info *) font; @@ -361,6 +359,39 @@ ftcrfont_draw (struct glyph_string *s, return len; } +#ifdef HAVE_HARFBUZZ + +static Lisp_Object +ftcrhbfont_list (struct frame *f, Lisp_Object spec) +{ + return ftfont_list2 (f, spec, Qftcrhb); +} + +static Lisp_Object +ftcrhbfont_match (struct frame *f, Lisp_Object spec) +{ + return ftfont_match2 (f, spec, Qftcrhb); +} + +static hb_font_t * +ftcrhbfont_begin_hb_font (struct font *font, double *position_unit) +{ + struct font_info *ftcrfont_info = (struct font_info *) font; + + FT_Activate_Size (ftcrfont_info->ft_size_draw); + hb_font_t *hb_font = fthbfont_begin_hb_font (font, position_unit); + int i = ftcrfont_info->bitmap_strike_index; + if (i >= 0) + { + FT_Face ft_face = ftcrfont_info->ft_size_draw->face; + *position_unit = ((double) font->height + / ft_face->available_sizes[i].height) / (1 << 6); + } + + return hb_font; +} + +#endif /* HAVE_HARFBUZZ */ static void syms_of_ftcrfont_for_pdumper (void); @@ -390,11 +421,17 @@ struct font_driver const ftcrfont_driver = .filter_properties = ftfont_filter_properties, .combining_capability = ftfont_combining_capability, }; +#ifdef HAVE_HARFBUZZ +struct font_driver ftcrhbfont_driver; +#endif /* HAVE_HARFBUZZ */ void syms_of_ftcrfont (void) { DEFSYM (Qftcr, "ftcr"); +#ifdef HAVE_HARFBUZZ + DEFSYM (Qftcrhb, "ftcrhb"); +#endif /* HAVE_HARFBUZZ */ pdumper_do_now_and_after_load (syms_of_ftcrfont_for_pdumper); } @@ -402,4 +439,14 @@ static void syms_of_ftcrfont_for_pdumper (void) { register_font_driver (&ftcrfont_driver, NULL); +#ifdef HAVE_HARFBUZZ + ftcrhbfont_driver = ftcrfont_driver; + 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.begin_hb_font = ftcrhbfont_begin_hb_font; + register_font_driver (&ftcrhbfont_driver, NULL); +#endif /* HAVE_HARFBUZZ */ } diff --git a/src/ftfont.c b/src/ftfont.c index 58c462a90fe..f4e0d7d8408 100644 --- a/src/ftfont.c +++ b/src/ftfont.c @@ -21,6 +21,7 @@ along with GNU Emacs. If not, see . */ #include #include +#include #include #include @@ -48,6 +49,9 @@ along with GNU Emacs. If not, see . */ #include "pdumper.h" static struct font_driver const ftfont_driver; +#ifdef HAVE_HARFBUZZ +static struct font_driver fthbfont_driver; +#endif /* HAVE_HARFBUZZ */ /* Flag to tell if FcInit is already called or not. */ static bool fc_initialized; @@ -466,19 +470,6 @@ ftfont_get_otf (struct font_info *ftfont_info) } #endif /* HAVE_LIBOTF */ -#ifdef HAVE_HARFBUZZ - -static hb_font_t * -ftfont_get_hb_font (struct font_info *ftfont_info) -{ - if (! ftfont_info->hb_font) - ftfont_info->hb_font - = hb_ft_font_create_referenced (ftfont_info->ft_size->face); - return ftfont_info->hb_font; -} - -#endif /* HAVE_HARFBUZZ */ - Lisp_Object ftfont_get_cache (struct frame *f) { @@ -801,7 +792,7 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots return pattern; } -Lisp_Object +static Lisp_Object ftfont_list (struct frame *f, Lisp_Object spec) { Lisp_Object val = Qnil, family, adstyle; @@ -1001,6 +992,16 @@ ftfont_list (struct frame *f, Lisp_Object spec) } Lisp_Object +ftfont_list2 (struct frame *f, Lisp_Object spec, Lisp_Object type) +{ + Lisp_Object list = ftfont_list (f, spec); + + for (Lisp_Object tail = list; CONSP (tail); tail = XCDR (tail)) + ASET (XCAR (tail), FONT_TYPE_INDEX, type); + return list; +} + +static Lisp_Object ftfont_match (struct frame *f, Lisp_Object spec) { Lisp_Object entity = Qnil; @@ -1050,6 +1051,16 @@ ftfont_match (struct frame *f, Lisp_Object spec) return entity; } +Lisp_Object +ftfont_match2 (struct frame *f, Lisp_Object spec, Lisp_Object type) +{ + Lisp_Object entity = ftfont_match (f, spec); + + if (! NILP (entity)) + ASET (entity, FONT_TYPE_INDEX, type); + return entity; +} + Lisp_Object ftfont_list_family (struct frame *f) { @@ -1185,6 +1196,11 @@ ftfont_open2 (struct frame *f, /* This means that there's no need of transformation. */ ftfont_info->matrix.xx = 0; font->pixel_size = size; +#ifdef HAVE_HARFBUZZ + if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qfreetypehb)) + font->driver = &fthbfont_driver; + else +#endif /* HAVE_HARFBUZZ */ font->driver = &ftfont_driver; font->encoding_charset = font->repertory_charset = -1; @@ -1266,7 +1282,8 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) if (size == 0) size = pixel_size; font_object = font_build_object (VECSIZE (struct font_info), - Qfreetype, entity, size); + AREF (entity, FONT_TYPE_INDEX), + entity, size); font_object = ftfont_open2 (f, entity, pixel_size, font_object); if (FONT_OBJECT_P (font_object)) { @@ -2673,6 +2690,17 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, return make_fixnum (i); } +Lisp_Object +ftfont_shape (Lisp_Object lgstring) +{ + struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); + struct font_info *ftfont_info = (struct font_info *) font; + OTF *otf = ftfont_get_otf (ftfont_info); + + return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf, + &ftfont_info->matrix); +} + #endif /* HAVE_M17N_FLT */ #ifdef HAVE_OTF_GET_VARIATION_GLYPHS @@ -2693,6 +2721,18 @@ ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) #ifdef HAVE_HARFBUZZ +hb_font_t * +fthbfont_begin_hb_font (struct font *font, double *position_unit) +{ + struct font_info *ftfont_info = (struct font_info *) font; + + *position_unit = 1.0 / (1 << 6); + if (! ftfont_info->hb_font) + ftfont_info->hb_font + = hb_ft_font_create_referenced (ftfont_info->ft_size->face); + 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) { @@ -2818,8 +2858,8 @@ get_hb_unicode_funcs (void) } static Lisp_Object -ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font, - FT_Matrix *matrix, Lisp_Object direction) +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; @@ -2892,7 +2932,15 @@ ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font, above. FIXME: drop once script handling is fixed above. */ hb_buffer_guess_segment_properties (hb_buffer); - if (!hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL)) + 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); @@ -2913,7 +2961,8 @@ ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font, { Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i); EMACS_INT from, to; - int advance = 0, lbearing, rbearing, ascent, descent; + struct font_metrics metrics = {.width = 0}; + int xoff, yoff, wadjust; ptrdiff_t j = i; if (NILP (lglyph)) @@ -2936,61 +2985,46 @@ ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font, LGLYPH_SET_CHAR (lglyph, LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, from))); LGLYPH_SET_CODE (lglyph, info[i].codepoint); - if (ftfont_glyph_metrics (ft_face, info[i].codepoint, &advance, &lbearing, - &rbearing, &ascent, &descent)) - { - LGLYPH_SET_WIDTH (lglyph, advance); - LGLYPH_SET_LBEARING (lglyph, lbearing); - LGLYPH_SET_RBEARING (lglyph, rbearing); - LGLYPH_SET_ASCENT (lglyph, ascent); - LGLYPH_SET_DESCENT (lglyph, descent); - } - - if (pos[i].x_offset || pos[i].y_offset || - (pos[i].x_advance >> 6) != advance) - { - Lisp_Object vec = make_uninit_vector (3); - ASET (vec, 0, make_fixnum (pos[i].x_offset >> 6)); - ASET (vec, 1, make_fixnum (-(pos[i].y_offset >> 6))); - ASET (vec, 2, make_fixnum (pos[i].x_advance >> 6)); - LGLYPH_SET_ADJUSTMENT (lglyph, vec); - } + 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); } -#endif /* HAVE_HARFBUZZ */ - -#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ +Lisp_Object +fthbfont_combining_capability (struct font *font) +{ + return Qt; +} Lisp_Object -ftfont_shape (Lisp_Object lgstring, Lisp_Object direction) +fthbfont_shape (Lisp_Object lgstring, Lisp_Object direction) { struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); struct font_info *ftfont_info = (struct font_info *) font; -#ifdef HAVE_HARFBUZZ - if (getenv ("EMACS_NO_HARFBUZZ") == NULL) - { - hb_font_t *hb_font = ftfont_get_hb_font (ftfont_info); - - return ftfont_shape_by_hb (lgstring, ftfont_info->ft_size->face, - hb_font, &ftfont_info->matrix, direction); - } - else -#endif /* HAVE_HARFBUZZ */ - { -#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF - OTF *otf = ftfont_get_otf (ftfont_info); - return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, - otf, &ftfont_info->matrix); -#endif /* defined HAVE_M17N_FLT && defined HAVE_LIBOTF */ - } - return make_fixnum (0); + return fthbfont_shape_by_hb (lgstring, font, direction); } -#endif /* (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ */ +#endif /* HAVE_HARFBUZZ */ static const char *const ftfont_booleans [] = { ":antialias", @@ -3046,7 +3080,7 @@ ftfont_filter_properties (Lisp_Object font, Lisp_Object alist) Lisp_Object ftfont_combining_capability (struct font *font) { -#if defined HAVE_M17N_FLT || defined HAVE_HARFBUZZ +#ifdef HAVE_M17N_FLT return Qt; #else return Qnil; @@ -3073,7 +3107,7 @@ static struct font_driver const ftfont_driver = #ifdef HAVE_LIBOTF .otf_capability = ftfont_otf_capability, #endif -#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ +#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF .shape = ftfont_shape, #endif #ifdef HAVE_OTF_GET_VARIATION_GLYPHS @@ -3082,12 +3116,18 @@ static struct font_driver const ftfont_driver = .filter_properties = ftfont_filter_properties, .combining_capability = ftfont_combining_capability, }; +#ifdef HAVE_HARFBUZZ +static struct font_driver fthbfont_driver; +#endif /* HAVE_HARFBUZZ */ void syms_of_ftfont (void) { /* Symbolic type of this font-driver. */ DEFSYM (Qfreetype, "freetype"); +#ifdef HAVE_HARFBUZZ + DEFSYM (Qfreetypehb, "freetypehb"); +#endif /* HAVE_HARFBUZZ */ /* Fontconfig's generic families and their aliases. */ DEFSYM (Qmonospace, "monospace"); @@ -3114,4 +3154,12 @@ syms_of_ftfont_for_pdumper (void) { PDUMPER_RESET_LV (ft_face_cache, Qnil); register_font_driver (&ftfont_driver, NULL); +#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.begin_hb_font = fthbfont_begin_hb_font; + register_font_driver (&fthbfont_driver, NULL); +#endif /* HAVE_HARFBUZZ */ } diff --git a/src/ftxfont.c b/src/ftxfont.c index a549fd723bb..949ef4c503b 100644 --- a/src/ftxfont.c +++ b/src/ftxfont.c @@ -209,21 +209,13 @@ ftxfont_draw_background (struct frame *f, struct font *font, GC gc, int x, int y static Lisp_Object ftxfont_list (struct frame *f, Lisp_Object spec) { - Lisp_Object list = ftfont_list (f, spec), tail; - - for (tail = list; CONSP (tail); tail = XCDR (tail)) - ASET (XCAR (tail), FONT_TYPE_INDEX, Qftx); - return list; + return ftfont_list2 (f, spec, Qftx); } static Lisp_Object ftxfont_match (struct frame *f, Lisp_Object spec) { - Lisp_Object entity = ftfont_match (f, spec); - - if (VECTORP (entity)) - ASET (entity, FONT_TYPE_INDEX, Qftx); - return entity; + return ftfont_match2 (f, spec, Qftx); } static Lisp_Object @@ -362,7 +354,7 @@ struct font_driver const ftxfont_driver = .otf_capability = ftfont_otf_capability, #endif .end_for_frame = ftxfont_end_for_frame, -#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ +#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF .shape = ftfont_shape, #endif #ifdef HAVE_OTF_GET_VARIATION_GLYPHS diff --git a/src/xfns.c b/src/xfns.c index 2ceb55a30ad..50a430aa78c 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -3774,10 +3774,16 @@ This function is an internal primitive--use `make-frame' instead. */) #ifdef USE_CAIRO register_font_driver (&ftcrfont_driver, f); +#ifdef HAVE_HARFBUZZ + register_font_driver (&ftcrhbfont_driver, f); +#endif /* HAVE_HARFBUZZ */ #else #ifdef HAVE_FREETYPE #ifdef HAVE_XFT register_font_driver (&xftfont_driver, f); +#ifdef HAVE_HARFBUZZ + register_font_driver (&xfthbfont_driver, f); +#endif #else /* not HAVE_XFT */ register_font_driver (&ftxfont_driver, f); #endif /* not HAVE_XFT */ diff --git a/src/xftfont.c b/src/xftfont.c index b636a759048..f7b87f96569 100644 --- a/src/xftfont.c +++ b/src/xftfont.c @@ -108,21 +108,13 @@ xftfont_get_colors (struct frame *f, struct face *face, GC gc, static Lisp_Object xftfont_list (struct frame *f, Lisp_Object spec) { - Lisp_Object list = ftfont_list (f, spec); - - for (Lisp_Object tail = list; CONSP (tail); tail = XCDR (tail)) - ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft); - return list; + return ftfont_list2 (f, spec, Qxft); } static Lisp_Object xftfont_match (struct frame *f, Lisp_Object spec) { - Lisp_Object entity = ftfont_match (f, spec); - - if (! NILP (entity)) - ASET (entity, FONT_TYPE_INDEX, Qxft); - return entity; + return ftfont_match2 (f, spec, Qxft); } static FcChar8 ascii_printable[95]; @@ -311,10 +303,16 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) /* We should not destroy PAT here because it is kept in XFTFONT and destroyed automatically when XFTFONT is closed. */ font_object = font_build_object (VECSIZE (struct font_info), - Qxft, entity, size); + AREF (entity, FONT_TYPE_INDEX), + entity, size); ASET (font_object, FONT_FILE_INDEX, filename); font = XFONT_OBJECT (font_object); font->pixel_size = size; +#ifdef HAVE_HARFBUZZ + if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qxfthb)) + font->driver = &xfthbfont_driver; + else +#endif /* HAVE_HARFBUZZ */ font->driver = &xftfont_driver; font->encoding_charset = font->repertory_charset = -1; @@ -649,7 +647,7 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, return len; } -#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ +#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF static Lisp_Object xftfont_shape (Lisp_Object lgstring, Lisp_Object direction) { @@ -739,6 +737,41 @@ xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object, return ok; } +#ifdef HAVE_HARFBUZZ + +static Lisp_Object +xfthbfont_list (struct frame *f, Lisp_Object spec) +{ + return ftfont_list2 (f, spec, Qxfthb); +} + +static Lisp_Object +xfthbfont_match (struct frame *f, Lisp_Object spec) +{ + return ftfont_match2 (f, spec, Qxfthb); +} + +static hb_font_t * +xfthbfont_begin_hb_font (struct font *font, double *position_unit) +{ + struct font_info *xftfont_info = (struct font_info *) font; + FT_Face ft_face = XftLockFace (xftfont_info->xftfont); + + xftfont_info->ft_size = ft_face->size; + + return fthbfont_begin_hb_font (font, position_unit); +} + +static void +xfthbfont_end_hb_font (struct font *font, hb_font_t *hb_font) +{ + struct font_info *xftfont_info = (struct font_info *) font; + + XftUnlockFace (xftfont_info->xftfont); +} + +#endif /* HAVE_HARFBUZZ */ + static void syms_of_xftfont_for_pdumper (void); struct font_driver const xftfont_driver = @@ -763,7 +796,7 @@ struct font_driver const xftfont_driver = .otf_capability = ftfont_otf_capability, #endif .end_for_frame = xftfont_end_for_frame, -#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ +#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF .shape = xftfont_shape, #endif #ifdef HAVE_OTF_GET_VARIATION_GLYPHS @@ -774,11 +807,17 @@ struct font_driver const xftfont_driver = .combining_capability = ftfont_combining_capability, .drop_xrender_surfaces = xftfont_drop_xrender_surfaces, }; +#ifdef HAVE_HARFBUZZ +struct font_driver xfthbfont_driver; +#endif /* HAVE_HARFBUZZ */ void syms_of_xftfont (void) { DEFSYM (Qxft, "xft"); +#ifdef HAVE_HARFBUZZ + DEFSYM (Qxfthb, "xfthb"); +#endif /* HAVE_HARFBUZZ */ DEFSYM (QChinting, ":hinting"); DEFSYM (QCautohint, ":autohint"); DEFSYM (QChintstyle, ":hintstyle"); @@ -799,4 +838,15 @@ static void syms_of_xftfont_for_pdumper (void) { register_font_driver (&xftfont_driver, NULL); +#ifdef HAVE_HARFBUZZ + xfthbfont_driver = xftfont_driver; + 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.begin_hb_font = xfthbfont_begin_hb_font; + xfthbfont_driver.end_hb_font = xfthbfont_end_hb_font; + register_font_driver (&xfthbfont_driver, NULL); +#endif /* HAVE_HARFBUZZ */ } -- 2.39.2