diff options
author | YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> | 2019-04-27 18:33:39 +0900 |
---|---|---|
committer | YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> | 2019-04-27 18:33:39 +0900 |
commit | 886bedb36c7b959b7e6fc8ce8e0c04e144b0ae28 (patch) | |
tree | b5770d9fc10a704ad8aeb3474c6940121252c770 /src/ftcrfont.c | |
parent | 015a6e1df2772bd43680df5cbeaffccf98a881da (diff) | |
parent | 8dc00b2f1e6523c634df3e24379afbe712a32b27 (diff) | |
download | emacs-886bedb36c7b959b7e6fc8ce8e0c04e144b0ae28.tar.gz |
Merge branch 'master' into harfbuzz
Diffstat (limited to 'src/ftcrfont.c')
-rw-r--r-- | src/ftcrfont.c | 177 |
1 files changed, 146 insertions, 31 deletions
diff --git a/src/ftcrfont.c b/src/ftcrfont.c index 45e526d24a4..c0f62e0418e 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c @@ -1,5 +1,5 @@ /* ftcrfont.c -- FreeType font driver on cairo. - Copyright (C) 2015-2018 Free Software Foundation, Inc. + Copyright (C) 2015-2019 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -19,13 +19,16 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include <stdio.h> +#include <math.h> #include <cairo-ft.h> #include "lisp.h" #include "xterm.h" #include "blockinput.h" +#include "composite.h" #include "font.h" #include "ftfont.h" +#include "pdumper.h" #define METRICS_NCOLS_PER_ROW (128) @@ -72,7 +75,19 @@ ftcrfont_glyph_extents (struct font *font, cache = ftcrfont_info->metrics[row] + col; if (METRICS_STATUS (cache) == METRICS_INVALID) - ftfont_text_extents (font, &glyph, 1, cache); + { + 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); + cache->rbearing = ceil (extents.width + extents.x_bearing); + cache->width = lround (extents.x_advance); + cache->ascent = ceil (- extents.y_bearing); + cache->descent = ceil (extents.height + extents.y_bearing); + } if (metrics) *metrics = *cache; @@ -104,31 +119,90 @@ static Lisp_Object ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) { Lisp_Object font_object; - struct font *font; - struct font_info *ftcrfont_info; - FT_Face ft_face; - FT_UInt size; - block_input (); - size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX)); + FT_UInt size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX)); if (size == 0) size = pixel_size; font_object = font_build_object (VECSIZE (struct font_info), Qftcr, entity, size); + block_input (); font_object = ftfont_open2 (f, entity, pixel_size, font_object); - if (NILP (font_object)) return Qnil; - - font = XFONT_OBJECT (font_object); - font->driver = &ftcrfont_driver; - ftcrfont_info = (struct font_info *) font; - ft_face = ftcrfont_info->ft_size->face; - FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw); - FT_Activate_Size (ftcrfont_info->ft_size_draw); - FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size); - ftcrfont_info->cr_font_face = - cairo_ft_font_face_create_for_ft_face (ft_face, 0); - ftcrfont_info->metrics = NULL; - ftcrfont_info->metrics_nrows = 0; + if (FONT_OBJECT_P (font_object)) + { + 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; + + 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) + { + /* 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++) + { + 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++; + } + } + } + if (n > 0) + font->average_width /= n; + + font->underline_position = -1; + font->underline_thickness = 0; + } + } unblock_input (); return font_object; @@ -150,7 +224,7 @@ ftcrfont_close (struct font *font) if (ftcrfont_info->metrics) xfree (ftcrfont_info->metrics); FT_Done_Size (ftcrfont_info->ft_size_draw); - cairo_font_face_destroy (ftcrfont_info->cr_font_face); + cairo_scaled_font_destroy (ftcrfont_info->cr_scaled_font); unblock_input (); ftfont_close (font); @@ -191,6 +265,44 @@ ftcrfont_text_extents (struct font *font, } static int +ftcrfont_get_bitmap (struct font *font, unsigned int code, + struct font_bitmap *bitmap, int bits_per_pixel) +{ + 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); + + return -1; +} + +static int +ftcrfont_anchor_point (struct font *font, unsigned int code, int idx, + int *x, int *y) +{ + 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); + + return -1; +} + +static Lisp_Object +ftcrfont_shape (Lisp_Object lgstring, Lisp_Object direction) +{ +#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ + 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); +#endif + + return make_fixnum (0); +} + +static int ftcrfont_draw (struct glyph_string *s, int from, int to, int x, int y, bool with_background) { @@ -229,10 +341,7 @@ ftcrfont_draw (struct glyph_string *s, } x_set_cr_source_with_gc_foreground (f, s->gc); - cairo_set_font_face (cr, ftcrfont_info->cr_font_face); - cairo_set_font_size (cr, s->font->pixel_size); - /* cairo_set_font_matrix */ - /* cairo_set_font_options */ + cairo_set_scaled_font (cr, ftcrfont_info->cr_scaled_font); FT_Activate_Size (ftcrfont_info->ft_size_draw); cairo_show_glyphs (cr, glyphs, len); @@ -254,6 +363,8 @@ ftcrfont_draw (struct glyph_string *s, +static void syms_of_ftcrfont_for_pdumper (void); + struct font_driver const ftcrfont_driver = { .type = LISPSYM_INITIALLY (Qftcr), @@ -267,14 +378,12 @@ struct font_driver const ftcrfont_driver = .encode_char = ftfont_encode_char, .text_extents = ftcrfont_text_extents, .draw = ftcrfont_draw, - .get_bitmap = ftfont_get_bitmap, - .anchor_point = ftfont_anchor_point, + .get_bitmap = ftcrfont_get_bitmap, + .anchor_point = ftcrfont_anchor_point, #ifdef HAVE_LIBOTF .otf_capability = ftfont_otf_capability, #endif -#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ - .shape = ftfont_shape, -#endif + .shape = ftcrfont_shape, #ifdef HAVE_OTF_GET_VARIATION_GLYPHS .get_variation_glyphs = ftfont_variation_glyphs, #endif @@ -286,5 +395,11 @@ void syms_of_ftcrfont (void) { DEFSYM (Qftcr, "ftcr"); + pdumper_do_now_and_after_load (syms_of_ftcrfont_for_pdumper); +} + +static void +syms_of_ftcrfont_for_pdumper (void) +{ register_font_driver (&ftcrfont_driver, NULL); } |