@openpresentation/opf-render 0.11.9 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +138 -8
- package/dist/annotations.js +45 -0
- package/dist/chart-options.js +177 -0
- package/dist/charts.js +194 -36
- package/dist/color-fonts.js +32 -0
- package/dist/deck-runtime.js +343 -0
- package/dist/element-define.d.ts +1 -0
- package/dist/element-define.js +5 -0
- package/dist/element.d.ts +86 -0
- package/dist/element.js +521 -0
- package/dist/export-browser.d.ts +26 -0
- package/dist/export-browser.js +228 -0
- package/dist/font-manifest.js +158 -0
- package/dist/font-policy.js +232 -16
- package/dist/fonts.d.ts +30 -0
- package/dist/fonts.js +48 -22
- package/dist/index.d.ts +100 -2
- package/dist/pdf-fonts.js +333 -0
- package/dist/pdf-style.js +429 -0
- package/dist/pdf-subset.js +176 -0
- package/dist/pdf-text.js +338 -0
- package/dist/pdf-vector.js +1249 -0
- package/dist/pdf-writer.js +154 -0
- package/dist/pdf-xml.js +78 -0
- package/dist/player.d.ts +79 -0
- package/dist/player.js +706 -0
- package/dist/preview-fonts-cli.js +15 -0
- package/dist/preview-fonts-node.d.ts +14 -0
- package/dist/preview-fonts-node.js +86 -0
- package/dist/preview-fonts.d.ts +23 -0
- package/dist/preview-fonts.js +78 -0
- package/dist/raster-images.js +19 -6
- package/dist/raster-text.js +468 -0
- package/dist/raster.js +81 -12
- package/dist/script-font-pack.js +19 -1
- package/dist/script-fonts.js +214 -23
- package/dist/sha256.js +47 -0
- package/dist/svg.d.ts +9 -1
- package/dist/svg.js +360 -53
- package/dist/symbol-encodings.js +7 -0
- package/dist/symbol-fonts.js +96 -0
- package/package.json +84 -7
package/dist/font-policy.js
CHANGED
|
@@ -23,7 +23,7 @@ const SNAPSHOT=freeze({
|
|
|
23
23
|
},
|
|
24
24
|
"source": {
|
|
25
25
|
"path": "spec/reference/font-policy.json",
|
|
26
|
-
"sha256": "
|
|
26
|
+
"sha256": "7c7699c6184318099cd7acb75d541654bd18d69be4468fcf518343dfa48e2636"
|
|
27
27
|
},
|
|
28
28
|
"families": [
|
|
29
29
|
{
|
|
@@ -135,7 +135,14 @@ const SNAPSHOT=freeze({
|
|
|
135
135
|
"replacement": {
|
|
136
136
|
"family": "Cousine",
|
|
137
137
|
"compatibility": "visual",
|
|
138
|
-
"measured":
|
|
138
|
+
"measured": {
|
|
139
|
+
"replacement": "Cousine",
|
|
140
|
+
"meanAbsWidthDelta": 0,
|
|
141
|
+
"meanWidthDelta": 0,
|
|
142
|
+
"maxAbsWidthDelta": 0,
|
|
143
|
+
"styles": 4,
|
|
144
|
+
"reference": "Aptos Mono 2.01;O365"
|
|
145
|
+
}
|
|
139
146
|
},
|
|
140
147
|
"alternates": [
|
|
141
148
|
"Roboto Mono"
|
|
@@ -203,6 +210,11 @@ const SNAPSHOT=freeze({
|
|
|
203
210
|
"replacement": {
|
|
204
211
|
"family": "Noto Naskh Arabic",
|
|
205
212
|
"compatibility": "visual",
|
|
213
|
+
"sizeAdjust": 0.64,
|
|
214
|
+
"lineAscent": 0.7,
|
|
215
|
+
"lineAscentMixed": 0.78,
|
|
216
|
+
"lineAscentBasis": "RR-38 native PowerPoint 365 probe (probe-arabic.pptx, 18, 24 and 32 pt, 100 percent line spacing, zero insets, top anchor, rtl paragraph): the baseline of an Arabic Typesetting-only line (the most common ink-bottom row of the line) sits 0.68, 0.71 and 0.72 em below the box top (regular) and 0.68, 0.72 and 0.73 em (bold), against Arabic Typesetting's hhea ascent of 0.701 em; a line that also holds an Aptos run (Arabic, 'PowerPoint 365', Arabic) sits 0.77, 0.78 and 0.78 em below it. Core places the baseline one em below the line top, so the preview drew Arabic lines 0.22 to 0.30 em lower.",
|
|
217
|
+
"sizeAdjustBasis": "RR-38: sum of Arabic Typesetting 6.85 advances over sum of Noto Naskh Arabic 400 advances (fontkit, each sample's OpenType language). 0.643 on the 12 Arabic-script corpus samples of opf-render test/fixtures/script-corpora.json (per-sample range 0.57 to 0.86); 0.598 on 29 Arabic strings of the RR-05b native deck (running Arabic text); 0.614 pooled; Noto Naskh Arabic 700 gives 0.62, 0.58 and 0.59, so bold runs draw about 3 percent long. Ink height of alef, lam, meem and heh is 0.71 of Noto Naskh Arabic's. 0.64 balances the two: lines come out about 4 percent longer than PowerPoint's and glyphs about 10 percent smaller. Native check (RR-38 probe): PowerPoint's BoundWidth of the 45-character probe line is 216.9, 289.0 and 386.1 pt at 18, 24 and 32 pt, 1.8 to 2.0 percent above the fontkit advance of the installed font (213.0, 284.0, 378.7).",
|
|
206
218
|
"measured": {
|
|
207
219
|
"replacement": "Noto Naskh Arabic",
|
|
208
220
|
"meanAbsWidthDelta": 0.6632,
|
|
@@ -546,7 +558,16 @@ const SNAPSHOT=freeze({
|
|
|
546
558
|
"office-cloud"
|
|
547
559
|
],
|
|
548
560
|
"embeddableByOpf": false,
|
|
549
|
-
"replacement":
|
|
561
|
+
"replacement": {
|
|
562
|
+
"family": "STIX Two Math",
|
|
563
|
+
"compatibility": "visual",
|
|
564
|
+
"measured": null,
|
|
565
|
+
"source": "https://github.com/stipub/stixfonts"
|
|
566
|
+
},
|
|
567
|
+
"alternates": [
|
|
568
|
+
"Noto Sans Math",
|
|
569
|
+
"Caladea"
|
|
570
|
+
]
|
|
550
571
|
},
|
|
551
572
|
{
|
|
552
573
|
"family": "Candara",
|
|
@@ -1042,7 +1063,14 @@ const SNAPSHOT=freeze({
|
|
|
1042
1063
|
"replacement": {
|
|
1043
1064
|
"family": "Barlow",
|
|
1044
1065
|
"compatibility": "visual",
|
|
1045
|
-
"measured":
|
|
1066
|
+
"measured": {
|
|
1067
|
+
"replacement": "Barlow",
|
|
1068
|
+
"meanAbsWidthDelta": 0.0467,
|
|
1069
|
+
"meanWidthDelta": -0.0467,
|
|
1070
|
+
"maxAbsWidthDelta": 0.0976,
|
|
1071
|
+
"styles": 4,
|
|
1072
|
+
"reference": "Grandview 1.04;O365"
|
|
1073
|
+
}
|
|
1046
1074
|
},
|
|
1047
1075
|
"alternates": [
|
|
1048
1076
|
"Roboto"
|
|
@@ -1059,7 +1087,14 @@ const SNAPSHOT=freeze({
|
|
|
1059
1087
|
"replacement": {
|
|
1060
1088
|
"family": "Barlow",
|
|
1061
1089
|
"compatibility": "visual",
|
|
1062
|
-
"measured":
|
|
1090
|
+
"measured": {
|
|
1091
|
+
"replacement": "Barlow",
|
|
1092
|
+
"meanAbsWidthDelta": 0.0249,
|
|
1093
|
+
"meanWidthDelta": -0.0242,
|
|
1094
|
+
"maxAbsWidthDelta": 0.0599,
|
|
1095
|
+
"styles": 2,
|
|
1096
|
+
"reference": "Grandview Display 0.90;O365"
|
|
1097
|
+
}
|
|
1063
1098
|
},
|
|
1064
1099
|
"alternates": [
|
|
1065
1100
|
"Roboto"
|
|
@@ -1219,7 +1254,19 @@ const SNAPSHOT=freeze({
|
|
|
1219
1254
|
"license": "OFL-1.1",
|
|
1220
1255
|
"availability": [],
|
|
1221
1256
|
"embeddableByOpf": true,
|
|
1222
|
-
"replacement":
|
|
1257
|
+
"replacement": {
|
|
1258
|
+
"family": "Cousine",
|
|
1259
|
+
"compatibility": "metric",
|
|
1260
|
+
"measured": {
|
|
1261
|
+
"replacement": "Cousine",
|
|
1262
|
+
"meanAbsWidthDelta": 0,
|
|
1263
|
+
"meanWidthDelta": 0,
|
|
1264
|
+
"maxAbsWidthDelta": 0,
|
|
1265
|
+
"styles": 4,
|
|
1266
|
+
"reference": "Liberation Mono 2.1.5"
|
|
1267
|
+
},
|
|
1268
|
+
"source": "https://github.com/liberationfonts/liberation-fonts/blob/2.1.5/README.md"
|
|
1269
|
+
}
|
|
1223
1270
|
},
|
|
1224
1271
|
{
|
|
1225
1272
|
"family": "Liberation Sans",
|
|
@@ -1227,7 +1274,19 @@ const SNAPSHOT=freeze({
|
|
|
1227
1274
|
"license": "OFL-1.1",
|
|
1228
1275
|
"availability": [],
|
|
1229
1276
|
"embeddableByOpf": true,
|
|
1230
|
-
"replacement":
|
|
1277
|
+
"replacement": {
|
|
1278
|
+
"family": "Arimo",
|
|
1279
|
+
"compatibility": "metric",
|
|
1280
|
+
"measured": {
|
|
1281
|
+
"replacement": "Arimo",
|
|
1282
|
+
"meanAbsWidthDelta": 0,
|
|
1283
|
+
"meanWidthDelta": 0,
|
|
1284
|
+
"maxAbsWidthDelta": 0,
|
|
1285
|
+
"styles": 4,
|
|
1286
|
+
"reference": "Liberation Sans 2.1.5"
|
|
1287
|
+
},
|
|
1288
|
+
"source": "https://github.com/liberationfonts/liberation-fonts/blob/2.1.5/README.md"
|
|
1289
|
+
}
|
|
1231
1290
|
},
|
|
1232
1291
|
{
|
|
1233
1292
|
"family": "Liberation Serif",
|
|
@@ -1235,7 +1294,19 @@ const SNAPSHOT=freeze({
|
|
|
1235
1294
|
"license": "OFL-1.1",
|
|
1236
1295
|
"availability": [],
|
|
1237
1296
|
"embeddableByOpf": true,
|
|
1238
|
-
"replacement":
|
|
1297
|
+
"replacement": {
|
|
1298
|
+
"family": "Tinos",
|
|
1299
|
+
"compatibility": "metric",
|
|
1300
|
+
"measured": {
|
|
1301
|
+
"replacement": "Tinos",
|
|
1302
|
+
"meanAbsWidthDelta": 0,
|
|
1303
|
+
"meanWidthDelta": 0,
|
|
1304
|
+
"maxAbsWidthDelta": 0,
|
|
1305
|
+
"styles": 4,
|
|
1306
|
+
"reference": "Liberation Serif 2.1.5"
|
|
1307
|
+
},
|
|
1308
|
+
"source": "https://github.com/liberationfonts/liberation-fonts/blob/2.1.5/README.md"
|
|
1309
|
+
}
|
|
1239
1310
|
},
|
|
1240
1311
|
{
|
|
1241
1312
|
"family": "Libre Caslon Text",
|
|
@@ -1547,6 +1618,22 @@ const SNAPSHOT=freeze({
|
|
|
1547
1618
|
}
|
|
1548
1619
|
}
|
|
1549
1620
|
},
|
|
1621
|
+
{
|
|
1622
|
+
"family": "Noto Color Emoji",
|
|
1623
|
+
"licenseClass": "open",
|
|
1624
|
+
"license": "OFL-1.1",
|
|
1625
|
+
"availability": [],
|
|
1626
|
+
"embeddableByOpf": true,
|
|
1627
|
+
"replacement": null
|
|
1628
|
+
},
|
|
1629
|
+
{
|
|
1630
|
+
"family": "Noto Emoji",
|
|
1631
|
+
"licenseClass": "open",
|
|
1632
|
+
"license": "OFL-1.1",
|
|
1633
|
+
"availability": [],
|
|
1634
|
+
"embeddableByOpf": true,
|
|
1635
|
+
"replacement": null
|
|
1636
|
+
},
|
|
1550
1637
|
{
|
|
1551
1638
|
"family": "Noto Naskh Arabic",
|
|
1552
1639
|
"licenseClass": "open",
|
|
@@ -1573,6 +1660,14 @@ const SNAPSHOT=freeze({
|
|
|
1573
1660
|
"embeddableByOpf": true,
|
|
1574
1661
|
"replacement": null
|
|
1575
1662
|
},
|
|
1663
|
+
{
|
|
1664
|
+
"family": "Noto Sans Arabic",
|
|
1665
|
+
"licenseClass": "open",
|
|
1666
|
+
"license": "OFL-1.1",
|
|
1667
|
+
"availability": [],
|
|
1668
|
+
"embeddableByOpf": true,
|
|
1669
|
+
"replacement": null
|
|
1670
|
+
},
|
|
1576
1671
|
{
|
|
1577
1672
|
"family": "Noto Sans Armenian",
|
|
1578
1673
|
"licenseClass": "open",
|
|
@@ -1671,6 +1766,14 @@ const SNAPSHOT=freeze({
|
|
|
1671
1766
|
"embeddableByOpf": true,
|
|
1672
1767
|
"replacement": null
|
|
1673
1768
|
},
|
|
1769
|
+
{
|
|
1770
|
+
"family": "Noto Sans Lao",
|
|
1771
|
+
"licenseClass": "open",
|
|
1772
|
+
"license": "OFL-1.1",
|
|
1773
|
+
"availability": [],
|
|
1774
|
+
"embeddableByOpf": true,
|
|
1775
|
+
"replacement": null
|
|
1776
|
+
},
|
|
1674
1777
|
{
|
|
1675
1778
|
"family": "Noto Sans Malayalam",
|
|
1676
1779
|
"licenseClass": "open",
|
|
@@ -1679,6 +1782,14 @@ const SNAPSHOT=freeze({
|
|
|
1679
1782
|
"embeddableByOpf": true,
|
|
1680
1783
|
"replacement": null
|
|
1681
1784
|
},
|
|
1785
|
+
{
|
|
1786
|
+
"family": "Noto Sans Math",
|
|
1787
|
+
"licenseClass": "open",
|
|
1788
|
+
"license": "OFL-1.1",
|
|
1789
|
+
"availability": [],
|
|
1790
|
+
"embeddableByOpf": true,
|
|
1791
|
+
"replacement": null
|
|
1792
|
+
},
|
|
1682
1793
|
{
|
|
1683
1794
|
"family": "Noto Sans Mongolian",
|
|
1684
1795
|
"licenseClass": "open",
|
|
@@ -1687,6 +1798,14 @@ const SNAPSHOT=freeze({
|
|
|
1687
1798
|
"embeddableByOpf": true,
|
|
1688
1799
|
"replacement": null
|
|
1689
1800
|
},
|
|
1801
|
+
{
|
|
1802
|
+
"family": "Noto Sans Myanmar",
|
|
1803
|
+
"licenseClass": "open",
|
|
1804
|
+
"license": "OFL-1.1",
|
|
1805
|
+
"availability": [],
|
|
1806
|
+
"embeddableByOpf": true,
|
|
1807
|
+
"replacement": null
|
|
1808
|
+
},
|
|
1690
1809
|
{
|
|
1691
1810
|
"family": "Noto Sans Oriya",
|
|
1692
1811
|
"licenseClass": "open",
|
|
@@ -1705,6 +1824,22 @@ const SNAPSHOT=freeze({
|
|
|
1705
1824
|
"embeddableByOpf": true,
|
|
1706
1825
|
"replacement": null
|
|
1707
1826
|
},
|
|
1827
|
+
{
|
|
1828
|
+
"family": "Noto Sans Sinhala",
|
|
1829
|
+
"licenseClass": "open",
|
|
1830
|
+
"license": "OFL-1.1",
|
|
1831
|
+
"availability": [],
|
|
1832
|
+
"embeddableByOpf": true,
|
|
1833
|
+
"replacement": null
|
|
1834
|
+
},
|
|
1835
|
+
{
|
|
1836
|
+
"family": "Noto Sans Syriac",
|
|
1837
|
+
"licenseClass": "open",
|
|
1838
|
+
"license": "OFL-1.1",
|
|
1839
|
+
"availability": [],
|
|
1840
|
+
"embeddableByOpf": true,
|
|
1841
|
+
"replacement": null
|
|
1842
|
+
},
|
|
1708
1843
|
{
|
|
1709
1844
|
"family": "Noto Sans Tamil",
|
|
1710
1845
|
"licenseClass": "open",
|
|
@@ -1729,6 +1864,14 @@ const SNAPSHOT=freeze({
|
|
|
1729
1864
|
"embeddableByOpf": true,
|
|
1730
1865
|
"replacement": null
|
|
1731
1866
|
},
|
|
1867
|
+
{
|
|
1868
|
+
"family": "Noto Sans Thaana",
|
|
1869
|
+
"licenseClass": "open",
|
|
1870
|
+
"license": "OFL-1.1",
|
|
1871
|
+
"availability": [],
|
|
1872
|
+
"embeddableByOpf": true,
|
|
1873
|
+
"replacement": null
|
|
1874
|
+
},
|
|
1732
1875
|
{
|
|
1733
1876
|
"family": "Noto Sans Thai",
|
|
1734
1877
|
"licenseClass": "open",
|
|
@@ -1745,6 +1888,14 @@ const SNAPSHOT=freeze({
|
|
|
1745
1888
|
"embeddableByOpf": true,
|
|
1746
1889
|
"replacement": null
|
|
1747
1890
|
},
|
|
1891
|
+
{
|
|
1892
|
+
"family": "Noto Serif Tibetan",
|
|
1893
|
+
"licenseClass": "open",
|
|
1894
|
+
"license": "OFL-1.1",
|
|
1895
|
+
"availability": [],
|
|
1896
|
+
"embeddableByOpf": true,
|
|
1897
|
+
"replacement": null
|
|
1898
|
+
},
|
|
1748
1899
|
{
|
|
1749
1900
|
"family": "Nyala",
|
|
1750
1901
|
"licenseClass": "proprietary-standard",
|
|
@@ -1947,7 +2098,14 @@ const SNAPSHOT=freeze({
|
|
|
1947
2098
|
"replacement": {
|
|
1948
2099
|
"family": "Source Sans 3",
|
|
1949
2100
|
"compatibility": "visual",
|
|
1950
|
-
"measured":
|
|
2101
|
+
"measured": {
|
|
2102
|
+
"replacement": "Source Sans 3",
|
|
2103
|
+
"meanAbsWidthDelta": 0.0483,
|
|
2104
|
+
"meanWidthDelta": -0.0483,
|
|
2105
|
+
"maxAbsWidthDelta": 0.0965,
|
|
2106
|
+
"styles": 4,
|
|
2107
|
+
"reference": "Seaford 1.04;O365"
|
|
2108
|
+
}
|
|
1951
2109
|
},
|
|
1952
2110
|
"alternates": [
|
|
1953
2111
|
"Carlito"
|
|
@@ -1964,7 +2122,14 @@ const SNAPSHOT=freeze({
|
|
|
1964
2122
|
"replacement": {
|
|
1965
2123
|
"family": "Source Sans 3",
|
|
1966
2124
|
"compatibility": "visual",
|
|
1967
|
-
"measured":
|
|
2125
|
+
"measured": {
|
|
2126
|
+
"replacement": "Source Sans 3",
|
|
2127
|
+
"meanAbsWidthDelta": 0.0389,
|
|
2128
|
+
"meanWidthDelta": 0.0388,
|
|
2129
|
+
"maxAbsWidthDelta": 0.0667,
|
|
2130
|
+
"styles": 2,
|
|
2131
|
+
"reference": "Seaford Display 1.04;O365"
|
|
2132
|
+
}
|
|
1968
2133
|
},
|
|
1969
2134
|
"alternates": [
|
|
1970
2135
|
"Carlito"
|
|
@@ -2006,7 +2171,15 @@ const SNAPSHOT=freeze({
|
|
|
2006
2171
|
"office-cloud"
|
|
2007
2172
|
],
|
|
2008
2173
|
"embeddableByOpf": false,
|
|
2009
|
-
"replacement":
|
|
2174
|
+
"replacement": {
|
|
2175
|
+
"family": "Noto Color Emoji",
|
|
2176
|
+
"compatibility": "visual",
|
|
2177
|
+
"measured": null,
|
|
2178
|
+
"source": "https://github.com/googlefonts/noto-emoji"
|
|
2179
|
+
},
|
|
2180
|
+
"alternates": [
|
|
2181
|
+
"Noto Emoji"
|
|
2182
|
+
]
|
|
2010
2183
|
},
|
|
2011
2184
|
{
|
|
2012
2185
|
"family": "Segoe UI Light",
|
|
@@ -2166,7 +2339,14 @@ const SNAPSHOT=freeze({
|
|
|
2166
2339
|
"replacement": {
|
|
2167
2340
|
"family": "Open Sans",
|
|
2168
2341
|
"compatibility": "visual",
|
|
2169
|
-
"measured":
|
|
2342
|
+
"measured": {
|
|
2343
|
+
"replacement": "Open Sans",
|
|
2344
|
+
"meanAbsWidthDelta": 0.0926,
|
|
2345
|
+
"meanWidthDelta": 0.0926,
|
|
2346
|
+
"maxAbsWidthDelta": 0.1593,
|
|
2347
|
+
"styles": 4,
|
|
2348
|
+
"reference": "Skeena 1.04;O365"
|
|
2349
|
+
}
|
|
2170
2350
|
},
|
|
2171
2351
|
"alternates": [
|
|
2172
2352
|
"Carlito"
|
|
@@ -2183,7 +2363,14 @@ const SNAPSHOT=freeze({
|
|
|
2183
2363
|
"replacement": {
|
|
2184
2364
|
"family": "Open Sans",
|
|
2185
2365
|
"compatibility": "visual",
|
|
2186
|
-
"measured":
|
|
2366
|
+
"measured": {
|
|
2367
|
+
"replacement": "Open Sans",
|
|
2368
|
+
"meanAbsWidthDelta": 0.1306,
|
|
2369
|
+
"meanWidthDelta": 0.1306,
|
|
2370
|
+
"maxAbsWidthDelta": 0.2001,
|
|
2371
|
+
"styles": 4,
|
|
2372
|
+
"reference": "Skeena Display 1.04;O365"
|
|
2373
|
+
}
|
|
2187
2374
|
},
|
|
2188
2375
|
"alternates": [
|
|
2189
2376
|
"Carlito"
|
|
@@ -2210,9 +2397,24 @@ const SNAPSHOT=freeze({
|
|
|
2210
2397
|
"replacement": {
|
|
2211
2398
|
"family": "Source Sans 3",
|
|
2212
2399
|
"compatibility": "visual",
|
|
2213
|
-
"measured":
|
|
2400
|
+
"measured": {
|
|
2401
|
+
"replacement": "Source Sans 3",
|
|
2402
|
+
"meanAbsWidthDelta": 0.0003,
|
|
2403
|
+
"meanWidthDelta": -0.0003,
|
|
2404
|
+
"maxAbsWidthDelta": 0.0041,
|
|
2405
|
+
"styles": 4,
|
|
2406
|
+
"reference": "Source Sans Pro 2.045"
|
|
2407
|
+
}
|
|
2214
2408
|
}
|
|
2215
2409
|
},
|
|
2410
|
+
{
|
|
2411
|
+
"family": "STIX Two Math",
|
|
2412
|
+
"licenseClass": "open",
|
|
2413
|
+
"license": "OFL-1.1",
|
|
2414
|
+
"availability": [],
|
|
2415
|
+
"embeddableByOpf": true,
|
|
2416
|
+
"replacement": null
|
|
2417
|
+
},
|
|
2216
2418
|
{
|
|
2217
2419
|
"family": "Sylfaen",
|
|
2218
2420
|
"licenseClass": "proprietary-standard",
|
|
@@ -2289,7 +2491,14 @@ const SNAPSHOT=freeze({
|
|
|
2289
2491
|
"replacement": {
|
|
2290
2492
|
"family": "Figtree",
|
|
2291
2493
|
"compatibility": "visual",
|
|
2292
|
-
"measured":
|
|
2494
|
+
"measured": {
|
|
2495
|
+
"replacement": "Figtree",
|
|
2496
|
+
"meanAbsWidthDelta": 0.042,
|
|
2497
|
+
"meanWidthDelta": 0.042,
|
|
2498
|
+
"maxAbsWidthDelta": 0.0836,
|
|
2499
|
+
"styles": 1,
|
|
2500
|
+
"reference": "Tenorite 1.04;O365"
|
|
2501
|
+
}
|
|
2293
2502
|
},
|
|
2294
2503
|
"alternates": [
|
|
2295
2504
|
"Roboto"
|
|
@@ -2306,7 +2515,14 @@ const SNAPSHOT=freeze({
|
|
|
2306
2515
|
"replacement": {
|
|
2307
2516
|
"family": "Figtree",
|
|
2308
2517
|
"compatibility": "visual",
|
|
2309
|
-
"measured":
|
|
2518
|
+
"measured": {
|
|
2519
|
+
"replacement": "Figtree",
|
|
2520
|
+
"meanAbsWidthDelta": 0.1476,
|
|
2521
|
+
"meanWidthDelta": 0.1476,
|
|
2522
|
+
"maxAbsWidthDelta": 0.1975,
|
|
2523
|
+
"styles": 2,
|
|
2524
|
+
"reference": "Tenorite Display 1.04;O365"
|
|
2525
|
+
}
|
|
2310
2526
|
},
|
|
2311
2527
|
"alternates": [
|
|
2312
2528
|
"Roboto"
|
package/dist/fonts.d.ts
CHANGED
|
@@ -96,8 +96,38 @@ export interface ScriptFontsOptions {
|
|
|
96
96
|
export declare function createScriptFonts(profile?: ScriptFontProfile, measurement?: TextMeasurement, options?: ScriptFontsOptions): ScriptFonts;
|
|
97
97
|
/** Designated open families a preview tries, in order, for a character its face lacks (own script, deck script, Noto Sans, other CJK, other Noto scripts). */
|
|
98
98
|
export declare function glyphFallbackFamilies(character: string, profile?: ScriptFontProfile, serif?: boolean): string[];
|
|
99
|
+
|
|
100
|
+
/** Symbol-encoded families (FF-45): Symbol, Wingdings, Wingdings 2, Wingdings 3 and Webdings preview through code-to-Unicode tables. */
|
|
101
|
+
export type SymbolFontFamily = "Symbol" | "Wingdings" | "Wingdings 2" | "Wingdings 3" | "Webdings";
|
|
102
|
+
/** The script key the open symbol faces load under (`scripts: ['Zsym']`). */
|
|
103
|
+
export declare const SYMBOL_SCRIPT: "Zsym";
|
|
104
|
+
/** Drawn for a code with no Unicode equivalent, or whose equivalent no loaded face has (U+25A1). */
|
|
105
|
+
export declare const SYMBOL_PLACEHOLDER: string;
|
|
106
|
+
/** The open faces that preview each symbol-encoded family, in the order a code tries them. */
|
|
107
|
+
export declare const SYMBOL_PREVIEW_FACES: Readonly<Record<SymbolFontFamily, readonly string[]>>;
|
|
108
|
+
/** Every open face a symbol preview may draw with. */
|
|
109
|
+
export declare const SYMBOL_FACE_FAMILIES: readonly string[];
|
|
110
|
+
/** Per family: the verified font version and, for codes 0x20..0xFF in order, `[unicode, advance, reason?]` (hex code points joined with '+', font units). */
|
|
111
|
+
export declare const SYMBOL_ENCODINGS: readonly Readonly<{ family: SymbolFontFamily; version: string; unitsPerEm: number; mapped: number; codes: readonly (readonly [string | null, number | null, string?])[] }>[];
|
|
112
|
+
/** Which core table (spec/reference/symbol-font-encodings.json) the snapshot came from. */
|
|
113
|
+
export declare const SYMBOL_ENCODINGS_SOURCE: Readonly<{ version: number; path: string; sha256: string }>;
|
|
114
|
+
export declare function isSymbolEncodedFamily(family: string): boolean;
|
|
115
|
+
export declare function symbolEncodingFor(family: string): (typeof SYMBOL_ENCODINGS)[number] | undefined;
|
|
116
|
+
export declare function symbolPreviewFaces(family: string): readonly string[];
|
|
117
|
+
/** The symbol code (0x20..0xFF) of one character: a private-use U+F0xx, an ASCII or Latin-1 character, or a Windows-1252 character at 0x80..0x9F; null for anything else. */
|
|
118
|
+
export declare function symbolCodeOf(character: string): number | null;
|
|
119
|
+
/** Normalise text in a symbol-encoded family: per character its code (null when not a code), the Unicode equivalent to draw (or null with a reason) and the verified font's advance in em. */
|
|
120
|
+
export declare function mapSymbolText(family: string, text: string): { source: string; code: number | null; unicode: string | null; advance: number | null; reason?: string }[];
|
|
99
121
|
/** Wrap a measurement so pagination, the renderer and the editor itemize script runs identically. */
|
|
100
122
|
export declare function createScriptTextMeasurement(measurement: TextMeasurement, profile: ScriptFontProfile, options?: ScriptFontsOptions): TextMeasurement;
|
|
101
123
|
export declare function openTypeLanguage(tag: string | undefined): string | undefined;
|
|
102
124
|
/** Heading or body role of a style from its OPF path; undefined without a slide path. */
|
|
103
125
|
export declare function textRole(style: { path?: string } | undefined): "heading" | "body" | undefined;
|
|
126
|
+
/** FF-45: the emoji faces (Noto Color Emoji, then Noto Emoji); they draw emoji-presentation clusters only. */
|
|
127
|
+
export declare const EMOJI_FONT_FAMILIES: readonly string[];
|
|
128
|
+
/** True when the text holds an emoji-presentation cluster (emoji-default characters, VS16, skin tones, flags, keycaps, tags). */
|
|
129
|
+
export declare function hasEmojiPresentation(text: string): boolean;
|
|
130
|
+
/** True when the text holds mathematical notation that text faces lack (math alphanumerics, letterlike math sets, rarer operator blocks). */
|
|
131
|
+
export declare function hasMathNotation(text: string): boolean;
|
|
132
|
+
/** Colour faces of the manifest: resvg draws their monochrome stand-in (`rasterFamily`); browsers draw them in colour. */
|
|
133
|
+
export declare const COLOR_FONT_FACES: readonly { family: string; file: string; package: string; format: string; rasterFamily: string }[];
|
package/dist/fonts.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { create } from "fontkit";
|
|
2
2
|
import { FONT_COMPATIBILITY, disabledFeaturesFor } from "./font-compatibility.js";
|
|
3
|
-
import { openTypeLanguage, scriptFontAliases } from "./script-fonts.js";
|
|
3
|
+
import { adjustedFontSize, openTypeLanguage, scriptFontAliases, sizeAdjustFor } from "./script-fonts.js";
|
|
4
4
|
import { fontPolicyFor } from "./font-policy.js";
|
|
5
5
|
import { BUNDLED_FONT_MANIFEST } from "./font-manifest.js";
|
|
6
|
+
import { SYMBOL_SCRIPT, isSymbolEncodedFamily, symbolEncodingFor, symbolPreviewFaces } from "./symbol-fonts.js";
|
|
7
|
+
export { SYMBOL_SCRIPT, SYMBOL_PLACEHOLDER, SYMBOL_PREVIEW_FACES, SYMBOL_FACE_FAMILIES, SYMBOL_ENCODINGS, SYMBOL_ENCODINGS_SOURCE, isSymbolEncodedFamily, symbolEncodingFor, symbolPreviewFaces, symbolCodeOf, mapSymbolText } from "./symbol-fonts.js";
|
|
6
8
|
export { FONT_COMPATIBILITY, EXPERIMENTAL_FONT_CANDIDATES, disabledFeaturesFor } from "./font-compatibility.js";
|
|
7
9
|
export { FONT_POLICY, FONT_POLICY_DECISIONS, FONT_POLICY_SOURCE, fontPolicyFor } from "./font-policy.js";
|
|
8
|
-
export { SCRIPT_FONT_FAMILIES, SCRIPT_FONT_REPLACEMENTS, createScriptFonts, createScriptTextMeasurement, designatedFamilies, glyphFallbackFamilies, detectScripts, itemizeScripts, openTypeLanguage, scriptFontAliases, scriptFontRole, scriptOfCharacter, textRole } from "./script-fonts.js";
|
|
10
|
+
export { EMOJI_FONT_FAMILIES, SCRIPT_FONT_FAMILIES, SCRIPT_FONT_REPLACEMENTS, createScriptFonts, createScriptTextMeasurement, designatedFamilies, glyphFallbackFamilies, detectScripts, hasEmojiPresentation, hasMathNotation, itemizeScripts, openTypeLanguage, scriptFontAliases, scriptFontRole, sizeAdjustFor, adjustedFontSize, lineAscentFor, baselineShift, scriptOfCharacter, textRole } from "./script-fonts.js";
|
|
11
|
+
export { COLOR_FONT_FACES } from "./color-fonts.js";
|
|
9
12
|
|
|
10
13
|
export class OPFFontError extends Error {
|
|
11
14
|
constructor(code, message, details = {}) { super(message); this.name = "OPFFontError"; this.code = code; this.details = details; }
|
|
@@ -51,7 +54,7 @@ function unavailableFontError(family, style, policy) {
|
|
|
51
54
|
// A lookup that cannot be decoded is treated as one that applies nothing (no subtables), so the rest of the feature still runs: advances equal
|
|
52
55
|
// a browser's for the face's Latin and Mongolian samples (test/mongolian-shaping.mjs). Applied only after shaping failed, once per font.
|
|
53
56
|
const lookupsGuarded = new WeakSet();
|
|
54
|
-
function skipUndecodableLookups(font) {
|
|
57
|
+
export function skipUndecodableLookups(font) {
|
|
55
58
|
if (lookupsGuarded.has(font)) return false;
|
|
56
59
|
lookupsGuarded.add(font);
|
|
57
60
|
let guarded = false;
|
|
@@ -75,9 +78,17 @@ function skipUndecodableLookups(font) {
|
|
|
75
78
|
export function pickFace(faces, family, style, {policy = "none", aliases = new Map(), fallbackFamily} = {}) {
|
|
76
79
|
const findFamily = name => faces.filter(face=>face.family.toLowerCase()===name.toLowerCase() || face.familyGroup.toLowerCase()===name.toLowerCase());
|
|
77
80
|
const weight = style.fontWeight ?? 400;
|
|
78
|
-
let matching = findFamily(family), compatibility = "exact", rule, targetWeight = weight, styleFallback = false, via = "family";
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
let matching = findFamily(family), compatibility = "exact", rule, targetWeight = weight, styleFallback = false, via = "family", encoding;
|
|
82
|
+
// FF-45: a symbol-encoded family (Symbol, Wingdings, Wingdings 2, Wingdings 3, Webdings) whose own face is not loaded
|
|
83
|
+
// draws the Unicode equivalent of each code with the first loaded open symbol face (symbol-fonts.js: Noto Sans Symbols 2,
|
|
84
|
+
// Noto Sans Symbols, Noto Sans Math, or the office pack's Noto Sans). The resolved style carries the encoding so the
|
|
85
|
+
// planner maps every character; the PPTX keeps the family and the original codes. Without any such face the caller's
|
|
86
|
+
// fallback family applies, else the request fails as before (font-encoding-required) and names the pack to load.
|
|
87
|
+
if (!matching.length && isSymbolEncodedFamily(family)) {
|
|
88
|
+
for (const candidate of symbolPreviewFaces(family)) { const pool = findFamily(candidate); if (pool.length) { matching = pool; break; } }
|
|
89
|
+
if (matching.length) { compatibility = "visual"; via = "encoding"; encoding = symbolEncodingFor(family).family; }
|
|
90
|
+
else if (!fallbackFamily) throw new OPFFontError("font-encoding-required", `Font '${family}' is symbol-encoded and no open symbol face is loaded: load the symbol faces (prepareNodeFonts or loadBrowserFontRegistry with scripts: ['${SYMBOL_SCRIPT}'], or scripts: 'auto' with the presentation) or supply '${family}' itself.`, {path:style.path,fontFamily:family,scripts:[SYMBOL_SCRIPT],faces:[...symbolPreviewFaces(family)]});
|
|
91
|
+
}
|
|
81
92
|
if (!matching.length && aliases.has(family.toLowerCase())) {
|
|
82
93
|
matching = findFamily(aliases.get(family.toLowerCase())); compatibility = "visual"; via = "alias";
|
|
83
94
|
}
|
|
@@ -107,19 +118,22 @@ export function pickFace(faces, family, style, {policy = "none", aliases = new M
|
|
|
107
118
|
}
|
|
108
119
|
}
|
|
109
120
|
}
|
|
110
|
-
//
|
|
111
|
-
|
|
121
|
+
// FF-45: Cambria Math previews with STIX Two Math (the math pack, loaded as a script face: the alias above resolves it
|
|
122
|
+
// under every policy). Without the pack the policy error below names the pack; the former `math-font-required` failure is gone.
|
|
112
123
|
if (!matching.length && fallbackFamily) { matching=findFamily(fallbackFamily); compatibility="generic"; via="fallback"; }
|
|
113
124
|
if (!matching.length) throw unavailableFontError(family, style, policy);
|
|
114
125
|
const styled = styleFallback ? matching : matching.filter(face=>face.italic===!!style.italic);
|
|
115
|
-
// Script replacement faces have no italics; use upright glyphs and advances.
|
|
116
|
-
|
|
126
|
+
// Script replacement faces have no italics; use upright glyphs and advances. RR-17 (FF-41): so does a visual preview of a
|
|
127
|
+
// single-style display face (Anton, Bebas Neue: the families Impact and the open font schemes name), reported visual; PowerPoint
|
|
128
|
+
// synthesizes the slant of such a face too, so the advances agree and the preview no longer refuses the deck. A strict registry
|
|
129
|
+
// (policy none) still reports font-style-unavailable.
|
|
130
|
+
if (!styled.length && style.italic && matching.length && (matching.every(face=>face.scripts) || policy==="visual" && matching.every(face=>!face.italic))) { if (compatibility!=="generic") compatibility="visual"; }
|
|
117
131
|
else matching = styled;
|
|
118
132
|
if (!matching.length) throw new OPFFontError("font-style-unavailable", `No ${style.italic ? "italic" : "upright"} face for '${family}'.`, {path:style.path});
|
|
119
133
|
matching.sort((a,b)=>Math.abs(a.weight-targetWeight)-Math.abs(b.weight-targetWeight) || a.weight-b.weight);
|
|
120
134
|
const face = matching[0];
|
|
121
135
|
if ((face.weight!==targetWeight || styleFallback) && compatibility!=="generic") compatibility="visual";
|
|
122
|
-
return {face, compatibility, rule, styleFallback, via};
|
|
136
|
+
return {face, compatibility, rule, styleFallback, via, ...(encoding ? {encoding} : {})};
|
|
123
137
|
}
|
|
124
138
|
|
|
125
139
|
export function createFontRegistry(entries, options = {}) {
|
|
@@ -193,26 +207,32 @@ export function createFontRegistry(entries, options = {}) {
|
|
|
193
207
|
const family = themeKey ? options.themeFonts?.[themeKey] : requested;
|
|
194
208
|
if (!family || family.startsWith("+")) throw new OPFFontError("unresolved-theme-font", `Supply a concrete theme family for '${requested}'.`, {path:style.path});
|
|
195
209
|
validFamily(family);
|
|
196
|
-
const {face, compatibility, rule, styleFallback, via} = pickFace(faces, family, style, {policy, aliases, fallbackFamily:options.fallbackFamily});
|
|
210
|
+
const {face, compatibility, rule, styleFallback, via, encoding} = pickFace(faces, family, style, {policy, aliases, fallbackFamily:options.fallbackFamily});
|
|
197
211
|
// FF-31: `substitute` is true whenever the face is not the chosen family itself (policy
|
|
198
212
|
// replacement, alias, script replacement or fallback). Exporters keep writing sourceFamily.
|
|
199
213
|
const substitute = via!=="family", policyRow = substitute ? fontPolicyFor(family) : undefined;
|
|
214
|
+
// RR-38: a policy row can scale its replacement's size (Arabic Typesetting -> Noto Naskh Arabic: 0.64) so measured and drawn
|
|
215
|
+
// advances approximate the real font's. It holds only for the face the multiplier was measured on.
|
|
216
|
+
const sizeAdjust = sizeAdjustFor(policyRow, face.family);
|
|
200
217
|
const measured = rule?.measured && rule.substituteIndex===0 ? rule.measured : undefined;
|
|
201
|
-
const resolution={requestedFamily:requested,sourceFamily:family,resolvedFamily:face.family,requestedWeight:weight,resolvedWeight:face.weight,italic:face.italic,compatibility,substitute,...(styleFallback?{styleFallback:true}:{}),...(face.fontFace?{fontFace:{...face.fontFace}}:{}),...(style.path?{path:style.path}:{}),...(rule?{source:rule.source,note:rule.note,...(rule.decision?{decision:rule.decision}:{})}:{}),...(measured?{measured:{...measured}}:{}),...(policyRow?{licenseClass:policyRow.licenseClass,availability:[...policyRow.availability]}:{})};
|
|
218
|
+
const resolution={requestedFamily:requested,sourceFamily:family,resolvedFamily:face.family,requestedWeight:weight,resolvedWeight:face.weight,italic:face.italic,compatibility,substitute,...(styleFallback?{styleFallback:true}:{}),...(face.fontFace?{fontFace:{...face.fontFace}}:{}),...(style.path?{path:style.path}:{}),...(rule?{source:rule.source,note:rule.note,...(rule.decision?{decision:rule.decision}:{})}:{}),...(measured?{measured:{...measured}}:{}),...(policyRow?{licenseClass:policyRow.licenseClass,availability:[...policyRow.availability]}:{}),...(sizeAdjust?{sizeAdjust}:{}),...(encoding?{symbolEncoding:encoding}:{})};
|
|
202
219
|
if (face.family.toLowerCase()!==family.toLowerCase() || face.weight!==weight || face.italic!==!!style.italic) substitutions.set(JSON.stringify([requested,weight,!!style.italic,style.path]),resolution);
|
|
203
220
|
return {face,resolution};
|
|
204
221
|
};
|
|
205
222
|
const resolveFace = style => resolve(style).face;
|
|
206
223
|
const resolveStyle = style => {
|
|
207
|
-
const face=
|
|
224
|
+
const {face,resolution}=resolve(style),resolved={...style,fontFamily:face.family,fontWeight:face.weight,italic:face.italic};
|
|
208
225
|
// Never carry a stale selection from a previously resolved style.
|
|
209
226
|
delete resolved.fontFace;
|
|
227
|
+
delete resolved.symbolEncoding;
|
|
210
228
|
if(face.fontFace) resolved.fontFace={...face.fontFace};
|
|
229
|
+
// FF-45: the planner maps a symbol-encoded family's codes (symbol-fonts.js); the face only lends its glyphs.
|
|
230
|
+
if(resolution.symbolEncoding) resolved.symbolEncoding=resolution.symbolEncoding;
|
|
211
231
|
return resolved;
|
|
212
232
|
};
|
|
213
233
|
const metrics = (text,size,style,includeOutline=false) => {
|
|
214
234
|
if (typeof text!=='string'||!Number.isFinite(size)||size<=0) throw new OPFFontError('invalid-text-measurement','Text measurement requires a string and a positive finite font size.');
|
|
215
|
-
const face=
|
|
235
|
+
const {face,resolution}=resolve(style);
|
|
216
236
|
// A BCP-47 `lang` selects the font's OpenType language system, as a browser
|
|
217
237
|
// does for an element's lang (FF-19). Without it, shaping is unchanged.
|
|
218
238
|
const language=openTypeLanguage(style.lang),key=language?`${language}\u0000${text}`:text;
|
|
@@ -248,21 +268,27 @@ export function createFontRegistry(entries, options = {}) {
|
|
|
248
268
|
}
|
|
249
269
|
value={width:run.positions.reduce((total,position)=>total+position.xAdvance,0)/face.font.unitsPerEm,...value};
|
|
250
270
|
if(includeOutline) {
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
271
|
+
const unit=face.font.unitsPerEm;
|
|
272
|
+
let bounds=null;
|
|
273
|
+
// FF-45: fontkit reads COLR v0 layers only; a COLRv1 colour face (Noto Color Emoji) has no outlines it can bound (its
|
|
274
|
+
// glyf outlines are empty), so its ink box is the face's em box over the run: the colour image fills the em square.
|
|
275
|
+
try { bounds=run.bbox; } catch { bounds=null; }
|
|
276
|
+
if(bounds&&[bounds.minX,bounds.minY,bounds.maxX,bounds.maxY].every(Number.isFinite)) value.outline={x:bounds.minX/unit,y:-bounds.maxY/unit,width:bounds.width/unit,height:bounds.height/unit};
|
|
277
|
+
else if(face.font.directory?.tables?.COLR&&value.width>0) { const ascent=face.font.ascent/unit,descent=face.font.descent/unit; value.outline={x:0,y:-ascent,width:value.width,height:ascent-descent}; }
|
|
278
|
+
else value.outline=null;
|
|
254
279
|
}
|
|
255
280
|
if (text.length<=2048) {
|
|
256
281
|
if (face.cache.size>=512&&!face.cache.has(key)) face.cache.delete(face.cache.keys().next().value);
|
|
257
282
|
face.cache.set(key,value);
|
|
258
283
|
}
|
|
259
284
|
}
|
|
260
|
-
|
|
285
|
+
// RR-38: the replacement is measured at its adjusted size, the one the SVG draws it at.
|
|
286
|
+
return {value,scale:resolution.sizeAdjust??1};
|
|
261
287
|
};
|
|
262
|
-
const measure=(text,size,style)=>metrics(text,size,style).width*size;
|
|
288
|
+
const measure=(text,size,style)=>{const {value,scale}=metrics(text,size,style);return value.width*adjustedFontSize(size,scale===1?undefined:scale);};
|
|
263
289
|
const outlineBounds=(text,size,style)=>{
|
|
264
|
-
const
|
|
265
|
-
return bounds===null?null:{x:bounds.x*
|
|
290
|
+
const {value,scale}=metrics(text,size,style,true),bounds=value.outline,drawn=adjustedFontSize(size,scale===1?undefined:scale);
|
|
291
|
+
return bounds===null?null:{x:bounds.x*drawn,y:bounds.y*drawn,width:bounds.width*drawn,height:bounds.height*drawn};
|
|
266
292
|
};
|
|
267
293
|
return {
|
|
268
294
|
// resolveFont lets exporters tell a substitute from the chosen family (FF-31).
|