summaryrefslogtreecommitdiff
path: root/src/ftcrfont.c
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>2019-04-27 18:33:39 +0900
committerYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>2019-04-27 18:33:39 +0900
commit886bedb36c7b959b7e6fc8ce8e0c04e144b0ae28 (patch)
treeb5770d9fc10a704ad8aeb3474c6940121252c770 /src/ftcrfont.c
parent015a6e1df2772bd43680df5cbeaffccf98a881da (diff)
parent8dc00b2f1e6523c634df3e24379afbe712a32b27 (diff)
downloademacs-886bedb36c7b959b7e6fc8ce8e0c04e144b0ae28.tar.gz
Merge branch 'master' into harfbuzz
Diffstat (limited to 'src/ftcrfont.c')
-rw-r--r--src/ftcrfont.c177
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);
}