mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-06-14 12:31:25 +00:00
Update Android port
* configure.ac (HAVE_OTF_GET_VARIATION_GLYPHS): Check for `hb_font_set_var_named_instance'. * src/sfnt.c (main): Update tests. * src/sfntfont-android.c (Fandroid_enumerate_fonts): Blacklist bad font. * src/sfntfont.c (struct sfnt_font_tables, struct sfnt_font_desc) (sfnt_decode_instance_name, sfnt_weight_descriptions) (sfnt_enum_font_1, sfntfont_list_1, sfntfont_desc_to_entity) (sfntfont_list, struct sfntfont_get_glyph_outline_dcontext) (sfntfont_get_glyph, sfntfont_get_glyph_outline) (struct sfnt_font_info, sfnt_close_tables, sfnt_open_tables) (sfntfont_open, sfntfont_measure_pcm, sfntfont_close) (sfntfont_draw, sfntfont_begin_hb_font, syms_of_sfntfont) (mark_sfntfont): Handle variable fonts correctly.
This commit is contained in:
parent
18b34e9ca0
commit
dd4924ca90
4 changed files with 377 additions and 54 deletions
15
configure.ac
15
configure.ac
|
|
@ -4586,14 +4586,19 @@ if test "${HAVE_X11}" = "yes" && test "${HAVE_FREETYPE}" = "yes" \
|
|||
|| test "$REALLY_ANDROID" = "yes"; then
|
||||
if test "${with_harfbuzz}" != "no"; then
|
||||
EMACS_CHECK_MODULES([HARFBUZZ], [harfbuzz >= $harfbuzz_required_ver])
|
||||
if test "$HAVE_HARFBUZZ" = "yes"; then
|
||||
AS_IF([test "$HAVE_HARFBUZZ" = "yes"],[
|
||||
AC_DEFINE([HAVE_HARFBUZZ], [1], [Define to 1 if using HarfBuzz.])
|
||||
### mingw32 and Cygwin-w32 don't use -lharfbuzz, since they load
|
||||
### the library dynamically.
|
||||
if test "${HAVE_W32}" = "yes"; then
|
||||
HARFBUZZ_LIBS=
|
||||
fi
|
||||
fi
|
||||
AS_IF([test "${HAVE_W32}" = "yes"], [HARFBUZZ_LIBS=])
|
||||
## Now check for `hb_font_set_var_named_instance'.
|
||||
OLD_CFLAGS=$CFLAGS
|
||||
CFLAGS="$HARFBUZZ_CFLAGS $CFLAGS"
|
||||
EMACS_CHECK_LIB([harfbuzz], [hb_font_set_var_named_instance],
|
||||
[AC_DEFINE([HAVE_HB_FONT_SET_VAR_NAMED_INSTANCE], [1],
|
||||
[Define to 1 if `hb_font_set_var_named_instance' is present.])],
|
||||
[], [$HARFBUZZ_LIBS], [#include <hb.h>])
|
||||
CFLAGS=$OLD_CFLAGS])
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -18922,8 +18922,8 @@ main (int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#define FANCY_PPEM 15
|
||||
#define EASY_PPEM 15
|
||||
#define FANCY_PPEM 40
|
||||
#define EASY_PPEM 40
|
||||
|
||||
interpreter = NULL;
|
||||
head = sfnt_read_head_table (fd, font);
|
||||
|
|
|
|||
|
|
@ -713,8 +713,11 @@ loaded before character sets are made available. */)
|
|||
/* If it contains (not ends with!) with .ttf or .ttc, then
|
||||
enumerate it. */
|
||||
|
||||
if (strstr (dirent->d_name, ".ttf")
|
||||
|| strstr (dirent->d_name, ".ttc"))
|
||||
if ((strstr (dirent->d_name, ".ttf")
|
||||
|| strstr (dirent->d_name, ".ttc"))
|
||||
/* Ignore the non-variable Roboto font. */
|
||||
&& (i != 0 || strcmp (dirent->d_name,
|
||||
"RobotoStatic-Regular.ttf")))
|
||||
{
|
||||
sprintf (name, "%s/%s", system_font_directories[i],
|
||||
dirent->d_name);
|
||||
|
|
|
|||
405
src/sfntfont.c
405
src/sfntfont.c
|
|
@ -69,6 +69,10 @@ struct sfnt_font_tables
|
|||
struct sfnt_prep_table *prep;
|
||||
struct sfnt_fpgm_table *fpgm;
|
||||
struct sfnt_cvt_table *cvt;
|
||||
struct sfnt_fvar_table *fvar;
|
||||
struct sfnt_avar_table *avar;
|
||||
struct sfnt_gvar_table *gvar;
|
||||
struct sfnt_cvar_table *cvar;
|
||||
|
||||
/* The selected character map. */
|
||||
struct sfnt_cmap_encoding_subtable_data *cmap_data;
|
||||
|
|
@ -118,6 +122,11 @@ struct sfnt_font_desc
|
|||
/* Font registry that this font supports. */
|
||||
Lisp_Object registry;
|
||||
|
||||
/* Vector of instances. Each element is another of the instance's
|
||||
`style', `adstyle', and numeric width, weight, and slant. May be
|
||||
nil. */
|
||||
Lisp_Object instances;
|
||||
|
||||
/* Numeric width, weight, slant and spacing. */
|
||||
int width, weight, slant, spacing;
|
||||
|
||||
|
|
@ -360,6 +369,29 @@ sfnt_decode_foundry_name (struct sfnt_name_table *name)
|
|||
designer_rec.length);
|
||||
}
|
||||
|
||||
/* Decode the name of the specified font INSTANCE using the given NAME
|
||||
table. Return the name of that instance, or nil upon failure. */
|
||||
|
||||
static Lisp_Object
|
||||
sfnt_decode_instance_name (struct sfnt_instance *instance,
|
||||
struct sfnt_name_table *name)
|
||||
{
|
||||
struct sfnt_name_record name_rec;
|
||||
unsigned char *name_data;
|
||||
|
||||
name_data = sfnt_find_name (name, instance->name_id,
|
||||
&name_rec);
|
||||
|
||||
if (!name_data)
|
||||
return Qnil;
|
||||
|
||||
return sfnt_decode_font_string (name_data,
|
||||
name_rec.platform_id,
|
||||
name_rec.platform_specific_id,
|
||||
name_rec.language_id,
|
||||
name_rec.length);
|
||||
}
|
||||
|
||||
struct sfnt_style_desc
|
||||
{
|
||||
/* The C string to match against. */
|
||||
|
|
@ -375,6 +407,7 @@ static struct sfnt_style_desc sfnt_weight_descriptions[] =
|
|||
{ "thin", 0, },
|
||||
{ "extralight", 40, },
|
||||
{ "ultralight", 40, },
|
||||
{ "light", 50, },
|
||||
{ "demilight", 55, },
|
||||
{ "semilight", 55, },
|
||||
{ "book", 75, },
|
||||
|
|
@ -809,7 +842,10 @@ sfnt_enum_font_1 (int fd, const char *file,
|
|||
struct sfnt_name_table *name;
|
||||
struct sfnt_meta_table *meta;
|
||||
struct sfnt_maxp_table *maxp;
|
||||
Lisp_Object family, style;
|
||||
struct sfnt_fvar_table *fvar;
|
||||
struct sfnt_font_desc temp;
|
||||
Lisp_Object family, style, instance, style1;
|
||||
int i;
|
||||
|
||||
/* Create the font desc and copy in the file name. */
|
||||
desc = xzalloc (sizeof *desc + strlen (file) + 1);
|
||||
|
|
@ -842,6 +878,10 @@ sfnt_enum_font_1 (int fd, const char *file,
|
|||
if (sfnt_decode_family_style (name, &family, &style))
|
||||
goto bail4;
|
||||
|
||||
/* See if this is a distortable/variable/multiple master font (all
|
||||
three terms mean the same time.) */
|
||||
fvar = sfnt_read_fvar_table (fd, subtables);
|
||||
|
||||
/* Set the family. */
|
||||
desc->family = family;
|
||||
desc->designer = sfnt_decode_foundry_name (name);
|
||||
|
|
@ -877,6 +917,43 @@ sfnt_enum_font_1 (int fd, const char *file,
|
|||
/* Figure out what registry this font is likely to support. */
|
||||
sfnt_grok_registry (fd, desc, subtables);
|
||||
|
||||
if (fvar && fvar->instance_count)
|
||||
{
|
||||
/* If there is an fvar table with instances, then this is a font
|
||||
which defines different axes along which the points in each
|
||||
glyph can be changed.
|
||||
|
||||
Instead of enumerating the font itself, enumerate each
|
||||
instance within, which specifies how to configure each axis
|
||||
to achieve a specified style. */
|
||||
|
||||
desc->instances = make_vector (fvar->instance_count, Qnil);
|
||||
|
||||
for (i = 0; i < fvar->instance_count; ++i)
|
||||
{
|
||||
style1 = sfnt_decode_instance_name (&fvar->instance[i],
|
||||
name);
|
||||
|
||||
if (!style1)
|
||||
continue;
|
||||
|
||||
/* Now parse the style. */
|
||||
temp.adstyle = Qnil;
|
||||
sfnt_parse_style (style1, &temp);
|
||||
|
||||
/* Set each field of the vector. */
|
||||
instance = make_vector (5, Qnil);
|
||||
ASET (instance, 0, style1);
|
||||
ASET (instance, 1, temp.adstyle);
|
||||
ASET (instance, 2, make_fixnum (temp.width));
|
||||
ASET (instance, 3, make_fixnum (temp.weight));
|
||||
ASET (instance, 4, make_fixnum (temp.slant));
|
||||
|
||||
/* Place the vector in desc->instances. */
|
||||
ASET (desc->instances, i, instance);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the style, link the desc onto system_fonts and return. */
|
||||
desc->style = style;
|
||||
desc->next = system_fonts;
|
||||
|
|
@ -898,6 +975,7 @@ sfnt_enum_font_1 (int fd, const char *file,
|
|||
next = &prev->next;
|
||||
}
|
||||
|
||||
xfree (fvar);
|
||||
xfree (meta);
|
||||
xfree (maxp);
|
||||
xfree (name);
|
||||
|
|
@ -1346,15 +1424,23 @@ sfntfont_registries_compatible_p (Lisp_Object a, Lisp_Object b)
|
|||
}
|
||||
|
||||
/* Return whether or not the font description DESC satisfactorily
|
||||
matches the font specification FONT_SPEC. */
|
||||
matches the font specification FONT_SPEC.
|
||||
|
||||
static bool
|
||||
sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec)
|
||||
Value is 0 if there is no match, -1 if there is a match against
|
||||
DESC itself, and the number of matching instances if the style
|
||||
matches one or more instances defined in in DESC. Return the index
|
||||
of each matching instance in INSTANCES; it should be SIZE big. */
|
||||
|
||||
static int
|
||||
sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec,
|
||||
int *instances, int size)
|
||||
{
|
||||
Lisp_Object tem, extra, tail;
|
||||
struct sfnt_cmap_encoding_subtable_data *cmap;
|
||||
size_t i;
|
||||
struct sfnt_cmap_encoding_subtable subtable;
|
||||
int instance, num_instance;
|
||||
Lisp_Object item;
|
||||
|
||||
/* cmap and subtable are caches for sfntfont_lookup_char. */
|
||||
|
||||
|
|
@ -1388,7 +1474,9 @@ sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec)
|
|||
|
||||
if (!NILP (tem) && NILP (Fstring_equal (SYMBOL_NAME (tem),
|
||||
desc->family)))
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
instance = -1;
|
||||
|
||||
/* If a registry is set and wrong, then reject the font desc
|
||||
immediately. This detects 50% of mismatches from fontset.c.
|
||||
|
|
@ -1399,33 +1487,82 @@ sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec)
|
|||
tem = AREF (spec, FONT_REGISTRY_INDEX);
|
||||
if (!NILP (tem) && !NILP (desc->registry)
|
||||
&& !sfntfont_registries_compatible_p (tem, desc->registry))
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
/* Check that the adstyle specified matches. */
|
||||
/* Check the style. If DESC is a fixed font, just check once.
|
||||
Otherwise, check each instance. */
|
||||
|
||||
tem = AREF (spec, FONT_ADSTYLE_INDEX);
|
||||
if (!NILP (tem) && NILP (Fequal (tem, desc->adstyle)))
|
||||
return false;
|
||||
if (NILP (desc->instances))
|
||||
{
|
||||
tem = AREF (spec, FONT_ADSTYLE_INDEX);
|
||||
if (!NILP (tem) && NILP (Fequal (tem, desc->adstyle)))
|
||||
return 0;
|
||||
|
||||
/* Check the style. */
|
||||
if (FONT_WIDTH_NUMERIC (spec) != -1
|
||||
&& FONT_WIDTH_NUMERIC (spec) != desc->width)
|
||||
return 0;
|
||||
|
||||
if (FONT_WIDTH_NUMERIC (spec) != -1
|
||||
&& FONT_WIDTH_NUMERIC (spec) != desc->width)
|
||||
return false;
|
||||
if (FONT_WEIGHT_NUMERIC (spec) != -1
|
||||
&& FONT_WEIGHT_NUMERIC (spec) != desc->weight)
|
||||
return 0;
|
||||
|
||||
if (FONT_WEIGHT_NUMERIC (spec) != -1
|
||||
&& FONT_WEIGHT_NUMERIC (spec) != desc->weight)
|
||||
return false;
|
||||
if (FONT_SLANT_NUMERIC (spec) != -1
|
||||
&& FONT_SLANT_NUMERIC (spec) != desc->slant)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
num_instance = 0;
|
||||
|
||||
if (FONT_SLANT_NUMERIC (spec) != -1
|
||||
&& FONT_SLANT_NUMERIC (spec) != desc->slant)
|
||||
return false;
|
||||
/* Find the indices of instances in this distortable font which
|
||||
match the given font spec. */
|
||||
|
||||
for (i = 0; i < ASIZE (desc->instances); ++i)
|
||||
{
|
||||
item = AREF (desc->instances, i);
|
||||
|
||||
if (NILP (item))
|
||||
continue;
|
||||
|
||||
/* Check that the adstyle specified matches. */
|
||||
|
||||
tem = AREF (spec, FONT_ADSTYLE_INDEX);
|
||||
if (!NILP (tem) && NILP (Fequal (tem, AREF (item, 1))))
|
||||
continue;
|
||||
|
||||
/* Check the style. */
|
||||
|
||||
if (FONT_WIDTH_NUMERIC (spec) != -1
|
||||
&& (FONT_WIDTH_NUMERIC (spec)
|
||||
!= XFIXNUM (AREF (item, 2))))
|
||||
continue;
|
||||
|
||||
if (FONT_WEIGHT_NUMERIC (spec) != -1
|
||||
&& (FONT_WEIGHT_NUMERIC (spec)
|
||||
!= XFIXNUM (AREF (item, 3))))
|
||||
continue;
|
||||
|
||||
if (FONT_SLANT_NUMERIC (spec) != -1
|
||||
&& (FONT_SLANT_NUMERIC (spec)
|
||||
!= XFIXNUM (AREF (item, 4))))
|
||||
continue;
|
||||
|
||||
if (num_instance == size)
|
||||
break;
|
||||
|
||||
/* A matching instance has been found. Set its index, then
|
||||
go back to the rest of the font matching. */
|
||||
instances[num_instance++] = i;
|
||||
}
|
||||
|
||||
instance = num_instance;
|
||||
}
|
||||
|
||||
/* Handle extras. */
|
||||
extra = AREF (spec, FONT_EXTRA_INDEX);
|
||||
|
||||
if (NILP (extra))
|
||||
return true;
|
||||
return instance;
|
||||
|
||||
tem = assq_no_quit (QCscript, extra);
|
||||
cmap = NULL;
|
||||
|
|
@ -1490,12 +1627,12 @@ sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec)
|
|||
desc->subtable = subtable;
|
||||
|
||||
xfree (cmap);
|
||||
return true;
|
||||
return instance;
|
||||
|
||||
fail:
|
||||
/* The cmap might've been read in and require deallocation. */
|
||||
xfree (cmap);
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Type of font entities and font objects created. */
|
||||
|
|
@ -1546,12 +1683,14 @@ sfntfont_registry_for_desc (struct sfnt_font_desc *desc)
|
|||
}
|
||||
|
||||
/* Return a font-entity that represents the font descriptor (unopened
|
||||
font) DESC. */
|
||||
font) DESC. If INSTANCE is more than or equal to 1, then it is the
|
||||
index of the instance in DESC that should be opened plus 1; in that
|
||||
case, DESC must be a distortable font. */
|
||||
|
||||
static Lisp_Object
|
||||
sfntfont_desc_to_entity (struct sfnt_font_desc *desc)
|
||||
sfntfont_desc_to_entity (struct sfnt_font_desc *desc, int instance)
|
||||
{
|
||||
Lisp_Object entity;
|
||||
Lisp_Object entity, vector;
|
||||
|
||||
entity = font_make_entity ();
|
||||
|
||||
|
|
@ -1572,19 +1711,40 @@ sfntfont_desc_to_entity (struct sfnt_font_desc *desc)
|
|||
ASET (entity, FONT_SPACING_INDEX,
|
||||
make_fixnum (desc->spacing));
|
||||
|
||||
FONT_SET_STYLE (entity, FONT_WIDTH_INDEX,
|
||||
make_fixnum (desc->width));
|
||||
FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
|
||||
make_fixnum (desc->weight));
|
||||
FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
|
||||
make_fixnum (desc->slant));
|
||||
if (instance >= 1)
|
||||
{
|
||||
if (NILP (desc->instances)
|
||||
|| instance > ASIZE (desc->instances))
|
||||
emacs_abort ();
|
||||
|
||||
ASET (entity, FONT_ADSTYLE_INDEX, Qnil);
|
||||
vector = AREF (desc->instances, instance - 1);
|
||||
FONT_SET_STYLE (entity, FONT_WIDTH_INDEX,
|
||||
AREF (vector, 2));
|
||||
FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
|
||||
AREF (vector, 3));
|
||||
FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
|
||||
AREF (vector, 4));
|
||||
ASET (entity, FONT_ADSTYLE_INDEX, AREF (vector, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
FONT_SET_STYLE (entity, FONT_WIDTH_INDEX,
|
||||
make_fixnum (desc->width));
|
||||
FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
|
||||
make_fixnum (desc->weight));
|
||||
FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
|
||||
make_fixnum (desc->slant));
|
||||
ASET (entity, FONT_ADSTYLE_INDEX, desc->adstyle);
|
||||
}
|
||||
|
||||
/* Set FONT_EXTRA_INDEX to a pointer to the font description. Font
|
||||
descriptions are never supposed to be freed. */
|
||||
|
||||
ASET (entity, FONT_EXTRA_INDEX,
|
||||
list1 (Fcons (Qfont_entity, make_mint_ptr (desc))));
|
||||
(instance >= 1
|
||||
? list2 (Fcons (Qfont_entity, make_mint_ptr (desc)),
|
||||
Fcons (Qfont_instance, make_fixnum (instance - 1)))
|
||||
: list1 (Fcons (Qfont_entity, make_mint_ptr (desc)))));
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
|
@ -1597,6 +1757,7 @@ sfntfont_list (struct frame *f, Lisp_Object font_spec)
|
|||
{
|
||||
Lisp_Object matching, tem;
|
||||
struct sfnt_font_desc *desc;
|
||||
int i, rc, instances[100];
|
||||
|
||||
matching = Qnil;
|
||||
|
||||
|
|
@ -1612,10 +1773,24 @@ sfntfont_list (struct frame *f, Lisp_Object font_spec)
|
|||
}
|
||||
|
||||
/* Loop through known system fonts and add them one-by-one. */
|
||||
|
||||
for (desc = system_fonts; desc; desc = desc->next)
|
||||
{
|
||||
if (sfntfont_list_1 (desc, font_spec))
|
||||
matching = Fcons (sfntfont_desc_to_entity (desc), matching);
|
||||
rc = sfntfont_list_1 (desc, font_spec, instances,
|
||||
ARRAYELTS (instances));
|
||||
|
||||
if (rc < 0)
|
||||
matching = Fcons (sfntfont_desc_to_entity (desc, 0),
|
||||
matching);
|
||||
else if (rc)
|
||||
{
|
||||
/* Add each matching instance. */
|
||||
|
||||
for (i = 0; i < rc; ++i)
|
||||
matching = Fcons (sfntfont_desc_to_entity (desc,
|
||||
instances[i] + 1),
|
||||
matching);
|
||||
}
|
||||
}
|
||||
|
||||
unblock_input ();
|
||||
|
|
@ -1688,23 +1863,45 @@ struct sfntfont_get_glyph_outline_dcontext
|
|||
|
||||
/* glyf table. */
|
||||
struct sfnt_glyf_table *glyf;
|
||||
|
||||
/* Variation settings, or NULL. */
|
||||
struct sfnt_blend *blend;
|
||||
};
|
||||
|
||||
/* Return the glyph identified by GLYPH from the glyf and loca table
|
||||
specified in DCONTEXT. Set *NEED_FREE to true. */
|
||||
/* Return the glyph identified by GLYPH_ID from the glyf and loca
|
||||
table specified in DCONTEXT. Set *NEED_FREE to true. */
|
||||
|
||||
static struct sfnt_glyph *
|
||||
sfntfont_get_glyph (sfnt_glyph glyph, void *dcontext,
|
||||
sfntfont_get_glyph (sfnt_glyph glyph_id, void *dcontext,
|
||||
bool *need_free)
|
||||
{
|
||||
struct sfntfont_get_glyph_outline_dcontext *tables;
|
||||
struct sfnt_glyph *glyph;
|
||||
struct sfnt_metrics_distortion distortion;
|
||||
|
||||
tables = dcontext;
|
||||
*need_free = true;
|
||||
|
||||
return sfnt_read_glyph (glyph, tables->glyf,
|
||||
tables->loca_short,
|
||||
tables->loca_long);
|
||||
glyph = sfnt_read_glyph (glyph_id, tables->glyf,
|
||||
tables->loca_short,
|
||||
tables->loca_long);
|
||||
|
||||
if (!tables->blend || !glyph)
|
||||
return glyph;
|
||||
|
||||
if ((glyph->simple
|
||||
&& sfnt_vary_simple_glyph (tables->blend, glyph_id,
|
||||
glyph, &distortion))
|
||||
|| (!glyph->simple
|
||||
&& sfnt_vary_compound_glyph (tables->blend, glyph_id,
|
||||
glyph, &distortion)))
|
||||
{
|
||||
sfnt_free_glyph (glyph);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Note that the distortion is not relevant for compound glyphs. */
|
||||
return glyph;
|
||||
}
|
||||
|
||||
/* Free the glyph identified by GLYPH. */
|
||||
|
|
@ -1734,6 +1931,8 @@ sfntfont_dereference_outline (struct sfnt_glyph_outline *outline)
|
|||
HEAD. Keep *CACHE_SIZE updated with the number of elements in the
|
||||
cache.
|
||||
|
||||
Distort the glyph using BLEND if INDEX is not -1.
|
||||
|
||||
Use the offset information in the long or short loca tables
|
||||
LOCA_LONG and LOCA_SHORT, whichever is set.
|
||||
|
||||
|
|
@ -1754,6 +1953,8 @@ static struct sfnt_glyph_outline *
|
|||
sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
|
||||
struct sfnt_outline_cache *cache,
|
||||
sfnt_fixed scale, int *cache_size,
|
||||
struct sfnt_blend *blend,
|
||||
int index,
|
||||
struct sfnt_glyf_table *glyf,
|
||||
struct sfnt_head_table *head,
|
||||
struct sfnt_hmtx_table *hmtx,
|
||||
|
|
@ -1772,8 +1973,10 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
|
|||
struct sfnt_instructed_outline *value;
|
||||
const char *error;
|
||||
struct sfnt_glyph_metrics temp;
|
||||
struct sfnt_metrics_distortion distortion;
|
||||
|
||||
start = cache->next;
|
||||
distortion.advance = 0;
|
||||
|
||||
/* See if the outline is already cached. */
|
||||
for (; start != cache; start = start->next)
|
||||
|
|
@ -1806,6 +2009,30 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
|
|||
if (!glyph)
|
||||
return NULL;
|
||||
|
||||
/* Distort the glyph if necessary. */
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
if (glyph->simple)
|
||||
{
|
||||
if (sfnt_vary_simple_glyph (blend, glyph_code,
|
||||
glyph, &distortion))
|
||||
{
|
||||
sfnt_free_glyph (glyph);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (!glyph->simple)
|
||||
{
|
||||
if (sfnt_vary_compound_glyph (blend, glyph_code,
|
||||
glyph, &distortion))
|
||||
{
|
||||
sfnt_free_glyph (glyph);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to instruct the glyph if INTERPRETER is specified. */
|
||||
|
||||
outline = NULL;
|
||||
|
|
@ -1813,6 +2040,7 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
|
|||
dcontext.loca_long = loca_long;
|
||||
dcontext.loca_short = loca_short;
|
||||
dcontext.glyf = glyf;
|
||||
dcontext.blend = (index != -1 ? blend : NULL);
|
||||
|
||||
/* Now load the glyph's unscaled metrics into TEMP. */
|
||||
|
||||
|
|
@ -1820,6 +2048,9 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
|
|||
head, maxp))
|
||||
goto fail;
|
||||
|
||||
/* Add the advance width distortion. */
|
||||
temp.advance += distortion.advance;
|
||||
|
||||
if (interpreter)
|
||||
{
|
||||
if (glyph->simple)
|
||||
|
|
@ -1878,6 +2109,13 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
|
|||
if (!outline)
|
||||
return NULL;
|
||||
|
||||
if (index != -1)
|
||||
/* Finally, adjust the left side bearing of the glyph metrics by
|
||||
the origin point of the outline, should a distortion have been
|
||||
applied. The left side bearing is the distance from the origin
|
||||
point to the left most point on the X axis. */
|
||||
temp.lbearing = outline->xmin - outline->origin;
|
||||
|
||||
start = xmalloc (sizeof *start);
|
||||
start->glyph = glyph_code;
|
||||
start->outline = outline;
|
||||
|
|
@ -2125,6 +2363,13 @@ struct sfnt_font_info
|
|||
/* Factor used to convert from em space to pixel space. */
|
||||
sfnt_fixed scale;
|
||||
|
||||
/* The blend (configuration of this multiple master font). */
|
||||
struct sfnt_blend blend;
|
||||
|
||||
/* The index of the named instance used to initialize BLEND.
|
||||
-1 if BLEND is not initialized. */
|
||||
int instance;
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
/* Whether or not the glyph table has been mmapped. */
|
||||
bool glyf_table_mapped;
|
||||
|
|
@ -2358,6 +2603,10 @@ sfnt_close_tables (struct sfnt_font_tables *tables)
|
|||
xfree (tables->prep);
|
||||
xfree (tables->fpgm);
|
||||
xfree (tables->cvt);
|
||||
xfree (tables->fvar);
|
||||
xfree (tables->avar);
|
||||
xfree (tables->gvar);
|
||||
xfree (tables->cvar);
|
||||
xfree (tables->cmap_data);
|
||||
|
||||
if (tables->uvs)
|
||||
|
|
@ -2524,6 +2773,15 @@ sfnt_open_tables (struct sfnt_font_desc *desc)
|
|||
tables->fpgm = sfnt_read_fpgm_table (fd, subtable);
|
||||
tables->cvt = sfnt_read_cvt_table (fd, subtable);
|
||||
|
||||
/* Read distortion related tables. These might not be present. */
|
||||
tables->fvar = sfnt_read_fvar_table (fd, subtable);
|
||||
tables->avar = sfnt_read_avar_table (fd, subtable);
|
||||
tables->gvar = sfnt_read_gvar_table (fd, subtable);
|
||||
|
||||
if (tables->cvt && tables->fvar)
|
||||
tables->cvar = sfnt_read_cvar_table (fd, subtable, tables->fvar,
|
||||
tables->cvt);
|
||||
|
||||
return tables;
|
||||
|
||||
bail5:
|
||||
|
|
@ -2614,9 +2872,10 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
|
|||
struct sfnt_font_desc *desc;
|
||||
Lisp_Object font_object;
|
||||
struct charset *charset;
|
||||
int point_size;
|
||||
int point_size, instance, i;
|
||||
Display_Info *dpyinfo;
|
||||
struct sfnt_font_tables *tables;
|
||||
Lisp_Object tem;
|
||||
|
||||
if (XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)) != 0)
|
||||
pixel_size = XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX));
|
||||
|
|
@ -2633,10 +2892,18 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
|
|||
|
||||
/* Now find the font description corresponding to FONT_ENTITY. */
|
||||
|
||||
if (NILP (AREF (font_entity, FONT_EXTRA_INDEX)))
|
||||
tem = AREF (font_entity, FONT_EXTRA_INDEX);
|
||||
if (NILP (tem))
|
||||
return Qnil;
|
||||
|
||||
desc = xmint_pointer (XCDR (XCAR (AREF (font_entity, FONT_EXTRA_INDEX))));
|
||||
desc = xmint_pointer (XCDR (XCAR (tem)));
|
||||
|
||||
/* Finally, see if a specific instance is associated with
|
||||
FONT_ENTITY. */
|
||||
|
||||
instance = -1;
|
||||
if (!NILP (XCDR (tem)))
|
||||
instance = XFIXNUM (XCDR (XCAR (XCDR (tem))));
|
||||
|
||||
/* Build the font object. */
|
||||
font_object = font_make_object (VECSIZE (struct sfnt_font_info),
|
||||
|
|
@ -2669,6 +2936,8 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
|
|||
font_info->raster_cache_size = 0;
|
||||
font_info->interpreter = NULL;
|
||||
font_info->scale = 0;
|
||||
font_info->instance = -1;
|
||||
font_info->blend.coords = NULL;
|
||||
#ifdef HAVE_MMAP
|
||||
font_info->glyf_table_mapped = false;
|
||||
#endif /* HAVE_MMAP */
|
||||
|
|
@ -2784,6 +3053,34 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
|
|||
/ 2));
|
||||
sfntfont_setup_interpreter (font_info, point_size);
|
||||
|
||||
/* If an instance was specified and the font is distortable, set up
|
||||
the blend. */
|
||||
|
||||
if (instance != -1
|
||||
&& desc->tables->fvar && desc->tables->gvar
|
||||
/* Make sure the instance is within range. */
|
||||
&& instance < desc->tables->fvar->instance_count)
|
||||
{
|
||||
sfnt_init_blend (&font_info->blend, desc->tables->fvar,
|
||||
desc->tables->gvar, desc->tables->avar,
|
||||
desc->tables->cvar);
|
||||
|
||||
/* Copy over the coordinates. */
|
||||
for (i = 0; i < desc->tables->fvar->axis_count; ++i)
|
||||
font_info->blend.coords[i]
|
||||
= desc->tables->fvar->instance[instance].coords[i];
|
||||
|
||||
sfnt_normalize_blend (&font_info->blend);
|
||||
|
||||
/* If an interpreter was specified, distort it now. */
|
||||
|
||||
if (font_info->interpreter)
|
||||
sfnt_vary_interpreter (font_info->interpreter,
|
||||
&font_info->blend);
|
||||
|
||||
font_info->instance = instance;
|
||||
}
|
||||
|
||||
#ifdef HAVE_HARFBUZZ
|
||||
/* HarfBuzz will potentially read font tables after the font has
|
||||
been opened by Emacs. Keep the font open, and record its offset
|
||||
|
|
@ -2855,6 +3152,8 @@ sfntfont_measure_pcm (struct sfnt_font_info *font, sfnt_glyph glyph,
|
|||
outline = sfntfont_get_glyph_outline (glyph, &font->outline_cache,
|
||||
font->scale,
|
||||
&font->outline_cache_size,
|
||||
&font->blend,
|
||||
font->instance,
|
||||
font->glyf, font->head,
|
||||
font->hmtx, font->hhea,
|
||||
font->maxp,
|
||||
|
|
@ -2960,6 +3259,11 @@ sfntfont_close (struct font *font)
|
|||
info->interpreter = NULL;
|
||||
info->uvs = NULL;
|
||||
|
||||
/* Deinitialize the blend. */
|
||||
if (info->instance != -1 && info->blend.coords)
|
||||
sfnt_free_blend (&info->blend);
|
||||
info->instance = -1;
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
|
||||
/* Unlink INFO. */
|
||||
|
|
@ -3035,6 +3339,8 @@ sfntfont_draw (struct glyph_string *s, int from, int to,
|
|||
&info->outline_cache,
|
||||
info->scale,
|
||||
&info->outline_cache_size,
|
||||
&info->blend,
|
||||
info->instance,
|
||||
info->glyf, info->head,
|
||||
info->hmtx, info->hhea,
|
||||
info->maxp,
|
||||
|
|
@ -3362,6 +3668,13 @@ sfntfont_begin_hb_font (struct font *font, double *position_unit)
|
|||
hb_font_set_scale (info->hb_font, factor * 64, factor * 64);
|
||||
hb_font_set_ppem (info->hb_font, factor, factor);
|
||||
|
||||
#ifdef HAVE_HB_FONT_SET_VAR_NAMED_INSTANCE
|
||||
/* Set the instance if this is a distortable font. */
|
||||
if (info->instance != -1)
|
||||
hb_font_set_var_named_instance (info->hb_font,
|
||||
info->instance);
|
||||
#endif /* HAVE_HB_FONT_SET_VAR_NAMED_INSTANCE */
|
||||
|
||||
/* This is needed for HarfBuzz before 2.0.0; it is the default
|
||||
in later versions. */
|
||||
hb_ot_font_set_funcs (info->hb_font);
|
||||
|
|
@ -3396,6 +3709,7 @@ syms_of_sfntfont (void)
|
|||
DEFSYM (Qzh, "zh");
|
||||
DEFSYM (Qja, "ja");
|
||||
DEFSYM (Qko, "ko");
|
||||
DEFSYM (Qfont_instance, "font-instance");
|
||||
|
||||
/* Char-table purpose. */
|
||||
DEFSYM (Qfont_lookup_cache, "font-lookup-cache");
|
||||
|
|
@ -3427,6 +3741,7 @@ mark_sfntfont (void)
|
|||
mark_object (desc->family);
|
||||
mark_object (desc->style);
|
||||
mark_object (desc->adstyle);
|
||||
mark_object (desc->instances);
|
||||
mark_object (desc->languages);
|
||||
mark_object (desc->registry);
|
||||
mark_object (desc->char_cache);
|
||||
|
|
|
|||
Loading…
Reference in a new issue