diff options
author | YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> | 2019-05-23 10:53:23 +0900 |
---|---|---|
committer | YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> | 2019-05-23 10:53:23 +0900 |
commit | b40dde705af4d53853de6185a2468153b442dc9a (patch) | |
tree | e8dabba695163c2d07439fad6accff761f8f714c /src/ftcrfont.c | |
parent | 5d7dafacf4afc888511649f6fc24c28210cd0dfc (diff) | |
parent | 03feb9376b54c489e24478954a11061e9b0d6db7 (diff) | |
download | emacs-b40dde705af4d53853de6185a2468153b442dc9a.tar.gz |
Merge branch 'master' into harfbuzz
Diffstat (limited to 'src/ftcrfont.c')
-rw-r--r-- | src/ftcrfont.c | 417 |
1 files changed, 293 insertions, 124 deletions
diff --git a/src/ftcrfont.c b/src/ftcrfont.c index dc59c2bcadc..79bf68141dc 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c @@ -79,7 +79,6 @@ ftcrfont_glyph_extents (struct font *font, cairo_glyph_t cr_glyph = {.index = glyph}; cairo_text_extents_t extents; - FT_Activate_Size (ftcrfont_info->ft_size_draw); cairo_scaled_font_glyph_extents (ftcrfont_info->cr_scaled_font, &cr_glyph, 1, &extents); cache->lbearing = floor (extents.x_bearing); @@ -110,99 +109,168 @@ ftcrfont_match (struct frame *f, Lisp_Object spec) 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), + 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,24 +281,70 @@ 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) xfree (ftcrfont_info->metrics); - FT_Done_Size (ftcrfont_info->ft_size_draw); cairo_scaled_font_destroy (ftcrfont_info->cr_scaled_font); unblock_input (); +} + +static int +ftcrfont_has_char (Lisp_Object font, int c) +{ + if (FONT_ENTITY_P (font)) + return ftfont_has_char (font, c); + + return -1; +} + +static unsigned +ftcrfont_encode_char (struct font *font, int c) +{ + struct font_info *ftcrfont_info = (struct font_info *) font; + unsigned code = FONT_INVALID_CODE; + unsigned char utf8[MAX_MULTIBYTE_LENGTH]; + unsigned char *p = utf8; + cairo_glyph_t stack_glyph; + cairo_glyph_t *glyphs = &stack_glyph; + int num_glyphs = 1; + + CHAR_STRING_ADVANCE (c, p); + if (cairo_scaled_font_text_to_glyphs (ftcrfont_info->cr_scaled_font, 0, 0, + (char *) utf8, p - utf8, + &glyphs, &num_glyphs, + NULL, NULL, NULL) + == CAIRO_STATUS_SUCCESS) + { + if (glyphs != &stack_glyph) + cairo_glyph_free (glyphs); + else if (stack_glyph.index) + code = stack_glyph.index; + } - ftfont_close (font); + return code; } static void ftcrfont_text_extents (struct font *font, - unsigned *code, + const unsigned *code, int nglyphs, struct font_metrics *metrics) { @@ -268,10 +382,18 @@ ftcrfont_get_bitmap (struct font *font, unsigned int code, { struct font_info *ftcrfont_info = (struct font_info *) font; - if (ftcrfont_info->bitmap_strike_index < 0) - return ftfont_get_bitmap (font, code, bitmap, bits_per_pixel); + 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_get_bitmap (font, code, bitmap, bits_per_pixel); + cairo_ft_scaled_font_unlock_face (scaled_font); + ftcrfont_info->ft_size = NULL; + + return result; } static int @@ -280,25 +402,75 @@ ftcrfont_anchor_point (struct font *font, unsigned int code, int idx, { 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, 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, 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, @@ -309,8 +481,6 @@ ftcrfont_draw (struct glyph_string *s, struct font_info *ftcrfont_info = (struct font_info *) s->font; cairo_t *cr; cairo_glyph_t *glyphs; - cairo_surface_t *surface; - cairo_surface_type_t surface_type; int len = to - from; int i; @@ -329,28 +499,17 @@ ftcrfont_draw (struct glyph_string *s, glyphs = alloca (sizeof (cairo_glyph_t) * len); for (i = 0; i < len; i++) { - unsigned code = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8) - | XCHAR2B_BYTE2 (s->char2b + from + i)); - - glyphs[i].index = code; + glyphs[i].index = s->char2b[from + i]; glyphs[i].x = x; glyphs[i].y = y; - x += (s->padding_p ? 1 : ftcrfont_glyph_extents (s->font, code, NULL)); + x += (s->padding_p ? 1 : ftcrfont_glyph_extents (s->font, + glyphs[i].index, + NULL)); } x_set_cr_source_with_gc_foreground (f, s->gc); cairo_set_scaled_font (cr, ftcrfont_info->cr_scaled_font); - - FT_Activate_Size (ftcrfont_info->ft_size_draw); cairo_show_glyphs (cr, glyphs, len); - surface = cairo_get_target (cr); - /* XXX: It used to be necessary to flush when exporting. It might - be the case that this is no longer necessary. */ - surface_type = cairo_surface_get_type (surface); - if (surface_type != CAIRO_SURFACE_TYPE_XLIB - && (surface_type != CAIRO_SURFACE_TYPE_IMAGE - || cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32)) - cairo_surface_flush (surface); x_end_cr_clip (f); @@ -377,20 +536,27 @@ 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 */ @@ -405,18 +571,20 @@ struct font_driver const ftcrfont_driver = .list_family = ftfont_list_family, .open = ftcrfont_open, .close = ftcrfont_close, - .has_char = ftfont_has_char, - .encode_char = ftfont_encode_char, + .has_char = ftcrfont_has_char, + .encode_char = ftcrfont_encode_char, .text_extents = ftcrfont_text_extents, .draw = ftcrfont_draw, .get_bitmap = ftcrfont_get_bitmap, .anchor_point = ftcrfont_anchor_point, #ifdef HAVE_LIBOTF - .otf_capability = ftfont_otf_capability, + .otf_capability = ftcrfont_otf_capability, #endif +#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF .shape = ftcrfont_shape, +#endif #ifdef HAVE_OTF_GET_VARIATION_GLYPHS - .get_variation_glyphs = ftfont_variation_glyphs, + .get_variation_glyphs = ftcrfont_variation_glyphs, #endif .filter_properties = ftfont_filter_properties, .combining_capability = ftfont_combining_capability, @@ -447,6 +615,7 @@ syms_of_ftcrfont_for_pdumper (void) 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 */ } |