summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>2019-05-23 10:30:59 +0900
committerYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>2019-05-23 10:30:59 +0900
commit03feb9376b54c489e24478954a11061e9b0d6db7 (patch)
tree3e20c6c3295c24d0d4053a68062bcc7e9c49a224
parent72047556fa391016ab507c02c2f489c97b53f088 (diff)
downloademacs-03feb9376b54c489e24478954a11061e9b0d6db7.tar.gz
Make Cairo build obey hint-style font setting (Bug#35781)
* src/ftfont.h (ftfont_open2): Remove extern. (ftfont_fix_match, ftfont_add_rendering_parameters) (ftfont_entity_pattern): Add externs. (struct font_info): Remove member bitmap_strike_index. (struct font_info) [USE_CAIRO]: Remove member ft_size_draw. All uses removed. Add member bitmap_position_unit. * src/xftfont.c (xftfont_fix_match, xftfont_add_rendering_parameters): Move functions from here ... * src/ftfont.c (ftfont_fix_match, ftfont_add_rendering_parameters): ... to here. All uses changed. * src/xftfont.c (xftfont_open): Extract FcPattern creation from font entity from here ... * src/ftfont.c (ftfont_entity_pattern): ... to here. * src/xftfont.c (syms_of_xftfont): Move DEFSYMs for Fontconfig's rendering parameters from here ... * src/ftfont.c (syms_of_ftfont): ... to here. * src/ftfont.c (ftfont_open, ftfont_open2): Undo introduction of bitmap_strike_index. Merge functions into ftfont_open. * src/ftcrfont.c (ftcrfont_open): Align code with xftfont_open rather than ftfont_open. (ftcrfont_close): Likewise. (ftcrfont_has_char, ftcrfont_encode_char): (ftcrfont_otf_capability) [HAVE_LIBOTF]: (ftcrfont_variation_glyphs) [HAVE_OTF_GET_VARIATION_GLYPHS]: New functions. (ftcrfont_driver): Register them. (ftcrfont_get_bitmap, ftcrfont_anchor_point): (ftcrfont_shape) [HAVE_M17N_FLT && HAVE_LIBOTF]: Use bitmap_position_unit instead of bitmap_strike_index to screen bitmap fonts. (ftcrfont_get_bitmap, ftcrfont_anchor_point): (ftcrfont_otf_capability) [HAVE_LIBOTF]: (ftcrfont_shape) [HAVE_M17N_FLT && HAVE_LIBOTF]: (ftcrfont_variation_glyphs) [HAVE_OTF_GET_VARIATION_GLYPHS]: Temporarily assign ftcrfont_info->ft_size and call corresponding ftfont functions. (ftcrfont_draw): Don't flush cairo surface when exporting.
-rw-r--r--src/ftcrfont.c370
-rw-r--r--src/ftfont.c222
-rw-r--r--src/ftfont.h18
-rw-r--r--src/xftfont.c151
4 files changed, 433 insertions, 328 deletions
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 2d5a7665578..9686cec0e8c 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);
@@ -118,103 +117,159 @@ 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;
+
+ block_input ();
+
+ 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)
+ {
+ 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);
+ ASET (font_object, FONT_FILE_INDEX, filename);
+ font = XFONT_OBJECT (font_object);
+ font->pixel_size = size;
+ 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 ();
- font_object = ftfont_open2 (f, entity, pixel_size, font_object);
- if (FONT_OBJECT_P (font_object))
+ 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++)
{
- 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)
+ 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);
- Lisp_Object 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
+ if (glyphs != &stack_glyph)
+ cairo_glyph_free (glyphs);
+ else if (stack_glyph.index)
{
- font->height = lround (extents.height);
- font->descent = font->height - font->ascent;
+ 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;
- 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 if (stack_glyph.index)
- {
- 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;
+ 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;
+ }
- font->underline_position = -1;
- font->underline_thickness = 0;
- }
+ 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 */
+ 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;
}
@@ -225,19 +280,58 @@ 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
+ 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);
- ftfont_close (font);
+ 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;
+ }
+
+ return code;
}
static void
@@ -280,10 +374,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
@@ -292,25 +394,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)
+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)
+{
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);
+ 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);
+ 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,
@@ -321,8 +473,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;
@@ -351,17 +501,7 @@ ftcrfont_draw (struct glyph_string *s,
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);
@@ -383,18 +523,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,
diff --git a/src/ftfont.c b/src/ftfont.c
index f17bd9ab3f7..d8b510d7032 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -1079,12 +1079,159 @@ ftfont_list_family (struct frame *f)
return list;
}
+void
+ftfont_fix_match (FcPattern *pat, FcPattern *match)
+{
+ /* These values are not used for matching (except antialias), but for
+ rendering, so make sure they are carried over to the match.
+ We also put antialias here because most fonts are antialiased, so
+ the match will have antialias true. */
+
+ FcBool b = FcTrue;
+ int i;
+ double dpi;
+
+ FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
+ if (! b)
+ {
+ FcPatternDel (match, FC_ANTIALIAS);
+ FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
+ }
+ FcPatternGetBool (pat, FC_HINTING, 0, &b);
+ if (! b)
+ {
+ FcPatternDel (match, FC_HINTING);
+ FcPatternAddBool (match, FC_HINTING, FcFalse);
+ }
+#ifndef FC_HINT_STYLE
+# define FC_HINT_STYLE "hintstyle"
+#endif
+ if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
+ {
+ FcPatternDel (match, FC_HINT_STYLE);
+ FcPatternAddInteger (match, FC_HINT_STYLE, i);
+ }
+#ifndef FC_LCD_FILTER
+ /* Older fontconfig versions don't have FC_LCD_FILTER. */
+#define FC_LCD_FILTER "lcdfilter"
+#endif
+ if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
+ {
+ FcPatternDel (match, FC_LCD_FILTER);
+ FcPatternAddInteger (match, FC_LCD_FILTER, i);
+ }
+ if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
+ {
+ FcPatternDel (match, FC_RGBA);
+ FcPatternAddInteger (match, FC_RGBA, i);
+ }
+ if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
+ {
+ FcPatternDel (match, FC_DPI);
+ FcPatternAddDouble (match, FC_DPI, dpi);
+ }
+}
+
+void
+ftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
+{
+ Lisp_Object tail;
+ int ival;
+
+ for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
+ {
+ Lisp_Object key = XCAR (XCAR (tail));
+ Lisp_Object val = XCDR (XCAR (tail));
+
+ if (EQ (key, QCantialias))
+ FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
+ else if (EQ (key, QChinting))
+ FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
+ else if (EQ (key, QCautohint))
+ FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
+ else if (EQ (key, QChintstyle))
+ {
+ if (FIXNUMP (val))
+ FcPatternAddInteger (pat, FC_HINT_STYLE, XFIXNUM (val));
+ else if (SYMBOLP (val)
+ && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
+ FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
+ }
+ else if (EQ (key, QCrgba))
+ {
+ if (FIXNUMP (val))
+ FcPatternAddInteger (pat, FC_RGBA, XFIXNUM (val));
+ else if (SYMBOLP (val)
+ && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
+ FcPatternAddInteger (pat, FC_RGBA, ival);
+ }
+ else if (EQ (key, QClcdfilter))
+ {
+ if (FIXNUMP (val))
+ FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XFIXNUM (val));
+ else if (SYMBOLP (val)
+ && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
+ FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
+ }
+#ifdef FC_EMBOLDEN
+ else if (EQ (key, QCembolden))
+ FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
+#endif
+ }
+}
+
+FcPattern *
+ftfont_entity_pattern (Lisp_Object entity, int pixel_size)
+{
+ Lisp_Object val, filename, idx;
+ FcPattern *pat;
+ int i;
+
+ val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
+ eassert (CONSP (val));
+ val = XCDR (val);
+ filename = XCAR (val);
+ idx = XCDR (val);
+ pat = FcPatternCreate ();
+ FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
+ i = FONT_SLANT_NUMERIC (entity) - 100;
+ if (i < 0) i = 0;
+ FcPatternAddInteger (pat, FC_SLANT, i);
+ FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
+ FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
+ val = AREF (entity, FONT_FAMILY_INDEX);
+ if (! NILP (val))
+ FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
+ val = AREF (entity, FONT_FOUNDRY_INDEX);
+ if (! NILP (val))
+ FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
+ val = AREF (entity, FONT_SPACING_INDEX);
+ if (! NILP (val))
+ FcPatternAddInteger (pat, FC_SPACING, XFIXNUM (val));
+ val = AREF (entity, FONT_DPI_INDEX);
+ if (! NILP (val))
+ {
+ double dbl = XFIXNUM (val);
+
+ FcPatternAddDouble (pat, FC_DPI, dbl);
+ }
+ val = AREF (entity, FONT_AVGWIDTH_INDEX);
+ if (FIXNUMP (val) && XFIXNUM (val) == 0)
+ FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
+ /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
+ over 10x20-ISO8859-1.pcf.gz). */
+ FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
+
+ ftfont_add_rendering_parameters (pat, entity);
+
+ FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
+ FcPatternAddInteger (pat, FC_INDEX, XFIXNUM (idx));
+
+ return pat;
+}
Lisp_Object
-ftfont_open2 (struct frame *f,
- Lisp_Object entity,
- int pixel_size,
- Lisp_Object font_object)
+ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
{
struct font_info *ftfont_info;
struct font *font;
@@ -1092,12 +1239,11 @@ ftfont_open2 (struct frame *f,
FT_Face ft_face;
FT_Size ft_size;
FT_UInt size;
- Lisp_Object val, filename, idx, cache;
+ Lisp_Object val, filename, idx, cache, font_object;
bool scalable;
int spacing;
int i;
double upEM;
- FT_Int strike_index = -1;
val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
if (! CONSP (val))
@@ -1126,35 +1272,17 @@ ftfont_open2 (struct frame *f,
size = pixel_size;
if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
{
- int min_distance = INT_MAX;
- bool magnify = true;
-
- for (FT_Int i = 0; i < ft_face->num_fixed_sizes; i++)
- {
- int distance = ft_face->available_sizes[i].height - (int) size;
-
- /* Prefer down-scaling to upscaling. */
- if (magnify == (distance < 0) ? abs (distance) <= min_distance
- : magnify)
- {
- magnify = distance < 0;
- min_distance = abs (distance);
- strike_index = i;
- }
- }
-
- if (strike_index < 0 || FT_Select_Size (ft_face, strike_index) != 0)
+ if (cache_data->face_refcount == 0)
{
- if (cache_data->face_refcount == 0)
- {
- FT_Done_Face (ft_face);
- cache_data->ft_face = NULL;
- }
- return Qnil;
+ FT_Done_Face (ft_face);
+ cache_data->ft_face = NULL;
}
+ return Qnil;
}
cache_data->face_refcount++;
+ font_object = font_build_object (VECSIZE (struct font_info),
+ Qfreetype, entity, size);
ASET (font_object, FONT_FILE_INDEX, filename);
font = XFONT_OBJECT (font_object);
ftfont_info = (struct font_info *) font;
@@ -1164,7 +1292,6 @@ ftfont_open2 (struct frame *f,
ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
ftfont_info->otf = NULL;
#endif /* HAVE_LIBOTF */
- 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;
@@ -1258,31 +1385,6 @@ ftfont_open2 (struct frame *f,
return font_object;
}
-Lisp_Object
-ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
-{
- Lisp_Object font_object;
- FT_UInt size;
- size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
- if (size == 0)
- size = pixel_size;
- font_object = font_build_object (VECSIZE (struct font_info),
- Qfreetype, entity, size);
- font_object = ftfont_open2 (f, entity, pixel_size, font_object);
- if (FONT_OBJECT_P (font_object))
- {
- struct font *font = XFONT_OBJECT (font_object);
- struct font_info *ftfont_info = (struct font_info *) font;
-
- if (ftfont_info->bitmap_strike_index >= 0)
- {
- ftfont_close (font);
- font_object = Qnil;
- }
- }
- return font_object;
-}
-
void
ftfont_close (struct font *font)
{
@@ -2789,6 +2891,14 @@ syms_of_ftfont (void)
/* The boolean-valued font property key specifying the use of leading. */
DEFSYM (QCminspace, ":minspace");
+ /* Fontconfig's rendering parameters. */
+ DEFSYM (QChinting, ":hinting");
+ DEFSYM (QCautohint, ":autohint");
+ DEFSYM (QChintstyle, ":hintstyle");
+ DEFSYM (QCrgba, ":rgba");
+ DEFSYM (QCembolden, ":embolden");
+ DEFSYM (QClcdfilter, ":lcdfilter");
+
staticpro (&freetype_font_cache);
freetype_font_cache = list1 (Qt);
diff --git a/src/ftfont.h b/src/ftfont.h
index adbda49ff1c..7860469491f 100644
--- a/src/ftfont.h
+++ b/src/ftfont.h
@@ -37,10 +37,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#endif /* HAVE_LIBOTF */
extern FcCharSet *ftfont_get_fc_charset (Lisp_Object);
-extern Lisp_Object ftfont_open2 (struct frame *f,
- Lisp_Object entity,
- int pixel_size,
- Lisp_Object font_object);
+extern void ftfont_fix_match (FcPattern *, FcPattern *);
+extern void ftfont_add_rendering_parameters (FcPattern *, Lisp_Object);
+extern FcPattern *ftfont_entity_pattern (Lisp_Object, int);
/* This struct is shared by the XFT, Freetype, and Cairo font
backends. Members up to and including 'matrix' are common, the
@@ -54,17 +53,14 @@ struct font_info
#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 USE_CAIRO
cairo_scaled_font_t *cr_scaled_font;
- /* To prevent cairo from cluttering the activated FT_Size maintained
- in ftfont.c, we activate this special FT_Size before drawing. */
- FT_Size ft_size_draw;
+ /* Scale factor from the bitmap strike metrics in 1/64 pixels, used
+ as the hb_position_t value in HarfBuzz, to those in (scaled)
+ pixels. The value is 0 for scalable fonts. */
+ double bitmap_position_unit;
/* Font metrics cache. */
struct font_metrics **metrics;
short metrics_nrows;
diff --git a/src/xftfont.c b/src/xftfont.c
index 2edc51fe356..4f0a0d81d85 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -127,120 +127,18 @@ xftfont_match (struct frame *f, Lisp_Object spec)
static FcChar8 ascii_printable[95];
-static void
-xftfont_fix_match (FcPattern *pat, FcPattern *match)
-{
- /* These values are not used for matching (except antialias), but for
- rendering, so make sure they are carried over to the match.
- We also put antialias here because most fonts are antialiased, so
- the match will have antialias true. */
-
- FcBool b = FcTrue;
- int i;
- double dpi;
-
- FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
- if (! b)
- {
- FcPatternDel (match, FC_ANTIALIAS);
- FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
- }
- FcPatternGetBool (pat, FC_HINTING, 0, &b);
- if (! b)
- {
- FcPatternDel (match, FC_HINTING);
- FcPatternAddBool (match, FC_HINTING, FcFalse);
- }
-#ifndef FC_HINT_STYLE
-# define FC_HINT_STYLE "hintstyle"
-#endif
- if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
- {
- FcPatternDel (match, FC_HINT_STYLE);
- FcPatternAddInteger (match, FC_HINT_STYLE, i);
- }
-#ifndef FC_LCD_FILTER
- /* Older fontconfig versions don't have FC_LCD_FILTER. */
-#define FC_LCD_FILTER "lcdfilter"
-#endif
- if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
- {
- FcPatternDel (match, FC_LCD_FILTER);
- FcPatternAddInteger (match, FC_LCD_FILTER, i);
- }
- if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
- {
- FcPatternDel (match, FC_RGBA);
- FcPatternAddInteger (match, FC_RGBA, i);
- }
- if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
- {
- FcPatternDel (match, FC_DPI);
- FcPatternAddDouble (match, FC_DPI, dpi);
- }
-}
-
-static void
-xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
-{
- Lisp_Object tail;
- int ival;
-
- for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
- {
- Lisp_Object key = XCAR (XCAR (tail));
- Lisp_Object val = XCDR (XCAR (tail));
-
- if (EQ (key, QCantialias))
- FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
- else if (EQ (key, QChinting))
- FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
- else if (EQ (key, QCautohint))
- FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
- else if (EQ (key, QChintstyle))
- {
- if (FIXNUMP (val))
- FcPatternAddInteger (pat, FC_HINT_STYLE, XFIXNUM (val));
- else if (SYMBOLP (val)
- && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
- FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
- }
- else if (EQ (key, QCrgba))
- {
- if (FIXNUMP (val))
- FcPatternAddInteger (pat, FC_RGBA, XFIXNUM (val));
- else if (SYMBOLP (val)
- && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
- FcPatternAddInteger (pat, FC_RGBA, ival);
- }
- else if (EQ (key, QClcdfilter))
- {
- if (FIXNUMP (val))
- FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XFIXNUM (val));
- else if (SYMBOLP (val)
- && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
- FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
- }
-#ifdef FC_EMBOLDEN
- else if (EQ (key, QCembolden))
- FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
-#endif
- }
-}
-
static Lisp_Object
xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
{
FcResult result;
Display *display = FRAME_X_DISPLAY (f);
- Lisp_Object val, filename, idx, font_object;
+ Lisp_Object val, filename, font_object;
FcPattern *pat = NULL, *match;
struct font_info *xftfont_info = NULL;
struct font *font;
double size = 0;
XftFont *xftfont = NULL;
int spacing;
- int i;
XGlyphInfo extents;
FT_Face ft_face;
FcMatrix *matrix;
@@ -250,52 +148,17 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
return Qnil;
val = XCDR (val);
filename = XCAR (val);
- idx = XCDR (val);
size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
if (size == 0)
size = pixel_size;
- pat = FcPatternCreate ();
- FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
- i = FONT_SLANT_NUMERIC (entity) - 100;
- if (i < 0) i = 0;
- FcPatternAddInteger (pat, FC_SLANT, i);
- FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
- FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
- val = AREF (entity, FONT_FAMILY_INDEX);
- if (! NILP (val))
- FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
- val = AREF (entity, FONT_FOUNDRY_INDEX);
- if (! NILP (val))
- FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
- val = AREF (entity, FONT_SPACING_INDEX);
- if (! NILP (val))
- FcPatternAddInteger (pat, FC_SPACING, XFIXNUM (val));
- val = AREF (entity, FONT_DPI_INDEX);
- if (! NILP (val))
- {
- double dbl = XFIXNUM (val);
-
- FcPatternAddDouble (pat, FC_DPI, dbl);
- }
- val = AREF (entity, FONT_AVGWIDTH_INDEX);
- if (FIXNUMP (val) && XFIXNUM (val) == 0)
- FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
- /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
- over 10x20-ISO8859-1.pcf.gz). */
- FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
-
- xftfont_add_rendering_parameters (pat, entity);
-
- FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
- FcPatternAddInteger (pat, FC_INDEX, XFIXNUM (idx));
-
block_input ();
+ pat = ftfont_entity_pattern (entity, pixel_size);
/* Substitute in values from X resources and XftDefaultSet. */
XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
- xftfont_fix_match (pat, match);
+ ftfont_fix_match (pat, match);
FcPatternDestroy (pat);
xftfont = XftFontOpenPattern (display, match);
@@ -695,7 +558,7 @@ xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
bool ok = false;
int i1, i2, r1, r2;
- xftfont_add_rendering_parameters (pat, entity);
+ ftfont_add_rendering_parameters (pat, entity);
XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
@@ -768,12 +631,6 @@ void
syms_of_xftfont (void)
{
DEFSYM (Qxft, "xft");
- 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,