aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-03-27 16:42:52 +0800
committerPo Lu2023-03-27 16:42:52 +0800
commitdd4924ca90a8ada26bb10e5df4557ae32c0d6403 (patch)
tree52b741e15c4074033746e44daaab26998a114618 /src
parent18b34e9ca01deff8e0bde4b1e53293f27712a149 (diff)
downloademacs-dd4924ca90a8ada26bb10e5df4557ae32c0d6403.tar.gz
emacs-dd4924ca90a8ada26bb10e5df4557ae32c0d6403.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/sfnt.c4
-rw-r--r--src/sfntfont-android.c7
-rw-r--r--src/sfntfont.c405
3 files changed, 367 insertions, 49 deletions
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)
18922 return 1; 18922 return 1;
18923 } 18923 }
18924 18924
18925#define FANCY_PPEM 15 18925#define FANCY_PPEM 40
18926#define EASY_PPEM 15 18926#define EASY_PPEM 40
18927 18927
18928 interpreter = NULL; 18928 interpreter = NULL;
18929 head = sfnt_read_head_table (fd, font); 18929 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. */)
713 /* If it contains (not ends with!) with .ttf or .ttc, then 713 /* If it contains (not ends with!) with .ttf or .ttc, then
714 enumerate it. */ 714 enumerate it. */
715 715
716 if (strstr (dirent->d_name, ".ttf") 716 if ((strstr (dirent->d_name, ".ttf")
717 || strstr (dirent->d_name, ".ttc")) 717 || strstr (dirent->d_name, ".ttc"))
718 /* Ignore the non-variable Roboto font. */
719 && (i != 0 || strcmp (dirent->d_name,
720 "RobotoStatic-Regular.ttf")))
718 { 721 {
719 sprintf (name, "%s/%s", system_font_directories[i], 722 sprintf (name, "%s/%s", system_font_directories[i],
720 dirent->d_name); 723 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
69 struct sfnt_prep_table *prep; 69 struct sfnt_prep_table *prep;
70 struct sfnt_fpgm_table *fpgm; 70 struct sfnt_fpgm_table *fpgm;
71 struct sfnt_cvt_table *cvt; 71 struct sfnt_cvt_table *cvt;
72 struct sfnt_fvar_table *fvar;
73 struct sfnt_avar_table *avar;
74 struct sfnt_gvar_table *gvar;
75 struct sfnt_cvar_table *cvar;
72 76
73 /* The selected character map. */ 77 /* The selected character map. */
74 struct sfnt_cmap_encoding_subtable_data *cmap_data; 78 struct sfnt_cmap_encoding_subtable_data *cmap_data;
@@ -118,6 +122,11 @@ struct sfnt_font_desc
118 /* Font registry that this font supports. */ 122 /* Font registry that this font supports. */
119 Lisp_Object registry; 123 Lisp_Object registry;
120 124
125 /* Vector of instances. Each element is another of the instance's
126 `style', `adstyle', and numeric width, weight, and slant. May be
127 nil. */
128 Lisp_Object instances;
129
121 /* Numeric width, weight, slant and spacing. */ 130 /* Numeric width, weight, slant and spacing. */
122 int width, weight, slant, spacing; 131 int width, weight, slant, spacing;
123 132
@@ -360,6 +369,29 @@ sfnt_decode_foundry_name (struct sfnt_name_table *name)
360 designer_rec.length); 369 designer_rec.length);
361} 370}
362 371
372/* Decode the name of the specified font INSTANCE using the given NAME
373 table. Return the name of that instance, or nil upon failure. */
374
375static Lisp_Object
376sfnt_decode_instance_name (struct sfnt_instance *instance,
377 struct sfnt_name_table *name)
378{
379 struct sfnt_name_record name_rec;
380 unsigned char *name_data;
381
382 name_data = sfnt_find_name (name, instance->name_id,
383 &name_rec);
384
385 if (!name_data)
386 return Qnil;
387
388 return sfnt_decode_font_string (name_data,
389 name_rec.platform_id,
390 name_rec.platform_specific_id,
391 name_rec.language_id,
392 name_rec.length);
393}
394
363struct sfnt_style_desc 395struct sfnt_style_desc
364{ 396{
365 /* The C string to match against. */ 397 /* The C string to match against. */
@@ -375,6 +407,7 @@ static struct sfnt_style_desc sfnt_weight_descriptions[] =
375 { "thin", 0, }, 407 { "thin", 0, },
376 { "extralight", 40, }, 408 { "extralight", 40, },
377 { "ultralight", 40, }, 409 { "ultralight", 40, },
410 { "light", 50, },
378 { "demilight", 55, }, 411 { "demilight", 55, },
379 { "semilight", 55, }, 412 { "semilight", 55, },
380 { "book", 75, }, 413 { "book", 75, },
@@ -809,7 +842,10 @@ sfnt_enum_font_1 (int fd, const char *file,
809 struct sfnt_name_table *name; 842 struct sfnt_name_table *name;
810 struct sfnt_meta_table *meta; 843 struct sfnt_meta_table *meta;
811 struct sfnt_maxp_table *maxp; 844 struct sfnt_maxp_table *maxp;
812 Lisp_Object family, style; 845 struct sfnt_fvar_table *fvar;
846 struct sfnt_font_desc temp;
847 Lisp_Object family, style, instance, style1;
848 int i;
813 849
814 /* Create the font desc and copy in the file name. */ 850 /* Create the font desc and copy in the file name. */
815 desc = xzalloc (sizeof *desc + strlen (file) + 1); 851 desc = xzalloc (sizeof *desc + strlen (file) + 1);
@@ -842,6 +878,10 @@ sfnt_enum_font_1 (int fd, const char *file,
842 if (sfnt_decode_family_style (name, &family, &style)) 878 if (sfnt_decode_family_style (name, &family, &style))
843 goto bail4; 879 goto bail4;
844 880
881 /* See if this is a distortable/variable/multiple master font (all
882 three terms mean the same time.) */
883 fvar = sfnt_read_fvar_table (fd, subtables);
884
845 /* Set the family. */ 885 /* Set the family. */
846 desc->family = family; 886 desc->family = family;
847 desc->designer = sfnt_decode_foundry_name (name); 887 desc->designer = sfnt_decode_foundry_name (name);
@@ -877,6 +917,43 @@ sfnt_enum_font_1 (int fd, const char *file,
877 /* Figure out what registry this font is likely to support. */ 917 /* Figure out what registry this font is likely to support. */
878 sfnt_grok_registry (fd, desc, subtables); 918 sfnt_grok_registry (fd, desc, subtables);
879 919
920 if (fvar && fvar->instance_count)
921 {
922 /* If there is an fvar table with instances, then this is a font
923 which defines different axes along which the points in each
924 glyph can be changed.
925
926 Instead of enumerating the font itself, enumerate each
927 instance within, which specifies how to configure each axis
928 to achieve a specified style. */
929
930 desc->instances = make_vector (fvar->instance_count, Qnil);
931
932 for (i = 0; i < fvar->instance_count; ++i)
933 {
934 style1 = sfnt_decode_instance_name (&fvar->instance[i],
935 name);
936
937 if (!style1)
938 continue;
939
940 /* Now parse the style. */
941 temp.adstyle = Qnil;
942 sfnt_parse_style (style1, &temp);
943
944 /* Set each field of the vector. */
945 instance = make_vector (5, Qnil);
946 ASET (instance, 0, style1);
947 ASET (instance, 1, temp.adstyle);
948 ASET (instance, 2, make_fixnum (temp.width));
949 ASET (instance, 3, make_fixnum (temp.weight));
950 ASET (instance, 4, make_fixnum (temp.slant));
951
952 /* Place the vector in desc->instances. */
953 ASET (desc->instances, i, instance);
954 }
955 }
956
880 /* Set the style, link the desc onto system_fonts and return. */ 957 /* Set the style, link the desc onto system_fonts and return. */
881 desc->style = style; 958 desc->style = style;
882 desc->next = system_fonts; 959 desc->next = system_fonts;
@@ -898,6 +975,7 @@ sfnt_enum_font_1 (int fd, const char *file,
898 next = &prev->next; 975 next = &prev->next;
899 } 976 }
900 977
978 xfree (fvar);
901 xfree (meta); 979 xfree (meta);
902 xfree (maxp); 980 xfree (maxp);
903 xfree (name); 981 xfree (name);
@@ -1346,15 +1424,23 @@ sfntfont_registries_compatible_p (Lisp_Object a, Lisp_Object b)
1346} 1424}
1347 1425
1348/* Return whether or not the font description DESC satisfactorily 1426/* Return whether or not the font description DESC satisfactorily
1349 matches the font specification FONT_SPEC. */ 1427 matches the font specification FONT_SPEC.
1350 1428
1351static bool 1429 Value is 0 if there is no match, -1 if there is a match against
1352sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec) 1430 DESC itself, and the number of matching instances if the style
1431 matches one or more instances defined in in DESC. Return the index
1432 of each matching instance in INSTANCES; it should be SIZE big. */
1433
1434static int
1435sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec,
1436 int *instances, int size)
1353{ 1437{
1354 Lisp_Object tem, extra, tail; 1438 Lisp_Object tem, extra, tail;
1355 struct sfnt_cmap_encoding_subtable_data *cmap; 1439 struct sfnt_cmap_encoding_subtable_data *cmap;
1356 size_t i; 1440 size_t i;
1357 struct sfnt_cmap_encoding_subtable subtable; 1441 struct sfnt_cmap_encoding_subtable subtable;
1442 int instance, num_instance;
1443 Lisp_Object item;
1358 1444
1359 /* cmap and subtable are caches for sfntfont_lookup_char. */ 1445 /* cmap and subtable are caches for sfntfont_lookup_char. */
1360 1446
@@ -1388,7 +1474,9 @@ sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec)
1388 1474
1389 if (!NILP (tem) && NILP (Fstring_equal (SYMBOL_NAME (tem), 1475 if (!NILP (tem) && NILP (Fstring_equal (SYMBOL_NAME (tem),
1390 desc->family))) 1476 desc->family)))
1391 return false; 1477 return 0;
1478
1479 instance = -1;
1392 1480
1393 /* If a registry is set and wrong, then reject the font desc 1481 /* If a registry is set and wrong, then reject the font desc
1394 immediately. This detects 50% of mismatches from fontset.c. 1482 immediately. This detects 50% of mismatches from fontset.c.
@@ -1399,33 +1487,82 @@ sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec)
1399 tem = AREF (spec, FONT_REGISTRY_INDEX); 1487 tem = AREF (spec, FONT_REGISTRY_INDEX);
1400 if (!NILP (tem) && !NILP (desc->registry) 1488 if (!NILP (tem) && !NILP (desc->registry)
1401 && !sfntfont_registries_compatible_p (tem, desc->registry)) 1489 && !sfntfont_registries_compatible_p (tem, desc->registry))
1402 return false; 1490 return 0;
1403 1491
1404 /* Check that the adstyle specified matches. */ 1492 /* Check the style. If DESC is a fixed font, just check once.
1493 Otherwise, check each instance. */
1405 1494
1406 tem = AREF (spec, FONT_ADSTYLE_INDEX); 1495 if (NILP (desc->instances))
1407 if (!NILP (tem) && NILP (Fequal (tem, desc->adstyle))) 1496 {
1408 return false; 1497 tem = AREF (spec, FONT_ADSTYLE_INDEX);
1498 if (!NILP (tem) && NILP (Fequal (tem, desc->adstyle)))
1499 return 0;
1409 1500
1410 /* Check the style. */ 1501 if (FONT_WIDTH_NUMERIC (spec) != -1
1502 && FONT_WIDTH_NUMERIC (spec) != desc->width)
1503 return 0;
1411 1504
1412 if (FONT_WIDTH_NUMERIC (spec) != -1 1505 if (FONT_WEIGHT_NUMERIC (spec) != -1
1413 && FONT_WIDTH_NUMERIC (spec) != desc->width) 1506 && FONT_WEIGHT_NUMERIC (spec) != desc->weight)
1414 return false; 1507 return 0;
1415 1508
1416 if (FONT_WEIGHT_NUMERIC (spec) != -1 1509 if (FONT_SLANT_NUMERIC (spec) != -1
1417 && FONT_WEIGHT_NUMERIC (spec) != desc->weight) 1510 && FONT_SLANT_NUMERIC (spec) != desc->slant)
1418 return false; 1511 return 0;
1512 }
1513 else
1514 {
1515 num_instance = 0;
1419 1516
1420 if (FONT_SLANT_NUMERIC (spec) != -1 1517 /* Find the indices of instances in this distortable font which
1421 && FONT_SLANT_NUMERIC (spec) != desc->slant) 1518 match the given font spec. */
1422 return false; 1519
1520 for (i = 0; i < ASIZE (desc->instances); ++i)
1521 {
1522 item = AREF (desc->instances, i);
1523
1524 if (NILP (item))
1525 continue;
1526
1527 /* Check that the adstyle specified matches. */
1528
1529 tem = AREF (spec, FONT_ADSTYLE_INDEX);
1530 if (!NILP (tem) && NILP (Fequal (tem, AREF (item, 1))))
1531 continue;
1532
1533 /* Check the style. */
1534
1535 if (FONT_WIDTH_NUMERIC (spec) != -1
1536 && (FONT_WIDTH_NUMERIC (spec)
1537 != XFIXNUM (AREF (item, 2))))
1538 continue;
1539
1540 if (FONT_WEIGHT_NUMERIC (spec) != -1
1541 && (FONT_WEIGHT_NUMERIC (spec)
1542 != XFIXNUM (AREF (item, 3))))
1543 continue;
1544
1545 if (FONT_SLANT_NUMERIC (spec) != -1
1546 && (FONT_SLANT_NUMERIC (spec)
1547 != XFIXNUM (AREF (item, 4))))
1548 continue;
1549
1550 if (num_instance == size)
1551 break;
1552
1553 /* A matching instance has been found. Set its index, then
1554 go back to the rest of the font matching. */
1555 instances[num_instance++] = i;
1556 }
1557
1558 instance = num_instance;
1559 }
1423 1560
1424 /* Handle extras. */ 1561 /* Handle extras. */
1425 extra = AREF (spec, FONT_EXTRA_INDEX); 1562 extra = AREF (spec, FONT_EXTRA_INDEX);
1426 1563
1427 if (NILP (extra)) 1564 if (NILP (extra))
1428 return true; 1565 return instance;
1429 1566
1430 tem = assq_no_quit (QCscript, extra); 1567 tem = assq_no_quit (QCscript, extra);
1431 cmap = NULL; 1568 cmap = NULL;
@@ -1490,12 +1627,12 @@ sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec)
1490 desc->subtable = subtable; 1627 desc->subtable = subtable;
1491 1628
1492 xfree (cmap); 1629 xfree (cmap);
1493 return true; 1630 return instance;
1494 1631
1495 fail: 1632 fail:
1496 /* The cmap might've been read in and require deallocation. */ 1633 /* The cmap might've been read in and require deallocation. */
1497 xfree (cmap); 1634 xfree (cmap);
1498 return false; 1635 return 0;
1499} 1636}
1500 1637
1501/* Type of font entities and font objects created. */ 1638/* Type of font entities and font objects created. */
@@ -1546,12 +1683,14 @@ sfntfont_registry_for_desc (struct sfnt_font_desc *desc)
1546} 1683}
1547 1684
1548/* Return a font-entity that represents the font descriptor (unopened 1685/* Return a font-entity that represents the font descriptor (unopened
1549 font) DESC. */ 1686 font) DESC. If INSTANCE is more than or equal to 1, then it is the
1687 index of the instance in DESC that should be opened plus 1; in that
1688 case, DESC must be a distortable font. */
1550 1689
1551static Lisp_Object 1690static Lisp_Object
1552sfntfont_desc_to_entity (struct sfnt_font_desc *desc) 1691sfntfont_desc_to_entity (struct sfnt_font_desc *desc, int instance)
1553{ 1692{
1554 Lisp_Object entity; 1693 Lisp_Object entity, vector;
1555 1694
1556 entity = font_make_entity (); 1695 entity = font_make_entity ();
1557 1696
@@ -1572,19 +1711,40 @@ sfntfont_desc_to_entity (struct sfnt_font_desc *desc)
1572 ASET (entity, FONT_SPACING_INDEX, 1711 ASET (entity, FONT_SPACING_INDEX,
1573 make_fixnum (desc->spacing)); 1712 make_fixnum (desc->spacing));
1574 1713
1575 FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, 1714 if (instance >= 1)
1576 make_fixnum (desc->width)); 1715 {
1577 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, 1716 if (NILP (desc->instances)
1578 make_fixnum (desc->weight)); 1717 || instance > ASIZE (desc->instances))
1579 FONT_SET_STYLE (entity, FONT_SLANT_INDEX, 1718 emacs_abort ();
1580 make_fixnum (desc->slant));
1581 1719
1582 ASET (entity, FONT_ADSTYLE_INDEX, Qnil); 1720 vector = AREF (desc->instances, instance - 1);
1721 FONT_SET_STYLE (entity, FONT_WIDTH_INDEX,
1722 AREF (vector, 2));
1723 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
1724 AREF (vector, 3));
1725 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
1726 AREF (vector, 4));
1727 ASET (entity, FONT_ADSTYLE_INDEX, AREF (vector, 1));
1728 }
1729 else
1730 {
1731 FONT_SET_STYLE (entity, FONT_WIDTH_INDEX,
1732 make_fixnum (desc->width));
1733 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
1734 make_fixnum (desc->weight));
1735 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
1736 make_fixnum (desc->slant));
1737 ASET (entity, FONT_ADSTYLE_INDEX, desc->adstyle);
1738 }
1583 1739
1584 /* Set FONT_EXTRA_INDEX to a pointer to the font description. Font 1740 /* Set FONT_EXTRA_INDEX to a pointer to the font description. Font
1585 descriptions are never supposed to be freed. */ 1741 descriptions are never supposed to be freed. */
1742
1586 ASET (entity, FONT_EXTRA_INDEX, 1743 ASET (entity, FONT_EXTRA_INDEX,
1587 list1 (Fcons (Qfont_entity, make_mint_ptr (desc)))); 1744 (instance >= 1
1745 ? list2 (Fcons (Qfont_entity, make_mint_ptr (desc)),
1746 Fcons (Qfont_instance, make_fixnum (instance - 1)))
1747 : list1 (Fcons (Qfont_entity, make_mint_ptr (desc)))));
1588 1748
1589 return entity; 1749 return entity;
1590} 1750}
@@ -1597,6 +1757,7 @@ sfntfont_list (struct frame *f, Lisp_Object font_spec)
1597{ 1757{
1598 Lisp_Object matching, tem; 1758 Lisp_Object matching, tem;
1599 struct sfnt_font_desc *desc; 1759 struct sfnt_font_desc *desc;
1760 int i, rc, instances[100];
1600 1761
1601 matching = Qnil; 1762 matching = Qnil;
1602 1763
@@ -1612,10 +1773,24 @@ sfntfont_list (struct frame *f, Lisp_Object font_spec)
1612 } 1773 }
1613 1774
1614 /* Loop through known system fonts and add them one-by-one. */ 1775 /* Loop through known system fonts and add them one-by-one. */
1776
1615 for (desc = system_fonts; desc; desc = desc->next) 1777 for (desc = system_fonts; desc; desc = desc->next)
1616 { 1778 {
1617 if (sfntfont_list_1 (desc, font_spec)) 1779 rc = sfntfont_list_1 (desc, font_spec, instances,
1618 matching = Fcons (sfntfont_desc_to_entity (desc), matching); 1780 ARRAYELTS (instances));
1781
1782 if (rc < 0)
1783 matching = Fcons (sfntfont_desc_to_entity (desc, 0),
1784 matching);
1785 else if (rc)
1786 {
1787 /* Add each matching instance. */
1788
1789 for (i = 0; i < rc; ++i)
1790 matching = Fcons (sfntfont_desc_to_entity (desc,
1791 instances[i] + 1),
1792 matching);
1793 }
1619 } 1794 }
1620 1795
1621 unblock_input (); 1796 unblock_input ();
@@ -1688,23 +1863,45 @@ struct sfntfont_get_glyph_outline_dcontext
1688 1863
1689 /* glyf table. */ 1864 /* glyf table. */
1690 struct sfnt_glyf_table *glyf; 1865 struct sfnt_glyf_table *glyf;
1866
1867 /* Variation settings, or NULL. */
1868 struct sfnt_blend *blend;
1691}; 1869};
1692 1870
1693/* Return the glyph identified by GLYPH from the glyf and loca table 1871/* Return the glyph identified by GLYPH_ID from the glyf and loca
1694 specified in DCONTEXT. Set *NEED_FREE to true. */ 1872 table specified in DCONTEXT. Set *NEED_FREE to true. */
1695 1873
1696static struct sfnt_glyph * 1874static struct sfnt_glyph *
1697sfntfont_get_glyph (sfnt_glyph glyph, void *dcontext, 1875sfntfont_get_glyph (sfnt_glyph glyph_id, void *dcontext,
1698 bool *need_free) 1876 bool *need_free)
1699{ 1877{
1700 struct sfntfont_get_glyph_outline_dcontext *tables; 1878 struct sfntfont_get_glyph_outline_dcontext *tables;
1879 struct sfnt_glyph *glyph;
1880 struct sfnt_metrics_distortion distortion;
1701 1881
1702 tables = dcontext; 1882 tables = dcontext;
1703 *need_free = true; 1883 *need_free = true;
1704 1884
1705 return sfnt_read_glyph (glyph, tables->glyf, 1885 glyph = sfnt_read_glyph (glyph_id, tables->glyf,
1706 tables->loca_short, 1886 tables->loca_short,
1707 tables->loca_long); 1887 tables->loca_long);
1888
1889 if (!tables->blend || !glyph)
1890 return glyph;
1891
1892 if ((glyph->simple
1893 && sfnt_vary_simple_glyph (tables->blend, glyph_id,
1894 glyph, &distortion))
1895 || (!glyph->simple
1896 && sfnt_vary_compound_glyph (tables->blend, glyph_id,
1897 glyph, &distortion)))
1898 {
1899 sfnt_free_glyph (glyph);
1900 return NULL;
1901 }
1902
1903 /* Note that the distortion is not relevant for compound glyphs. */
1904 return glyph;
1708} 1905}
1709 1906
1710/* Free the glyph identified by GLYPH. */ 1907/* Free the glyph identified by GLYPH. */
@@ -1734,6 +1931,8 @@ sfntfont_dereference_outline (struct sfnt_glyph_outline *outline)
1734 HEAD. Keep *CACHE_SIZE updated with the number of elements in the 1931 HEAD. Keep *CACHE_SIZE updated with the number of elements in the
1735 cache. 1932 cache.
1736 1933
1934 Distort the glyph using BLEND if INDEX is not -1.
1935
1737 Use the offset information in the long or short loca tables 1936 Use the offset information in the long or short loca tables
1738 LOCA_LONG and LOCA_SHORT, whichever is set. 1937 LOCA_LONG and LOCA_SHORT, whichever is set.
1739 1938
@@ -1754,6 +1953,8 @@ static struct sfnt_glyph_outline *
1754sfntfont_get_glyph_outline (sfnt_glyph glyph_code, 1953sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
1755 struct sfnt_outline_cache *cache, 1954 struct sfnt_outline_cache *cache,
1756 sfnt_fixed scale, int *cache_size, 1955 sfnt_fixed scale, int *cache_size,
1956 struct sfnt_blend *blend,
1957 int index,
1757 struct sfnt_glyf_table *glyf, 1958 struct sfnt_glyf_table *glyf,
1758 struct sfnt_head_table *head, 1959 struct sfnt_head_table *head,
1759 struct sfnt_hmtx_table *hmtx, 1960 struct sfnt_hmtx_table *hmtx,
@@ -1772,8 +1973,10 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
1772 struct sfnt_instructed_outline *value; 1973 struct sfnt_instructed_outline *value;
1773 const char *error; 1974 const char *error;
1774 struct sfnt_glyph_metrics temp; 1975 struct sfnt_glyph_metrics temp;
1976 struct sfnt_metrics_distortion distortion;
1775 1977
1776 start = cache->next; 1978 start = cache->next;
1979 distortion.advance = 0;
1777 1980
1778 /* See if the outline is already cached. */ 1981 /* See if the outline is already cached. */
1779 for (; start != cache; start = start->next) 1982 for (; start != cache; start = start->next)
@@ -1806,6 +2009,30 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
1806 if (!glyph) 2009 if (!glyph)
1807 return NULL; 2010 return NULL;
1808 2011
2012 /* Distort the glyph if necessary. */
2013
2014 if (index != -1)
2015 {
2016 if (glyph->simple)
2017 {
2018 if (sfnt_vary_simple_glyph (blend, glyph_code,
2019 glyph, &distortion))
2020 {
2021 sfnt_free_glyph (glyph);
2022 return NULL;
2023 }
2024 }
2025 else if (!glyph->simple)
2026 {
2027 if (sfnt_vary_compound_glyph (blend, glyph_code,
2028 glyph, &distortion))
2029 {
2030 sfnt_free_glyph (glyph);
2031 return NULL;
2032 }
2033 }
2034 }
2035
1809 /* Try to instruct the glyph if INTERPRETER is specified. */ 2036 /* Try to instruct the glyph if INTERPRETER is specified. */
1810 2037
1811 outline = NULL; 2038 outline = NULL;
@@ -1813,6 +2040,7 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
1813 dcontext.loca_long = loca_long; 2040 dcontext.loca_long = loca_long;
1814 dcontext.loca_short = loca_short; 2041 dcontext.loca_short = loca_short;
1815 dcontext.glyf = glyf; 2042 dcontext.glyf = glyf;
2043 dcontext.blend = (index != -1 ? blend : NULL);
1816 2044
1817 /* Now load the glyph's unscaled metrics into TEMP. */ 2045 /* Now load the glyph's unscaled metrics into TEMP. */
1818 2046
@@ -1820,6 +2048,9 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
1820 head, maxp)) 2048 head, maxp))
1821 goto fail; 2049 goto fail;
1822 2050
2051 /* Add the advance width distortion. */
2052 temp.advance += distortion.advance;
2053
1823 if (interpreter) 2054 if (interpreter)
1824 { 2055 {
1825 if (glyph->simple) 2056 if (glyph->simple)
@@ -1878,6 +2109,13 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
1878 if (!outline) 2109 if (!outline)
1879 return NULL; 2110 return NULL;
1880 2111
2112 if (index != -1)
2113 /* Finally, adjust the left side bearing of the glyph metrics by
2114 the origin point of the outline, should a distortion have been
2115 applied. The left side bearing is the distance from the origin
2116 point to the left most point on the X axis. */
2117 temp.lbearing = outline->xmin - outline->origin;
2118
1881 start = xmalloc (sizeof *start); 2119 start = xmalloc (sizeof *start);
1882 start->glyph = glyph_code; 2120 start->glyph = glyph_code;
1883 start->outline = outline; 2121 start->outline = outline;
@@ -2125,6 +2363,13 @@ struct sfnt_font_info
2125 /* Factor used to convert from em space to pixel space. */ 2363 /* Factor used to convert from em space to pixel space. */
2126 sfnt_fixed scale; 2364 sfnt_fixed scale;
2127 2365
2366 /* The blend (configuration of this multiple master font). */
2367 struct sfnt_blend blend;
2368
2369 /* The index of the named instance used to initialize BLEND.
2370 -1 if BLEND is not initialized. */
2371 int instance;
2372
2128#ifdef HAVE_MMAP 2373#ifdef HAVE_MMAP
2129 /* Whether or not the glyph table has been mmapped. */ 2374 /* Whether or not the glyph table has been mmapped. */
2130 bool glyf_table_mapped; 2375 bool glyf_table_mapped;
@@ -2358,6 +2603,10 @@ sfnt_close_tables (struct sfnt_font_tables *tables)
2358 xfree (tables->prep); 2603 xfree (tables->prep);
2359 xfree (tables->fpgm); 2604 xfree (tables->fpgm);
2360 xfree (tables->cvt); 2605 xfree (tables->cvt);
2606 xfree (tables->fvar);
2607 xfree (tables->avar);
2608 xfree (tables->gvar);
2609 xfree (tables->cvar);
2361 xfree (tables->cmap_data); 2610 xfree (tables->cmap_data);
2362 2611
2363 if (tables->uvs) 2612 if (tables->uvs)
@@ -2524,6 +2773,15 @@ sfnt_open_tables (struct sfnt_font_desc *desc)
2524 tables->fpgm = sfnt_read_fpgm_table (fd, subtable); 2773 tables->fpgm = sfnt_read_fpgm_table (fd, subtable);
2525 tables->cvt = sfnt_read_cvt_table (fd, subtable); 2774 tables->cvt = sfnt_read_cvt_table (fd, subtable);
2526 2775
2776 /* Read distortion related tables. These might not be present. */
2777 tables->fvar = sfnt_read_fvar_table (fd, subtable);
2778 tables->avar = sfnt_read_avar_table (fd, subtable);
2779 tables->gvar = sfnt_read_gvar_table (fd, subtable);
2780
2781 if (tables->cvt && tables->fvar)
2782 tables->cvar = sfnt_read_cvar_table (fd, subtable, tables->fvar,
2783 tables->cvt);
2784
2527 return tables; 2785 return tables;
2528 2786
2529 bail5: 2787 bail5:
@@ -2614,9 +2872,10 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
2614 struct sfnt_font_desc *desc; 2872 struct sfnt_font_desc *desc;
2615 Lisp_Object font_object; 2873 Lisp_Object font_object;
2616 struct charset *charset; 2874 struct charset *charset;
2617 int point_size; 2875 int point_size, instance, i;
2618 Display_Info *dpyinfo; 2876 Display_Info *dpyinfo;
2619 struct sfnt_font_tables *tables; 2877 struct sfnt_font_tables *tables;
2878 Lisp_Object tem;
2620 2879
2621 if (XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)) != 0) 2880 if (XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)) != 0)
2622 pixel_size = XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)); 2881 pixel_size = XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX));
@@ -2633,10 +2892,18 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
2633 2892
2634 /* Now find the font description corresponding to FONT_ENTITY. */ 2893 /* Now find the font description corresponding to FONT_ENTITY. */
2635 2894
2636 if (NILP (AREF (font_entity, FONT_EXTRA_INDEX))) 2895 tem = AREF (font_entity, FONT_EXTRA_INDEX);
2896 if (NILP (tem))
2637 return Qnil; 2897 return Qnil;
2638 2898
2639 desc = xmint_pointer (XCDR (XCAR (AREF (font_entity, FONT_EXTRA_INDEX)))); 2899 desc = xmint_pointer (XCDR (XCAR (tem)));
2900
2901 /* Finally, see if a specific instance is associated with
2902 FONT_ENTITY. */
2903
2904 instance = -1;
2905 if (!NILP (XCDR (tem)))
2906 instance = XFIXNUM (XCDR (XCAR (XCDR (tem))));
2640 2907
2641 /* Build the font object. */ 2908 /* Build the font object. */
2642 font_object = font_make_object (VECSIZE (struct sfnt_font_info), 2909 font_object = font_make_object (VECSIZE (struct sfnt_font_info),
@@ -2669,6 +2936,8 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
2669 font_info->raster_cache_size = 0; 2936 font_info->raster_cache_size = 0;
2670 font_info->interpreter = NULL; 2937 font_info->interpreter = NULL;
2671 font_info->scale = 0; 2938 font_info->scale = 0;
2939 font_info->instance = -1;
2940 font_info->blend.coords = NULL;
2672#ifdef HAVE_MMAP 2941#ifdef HAVE_MMAP
2673 font_info->glyf_table_mapped = false; 2942 font_info->glyf_table_mapped = false;
2674#endif /* HAVE_MMAP */ 2943#endif /* HAVE_MMAP */
@@ -2784,6 +3053,34 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
2784 / 2)); 3053 / 2));
2785 sfntfont_setup_interpreter (font_info, point_size); 3054 sfntfont_setup_interpreter (font_info, point_size);
2786 3055
3056 /* If an instance was specified and the font is distortable, set up
3057 the blend. */
3058
3059 if (instance != -1
3060 && desc->tables->fvar && desc->tables->gvar
3061 /* Make sure the instance is within range. */
3062 && instance < desc->tables->fvar->instance_count)
3063 {
3064 sfnt_init_blend (&font_info->blend, desc->tables->fvar,
3065 desc->tables->gvar, desc->tables->avar,
3066 desc->tables->cvar);
3067
3068 /* Copy over the coordinates. */
3069 for (i = 0; i < desc->tables->fvar->axis_count; ++i)
3070 font_info->blend.coords[i]
3071 = desc->tables->fvar->instance[instance].coords[i];
3072
3073 sfnt_normalize_blend (&font_info->blend);
3074
3075 /* If an interpreter was specified, distort it now. */
3076
3077 if (font_info->interpreter)
3078 sfnt_vary_interpreter (font_info->interpreter,
3079 &font_info->blend);
3080
3081 font_info->instance = instance;
3082 }
3083
2787#ifdef HAVE_HARFBUZZ 3084#ifdef HAVE_HARFBUZZ
2788 /* HarfBuzz will potentially read font tables after the font has 3085 /* HarfBuzz will potentially read font tables after the font has
2789 been opened by Emacs. Keep the font open, and record its offset 3086 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,
2855 outline = sfntfont_get_glyph_outline (glyph, &font->outline_cache, 3152 outline = sfntfont_get_glyph_outline (glyph, &font->outline_cache,
2856 font->scale, 3153 font->scale,
2857 &font->outline_cache_size, 3154 &font->outline_cache_size,
3155 &font->blend,
3156 font->instance,
2858 font->glyf, font->head, 3157 font->glyf, font->head,
2859 font->hmtx, font->hhea, 3158 font->hmtx, font->hhea,
2860 font->maxp, 3159 font->maxp,
@@ -2960,6 +3259,11 @@ sfntfont_close (struct font *font)
2960 info->interpreter = NULL; 3259 info->interpreter = NULL;
2961 info->uvs = NULL; 3260 info->uvs = NULL;
2962 3261
3262 /* Deinitialize the blend. */
3263 if (info->instance != -1 && info->blend.coords)
3264 sfnt_free_blend (&info->blend);
3265 info->instance = -1;
3266
2963#ifdef HAVE_MMAP 3267#ifdef HAVE_MMAP
2964 3268
2965 /* Unlink INFO. */ 3269 /* Unlink INFO. */
@@ -3035,6 +3339,8 @@ sfntfont_draw (struct glyph_string *s, int from, int to,
3035 &info->outline_cache, 3339 &info->outline_cache,
3036 info->scale, 3340 info->scale,
3037 &info->outline_cache_size, 3341 &info->outline_cache_size,
3342 &info->blend,
3343 info->instance,
3038 info->glyf, info->head, 3344 info->glyf, info->head,
3039 info->hmtx, info->hhea, 3345 info->hmtx, info->hhea,
3040 info->maxp, 3346 info->maxp,
@@ -3362,6 +3668,13 @@ sfntfont_begin_hb_font (struct font *font, double *position_unit)
3362 hb_font_set_scale (info->hb_font, factor * 64, factor * 64); 3668 hb_font_set_scale (info->hb_font, factor * 64, factor * 64);
3363 hb_font_set_ppem (info->hb_font, factor, factor); 3669 hb_font_set_ppem (info->hb_font, factor, factor);
3364 3670
3671#ifdef HAVE_HB_FONT_SET_VAR_NAMED_INSTANCE
3672 /* Set the instance if this is a distortable font. */
3673 if (info->instance != -1)
3674 hb_font_set_var_named_instance (info->hb_font,
3675 info->instance);
3676#endif /* HAVE_HB_FONT_SET_VAR_NAMED_INSTANCE */
3677
3365 /* This is needed for HarfBuzz before 2.0.0; it is the default 3678 /* This is needed for HarfBuzz before 2.0.0; it is the default
3366 in later versions. */ 3679 in later versions. */
3367 hb_ot_font_set_funcs (info->hb_font); 3680 hb_ot_font_set_funcs (info->hb_font);
@@ -3396,6 +3709,7 @@ syms_of_sfntfont (void)
3396 DEFSYM (Qzh, "zh"); 3709 DEFSYM (Qzh, "zh");
3397 DEFSYM (Qja, "ja"); 3710 DEFSYM (Qja, "ja");
3398 DEFSYM (Qko, "ko"); 3711 DEFSYM (Qko, "ko");
3712 DEFSYM (Qfont_instance, "font-instance");
3399 3713
3400 /* Char-table purpose. */ 3714 /* Char-table purpose. */
3401 DEFSYM (Qfont_lookup_cache, "font-lookup-cache"); 3715 DEFSYM (Qfont_lookup_cache, "font-lookup-cache");
@@ -3427,6 +3741,7 @@ mark_sfntfont (void)
3427 mark_object (desc->family); 3741 mark_object (desc->family);
3428 mark_object (desc->style); 3742 mark_object (desc->style);
3429 mark_object (desc->adstyle); 3743 mark_object (desc->adstyle);
3744 mark_object (desc->instances);
3430 mark_object (desc->languages); 3745 mark_object (desc->languages);
3431 mark_object (desc->registry); 3746 mark_object (desc->registry);
3432 mark_object (desc->char_cache); 3747 mark_object (desc->char_cache);