summaryrefslogtreecommitdiff
path: root/src/ftfont.c
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>2019-05-23 10:53:23 +0900
committerYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>2019-05-23 10:53:23 +0900
commitb40dde705af4d53853de6185a2468153b442dc9a (patch)
treee8dabba695163c2d07439fad6accff761f8f714c /src/ftfont.c
parent5d7dafacf4afc888511649f6fc24c28210cd0dfc (diff)
parent03feb9376b54c489e24478954a11061e9b0d6db7 (diff)
downloademacs-b40dde705af4d53853de6185a2468153b442dc9a.tar.gz
Merge branch 'master' into harfbuzz
Diffstat (limited to 'src/ftfont.c')
-rw-r--r--src/ftfont.c255
1 files changed, 192 insertions, 63 deletions
diff --git a/src/ftfont.c b/src/ftfont.c
index 2373af8766a..5694c49aaf9 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -1103,12 +1103,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;
@@ -1116,12 +1263,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))
@@ -1132,7 +1278,6 @@ ftfont_open2 (struct frame *f,
return Qnil;
filename = XCAR (val);
idx = XCDR (val);
- val = XCDR (cache);
cache_data = xmint_pointer (XCDR (cache));
ft_face = cache_data->ft_face;
if (cache_data->face_refcount > 0)
@@ -1151,35 +1296,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;
@@ -1192,7 +1319,6 @@ ftfont_open2 (struct frame *f,
#ifdef HAVE_HARFBUZZ
ftfont_info->hb_font = NULL;
#endif /* HAVE_HARFBUZZ */
- 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;
@@ -1204,20 +1330,38 @@ ftfont_open2 (struct frame *f,
font->driver = &ftfont_driver;
font->encoding_charset = font->repertory_charset = -1;
+ val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
+ bool no_leading_p = !(CONSP (val) && NILP (XCDR (val)));
upEM = ft_face->units_per_EM;
scalable = (FIXNUMP (AREF (entity, FONT_AVGWIDTH_INDEX))
&& XFIXNUM (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0);
if (scalable)
{
font->ascent = ft_face->ascender * size / upEM + 0.5;
- font->descent = - ft_face->descender * size / upEM + 0.5;
- font->height = ft_face->height * size / upEM + 0.5;
+ if (no_leading_p)
+ {
+ font->descent = - ft_face->descender * size / upEM + 0.5;
+ font->height = font->ascent + font->descent;
+ }
+ else
+ {
+ font->height = ft_face->height * size / upEM + 0.5;
+ font->descent = font->height - font->ascent;
+ }
}
else
{
font->ascent = ft_face->size->metrics.ascender >> 6;
- font->descent = - ft_face->size->metrics.descender >> 6;
- font->height = ft_face->size->metrics.height >> 6;
+ if (no_leading_p)
+ {
+ font->descent = - ft_face->size->metrics.descender >> 6;
+ font->height = font->ascent + font->descent;
+ }
+ else
+ {
+ font->height = ft_face->size->metrics.height >> 6;
+ font->descent = font->height - font->ascent;
+ }
}
if (FIXNUMP (AREF (entity, FONT_SPACING_INDEX)))
spacing = XFIXNUM (AREF (entity, FONT_SPACING_INDEX));
@@ -1273,32 +1417,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),
- AREF (entity, FONT_TYPE_INDEX),
- 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)
{
@@ -1391,7 +1509,7 @@ ftfont_glyph_metrics (FT_Face ft_face, int c, int *advance, int *lbearing,
}
void
-ftfont_text_extents (struct font *font, unsigned int *code,
+ftfont_text_extents (struct font *font, const unsigned int *code,
int nglyphs, struct font_metrics *metrics)
{
struct font_info *ftfont_info = (struct font_info *) font;
@@ -3131,6 +3249,17 @@ syms_of_ftfont (void)
DEFSYM (Qsans, "sans");
DEFSYM (Qsans__serif, "sans serif");
+ /* 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);