Commit f208d5ae authored by YAMAMOTO Mitsuharu's avatar YAMAMOTO Mitsuharu

Add new font backend drivers for text shaping by HarfBuzz

* etc/NEWS: Mention new font backend drivers xfthb and ftcrhb.

* src/font.h [HAVE_HARFBUZZ]: Include hb.h.
(struct font_driver) [HAVE_HARFBUZZ]: New members begin_hb_font and
end_hb_font.
(ftfont_match, ftfont_list): Remove externs.
(ftfont_match2, ftfont_list2):
(fthbfont_combining_capability, fthbfont_begin_hb_font)
(fthbfont_shape) [HAVE_HARFBUZZ]:
(xfthbfont_driver) [HAVE_XFT && HAVE_HARFBUZZ]:
(ftcrhbfont_driver) [USE_CAIRO && HAVE_HARFBUZZ]: Add externs.

* src/ftcrfont.c (ftcrfont_list): Use ftfont_list2.
(ftcrfont_match): Use ftfont_match2.
(ftcrfont_open): Get font type from entity.
(ftcrfont_open) [HAVE_HARFBUZZ]: Use HarfBuzz version of driver if specified.
(ftcrfont_shape) [HAVE_HARFBUZZ]: Make shaping fail.
(ftcrhbfont_list, ftcrhbfont_match)
(ftcrhbfont_begin_hb_font) [HAVE_HARFBUZZ]: New functions.
(ftcrhbfont_driver) [HAVE_HARFBUZZ]: New variable.
(syms_of_ftcrfont_for_pdumper) [HAVE_HARFBUZZ]: Initialize and register it.
(syms_of_ftcrfont) [HAVE_HARFBUZZ]: New symbol Qftcrhb.

* src/ftfont.c: Include math.h for lround.
(fthbfont_driver) [HAVE_HARFBUZZ]: New variable.
(ftfont_get_hb_font) [HAVE_HARFBUZZ]: Remove function.
(ftfont_list, ftfont_match): Make static.
(ftfont_list2, ftfont_match2): New functions.
(ftfont_open2) [HAVE_HARFBUZZ]: Use HarfBuzz version of driver if specified.
(ftfont_open): Get font type from entity.
(ftfont_shape, ftfont_combining_capability, ftfont_driver) [HAVE_HARFBUZZ]:
Move HarfBuzz specific part from here ...
(fthbfont_shape, fthbfont_combining_capability)
(fthbfont_driver) [HAVE_HARFBUZZ]: ... to here.   New functions and variable.
(fthbfont_begin_hb_font) [HAVE_HARFBUZZ]: New function.
(fthbfont_shape_by_hb) [HAVE_HARFBUZZ]: Rename from ftfont_shape_by_hb.
Don't take FreeType specific arguments ft_face and matrix.  Use begin_hb_font
and end_hb_font font driver functions.  Use text_extents font driver functions
instead of ftfont_glyph_metrics.
(syms_of_ftfont) [HAVE_HARFBUZZ]: New symbol Qfreetypehb.
(syms_of_ftfont_for_pdumper) [HAVE_HARFBUZZ]: Initialize and register
fthbfont_drivert.

* src/ftxfont.c (ftxfont_list): Use ftfont_list2.
(ftxfont_match): Use ftfont_match2.
(ftxfont_driver) [HAVE_HARFBUZZ]: Don't initialize shape member explicitly.

* src/xfns.c (Fx_create_frame) [USE_CAIRO && HAVE_HARFBUZZ]:
(Fx_create_frame) [HAVE_XFT && HAVE_HARFBUZZ]: Register HarfBuzz versions of
font drivers.

