From: YAMAMOTO Mitsuharu Date: Thu, 23 May 2019 01:53:23 +0000 (+0900) Subject: Merge branch 'master' into harfbuzz X-Git-Tag: emacs-27.0.90~2671^2~20 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=b40dde705af4d53853de6185a2468153b442dc9a;p=emacs.git Merge branch 'master' into harfbuzz --- b40dde705af4d53853de6185a2468153b442dc9a diff --cc src/font.h index 1f62a61f0be,9ca0c97dc52..a590bda3db4 --- a/src/font.h +++ b/src/font.h @@@ -920,13 -894,8 +920,13 @@@ extern Lisp_Object ftfont_shape (Lisp_O extern unsigned ftfont_encode_char (struct font *, int); extern void ftfont_close (struct font *); extern void ftfont_filter_properties (Lisp_Object, Lisp_Object); - extern void ftfont_text_extents (struct font *, unsigned *, int, + 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 */ #ifdef HAVE_X_WINDOWS diff --cc src/ftcrfont.c index dc59c2bcadc,9686cec0e8c..79bf68141dc --- a/src/ftcrfont.c +++ b/src/ftcrfont.c @@@ -110,99 -117,159 +109,168 @@@ ftcrfont_match (struct frame *f, Lisp_O static Lisp_Object ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) { - Lisp_Object font_object; - - FT_UInt size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX)); + FcResult result; + Lisp_Object val, filename, font_object; + FcPattern *pat, *match; + struct font_info *ftcrfont_info; + struct font *font; + double size = 0; + cairo_font_face_t *font_face; + cairo_font_extents_t extents; + FT_Face ft_face; + FcMatrix *matrix; + + val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); + if (! CONSP (val)) + return Qnil; + val = XCDR (val); + filename = XCAR (val); + size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX)); if (size == 0) size = pixel_size; - font_object = font_build_object (VECSIZE (struct font_info), - 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)) + + pat = ftfont_entity_pattern (entity, pixel_size); + FcConfigSubstitute (NULL, pat, FcMatchPattern); + FcDefaultSubstitute (pat); + match = FcFontMatch (NULL, pat, &result); + ftfont_fix_match (pat, match); + + FcPatternDestroy (pat); + font_face = cairo_ft_font_face_create_for_pattern (match); + if (!font_face) { - struct font *font = XFONT_OBJECT (font_object); - struct font_info *ftcrfont_info = (struct font_info *) font; - FT_Face ft_face = ftcrfont_info->ft_size->face; + unblock_input (); + FcPatternDestroy (match); + return Qnil; + } + cairo_matrix_t font_matrix, ctm; + cairo_matrix_init_scale (&font_matrix, pixel_size, pixel_size); + cairo_matrix_init_identity (&ctm); + cairo_font_options_t *options = cairo_font_options_create (); + cairo_scaled_font_t *scaled_font + = cairo_scaled_font_create (font_face, &font_matrix, &ctm, options); + cairo_font_face_destroy (font_face); + cairo_font_options_destroy (options); + unblock_input (); + font_object = font_build_object (VECSIZE (struct font_info), - Qftcr, 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), Qftcrhb)) - font->driver = &ftcrhbfont_driver; - else ++ 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); - if (ftcrfont_info->bitmap_strike_index < 0) - FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size); - else - FT_Select_Size (ft_face, ftcrfont_info->bitmap_strike_index); - cairo_font_face_t *font_face = - cairo_ft_font_face_create_for_ft_face (ft_face, 0); - cairo_matrix_t font_matrix, ctm; - cairo_matrix_init_scale (&font_matrix, pixel_size, pixel_size); - cairo_matrix_init_identity (&ctm); - cairo_font_options_t *options = cairo_font_options_create (); - ftcrfont_info->cr_scaled_font = - cairo_scaled_font_create (font_face, &font_matrix, &ctm, options); - cairo_font_face_destroy (font_face); - cairo_font_options_destroy (options); - ftcrfont_info->metrics = NULL; - ftcrfont_info->metrics_nrows = 0; - if (ftcrfont_info->bitmap_strike_index >= 0) + font->driver = &ftcrfont_driver; + font->encoding_charset = font->repertory_charset = -1; + + ftcrfont_info = (struct font_info *) font; + ftcrfont_info->cr_scaled_font = scaled_font; + + /* This means that there's no need of transformation. */ + ftcrfont_info->matrix.xx = 0; + if (FcPatternGetMatrix (match, FC_MATRIX, 0, &matrix) == FcResultMatch) + { + ftcrfont_info->matrix.xx = 0x10000L * matrix->xx; + ftcrfont_info->matrix.yy = 0x10000L * matrix->yy; + ftcrfont_info->matrix.xy = 0x10000L * matrix->xy; + ftcrfont_info->matrix.yx = 0x10000L * matrix->yx; + } + + ftcrfont_info->metrics = NULL; + ftcrfont_info->metrics_nrows = 0; + + block_input (); + cairo_glyph_t stack_glyph; + int n = 0; + font->min_width = font->average_width = font->space_width = 0; + for (char c = 32; c < 127; c++) + { + cairo_glyph_t *glyphs = &stack_glyph; + int num_glyphs = 1; + cairo_status_t status = + cairo_scaled_font_text_to_glyphs (ftcrfont_info->cr_scaled_font, + 0, 0, &c, 1, &glyphs, &num_glyphs, + NULL, NULL, NULL); + + if (status == CAIRO_STATUS_SUCCESS) { - /* Several members of struct font/font_info set by - ftfont_open2 are bogus. Recalculate them with cairo - scaled font functions. */ - cairo_font_extents_t extents; - cairo_scaled_font_extents (ftcrfont_info->cr_scaled_font, &extents); - font->ascent = lround (extents.ascent); - font->descent = lround (extents.descent); - font->height = lround (extents.height); - - cairo_glyph_t stack_glyph; - int n = 0; - font->min_width = font->average_width = font->space_width = 0; - for (char c = 32; c < 127; c++) + if (glyphs != &stack_glyph) + cairo_glyph_free (glyphs); + else if (stack_glyph.index) { - cairo_glyph_t *glyphs = &stack_glyph; - int num_glyphs = 1; - cairo_status_t status = - cairo_scaled_font_text_to_glyphs (ftcrfont_info->cr_scaled_font, - 0, 0, &c, 1, - &glyphs, &num_glyphs, - NULL, NULL, NULL); - - if (status == CAIRO_STATUS_SUCCESS) - { - if (glyphs != &stack_glyph) - cairo_glyph_free (glyphs); - else - { - int this_width = - ftcrfont_glyph_extents (font, stack_glyph.index, NULL); - - if (this_width > 0 - && (! font->min_width - || font->min_width > this_width)) - font->min_width = this_width; - if (c == 32) - font->space_width = this_width; - font->average_width += this_width; - n++; - } - } + int this_width = ftcrfont_glyph_extents (font, stack_glyph.index, + NULL); + + if (this_width > 0 + && (! font->min_width + || font->min_width > this_width)) + font->min_width = this_width; + if (c == 32) + font->space_width = this_width; + font->average_width += this_width; + n++; } - if (n > 0) - font->average_width /= n; - - font->underline_position = -1; - font->underline_thickness = 0; } } + if (n > 0) + font->average_width /= n; + + cairo_scaled_font_extents (ftcrfont_info->cr_scaled_font, &extents); + font->ascent = lround (extents.ascent); + val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX)); + if (!(CONSP (val) && NILP (XCDR (val)))) + { + font->descent = lround (extents.descent); + font->height = font->ascent + font->descent; + } + else + { + font->height = lround (extents.height); + font->descent = font->height - font->ascent; + } + + ft_face = cairo_ft_scaled_font_lock_face (scaled_font); + if (XFIXNUM (AREF (entity, FONT_SIZE_INDEX)) == 0) + { + int upEM = ft_face->units_per_EM; + + font->underline_position = -ft_face->underline_position * size / upEM; + font->underline_thickness = ft_face->underline_thickness * size / upEM; + if (font->underline_thickness > 2) + font->underline_position -= font->underline_thickness / 2; + } + else + { + font->underline_position = -1; + font->underline_thickness = 0; + } + #ifdef HAVE_LIBOTF + ftcrfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0; + ftcrfont_info->otf = NULL; + #endif /* HAVE_LIBOTF */ ++#ifdef HAVE_HARFBUZZ ++ ftcrfont_info->hb_font = NULL; ++#endif /* HAVE_HARFBUZZ */ + if (ft_face->units_per_EM) + ftcrfont_info->bitmap_position_unit = 0; + else + ftcrfont_info->bitmap_position_unit = (extents.height + / ft_face->size->metrics.height); + cairo_ft_scaled_font_unlock_face (scaled_font); + ftcrfont_info->ft_size = NULL; unblock_input (); + font->baseline_offset = 0; + font->relative_compose = 0; + font->default_ascent = 0; + font->vertical_centering = false; + return font_object; } @@@ -213,10 -280,16 +281,23 @@@ ftcrfont_close (struct font *font return; struct font_info *ftcrfont_info = (struct font_info *) font; - int i; block_input (); - for (i = 0; i < ftcrfont_info->metrics_nrows; i++) + #ifdef HAVE_LIBOTF + if (ftcrfont_info->otf) + { + OTF_close (ftcrfont_info->otf); + ftcrfont_info->otf = NULL; + } ++#endif ++#ifdef HAVE_HARFBUZZ ++ if (ftcrfont_info->hb_font) ++ { ++ hb_font_destroy (ftcrfont_info->hb_font); ++ ftcrfont_info->hb_font = NULL; ++ } + #endif + for (int i = 0; i < ftcrfont_info->metrics_nrows; i++) if (ftcrfont_info->metrics[i]) xfree (ftcrfont_info->metrics[i]); if (ftcrfont_info->metrics) @@@ -280,25 -394,75 +402,75 @@@ ftcrfont_anchor_point (struct font *fon { struct font_info *ftcrfont_info = (struct font_info *) font; - if (ftcrfont_info->bitmap_strike_index < 0) - return ftfont_anchor_point (font, code, idx, x, y); + if (ftcrfont_info->bitmap_position_unit) + return -1; - return -1; + cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font; + FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font); + + ftcrfont_info->ft_size = ft_face->size; + int result = ftfont_anchor_point (font, code, idx, x, y); + cairo_ft_scaled_font_unlock_face (scaled_font); + ftcrfont_info->ft_size = NULL; + + return result; } + #ifdef HAVE_LIBOTF static Lisp_Object - ftcrfont_shape (Lisp_Object lgstring, Lisp_Object direction) + ftcrfont_otf_capability (struct font *font) { + struct font_info *ftcrfont_info = (struct font_info *) font; + cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font; + FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font); + + ftcrfont_info->ft_size = ft_face->size; + Lisp_Object result = ftfont_otf_capability (font); + cairo_ft_scaled_font_unlock_face (scaled_font); + ftcrfont_info->ft_size = NULL; + + return result; + } + #endif + #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF + static Lisp_Object -ftcrfont_shape (Lisp_Object lgstring) ++ftcrfont_shape (Lisp_Object lgstring, Lisp_Object direction) + { struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); struct font_info *ftcrfont_info = (struct font_info *) font; - if (ftcrfont_info->bitmap_strike_index < 0) - return ftfont_shape (lgstring, direction); + if (ftcrfont_info->bitmap_position_unit) + return make_fixnum (0); + + cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font; + FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font); + + ftcrfont_info->ft_size = ft_face->size; - Lisp_Object result = ftfont_shape (lgstring); ++ Lisp_Object result = ftfont_shape (lgstring, direction); + cairo_ft_scaled_font_unlock_face (scaled_font); + ftcrfont_info->ft_size = NULL; + + return result; + } #endif - return make_fixnum (0); + #ifdef HAVE_OTF_GET_VARIATION_GLYPHS + static int + ftcrfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) + { + struct font_info *ftcrfont_info = (struct font_info *) font; + cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font; + FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font); + + ftcrfont_info->ft_size = ft_face->size; + int result = ftfont_variation_glyphs (font, c, variations); + cairo_ft_scaled_font_unlock_face (scaled_font); + ftcrfont_info->ft_size = NULL; + + return result; } + #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */ static int ftcrfont_draw (struct glyph_string *s, @@@ -359,39 -510,6 +518,46 @@@ 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; ++ cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font; ++ FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font); + - FT_Activate_Size (ftcrfont_info->ft_size_draw); ++ ftcrfont_info->ft_size = ft_face->size; + 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); - } ++ if (ftcrfont_info->bitmap_position_unit) ++ *position_unit = ftcrfont_info->bitmap_position_unit; + + return hb_font; +} + ++static void ++ftcrhbfont_end_hb_font (struct font *font, hb_font_t *hb_font) ++{ ++ struct font_info *ftcrfont_info = (struct font_info *) font; ++ cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font; ++ ++ cairo_ft_scaled_font_unlock_face (scaled_font); ++ ftcrfont_info->ft_size = NULL; ++} ++ +#endif /* HAVE_HARFBUZZ */ static void syms_of_ftcrfont_for_pdumper (void); @@@ -439,14 -553,4 +607,15 @@@ static voi 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; ++ ftcrhbfont_driver.end_hb_font = ftcrhbfont_end_hb_font; + register_font_driver (&ftcrhbfont_driver, NULL); +#endif /* HAVE_HARFBUZZ */ } diff --cc src/ftfont.c index 2373af8766a,d8b510d7032..5694c49aaf9 --- a/src/ftfont.c +++ b/src/ftfont.c @@@ -1189,10 -1292,6 +1316,9 @@@ ftfont_open (struct frame *f, Lisp_Obje ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0; ftfont_info->otf = NULL; #endif /* HAVE_LIBOTF */ +#ifdef HAVE_HARFBUZZ + ftfont_info->hb_font = NULL; +#endif /* HAVE_HARFBUZZ */ - ftfont_info->bitmap_strike_index = strike_index; /* This means that there's no need of transformation. */ ftfont_info->matrix.xx = 0; font->pixel_size = size; @@@ -1372,26 -1454,8 +1490,26 @@@ ftfont_encode_char (struct font *font, return (code > 0 ? code : FONT_INVALID_CODE); } +static bool +ftfont_glyph_metrics (FT_Face ft_face, int c, int *advance, int *lbearing, + int *rbearing, int *ascent, int *descent) +{ + if (FT_Load_Glyph (ft_face, c, FT_LOAD_DEFAULT) == 0) + { + FT_Glyph_Metrics *m = &ft_face->glyph->metrics; + *advance = m->horiAdvance >> 6; + *lbearing = m->horiBearingX >> 6; + *rbearing = (m->horiBearingX + m->width) >> 6; + *ascent = m->horiBearingY >> 6; + *descent = (m->height - m->horiBearingY) >> 6; + return true; + } + + return false; +} + void - ftfont_text_extents (struct font *font, unsigned int *code, + ftfont_text_extents (struct font *font, const unsigned int *code, int nglyphs, struct font_metrics *metrics) { struct font_info *ftfont_info = (struct font_info *) font; diff --cc src/ftfont.h index f877860895e,7860469491f..b2280e9aab9 --- a/src/ftfont.h +++ b/src/ftfont.h @@@ -59,14 -53,7 +58,10 @@@ struct font_inf #endif /* HAVE_LIBOTF */ FT_Size ft_size; int index; - /* Index of the bitmap strike used as a fallback for - FT_Set_Pixel_Sizes failure. If the value is non-negative, then - ft_size is not of the requested size. Otherwise it is -1. */ - FT_Int bitmap_strike_index; FT_Matrix matrix; +#ifdef HAVE_HARFBUZZ + hb_font_t *hb_font; +#endif /* HAVE_HARFBUZZ */ #ifdef USE_CAIRO cairo_scaled_font_t *cr_scaled_font; diff --cc src/macfont.m index 8fcbd50fe33,f825e6291d3..abdf0ecfe59 --- a/src/macfont.m +++ b/src/macfont.m @@@ -1647,10 -1639,10 +1647,10 @@@ static Lisp_Object macfont_open (struc static void macfont_close (struct font *); static int macfont_has_char (Lisp_Object, int); static unsigned macfont_encode_char (struct font *, int); - static void macfont_text_extents (struct font *, unsigned int *, int, + static void macfont_text_extents (struct font *, const unsigned int *, int, struct font_metrics *); static int macfont_draw (struct glyph_string *, int, int, int, int, bool); -static Lisp_Object macfont_shape (Lisp_Object); +static Lisp_Object macfont_shape (Lisp_Object, Lisp_Object); static int macfont_variation_glyphs (struct font *, int c, unsigned variations[256]); static void macfont_filter_properties (Lisp_Object, Lisp_Object); diff --cc src/xftfont.c index f7b87f96569,4f0a0d81d85..08e4edb535a --- a/src/xftfont.c +++ b/src/xftfont.c @@@ -815,15 -631,6 +677,9 @@@ voi 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"); - DEFSYM (QCrgba, ":rgba"); - DEFSYM (QCembolden, ":embolden"); - DEFSYM (QClcdfilter, ":lcdfilter"); DEFVAR_BOOL ("xft-font-ascent-descent-override", xft_font_ascent_descent_override,