/* Xft font driver. */
static Lisp_Object Qxft;
+static Lisp_Object QChinting , QCautohint, QChintstyle, QCrgba, QCembolden;
/* The actual structure for Xft font that can be casted to struct
font. */
struct xftfont_info
{
struct font font;
- Display *display;
- int screen;
- XftFont *xftfont;
+ /* The following three members must be here in this order to be
+ compatible with struct ftfont_info (in ftfont.c). */
#ifdef HAVE_LIBOTF
int maybe_otf; /* Flag to tell if this may be OTF or not. */
OTF *otf;
#endif /* HAVE_LIBOTF */
+ FT_Size ft_size;
+ Display *display;
+ int screen;
+ XftFont *xftfont;
};
/* Structure pointed by (struct face *)->extra */
static int xftfont_text_extents P_ ((struct font *, unsigned *, int,
struct font_metrics *));
static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
-
-static int xftfont_anchor_point P_ ((struct font *, unsigned, int,
- int *, int *));
static int xftfont_end_for_frame P_ ((FRAME_PTR f));
struct font_driver xftfont_driver;
return entity;
}
-extern Lisp_Object ftfont_font_format P_ ((FcPattern *));
+extern Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
+extern FcCharSet *ftfont_get_fc_charset P_ ((Lisp_Object));
+extern Lisp_Object QCantialias;
static FcChar8 ascii_printable[95];
Lisp_Object entity;
int pixel_size;
{
+ FcResult result;
Display *display = FRAME_X_DISPLAY (f);
- Lisp_Object val, filename, font_object;
- FcPattern *pat = NULL;
+ Lisp_Object val, filename, index, tail, font_object;
+ FcPattern *pat = NULL, *match;
struct xftfont_info *xftfont_info = NULL;
struct font *font;
double size = 0;
return Qnil;
val = XCDR (val);
filename = XCAR (val);
+ index = XCDR (val);
size = XINT (AREF (entity, FONT_SIZE_INDEX));
if (size == 0)
size = pixel_size;
pat = FcPatternCreate ();
- FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
+ 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);
- /*FcPatternAddBool (pat, FC_ANTIALIAS, FcTrue);*/
val = AREF (entity, FONT_FAMILY_INDEX);
if (! NILP (val))
FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
- FcConfigSubstitute (NULL, pat, FcMatchPattern);
+ 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, XINT (val));
+ val = AREF (entity, FONT_DPI_INDEX);
+ if (! NILP (val))
+ {
+ double dbl = XINT (val);
+
+ FcPatternAddDouble (pat, FC_DPI, dbl);
+ }
+ val = AREF (entity, FONT_AVGWIDTH_INDEX);
+ if (INTEGERP (val) && XINT (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));
+
+ for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
+ {
+ Lisp_Object key, val;
+
+ key = XCAR (XCAR (tail)), 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 (INTEGERP (val))
+ FcPatternAddInteger (pat, FC_RGBA, XINT (val));
+ }
+ else if (EQ (key, QCrgba))
+ {
+ if (INTEGERP (val))
+ FcPatternAddInteger (pat, FC_RGBA, XINT (val));
+ }
+#ifdef FC_EMBOLDEN
+ else if (EQ (key, QCembolden))
+ FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
+#endif
+ }
+
+ FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
+ FcPatternAddInteger (pat, FC_INDEX, XINT (index));
+
BLOCK_INPUT;
- XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
- xftfont = XftFontOpenPattern (display, pat);
+ match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
+ FcPatternDestroy (pat);
+ xftfont = XftFontOpenPattern (display, match);
+ ft_face = XftLockFace (xftfont);
UNBLOCK_INPUT;
+
if (! xftfont)
- return Qnil;
+ {
+ XftPatternDestroy (match);
+ return Qnil;
+ }
/* We should not destroy PAT here because it is kept in XFTFONT and
destroyed automatically when XFTFONT is closed. */
- font_object = font_make_object (VECSIZE (struct xftfont_info));
+ font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
ASET (font_object, FONT_TYPE_INDEX, Qxft);
- for (i = 1; i < FONT_ENTITY_MAX; i++)
- ASET (font_object, i, AREF (entity, i));
- ASET (font_object, FONT_SIZE_INDEX, make_number (size));
len = font_unparse_xlfd (entity, size, name, 256);
if (len > 0)
- ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
+ ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
len = font_unparse_fcname (entity, size, name, 256);
if (len > 0)
- ASET (font_object, FONT_FULLNAME_INDEX, make_unibyte_string (name, len));
+ ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
else
ASET (font_object, FONT_FULLNAME_INDEX,
AREF (font_object, FONT_NAME_INDEX));
ASET (font_object, FONT_FILE_INDEX, filename);
ASET (font_object, FONT_FORMAT_INDEX,
- ftfont_font_format (xftfont->pattern));
+ ftfont_font_format (xftfont->pattern, filename));
font = XFONT_OBJECT (font_object);
font->pixel_size = pixel_size;
font->driver = &xftfont_driver;
UNBLOCK_INPUT;
font->ascent = xftfont->ascent;
- if (font->ascent < extents.y)
- font->ascent = extents.y;
font->descent = xftfont->descent;
- if (font->descent < extents.height - extents.y)
- font->descent = extents.height - extents.y;
+ if (pixel_size >= 5)
+ {
+ /* The above condition is a dirty workaround because
+ XftTextExtents8 behaves strangely for some fonts
+ (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
+ if (font->ascent < extents.y)
+ font->ascent = extents.y;
+ if (font->descent < extents.height - extents.y)
+ font->descent = extents.height - extents.y;
+ }
font->height = font->ascent + font->descent;
- ft_face = XftLockFace (xftfont);
if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
{
int upEM = ft_face->units_per_EM;
xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
xftfont_info->otf = NULL;
#endif /* HAVE_LIBOTF */
- XftUnlockFace (xftfont);
+ xftfont_info->ft_size = ft_face->size;
/* Unfortunately Xft doesn't provide a way to get minimum char
width. So, we use space_width instead. */
font->relative_compose = 0;
font->default_ascent = 0;
font->vertical_centering = 0;
+#ifdef FT_BDF_H
+ if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
+ {
+ BDF_PropertyRec rec;
+
+ if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
+ && rec.type == BDF_PROPERTY_TYPE_INTEGER)
+ font->baseline_offset = rec.u.integer;
+ if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
+ && rec.type == BDF_PROPERTY_TYPE_INTEGER)
+ font->relative_compose = rec.u.integer;
+ if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
+ && rec.type == BDF_PROPERTY_TYPE_INTEGER)
+ font->default_ascent = rec.u.integer;
+ }
+#endif
return font_object;
}
OTF_close (xftfont_info->otf);
#endif
BLOCK_INPUT;
+ XftUnlockFace (xftfont_info->xftfont);
XftFontClose (xftfont_info->display, xftfont_info->xftfont);
UNBLOCK_INPUT;
}
return len;
}
-static int
-xftfont_anchor_point (font, code, index, x, y)
- struct font *font;
- unsigned code;
- int index;
- int *x, *y;
-{
- struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
- FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
- int result;
-
- if (FT_Load_Glyph (ft_face, code, FT_LOAD_DEFAULT) != 0)
- result = -1;
- else if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
- result = -1;
- else if (index >= ft_face->glyph->outline.n_points)
- result = -1;
- else
- {
- *x = ft_face->glyph->outline.points[index].x;
- *y = ft_face->glyph->outline.points[index].y;
- }
- XftUnlockFace (xftfont_info->xftfont);
- return result;
-}
-
static int
xftfont_end_for_frame (f)
FRAME_PTR f;
return 0;
}
-#ifdef HAVE_LIBOTF
-#ifdef HAVE_M17N_FLT
-static Lisp_Object
-xftfont_shape (lgstring)
- Lisp_Object lgstring;
-{
- struct font *font;
- struct xftfont_info *xftfont_info;
- Lisp_Object result;
- FT_Face ft_face;
-
- CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
- xftfont_info = (struct xftfont_info *) font;
- if (! xftfont_info->maybe_otf)
- return Qnil;
- ft_face = XftLockFace (xftfont_info->xftfont);
- if (! xftfont_info->otf)
- {
- OTF *otf = OTF_open_ft_face (ft_face);
-
- if (! otf || OTF_get_table (otf, "head") < 0)
- {
- if (otf)
- OTF_close (otf);
- xftfont_info->maybe_otf = 0;
- XftUnlockFace (xftfont_info->xftfont);
- return Qnil;
- }
- xftfont_info->otf = otf;
- }
-
- result = ftfont_shape_by_flt (lgstring, font, ft_face, xftfont_info->otf);
- XftUnlockFace (xftfont_info->xftfont);
- return result;
-}
-#endif /* HAVE_M17N_FLT */
-#endif /* HAVE_LIBOTF */
-
void
syms_of_xftfont ()
{
DEFSYM (Qxft, "xft");
+ DEFSYM (QChinting, ":hinting");
+ DEFSYM (QCautohint, ":autohint");
+ DEFSYM (QChintstyle, ":hintstyle");
+ DEFSYM (QCrgba, ":rgba");
+ DEFSYM (QCembolden, ":embolden");
xftfont_driver = ftfont_driver;
xftfont_driver.type = Qxft;
xftfont_driver.encode_char = xftfont_encode_char;
xftfont_driver.text_extents = xftfont_text_extents;
xftfont_driver.draw = xftfont_draw;
- xftfont_driver.anchor_point = xftfont_anchor_point;
xftfont_driver.end_for_frame = xftfont_end_for_frame;
-#ifdef HAVE_LIBOTF
-#ifdef HAVE_M17N_FLT
- xftfont_driver.shape = xftfont_shape;
-#endif /* HAVE_M17N_FLT */
-#endif /* HAVE_LIBOTF */
register_font_driver (&xftfont_driver, NULL);
}