1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-15 09:47:20 +00:00

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.
This commit is contained in:
YAMAMOTO Mitsuharu 2019-05-23 10:30:59 +09:00
parent 72047556fa
commit 03feb9376b
4 changed files with 433 additions and 328 deletions

View File

@ -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;
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;
FT_UInt size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
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);
block_input ();
font_object = ftfont_open2 (f, entity, pixel_size, font_object);
if (FONT_OBJECT_P (font_object))
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)
{
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;
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;
}
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)
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);
Lisp_Object val = assq_no_quit (QCminspace,
AREF (entity, FONT_EXTRA_INDEX));
if (!(CONSP (val) && NILP (XCDR (val))))
if (glyphs != &stack_glyph)
cairo_glyph_free (glyphs);
else if (stack_glyph.index)
{
font->descent = lround (extents.descent);
font->height = font->ascent + font->descent;
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++;
}
else
{
font->height = lround (extents.height);
font->descent = font->height - font->ascent;
}
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;
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 */
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 ();
}
ftfont_close (font);
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;
}
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_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)
{
#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
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,

View File

@ -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++)
if (cache_data->face_refcount == 0)
{
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)
{
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);

View File

@ -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;

View File

@ -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,