Make fthbfont and derivatives use common HarfBuzz code in hbfont.c
* src/font.h (fthbfont_shape, fthbfont_combining_capability) [HAVE_HARFBUZZ]: Remove prototypes. * src/ftfont.c: Don't include math.h. (uni_combining, uni_general, uni_mirroring, get_hb_unicode_funcs) (fthbfont_shape_by_hb, fthbfont_combining_capability, fthbfont_shape) [HAVE_HARFBUZZ]: Remove functions. * src/ftfont.c (syms_of_ftfont_for_pdumper) [HAVE_HARFBUZZ]: * src/xftfont.c (syms_of_xftfont_for_pdumper) [HAVE_HARFBUZZ]: * src/ftcrfont.c (syms_of_ftcrfont_for_pdumper) [HAVE_HARFBUZZ]: Use hbfont_shape and hbfont_combining_capability instead of fthbfont_shape and fthbfont_combining_capability, respectively.
This commit is contained in:
parent
fd380b4f55
commit
ab1d5d4005
4 changed files with 6 additions and 299 deletions
|
@ -928,9 +928,7 @@ extern void ftfont_filter_properties (Lisp_Object, Lisp_Object);
|
|||
extern void ftfont_text_extents (struct font *, const 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 */
|
||||
|
|
|
@ -612,8 +612,8 @@ syms_of_ftcrfont_for_pdumper (void)
|
|||
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.shape = hbfont_shape;
|
||||
ftcrhbfont_driver.combining_capability = hbfont_combining_capability;
|
||||
ftcrhbfont_driver.begin_hb_font = ftcrhbfont_begin_hb_font;
|
||||
ftcrhbfont_driver.end_hb_font = ftcrhbfont_end_hb_font;
|
||||
register_font_driver (&ftcrhbfont_driver, NULL);
|
||||
|
|
295
src/ftfont.c
295
src/ftfont.c
|
@ -21,7 +21,6 @@ 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>
|
||||
|
||||
|
@ -2851,296 +2850,6 @@ fthbfont_begin_hb_font (struct font *font, double *position_unit)
|
|||
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)
|
||||
{
|
||||
Lisp_Object table, combining;
|
||||
|
||||
/* FIXME: Is it efficient to load the table each time? */
|
||||
table = Funicode_property_table_internal (intern ("canonical-combining-class"));
|
||||
combining = Fget_unicode_property_internal (table, make_fixnum (ch));
|
||||
|
||||
if (INTEGERP (combining))
|
||||
return (hb_unicode_combining_class_t) XFIXNUM (combining);
|
||||
|
||||
return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED;
|
||||
}
|
||||
|
||||
static hb_unicode_general_category_t
|
||||
uni_general (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
|
||||
{
|
||||
Lisp_Object category = CHAR_TABLE_REF (Vunicode_category_table, ch);
|
||||
|
||||
if (INTEGERP (category))
|
||||
{
|
||||
switch (XFIXNUM (category))
|
||||
{
|
||||
case UNICODE_CATEGORY_Cc:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_CONTROL;
|
||||
case UNICODE_CATEGORY_Cf:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_FORMAT;
|
||||
case UNICODE_CATEGORY_Cn:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
|
||||
case UNICODE_CATEGORY_Co:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE;
|
||||
case UNICODE_CATEGORY_Cs:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_SURROGATE;
|
||||
case UNICODE_CATEGORY_Ll:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER;
|
||||
case UNICODE_CATEGORY_Lm:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER;
|
||||
case UNICODE_CATEGORY_Lo:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
|
||||
case UNICODE_CATEGORY_Lt:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER;
|
||||
case UNICODE_CATEGORY_Lu:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER;
|
||||
case UNICODE_CATEGORY_Mc:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK;
|
||||
case UNICODE_CATEGORY_Me:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
|
||||
case UNICODE_CATEGORY_Mn:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK;
|
||||
case UNICODE_CATEGORY_Nd:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER;
|
||||
case UNICODE_CATEGORY_Nl:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER;
|
||||
case UNICODE_CATEGORY_No:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER;
|
||||
case UNICODE_CATEGORY_Pc:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION;
|
||||
case UNICODE_CATEGORY_Pd:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION;
|
||||
case UNICODE_CATEGORY_Pe:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION;
|
||||
case UNICODE_CATEGORY_Pf:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION;
|
||||
case UNICODE_CATEGORY_Pi:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION;
|
||||
case UNICODE_CATEGORY_Po:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION;
|
||||
case UNICODE_CATEGORY_Ps:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION;
|
||||
case UNICODE_CATEGORY_Sc:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL;
|
||||
case UNICODE_CATEGORY_Sk:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL;
|
||||
case UNICODE_CATEGORY_Sm:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL;
|
||||
case UNICODE_CATEGORY_So:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL;
|
||||
case UNICODE_CATEGORY_Zl:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR;
|
||||
case UNICODE_CATEGORY_Zp:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR;
|
||||
case UNICODE_CATEGORY_Zs:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
|
||||
case UNICODE_CATEGORY_UNKNOWN:
|
||||
return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
|
||||
}
|
||||
}
|
||||
|
||||
return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
|
||||
}
|
||||
|
||||
static hb_codepoint_t
|
||||
uni_mirroring (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
|
||||
{
|
||||
return bidi_mirror_char (ch);
|
||||
}
|
||||
|
||||
static hb_unicode_funcs_t *
|
||||
get_hb_unicode_funcs (void)
|
||||
{
|
||||
/* Subclass HarfBuzz's default Unicode functions and override functions that
|
||||
* use data Emacs can provide. This way changing Emacs data is reflected in
|
||||
* the shaped output. */
|
||||
hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (hb_unicode_funcs_get_default ());
|
||||
|
||||
hb_unicode_funcs_set_combining_class_func (funcs, uni_combining, NULL, NULL);
|
||||
hb_unicode_funcs_set_general_category_func (funcs, uni_general, NULL, NULL);
|
||||
hb_unicode_funcs_set_mirroring_func (funcs, uni_mirroring, NULL, NULL);
|
||||
|
||||
/* Use default implmentation for Unicode composition/decomposition, we might
|
||||
* want to revisit this later.
|
||||
hb_unicode_funcs_set_compose_func (funcs, uni_compose, NULL, NULL);
|
||||
hb_unicode_funcs_set_decompose_func (funcs, uni_decompose, NULL, NULL);
|
||||
*/
|
||||
|
||||
/* Emacs own script mapping for characters differs from Unicode, so we want
|
||||
* to keep the default HarfBuzz's implementation here.
|
||||
hb_unicode_funcs_set_script_func (funcs, uni_script, NULL, NULL);
|
||||
*/
|
||||
|
||||
return funcs;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
fthbfont_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;
|
||||
|
||||
hb_glyph_info_t *info;
|
||||
hb_glyph_position_t *pos;
|
||||
|
||||
/* Cache the HarfBuzz buffer for better performance and less allocations.
|
||||
* We intentionally never destroy the buffer. */
|
||||
static hb_buffer_t *hb_buffer = NULL;
|
||||
if (! hb_buffer)
|
||||
{
|
||||
hb_buffer = hb_buffer_create ();
|
||||
hb_unicode_funcs_t* ufuncs = get_hb_unicode_funcs();
|
||||
hb_buffer_set_unicode_funcs(hb_buffer, ufuncs);
|
||||
}
|
||||
|
||||
hb_buffer_clear_contents (hb_buffer);
|
||||
hb_buffer_pre_allocate (hb_buffer, text_len);
|
||||
|
||||
for (i = 0; i < text_len; i++)
|
||||
{
|
||||
Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
|
||||
int c;
|
||||
|
||||
if (NILP (g))
|
||||
break;
|
||||
c = LGLYPH_CHAR (g);
|
||||
hb_buffer_add (hb_buffer, c, i);
|
||||
}
|
||||
|
||||
text_len = i;
|
||||
if (!text_len)
|
||||
return Qnil;
|
||||
|
||||
hb_buffer_set_content_type (hb_buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
|
||||
hb_buffer_set_cluster_level (hb_buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
|
||||
|
||||
/* If the caller didn't provide a meaningful DIRECTION, default to L2R. */
|
||||
hb_direction_t dir = HB_DIRECTION_LTR;
|
||||
if (EQ (direction, QL2R))
|
||||
dir = HB_DIRECTION_LTR;
|
||||
else if (EQ (direction, QR2L))
|
||||
dir = HB_DIRECTION_RTL;
|
||||
hb_buffer_set_direction (hb_buffer, dir);
|
||||
|
||||
/* Leave the script determination to HarfBuzz, until Emacs has a
|
||||
better idea of the script of LGSTRING. FIXME. */
|
||||
#if 0
|
||||
hb_buffer_set_script (hb_buffer, XXX);
|
||||
#endif
|
||||
|
||||
/* FIXME: This can only handle the single global language, which
|
||||
normally comes from the locale. In addition, if
|
||||
current-iso639-language is a list, we arbitrarily use the first
|
||||
one. We should instead have a notion of the language of the text
|
||||
being shaped. */
|
||||
Lisp_Object lang = Vcurrent_iso639_language;
|
||||
if (CONSP (Vcurrent_iso639_language))
|
||||
lang = XCAR (Vcurrent_iso639_language);
|
||||
if (SYMBOLP (lang))
|
||||
{
|
||||
Lisp_Object lang_str = SYMBOL_NAME (lang);
|
||||
hb_buffer_set_language (hb_buffer,
|
||||
hb_language_from_string (SSDATA (lang_str),
|
||||
SBYTES (lang_str)));
|
||||
}
|
||||
|
||||
/* Guess the default properties for when they cannot be determined
|
||||
above. FIXME: drop once script handling is fixed above. */
|
||||
hb_buffer_guess_segment_properties (hb_buffer);
|
||||
|
||||
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);
|
||||
/* FIXME: can't we just grew the lgstring in this case? Givving up is an
|
||||
* overly heavy handed solution. */
|
||||
if (glyph_len > LGSTRING_GLYPH_LEN (lgstring))
|
||||
return Qnil;
|
||||
|
||||
/* Somewhere up the pipeline wants the glyphs in logical order, while keeping
|
||||
* clusters in visual order. I don't know where exactly, but lets satisfy
|
||||
* that. */
|
||||
if (HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (hb_buffer)))
|
||||
hb_buffer_reverse_clusters (hb_buffer);
|
||||
|
||||
info = hb_buffer_get_glyph_infos (hb_buffer, NULL);
|
||||
pos = hb_buffer_get_glyph_positions (hb_buffer, NULL);
|
||||
for (i = 0; i < glyph_len; i++)
|
||||
{
|
||||
Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
|
||||
EMACS_INT from, to;
|
||||
struct font_metrics metrics = {.width = 0};
|
||||
int xoff, yoff, wadjust;
|
||||
ptrdiff_t j = i;
|
||||
|
||||
if (NILP (lglyph))
|
||||
{
|
||||
lglyph = LGLYPH_NEW ();
|
||||
LGSTRING_SET_GLYPH (lgstring, i, lglyph);
|
||||
}
|
||||
|
||||
from = to = info[i].cluster;
|
||||
/* FIXME: what does “from” mean here? */
|
||||
LGLYPH_SET_FROM (lglyph, from);
|
||||
|
||||
/* FIXME: what does “to” mean here? */
|
||||
for (j = i; j < glyph_len && info[j].cluster == info[i].cluster; j++)
|
||||
;
|
||||
to = (j == glyph_len) ? text_len - 1 : info[j].cluster - 1;
|
||||
LGLYPH_SET_TO (lglyph, to);
|
||||
|
||||
/* FIXME: is this really needed? Not all glyphs map directly to a single character */
|
||||
LGLYPH_SET_CHAR (lglyph, LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, from)));
|
||||
LGLYPH_SET_CODE (lglyph, info[i].codepoint);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Lisp_Object
|
||||
fthbfont_combining_capability (struct font *font)
|
||||
{
|
||||
return Qt;
|
||||
}
|
||||
|
||||
Lisp_Object
|
||||
fthbfont_shape (Lisp_Object lgstring, Lisp_Object direction)
|
||||
{
|
||||
struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
|
||||
|
||||
return fthbfont_shape_by_hb (lgstring, font, direction);
|
||||
}
|
||||
|
||||
#endif /* HAVE_HARFBUZZ */
|
||||
|
||||
static const char *const ftfont_booleans [] = {
|
||||
|
@ -3282,8 +2991,8 @@ syms_of_ftfont_for_pdumper (void)
|
|||
#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.shape = hbfont_shape;
|
||||
fthbfont_driver.combining_capability = hbfont_combining_capability;
|
||||
fthbfont_driver.begin_hb_font = fthbfont_begin_hb_font;
|
||||
register_font_driver (&fthbfont_driver, NULL);
|
||||
#endif /* HAVE_HARFBUZZ */
|
||||
|
|
|
@ -699,8 +699,8 @@ syms_of_xftfont_for_pdumper (void)
|
|||
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.shape = hbfont_shape;
|
||||
xfthbfont_driver.combining_capability = hbfont_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);
|
||||
|
|
Loading…
Add table
Reference in a new issue