* src/xftfont.c (xftfont_list): Use ftfont_list2.
(xftfont_match): Use ftfont_match2.
(xftfont_open): Get font type from entity.
(xftfont_open) [HAVE_HARFBUZZ]: Use HarfBuzz version of driver if specified.
(xftfont_shape) [HAVE_HARFBUZZ]: Make shaping fail.
(xfthbfont_list, xfthbfont_match, xfthbfont_begin_hb_font)
(xfthbfont_end_hb_font) [HAVE_HARFBUZZ]: New functions.
(xftfont_driver) [HAVE_HARFBUZZ]: Don't initialize shape member explicitly.
(xfthbfont_driver) [HAVE_HARFBUZZ]: New variable.
(syms_of_xftfont_for_pdumper) [HAVE_HARFBUZZ]: Initialize and register it.
(syms_of_xftfont) [HAVE_HARFBUZZ]: New symbol Qxfthb.
parent 27511b98
Pipeline #1562 passed with stage
in 69 minutes and 5 seconds
......@@ -32,7 +32,9 @@ suitable libgmp is available.
** The new configure option '--with-harfbuzz' adds support for the
HarfBuzz text shaping engine. It is on by default; use './configure
--without-harfbuzz' to build without it.
--without-harfbuzz' to build without it. The HarfBuzz text shaping is
available via new font backend drivers 'xfthb' and 'ftcrhb' for Xft
and Cairo drawings, respectively.
** The new configure option '--with-json' adds support for JSON using
the Jansson library. It is on by default; use './configure
......
......@@ -22,6 +22,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifndef EMACS_FONT_H
#define EMACS_FONT_H
#ifdef HAVE_HARFBUZZ
#include <hb.h>
#endif /* HAVE_HARFBUZZ */
struct composition_it;
struct face;
struct glyph_string;
......@@ -780,6 +784,21 @@ struct font_driver
relies on this hook to throw away its old XftDraw (which won't
work after the size change) and get a new one. */
void (*drop_xrender_surfaces) (struct frame *f);
#ifdef HAVE_HARFBUZZ
/* Optional.
Return a HarfBuzz font object for FONT and store to
*POSITION_UNIT the scale factor to convert a hb_position_t value
to the number of pixels. Return NULL if HarfBuzz font object is
not available for FONT. */
hb_font_t *(*begin_hb_font) (struct font *font, double *position_unit);
/* Optional.
Called when the return value (passed as HB_FONT) of begin_hb_font
above is no longer used. Not called if the return value of
begin_hb_font was NULL. */
void (*end_hb_font) (struct font *font, hb_font_t *hb_font);
#endif /* HAVE_HARFBUZZ */
};
......@@ -892,9 +911,9 @@ extern int ftfont_has_char (Lisp_Object, int);
extern int ftfont_variation_glyphs (struct font *, int, unsigned[256]);
extern Lisp_Object ftfont_combining_capability (struct font *);
extern Lisp_Object ftfont_get_cache (struct frame *);
extern Lisp_Object ftfont_list (struct frame *, Lisp_Object);
extern Lisp_Object ftfont_list2 (struct frame *, Lisp_Object, Lisp_Object);
extern Lisp_Object ftfont_list_family (struct frame *);
extern Lisp_Object ftfont_match (struct frame *, Lisp_Object);
extern Lisp_Object ftfont_match2 (struct frame *, Lisp_Object, Lisp_Object);
extern Lisp_Object ftfont_open (struct frame *, Lisp_Object, int);
extern Lisp_Object ftfont_otf_capability (struct font *);
extern Lisp_Object ftfont_shape (Lisp_Object, Lisp_Object);
......@@ -903,6 +922,11 @@ extern void ftfont_close (struct font *);
extern void ftfont_filter_properties (Lisp_Object, Lisp_Object);
extern void ftfont_text_extents (struct font *, unsigned *, int,
struct font_metrics *);
#ifdef HAVE_HARFBUZZ
extern Lisp_Object fthbfont_combining_capability (struct font *);
extern hb_font_t *fthbfont_begin_hb_font (struct font *, double *);
extern Lisp_Object fthbfont_shape (Lisp_Object, Lisp_Object);
#endif /* HAVE_HARFBUZZ */
extern void syms_of_ftfont (void);
#endif /* HAVE_FREETYPE */
#ifdef HAVE_X_WINDOWS
......@@ -912,6 +936,9 @@ extern void syms_of_xfont (void);
extern void syms_of_ftxfont (void);
#ifdef HAVE_XFT
extern struct font_driver const xftfont_driver;
#ifdef HAVE_HARFBUZZ
extern struct font_driver xfthbfont_driver;
#endif /* HAVE_HARFBUZZ */
#endif
#if defined HAVE_FREETYPE || defined HAVE_XFT
extern struct font_driver const ftxfont_driver;
......@@ -933,6 +960,9 @@ extern void syms_of_macfont (void);
#endif /* HAVE_NS */
#ifdef USE_CAIRO
extern struct font_driver const ftcrfont_driver;
#ifdef HAVE_HARFBUZZ
extern struct font_driver ftcrhbfont_driver;
#endif /* HAVE_HARFBUZZ */
extern void syms_of_ftcrfont (void);
#endif
......
......@@ -98,21 +98,13 @@ ftcrfont_glyph_extents (struct font *font,
static Lisp_Object
ftcrfont_list (struct frame *f, Lisp_Object spec)
{
Lisp_Object list = ftfont_list (f, spec), tail;
for (tail = list; CONSP (tail); tail = XCDR (tail))
ASET (XCAR (tail), FONT_TYPE_INDEX, Qftcr);
return list;
return ftfont_list2 (f, spec, Qftcr);
}
static Lisp_Object
ftcrfont_match (struct frame *f, Lisp_Object spec)
{
Lisp_Object entity = ftfont_match (f, spec);
if (VECTORP (entity))
ASET (entity, FONT_TYPE_INDEX, Qftcr);
return entity;
return ftfont_match2 (f, spec, Qftcr);
}
static Lisp_Object
......@@ -124,7 +116,8 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
if (size == 0)
size = pixel_size;
font_object = font_build_object (VECSIZE (struct font_info),
Qftcr, entity, size);
AREF (entity, FONT_TYPE_INDEX),
entity, size);
block_input ();
font_object = ftfont_open2 (f, entity, pixel_size, font_object);
if (FONT_OBJECT_P (font_object))
......@@ -133,6 +126,11 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
struct font_info *ftcrfont_info = (struct font_info *) font;
FT_Face ft_face = ftcrfont_info->ft_size->face;
#ifdef HAVE_HARFBUZZ
if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qftcrhb))
font->driver = &ftcrhbfont_driver;
else
#endif /* HAVE_HARFBUZZ */
font->driver = &ftcrfont_driver;
FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw);
FT_Activate_Size (ftcrfont_info->ft_size_draw);
......@@ -291,7 +289,7 @@ ftcrfont_anchor_point (struct font *font, unsigned int code, int idx,
static Lisp_Object
ftcrfont_shape (Lisp_Object lgstring, Lisp_Object direction)
{
#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ
#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;
......@@ -361,6 +359,39 @@ ftcrfont_draw (struct glyph_string *s,
return len;
}
#ifdef HAVE_HARFBUZZ
static Lisp_Object
ftcrhbfont_list (struct frame *f, Lisp_Object spec)
{
return ftfont_list2 (f, spec, Qftcrhb);
}
static Lisp_Object
ftcrhbfont_match (struct frame *f, Lisp_Object spec)
{
return ftfont_match2 (f, spec, Qftcrhb);
}
static hb_font_t *
ftcrhbfont_begin_hb_font (struct font *font, double *position_unit)
{
struct font_info *ftcrfont_info = (struct font_info *) font;
FT_Activate_Size (ftcrfont_info->ft_size_draw);
hb_font_t *hb_font = fthbfont_begin_hb_font (font, position_unit);
int i = ftcrfont_info->bitmap_strike_index;
if (i >= 0)
{
FT_Face ft_face = ftcrfont_info->ft_size_draw->face;
*position_unit = ((double) font->height
/ ft_face->available_sizes[i].height) / (1 << 6);
}
return hb_font;
}
#endif /* HAVE_HARFBUZZ */
static void syms_of_ftcrfont_for_pdumper (void);
......@@ -390,11 +421,17 @@ struct font_driver const ftcrfont_driver =
.filter_properties = ftfont_filter_properties,
.combining_capability = ftfont_combining_capability,
};
#ifdef HAVE_HARFBUZZ
struct font_driver ftcrhbfont_driver;
#endif /* HAVE_HARFBUZZ */
void
syms_of_ftcrfont (void)
{
DEFSYM (Qftcr, "ftcr");
#ifdef HAVE_HARFBUZZ
DEFSYM (Qftcrhb, "ftcrhb");
#endif /* HAVE_HARFBUZZ */
pdumper_do_now_and_after_load (syms_of_ftcrfont_for_pdumper);
}
......@@ -402,4 +439,14 @@ static void
syms_of_ftcrfont_for_pdumper (void)
{
register_font_driver (&ftcrfont_driver, NULL);
#ifdef HAVE_HARFBUZZ
ftcrhbfont_driver = ftcrfont_driver;
ftcrhbfont_driver.type = Qftcrhb;
ftcrhbfont_driver.list = ftcrhbfont_list;
ftcrhbfont_driver.match = ftcrhbfont_match;
ftcrhbfont_driver.shape = fthbfont_shape;
ftcrhbfont_driver.combining_capability = fthbfont_combining_capability;
ftcrhbfont_driver.begin_hb_font = ftcrhbfont_begin_hb_font;
register_font_driver (&ftcrhbfont_driver, NULL);
#endif /* HAVE_HARFBUZZ */
}
This diff is collapsed.
......@@ -209,21 +209,13 @@ ftxfont_draw_background (struct frame *f, struct font *font, GC gc, int x, int y
static Lisp_Object
ftxfont_list (struct frame *f, Lisp_Object spec)
{
Lisp_Object list = ftfont_list (f, spec), tail;
for (tail = list; CONSP (tail); tail = XCDR (tail))
ASET (XCAR (tail), FONT_TYPE_INDEX, Qftx);
return list;
return ftfont_list2 (f, spec, Qftx);
}
static Lisp_Object
ftxfont_match (struct frame *f, Lisp_Object spec)
{
Lisp_Object entity = ftfont_match (f, spec);
if (VECTORP (entity))
ASET (entity, FONT_TYPE_INDEX, Qftx);
return entity;
return ftfont_match2 (f, spec, Qftx);
}
static Lisp_Object
......@@ -362,7 +354,7 @@ struct font_driver const ftxfont_driver =
.otf_capability = ftfont_otf_capability,
#endif
.end_for_frame = ftxfont_end_for_frame,
#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ
#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
.shape = ftfont_shape,
#endif
#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
......
......@@ -3774,10 +3774,16 @@ This function is an internal primitive--use `make-frame' instead. */)
#ifdef USE_CAIRO
register_font_driver (&ftcrfont_driver, f);
#ifdef HAVE_HARFBUZZ
register_font_driver (&ftcrhbfont_driver, f);
#endif /* HAVE_HARFBUZZ */
#else
#ifdef HAVE_FREETYPE
#ifdef HAVE_XFT
register_font_driver (&xftfont_driver, f);
#ifdef HAVE_HARFBUZZ
register_font_driver (&xfthbfont_driver, f);
#endif
#else /* not HAVE_XFT */
register_font_driver (&ftxfont_driver, f);
#endif /* not HAVE_XFT */
......
......@@ -108,21 +108,13 @@ xftfont_get_colors (struct frame *f, struct face *face, GC gc,
static Lisp_Object
xftfont_list (struct frame *f, Lisp_Object spec)
{
Lisp_Object list = ftfont_list (f, spec);
for (Lisp_Object tail = list; CONSP (tail); tail = XCDR (tail))
ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
return list;
return ftfont_list2 (f, spec, Qxft);
}
static Lisp_Object
xftfont_match (struct frame *f, Lisp_Object spec)
{
Lisp_Object entity = ftfont_match (f, spec);
if (! NILP (entity))
ASET (entity, FONT_TYPE_INDEX, Qxft);
return entity;
return ftfont_match2 (f, spec, Qxft);
}
static FcChar8 ascii_printable[95];
......@@ -311,10 +303,16 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
/* We should not destroy PAT here because it is kept in XFTFONT and
destroyed automatically when XFTFONT is closed. */
font_object = font_build_object (VECSIZE (struct font_info),
Qxft, entity, size);
AREF (entity, FONT_TYPE_INDEX),
entity, size);
ASET (font_object, FONT_FILE_INDEX, filename);
font = XFONT_OBJECT (font_object);
font->pixel_size = size;
#ifdef HAVE_HARFBUZZ
if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qxfthb))
font->driver = &xfthbfont_driver;
else
#endif /* HAVE_HARFBUZZ */
font->driver = &xftfont_driver;
font->encoding_charset = font->repertory_charset = -1;
......@@ -649,7 +647,7 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
return len;
}
#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ
#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
static Lisp_Object
xftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
{
......@@ -739,6 +737,41 @@ xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
return ok;
}
#ifdef HAVE_HARFBUZZ
static Lisp_Object
xfthbfont_list (struct frame *f, Lisp_Object spec)
{
return ftfont_list2 (f, spec, Qxfthb);
}
static Lisp_Object
xfthbfont_match (struct frame *f, Lisp_Object spec)
{
return ftfont_match2 (f, spec, Qxfthb);
}
static hb_font_t *
xfthbfont_begin_hb_font (struct font *font, double *position_unit)
{
struct font_info *xftfont_info = (struct font_info *) font;
FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
xftfont_info->ft_size = ft_face->size;
return fthbfont_begin_hb_font (font, position_unit);
}
static void
xfthbfont_end_hb_font (struct font *font, hb_font_t *hb_font)
{
struct font_info *xftfont_info = (struct font_info *) font;
XftUnlockFace (xftfont_info->xftfont);
}
#endif /* HAVE_HARFBUZZ */
static void syms_of_xftfont_for_pdumper (void);
struct font_driver const xftfont_driver =
......@@ -763,7 +796,7 @@ struct font_driver const xftfont_driver =
.otf_capability = ftfont_otf_capability,
#endif
.end_for_frame = xftfont_end_for_frame,
#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ
#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
.shape = xftfont_shape,
#endif
#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
......@@ -774,11 +807,17 @@ struct font_driver const xftfont_driver =
.combining_capability = ftfont_combining_capability,
.drop_xrender_surfaces = xftfont_drop_xrender_surfaces,
};
#ifdef HAVE_HARFBUZZ
struct font_driver xfthbfont_driver;
#endif /* HAVE_HARFBUZZ */
void
syms_of_xftfont (void)
{
DEFSYM (Qxft, "xft");
#ifdef HAVE_HARFBUZZ
DEFSYM (Qxfthb, "xfthb");
#endif /* HAVE_HARFBUZZ */
DEFSYM (QChinting, ":hinting");
DEFSYM (QCautohint, ":autohint");
DEFSYM (QChintstyle, ":hintstyle");
......@@ -799,4 +838,15 @@ static void
syms_of_xftfont_for_pdumper (void)
{
register_font_driver (&xftfont_driver, NULL);
#ifdef HAVE_HARFBUZZ
xfthbfont_driver = xftfont_driver;
xfthbfont_driver.type = Qxfthb;
xfthbfont_driver.list = xfthbfont_list;
xfthbfont_driver.match = xfthbfont_match;
xfthbfont_driver.shape = fthbfont_shape;
xfthbfont_driver.combining_capability = fthbfont_combining_capability;
xfthbfont_driver.begin_hb_font = xfthbfont_begin_hb_font;
xfthbfont_driver.end_hb_font = xfthbfont_end_hb_font;
register_font_driver (&xfthbfont_driver, NULL);
#endif /* HAVE_HARFBUZZ */
}
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