Commit 03feb937 authored by YAMAMOTO Mitsuharu's avatar YAMAMOTO Mitsuharu

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.
parent 72047556
Pipeline #1777 failed with stage
in 64 minutes and 12 seconds
This diff is collapsed.
......@@ -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);
......
......@@ -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;
......
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment