From: Po Lu Date: Mon, 27 Mar 2023 08:42:52 +0000 (+0800) Subject: Update Android port X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=dd4924ca90a8ada26bb10e5df4557ae32c0d6403;p=emacs.git 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. --- diff --git a/configure.ac b/configure.ac index 1097be48e26..760188bf369 100644 --- a/configure.ac +++ b/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 ]) + CFLAGS=$OLD_CFLAGS]) fi fi diff --git a/src/sfnt.c b/src/sfnt.c index 9a1094a1ca9..99649698557 100644 --- a/src/sfnt.c +++ b/src/sfnt.c @@ -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); diff --git a/src/sfntfont-android.c b/src/sfntfont-android.c index 37f43465097..5e4c8fc6c9f 100644 --- a/src/sfntfont-android.c +++ b/src/sfntfont-android.c @@ -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); diff --git a/src/sfntfont.c b/src/sfntfont.c index 346e145082a..808c8b7c629 100644 --- a/src/sfntfont.c +++ b/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);