From: mituharu@math.s.chiba-u.ac.jp
To: emacs-devel@gnu.org
Subject: landing harfbuzz branch (Re: Status of multicolor fonts?)
Date: Fri, 3 May 2019 18:59:26 +0900 [thread overview]
Message-ID: <b7dbea956a6b0dae218def2bddaaf30b.squirrel@weber.math.s.chiba-u.ac.jp> (raw)
In-Reply-To: <837ebfx2dd.fsf@gnu.org>
[-- Attachment #1: Type: text/plain, Size: 1263 bytes --]
> The general idea is to use HarfBuzz as a font backend which supports
> layout of complex scripts, as a replacement for libm17n-flt on
> GNU/Linux and as a replacement for Uniscribe on MS-Windows. The
> current code on the branch uses compile-time CPP directives to select
> HarfBuzz as the shaper for xftfont and other font back-ends, but I
> would like to make it a separate font backend instead, so that people
> could choose which one to use. I also think not every existing font
> backend needs to be able to use HarfBuzz, only those which support OTF
> and TTF font features should.
The attached patch is against the harfbuzz branch, and it adds
`xfthb' and `ftcrhb' backends that use HarfBuzz for shaping. I
also tried adding the `mac-cthb' backend, but it is not included
in the patch.
With the `ftcrhb' font backend, one can now display regional flag
emojis:
(make-frame '((font-backend ftcrhb)))
(set-fontset-font t '(#x1F1E6 . #x1F1FF) (font-spec :family "Noto Color
Emoji"))
(set-char-table-range composition-function-table '(#x1F1E6 . #x1F1FF)
'([".[\x1F1E6-\x1F1FF]" 0 font-shape-gstring]))
(insert (+ ?j (- #x1F1E6 ?a)) (+ ?p (- #x1F1E6 ?a)))
YAMAMOTO Mitsuharu
mituharu@math.s.chiba-u.ac.jp
[-- Attachment #2: hb-font-backends.diff --]
[-- Type: application/octet-stream, Size: 24093 bytes --]
diff --git a/src/font.h b/src/font.h
index 3540a8dba22..1f62a61f0be 100644
--- a/src/font.h
+++ b/src/font.h
@@ -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
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index c0f62e0418e..dc59c2bcadc 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -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 */
\f
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 */
}
diff --git a/src/ftfont.c b/src/ftfont.c
index 58c462a90fe..718fae2b87b 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
+#include <math.h>
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
@@ -48,6 +49,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "pdumper.h"
static struct font_driver const ftfont_driver;
+#ifdef HAVE_HARFBUZZ
+static struct font_driver fthbfont_driver;
+#endif /* HAVE_HARFBUZZ */
/* Flag to tell if FcInit is already called or not. */
static bool fc_initialized;
@@ -466,19 +470,6 @@ ftfont_get_otf (struct font_info *ftfont_info)
}
#endif /* HAVE_LIBOTF */
-#ifdef HAVE_HARFBUZZ
-
-static hb_font_t *
-ftfont_get_hb_font (struct font_info *ftfont_info)
-{
- if (! ftfont_info->hb_font)
- ftfont_info->hb_font
- = hb_ft_font_create_referenced (ftfont_info->ft_size->face);
- return ftfont_info->hb_font;
-}
-
-#endif /* HAVE_HARFBUZZ */
-
Lisp_Object
ftfont_get_cache (struct frame *f)
{
@@ -801,7 +792,7 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots
return pattern;
}
-Lisp_Object
+static Lisp_Object
ftfont_list (struct frame *f, Lisp_Object spec)
{
Lisp_Object val = Qnil, family, adstyle;
@@ -1001,6 +992,16 @@ ftfont_list (struct frame *f, Lisp_Object spec)
}
Lisp_Object
+ftfont_list2 (struct frame *f, Lisp_Object spec, Lisp_Object type)
+{
+ Lisp_Object list = ftfont_list (f, spec);
+
+ for (Lisp_Object tail = list; CONSP (tail); tail = XCDR (tail))
+ ASET (XCAR (tail), FONT_TYPE_INDEX, type);
+ return list;
+}
+
+static Lisp_Object
ftfont_match (struct frame *f, Lisp_Object spec)
{
Lisp_Object entity = Qnil;
@@ -1050,6 +1051,16 @@ ftfont_match (struct frame *f, Lisp_Object spec)
return entity;
}
+Lisp_Object
+ftfont_match2 (struct frame *f, Lisp_Object spec, Lisp_Object type)
+{
+ Lisp_Object entity = ftfont_match (f, spec);
+
+ if (! NILP (entity))
+ ASET (entity, FONT_TYPE_INDEX, type);
+ return entity;
+}
+
Lisp_Object
ftfont_list_family (struct frame *f)
{
@@ -1185,6 +1196,11 @@ ftfont_open2 (struct frame *f,
/* This means that there's no need of transformation. */
ftfont_info->matrix.xx = 0;
font->pixel_size = size;
+#ifdef HAVE_HARFBUZZ
+ if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qfreetypehb))
+ font->driver = &fthbfont_driver;
+ else
+#endif /* HAVE_HARFBUZZ */
font->driver = &ftfont_driver;
font->encoding_charset = font->repertory_charset = -1;
@@ -1266,7 +1282,8 @@ ftfont_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),
- Qfreetype, entity, size);
+ AREF (entity, FONT_TYPE_INDEX),
+ entity, size);
font_object = ftfont_open2 (f, entity, pixel_size, font_object);
if (FONT_OBJECT_P (font_object))
{
@@ -2673,6 +2690,17 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
return make_fixnum (i);
}
+Lisp_Object
+ftfont_shape (Lisp_Object lgstring)
+{
+ struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
+ struct font_info *ftfont_info = (struct font_info *) font;
+ OTF *otf = ftfont_get_otf (ftfont_info);
+
+ return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf,
+ &ftfont_info->matrix);
+}
+
#endif /* HAVE_M17N_FLT */
#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
@@ -2693,6 +2721,18 @@ ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
#ifdef HAVE_HARFBUZZ
+hb_font_t *
+fthbfont_begin_hb_font (struct font *font, double *position_unit)
+{
+ struct font_info *ftfont_info = (struct font_info *) font;
+
+ *position_unit = 1.0 / (1 << 6);
+ if (! ftfont_info->hb_font)
+ ftfont_info->hb_font
+ = hb_ft_font_create_referenced (ftfont_info->ft_size->face);
+ return ftfont_info->hb_font;
+}
+
static hb_unicode_combining_class_t
uni_combining (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
{
@@ -2818,8 +2858,8 @@ get_hb_unicode_funcs (void)
}
static Lisp_Object
-ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font,
- FT_Matrix *matrix, Lisp_Object direction)
+ftfont_shape_by_hb (Lisp_Object lgstring, struct font *font,
+ Lisp_Object direction)
{
ptrdiff_t glyph_len = 0, text_len = LGSTRING_GLYPH_LEN (lgstring);
ptrdiff_t i;
@@ -2892,7 +2932,15 @@ ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font,
above. FIXME: drop once script handling is fixed above. */
hb_buffer_guess_segment_properties (hb_buffer);
- if (!hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL))
+ double position_unit;
+ hb_font_t *hb_font = font->driver->begin_hb_font (font, &position_unit);
+ if (!hb_font)
+ return make_fixnum (0);
+
+ hb_bool_t success = hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL);
+ if (font->driver->end_hb_font)
+ font->driver->end_hb_font (font, hb_font);
+ if (!success)
return Qnil;
glyph_len = hb_buffer_get_length (hb_buffer);
@@ -2913,7 +2961,8 @@ ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font,
{
Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
EMACS_INT from, to;
- int advance = 0, lbearing, rbearing, ascent, descent;
+ struct font_metrics metrics = {.width = 0};
+ int xoff, yoff, wadjust;
ptrdiff_t j = i;
if (NILP (lglyph))
@@ -2936,61 +2985,46 @@ ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font,
LGLYPH_SET_CHAR (lglyph, LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, from)));
LGLYPH_SET_CODE (lglyph, info[i].codepoint);
- if (ftfont_glyph_metrics (ft_face, info[i].codepoint, &advance, &lbearing,
- &rbearing, &ascent, &descent))
- {
- LGLYPH_SET_WIDTH (lglyph, advance);
- LGLYPH_SET_LBEARING (lglyph, lbearing);
- LGLYPH_SET_RBEARING (lglyph, rbearing);
- LGLYPH_SET_ASCENT (lglyph, ascent);
- LGLYPH_SET_DESCENT (lglyph, descent);
- }
-
- if (pos[i].x_offset || pos[i].y_offset ||
- (pos[i].x_advance >> 6) != advance)
- {
- Lisp_Object vec = make_uninit_vector (3);
- ASET (vec, 0, make_fixnum (pos[i].x_offset >> 6));
- ASET (vec, 1, make_fixnum (-(pos[i].y_offset >> 6)));
- ASET (vec, 2, make_fixnum (pos[i].x_advance >> 6));
- LGLYPH_SET_ADJUSTMENT (lglyph, vec);
- }
+ unsigned code = info[i].codepoint;
+ font->driver->text_extents (font, &code, 1, &metrics);
+ LGLYPH_SET_WIDTH (lglyph, metrics.width);
+ LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
+ LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
+ LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
+ LGLYPH_SET_DESCENT (lglyph, metrics.descent);
+
+ xoff = lround (pos[i].x_offset * position_unit);
+ yoff = - lround (pos[i].y_offset * position_unit);
+ wadjust = lround (pos[i].x_advance * position_unit);
+ if (xoff || yoff || wadjust != metrics.width)
+ {
+ Lisp_Object vec = make_uninit_vector (3);
+ ASET (vec, 0, make_fixnum (xoff));
+ ASET (vec, 1, make_fixnum (yoff));
+ ASET (vec, 2, make_fixnum (wadjust));
+ LGLYPH_SET_ADJUSTMENT (lglyph, vec);
+ }
}
return make_fixnum (glyph_len);
}
-#endif /* HAVE_HARFBUZZ */
-
-#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ
+Lisp_Object
+fthbfont_combining_capability (struct font *font)
+{
+ return Qt;
+}
Lisp_Object
-ftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
+fthbfont_shape (Lisp_Object lgstring, Lisp_Object direction)
{
struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
struct font_info *ftfont_info = (struct font_info *) font;
-#ifdef HAVE_HARFBUZZ
- if (getenv ("EMACS_NO_HARFBUZZ") == NULL)
- {
- hb_font_t *hb_font = ftfont_get_hb_font (ftfont_info);
-
- return ftfont_shape_by_hb (lgstring, ftfont_info->ft_size->face,
- hb_font, &ftfont_info->matrix, direction);
- }
- else
-#endif /* HAVE_HARFBUZZ */
- {
-#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
- OTF *otf = ftfont_get_otf (ftfont_info);
- return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face,
- otf, &ftfont_info->matrix);
-#endif /* defined HAVE_M17N_FLT && defined HAVE_LIBOTF */
- }
- return make_fixnum (0);
+ return ftfont_shape_by_hb (lgstring, font, direction);
}
-#endif /* (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ */
+#endif /* HAVE_HARFBUZZ */
static const char *const ftfont_booleans [] = {
":antialias",
@@ -3046,7 +3080,7 @@ ftfont_filter_properties (Lisp_Object font, Lisp_Object alist)
Lisp_Object
ftfont_combining_capability (struct font *font)
{
-#if defined HAVE_M17N_FLT || defined HAVE_HARFBUZZ
+#ifdef HAVE_M17N_FLT
return Qt;
#else
return Qnil;
@@ -3073,7 +3107,7 @@ static struct font_driver const ftfont_driver =
#ifdef HAVE_LIBOTF
.otf_capability = ftfont_otf_capability,
#endif
-#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
@@ -3082,12 +3116,18 @@ static struct font_driver const ftfont_driver =
.filter_properties = ftfont_filter_properties,
.combining_capability = ftfont_combining_capability,
};
+#ifdef HAVE_HARFBUZZ
+static struct font_driver fthbfont_driver;
+#endif /* HAVE_HARFBUZZ */
void
syms_of_ftfont (void)
{
/* Symbolic type of this font-driver. */
DEFSYM (Qfreetype, "freetype");
+#ifdef HAVE_HARFBUZZ
+ DEFSYM (Qfreetypehb, "freetypehb");
+#endif /* HAVE_HARFBUZZ */
/* Fontconfig's generic families and their aliases. */
DEFSYM (Qmonospace, "monospace");
@@ -3114,4 +3154,12 @@ syms_of_ftfont_for_pdumper (void)
{
PDUMPER_RESET_LV (ft_face_cache, Qnil);
register_font_driver (&ftfont_driver, NULL);
+#ifdef HAVE_HARFBUZZ
+ fthbfont_driver = ftfont_driver;
+ fthbfont_driver.type = Qfreetypehb;
+ fthbfont_driver.shape = fthbfont_shape;
+ fthbfont_driver.combining_capability = fthbfont_combining_capability;
+ fthbfont_driver.begin_hb_font = fthbfont_begin_hb_font;
+ register_font_driver (&fthbfont_driver, NULL);
+#endif /* HAVE_HARFBUZZ */
}
diff --git a/src/ftxfont.c b/src/ftxfont.c
index a549fd723bb..949ef4c503b 100644
--- a/src/ftxfont.c
+++ b/src/ftxfont.c
@@ -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
diff --git a/src/xfns.c b/src/xfns.c
index 2ceb55a30ad..50a430aa78c 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -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 */
diff --git a/src/xftfont.c b/src/xftfont.c
index b636a759048..f7b87f96569 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -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 */
}
next prev parent reply other threads:[~2019-05-03 9:59 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-16 13:40 Status of multicolor fonts? Clément Pit--Claudel
2015-12-16 14:10 ` Eli Zaretskii
2015-12-16 15:54 ` Clément Pit--Claudel
2015-12-16 22:20 ` Clément Pit--Claudel
2015-12-17 2:47 ` Yuri Khan
2015-12-17 3:14 ` Clément Pit--Claudel
2015-12-17 16:11 ` Eli Zaretskii
2015-12-19 9:43 ` Rüdiger Sonderfeld
2016-01-06 3:51 ` YAMAMOTO Mitsuharu
2016-01-06 6:23 ` John Wiegley
2016-04-11 22:34 ` YAMAMOTO Mitsuharu
2016-04-11 23:19 ` John Wiegley
2016-04-11 23:34 ` YAMAMOTO Mitsuharu
2019-04-24 3:45 ` YAMAMOTO Mitsuharu
2019-04-24 6:34 ` Eli Zaretskii
2019-04-27 8:13 ` mituharu
2019-04-27 8:45 ` Eli Zaretskii
2019-05-03 9:59 ` mituharu [this message]
2019-05-03 20:56 ` landing harfbuzz branch (Re: Status of multicolor fonts?) Alan Third
2019-05-03 21:46 ` mituharu
2019-05-04 8:54 ` Eli Zaretskii
2019-05-04 23:42 ` mituharu
2019-05-05 16:02 ` Eli Zaretskii
2019-04-24 15:03 ` Status of multicolor fonts? Stefan Monnier
2015-12-16 14:37 ` Yuri Khan
2015-12-16 15:32 ` Elias Mårtenson
2015-12-16 15:48 ` Eli Zaretskii
2015-12-16 16:03 ` Clément Pit--Claudel
2015-12-16 17:10 ` Eli Zaretskii
2015-12-16 18:22 ` Clément Pit--Claudel
2015-12-16 16:10 ` Elias Mårtenson
2015-12-16 16:41 ` Random832
2015-12-16 16:56 ` David Kastrup
2015-12-17 4:58 ` Richard Stallman
2015-12-17 17:25 ` John Wiegley
2015-12-16 17:17 ` Eli Zaretskii
2015-12-16 18:31 ` Clément Pit--Claudel
2015-12-16 18:54 ` Eli Zaretskii
2015-12-16 18:31 ` Random832
2015-12-16 16:00 ` Clément Pit--Claudel
2015-12-16 17:08 ` Eli Zaretskii
2015-12-22 0:59 ` David De La Harpe Golden
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b7dbea956a6b0dae218def2bddaaf30b.squirrel@weber.math.s.chiba-u.ac.jp \
--to=mituharu@math.s.chiba-u.ac.jp \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).