@cantoo/fontkit 2.0.5 → 2.0.7
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/dist/browser-module.d.ts +239 -0
- package/dist/browser-module.mjs +4423 -1117
- package/dist/browser-module.mjs.map +1 -1
- package/dist/browser.cjs +4424 -1117
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +239 -0
- package/dist/fontkit.umd.d.ts +239 -0
- package/dist/fontkit.umd.js +22076 -0
- package/dist/fontkit.umd.js.map +7 -0
- package/dist/index.d.ts +239 -0
- package/dist/main.cjs +4424 -1117
- package/dist/main.cjs.map +1 -1
- package/dist/main.d.ts +239 -0
- package/dist/module.d.ts +239 -0
- package/dist/module.mjs +4423 -1117
- package/dist/module.mjs.map +1 -1
- package/package.json +22 -5
- package/src/CmapProcessor.js +59 -20
- package/src/DFont.js +114 -14
- package/src/TTFFont.js +259 -57
- package/src/TrueTypeCollection.js +54 -10
- package/src/WOFF2Font.js +128 -16
- package/src/WOFFFont.js +45 -8
- package/src/aat/AATFeatureMap.js +62 -18
- package/src/aat/AATLayoutEngine.js +33 -1
- package/src/aat/AATLookupTable.js +22 -4
- package/src/aat/AATMorxProcessor.js +189 -52
- package/src/aat/AATStateMachine.js +32 -0
- package/src/base.js +19 -0
- package/src/cff/CFFCharsets.js +3 -0
- package/src/cff/CFFDict.js +79 -9
- package/src/cff/CFFEncodings.js +2 -0
- package/src/cff/CFFFont.js +119 -23
- package/src/cff/CFFIndex.js +62 -5
- package/src/cff/CFFOperand.js +52 -17
- package/src/cff/CFFPointer.js +41 -2
- package/src/cff/CFFPrivateDict.js +14 -4
- package/src/cff/CFFStandardStrings.js +1 -0
- package/src/cff/CFFTop.js +103 -10
- package/src/decorators.js +32 -13
- package/src/encodings.js +22 -5
- package/src/fs.js +10 -0
- package/src/glyph/BBox.js +14 -0
- package/src/glyph/CFFGlyph.js +290 -148
- package/src/glyph/COLRGlyph.js +38 -3
- package/src/glyph/Glyph.js +68 -9
- package/src/glyph/GlyphVariationProcessor.js +135 -34
- package/src/glyph/Path.js +107 -20
- package/src/glyph/SBIXGlyph.js +57 -8
- package/src/glyph/StandardNames.js +1 -0
- package/src/glyph/TTFGlyph.js +176 -29
- package/src/glyph/TTFGlyphEncoder.js +32 -0
- package/src/glyph/WOFF2Glyph.js +23 -4
- package/src/layout/GlyphPosition.js +6 -0
- package/src/layout/GlyphRun.js +25 -7
- package/src/layout/KernProcessor.js +62 -3
- package/src/layout/LayoutEngine.js +86 -12
- package/src/layout/Script.js +27 -1
- package/src/layout/UnicodeLayoutEngine.js +29 -4
- package/src/opentype/GPOSProcessor.js +156 -45
- package/src/opentype/GSUBProcessor.js +92 -33
- package/src/opentype/GlyphInfo.js +52 -4
- package/src/opentype/GlyphIterator.js +51 -2
- package/src/opentype/OTLayoutEngine.js +66 -8
- package/src/opentype/OTProcessor.js +283 -70
- package/src/opentype/ShapingPlan.js +51 -3
- package/src/opentype/shapers/ArabicShaper.js +19 -0
- package/src/opentype/shapers/DefaultShaper.js +51 -7
- package/src/opentype/shapers/HangulShaper.js +85 -7
- package/src/opentype/shapers/HebrewShaper.js +45 -11
- package/src/opentype/shapers/IndicShaper.js +141 -26
- package/src/opentype/shapers/ThaiShaper.js +35 -4
- package/src/opentype/shapers/UniversalShaper.js +83 -17
- package/src/opentype/shapers/index.js +15 -2
- package/src/packages/unicode-properties/data-trie.js +1 -0
- package/src/packages/unicode-properties/data.js +12 -0
- package/src/packages/unicode-properties/dist/index.cjs +22 -9
- package/src/packages/unicode-properties/dist/index.cjs.map +2 -2
- package/src/packages/unicode-properties/dist/index.mjs +21 -9
- package/src/packages/unicode-properties/dist/index.mjs.map +2 -2
- package/src/packages/unicode-properties/index.js +65 -0
- package/src/packages/unicode-properties/package.json +1 -1
- package/src/packages/unicode-trie/builder.js +128 -7
- package/src/packages/unicode-trie/dist/builder.cjs +129 -16
- package/src/packages/unicode-trie/dist/builder.cjs.map +2 -2
- package/src/packages/unicode-trie/dist/builder.mjs +128 -16
- package/src/packages/unicode-trie/dist/builder.mjs.map +2 -2
- package/src/packages/unicode-trie/dist/index.cjs +22 -9
- package/src/packages/unicode-trie/dist/index.cjs.map +2 -2
- package/src/packages/unicode-trie/dist/index.mjs +21 -9
- package/src/packages/unicode-trie/dist/index.mjs.map +2 -2
- package/src/packages/unicode-trie/index.js +62 -10
- package/src/packages/unicode-trie/package.json +1 -1
- package/src/packages/unicode-trie/swap.js +13 -0
- package/src/subset/CFFSubset.js +112 -22
- package/src/subset/Subset.js +21 -1
- package/src/subset/TTFSubset.js +79 -36
- package/src/tables/BASE.js +1 -0
- package/src/tables/COLR.js +1 -0
- package/src/tables/CPAL.js +1 -0
- package/src/tables/DSIG.js +1 -0
- package/src/tables/EBDT.js +10 -3
- package/src/tables/EBLC.js +67 -7
- package/src/tables/GDEF.js +1 -0
- package/src/tables/GPOS.js +79 -16
- package/src/tables/GSUB.js +14 -3
- package/src/tables/HVAR.js +51 -5
- package/src/tables/JSTF.js +3 -2
- package/src/tables/LTSH.js +1 -0
- package/src/tables/OS2.js +1 -0
- package/src/tables/PCLT.js +1 -0
- package/src/tables/STAT.js +46 -6
- package/src/tables/VDMX.js +1 -0
- package/src/tables/VORG.js +1 -0
- package/src/tables/WOFF2Directory.js +56 -8
- package/src/tables/WOFFDirectory.js +14 -2
- package/src/tables/aat.js +160 -35
- package/src/tables/avar.js +1 -0
- package/src/tables/bsln.js +3 -2
- package/src/tables/cmap.js +26 -6
- package/src/tables/cvt.js +1 -0
- package/src/tables/directory.js +44 -16
- package/src/tables/feat.js +24 -2
- package/src/tables/fpgm.js +1 -0
- package/src/tables/fvar.js +32 -4
- package/src/tables/gasp.js +1 -0
- package/src/tables/glyf.js +1 -0
- package/src/tables/gvar.js +29 -2
- package/src/tables/hdmx.js +12 -1
- package/src/tables/head.js +1 -0
- package/src/tables/hhea.js +1 -0
- package/src/tables/hmtx.js +18 -2
- package/src/tables/index.js +1 -0
- package/src/tables/just.js +15 -4
- package/src/tables/kern.js +43 -6
- package/src/tables/loca.js +21 -8
- package/src/tables/maxp.js +1 -0
- package/src/tables/morx.js +14 -7
- package/src/tables/name.js +104 -23
- package/src/tables/opbd.js +2 -1
- package/src/tables/opentype.js +39 -4
- package/src/tables/post.js +8 -1
- package/src/tables/prep.js +1 -0
- package/src/tables/sbix.js +12 -1
- package/src/tables/variations.js +23 -3
- package/src/tables/vhea.js +1 -0
- package/src/tables/vmtx.js +18 -2
- package/src/utils.js +15 -0
- package/types/assets.d.ts +13 -0
- package/types/deps.d.ts +83 -0
- package/types/fontkit.d.ts +1324 -0
- package/types/index.d.ts +239 -0
- package/types/restructure.d.ts +354 -0
|
@@ -1,10 +1,54 @@
|
|
|
1
1
|
import { binarySearch } from '../utils';
|
|
2
2
|
|
|
3
|
+
/** @typedef {import('../../types/fontkit').LayoutFont} LayoutFont */
|
|
4
|
+
/** @typedef {import('../../types/fontkit').KernTable} KernTable */
|
|
5
|
+
/** @typedef {import('../../types/fontkit').KernPair} KernPair */
|
|
6
|
+
/** @typedef {import('../../types/fontkit').KernFormat0} KernFormat0 */
|
|
7
|
+
/** @typedef {import('../../types/fontkit').KernFormat2} KernFormat2 */
|
|
8
|
+
/** @typedef {import('../../types/fontkit').KernFormat3} KernFormat3 */
|
|
9
|
+
/** @typedef {import('../../types/fontkit').GlyphInfoLike} GlyphInfoLike */
|
|
10
|
+
/** @typedef {import('../../types/fontkit').LayoutGlyph} LayoutGlyph */
|
|
11
|
+
/** @typedef {import('../../types/fontkit').GlyphPositionLike} GlyphPositionLike */
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {unknown} s
|
|
15
|
+
* @returns {s is KernFormat0}
|
|
16
|
+
*/
|
|
17
|
+
function isKernFormat0(s) {
|
|
18
|
+
return typeof s === 'object' && s !== null && Array.isArray(/** @type {{ pairs?: unknown }} */ (s).pairs);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {unknown} s
|
|
23
|
+
* @returns {s is KernFormat2}
|
|
24
|
+
*/
|
|
25
|
+
function isKernFormat2(s) {
|
|
26
|
+
return typeof s === 'object' && s !== null
|
|
27
|
+
&& 'leftTable' in s && 'rightTable' in s && 'array' in s;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {unknown} s
|
|
32
|
+
* @returns {s is KernFormat3}
|
|
33
|
+
*/
|
|
34
|
+
function isKernFormat3(s) {
|
|
35
|
+
return typeof s === 'object' && s !== null
|
|
36
|
+
&& 'glyphCount' in s && 'kernValue' in s && 'kernIndex' in s;
|
|
37
|
+
}
|
|
38
|
+
|
|
3
39
|
export default class KernProcessor {
|
|
40
|
+
/**
|
|
41
|
+
* @param {LayoutFont} font
|
|
42
|
+
*/
|
|
4
43
|
constructor(font) {
|
|
5
|
-
|
|
44
|
+
/** @type {KernTable} */
|
|
45
|
+
this.kern = /** @type {KernTable} */ (font.kern);
|
|
6
46
|
}
|
|
7
47
|
|
|
48
|
+
/**
|
|
49
|
+
* @param {Array<LayoutGlyph | GlyphInfoLike>} glyphs
|
|
50
|
+
* @param {GlyphPositionLike[]} positions
|
|
51
|
+
*/
|
|
8
52
|
process(glyphs, positions) {
|
|
9
53
|
for (let glyphIndex = 0; glyphIndex < glyphs.length - 1; glyphIndex++) {
|
|
10
54
|
let left = glyphs[glyphIndex].id;
|
|
@@ -13,6 +57,11 @@ export default class KernProcessor {
|
|
|
13
57
|
}
|
|
14
58
|
}
|
|
15
59
|
|
|
60
|
+
/**
|
|
61
|
+
* @param {number} left
|
|
62
|
+
* @param {number} right
|
|
63
|
+
* @returns {number}
|
|
64
|
+
*/
|
|
16
65
|
getKerning(left, right) {
|
|
17
66
|
let res = 0;
|
|
18
67
|
|
|
@@ -42,7 +91,10 @@ export default class KernProcessor {
|
|
|
42
91
|
let s = table.subtable;
|
|
43
92
|
switch (table.format) {
|
|
44
93
|
case 0: {
|
|
45
|
-
|
|
94
|
+
if (!isKernFormat0(s)) {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
let pairIdx = binarySearch(s.pairs, /** @param {KernPair} pair */ (pair) => {
|
|
46
98
|
return (left - pair.left) || (right - pair.right);
|
|
47
99
|
});
|
|
48
100
|
|
|
@@ -54,7 +106,11 @@ export default class KernProcessor {
|
|
|
54
106
|
}
|
|
55
107
|
|
|
56
108
|
case 2: {
|
|
57
|
-
|
|
109
|
+
if (!isKernFormat2(s)) {
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
let leftOffset = 0;
|
|
113
|
+
let rightOffset = 0;
|
|
58
114
|
if (left >= s.leftTable.firstGlyph && left < s.leftTable.firstGlyph + s.leftTable.nGlyphs) {
|
|
59
115
|
leftOffset = s.leftTable.offsets[left - s.leftTable.firstGlyph];
|
|
60
116
|
} else {
|
|
@@ -71,6 +127,9 @@ export default class KernProcessor {
|
|
|
71
127
|
}
|
|
72
128
|
|
|
73
129
|
case 3: {
|
|
130
|
+
if (!isKernFormat3(s)) {
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
74
133
|
if (left >= s.glyphCount || right >= s.glyphCount) {
|
|
75
134
|
return 0;
|
|
76
135
|
}
|
|
@@ -6,31 +6,60 @@ import * as Script from './Script';
|
|
|
6
6
|
import AATLayoutEngine from '../aat/AATLayoutEngine';
|
|
7
7
|
import OTLayoutEngine from '../opentype/OTLayoutEngine';
|
|
8
8
|
|
|
9
|
+
/** @typedef {import('../../types/fontkit').LayoutFont} LayoutFont */
|
|
10
|
+
/** @typedef {import('../../types/fontkit').LayoutGlyph} LayoutGlyph */
|
|
11
|
+
/** @typedef {import('../../types/fontkit').FeatureInput} FeatureInput */
|
|
12
|
+
/** @typedef {import('../../types/fontkit').FeatureMap} FeatureMap */
|
|
13
|
+
/** @typedef {import('../../types/fontkit').ScriptTag} ScriptTag */
|
|
14
|
+
/** @typedef {import('../../types/fontkit').LanguageTag} LanguageTag */
|
|
15
|
+
/** @typedef {import('../../types/fontkit').TextDirection} TextDirection */
|
|
16
|
+
/** @typedef {import('../../types/fontkit').AdvancedLayoutEngine} AdvancedLayoutEngine */
|
|
17
|
+
/** @typedef {import('../../types/fontkit').GlyphRunLike} GlyphRunLike */
|
|
18
|
+
/** @typedef {import('../../types/fontkit').GlyphPositionLike} GlyphPositionLike */
|
|
19
|
+
/** @typedef {import('./GlyphRun').default} GlyphRunInstance */
|
|
20
|
+
|
|
9
21
|
export default class LayoutEngine {
|
|
22
|
+
/**
|
|
23
|
+
* @param {LayoutFont} font
|
|
24
|
+
*/
|
|
10
25
|
constructor(font) {
|
|
26
|
+
/** @type {LayoutFont} */
|
|
11
27
|
this.font = font;
|
|
28
|
+
/** @type {UnicodeLayoutEngine | null} */
|
|
12
29
|
this.unicodeLayoutEngine = null;
|
|
30
|
+
/** @type {KernProcessor | null} */
|
|
13
31
|
this.kernProcessor = null;
|
|
32
|
+
/** @type {AdvancedLayoutEngine | undefined} */
|
|
33
|
+
this.engine = undefined;
|
|
14
34
|
|
|
15
35
|
// Choose an advanced layout engine. We try the AAT morx table first since more
|
|
16
36
|
// scripts are currently supported because the shaping logic is built into the font.
|
|
17
37
|
if (this.font.morx) {
|
|
18
|
-
this.engine = new AATLayoutEngine(this.font);
|
|
38
|
+
this.engine = /** @type {AdvancedLayoutEngine} */ (new AATLayoutEngine(this.font));
|
|
19
39
|
} else if (this.font.GSUB || this.font.GPOS) {
|
|
20
|
-
this.engine = new OTLayoutEngine(this.font);
|
|
40
|
+
this.engine = /** @type {AdvancedLayoutEngine} */ (new OTLayoutEngine(this.font));
|
|
21
41
|
}
|
|
22
42
|
}
|
|
23
43
|
|
|
44
|
+
/**
|
|
45
|
+
* @param {string | LayoutGlyph[]} string
|
|
46
|
+
* @param {FeatureInput | ScriptTag | string[] | null | undefined} [features]
|
|
47
|
+
* @param {ScriptTag | string[] | LanguageTag | null | undefined} [script]
|
|
48
|
+
* @param {LanguageTag | TextDirection | null | undefined} [language]
|
|
49
|
+
* @param {TextDirection | null | undefined} [direction]
|
|
50
|
+
* @returns {GlyphRunInstance}
|
|
51
|
+
*/
|
|
24
52
|
layout(string, features, script, language, direction) {
|
|
25
53
|
// Make the features parameter optional
|
|
26
54
|
if (typeof features === 'string') {
|
|
27
|
-
direction = language;
|
|
28
|
-
language = script;
|
|
55
|
+
direction = /** @type {TextDirection | null | undefined} */ (language);
|
|
56
|
+
language = /** @type {LanguageTag | null | undefined} */ (script);
|
|
29
57
|
script = features;
|
|
30
58
|
features = [];
|
|
31
59
|
}
|
|
32
60
|
|
|
33
61
|
// Map string to glyphs if needed
|
|
62
|
+
/** @type {LayoutGlyph[]} */
|
|
34
63
|
let glyphs;
|
|
35
64
|
if (typeof string === 'string') {
|
|
36
65
|
// Attempt to detect the script from the string if not provided.
|
|
@@ -42,6 +71,7 @@ export default class LayoutEngine {
|
|
|
42
71
|
} else {
|
|
43
72
|
// Attempt to detect the script from the glyph code points if not provided.
|
|
44
73
|
if (script == null) {
|
|
74
|
+
/** @type {number[]} */
|
|
45
75
|
let codePoints = [];
|
|
46
76
|
for (let glyph of string) {
|
|
47
77
|
codePoints.push(...glyph.codePoints);
|
|
@@ -53,7 +83,13 @@ export default class LayoutEngine {
|
|
|
53
83
|
glyphs = string;
|
|
54
84
|
}
|
|
55
85
|
|
|
56
|
-
let glyphRun = new GlyphRun(
|
|
86
|
+
let glyphRun = new GlyphRun(
|
|
87
|
+
/** @type {import('../glyph/Glyph').default[]} */ (glyphs),
|
|
88
|
+
/** @type {FeatureInput | null | undefined} */ (features),
|
|
89
|
+
script,
|
|
90
|
+
/** @type {LanguageTag | null | undefined} */ (language),
|
|
91
|
+
/** @type {TextDirection | null | undefined} */ (direction)
|
|
92
|
+
);
|
|
57
93
|
|
|
58
94
|
// Return early if there are no glyphs
|
|
59
95
|
if (glyphs.length === 0) {
|
|
@@ -63,14 +99,16 @@ export default class LayoutEngine {
|
|
|
63
99
|
|
|
64
100
|
// Setup the advanced layout engine
|
|
65
101
|
if (this.engine && this.engine.setup) {
|
|
66
|
-
this.engine.setup(glyphRun);
|
|
102
|
+
this.engine.setup(/** @type {GlyphRunLike} */ (glyphRun));
|
|
67
103
|
}
|
|
68
104
|
|
|
69
105
|
// Substitute and position the glyphs
|
|
70
106
|
this.substitute(glyphRun);
|
|
71
107
|
this.position(glyphRun);
|
|
72
108
|
|
|
73
|
-
|
|
109
|
+
if (glyphRun.positions) {
|
|
110
|
+
this.hideDefaultIgnorables(/** @type {LayoutGlyph[]} */ (glyphRun.glyphs), glyphRun.positions);
|
|
111
|
+
}
|
|
74
112
|
|
|
75
113
|
// Let the layout engine clean up any state it might have
|
|
76
114
|
if (this.engine && this.engine.cleanup) {
|
|
@@ -80,21 +118,30 @@ export default class LayoutEngine {
|
|
|
80
118
|
return glyphRun;
|
|
81
119
|
}
|
|
82
120
|
|
|
121
|
+
/**
|
|
122
|
+
* @param {GlyphRunInstance} glyphRun
|
|
123
|
+
*/
|
|
83
124
|
substitute(glyphRun) {
|
|
84
125
|
// Call the advanced layout engine to make substitutions
|
|
85
126
|
if (this.engine && this.engine.substitute) {
|
|
86
|
-
this.engine.substitute(glyphRun);
|
|
127
|
+
this.engine.substitute(/** @type {GlyphRunLike} */ (glyphRun));
|
|
87
128
|
}
|
|
88
129
|
}
|
|
89
130
|
|
|
131
|
+
/**
|
|
132
|
+
* @param {GlyphRunInstance} glyphRun
|
|
133
|
+
*/
|
|
90
134
|
position(glyphRun) {
|
|
91
135
|
// Get initial glyph positions
|
|
92
|
-
glyphRun.positions = glyphRun.glyphs.map(
|
|
136
|
+
glyphRun.positions = /** @type {LayoutGlyph[]} */ (glyphRun.glyphs).map(
|
|
137
|
+
/** @param {LayoutGlyph} glyph */ glyph => new GlyphPosition(glyph.advanceWidth)
|
|
138
|
+
);
|
|
139
|
+
/** @type {FeatureMap | Record<string, import('../../types/fontkit').OTFeature> | null | undefined | false} */
|
|
93
140
|
let positioned = null;
|
|
94
141
|
|
|
95
142
|
// Call the advanced layout engine. Returns the features applied.
|
|
96
143
|
if (this.engine && this.engine.position) {
|
|
97
|
-
positioned = this.engine.position(glyphRun);
|
|
144
|
+
positioned = this.engine.position(/** @type {GlyphRunLike} */ (glyphRun));
|
|
98
145
|
}
|
|
99
146
|
|
|
100
147
|
// if there is no GPOS table, use unicode properties to position marks.
|
|
@@ -103,7 +150,10 @@ export default class LayoutEngine {
|
|
|
103
150
|
this.unicodeLayoutEngine = new UnicodeLayoutEngine(this.font);
|
|
104
151
|
}
|
|
105
152
|
|
|
106
|
-
this.unicodeLayoutEngine.positionGlyphs(
|
|
153
|
+
this.unicodeLayoutEngine.positionGlyphs(
|
|
154
|
+
/** @type {LayoutGlyph[]} */ (glyphRun.glyphs),
|
|
155
|
+
/** @type {GlyphPositionLike[]} */ (glyphRun.positions)
|
|
156
|
+
);
|
|
107
157
|
}
|
|
108
158
|
|
|
109
159
|
// if kerning is not supported by GPOS, do kerning with the TrueType/AAT kern table
|
|
@@ -112,13 +162,23 @@ export default class LayoutEngine {
|
|
|
112
162
|
this.kernProcessor = new KernProcessor(this.font);
|
|
113
163
|
}
|
|
114
164
|
|
|
115
|
-
this.kernProcessor.process(
|
|
165
|
+
this.kernProcessor.process(
|
|
166
|
+
/** @type {LayoutGlyph[]} */ (glyphRun.glyphs),
|
|
167
|
+
/** @type {GlyphPositionLike[]} */ (glyphRun.positions)
|
|
168
|
+
);
|
|
116
169
|
glyphRun.features.kern = true;
|
|
117
170
|
}
|
|
118
171
|
}
|
|
119
172
|
|
|
173
|
+
/**
|
|
174
|
+
* @param {LayoutGlyph[]} glyphs
|
|
175
|
+
* @param {GlyphPositionLike[]} positions
|
|
176
|
+
*/
|
|
120
177
|
hideDefaultIgnorables(glyphs, positions) {
|
|
121
178
|
let space = this.font.glyphForCodePoint(0x20);
|
|
179
|
+
if (!space) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
122
182
|
for (let i = 0; i < glyphs.length; i++) {
|
|
123
183
|
if (this.isDefaultIgnorable(glyphs[i].codePoints[0])) {
|
|
124
184
|
glyphs[i] = space;
|
|
@@ -128,6 +188,10 @@ export default class LayoutEngine {
|
|
|
128
188
|
}
|
|
129
189
|
}
|
|
130
190
|
|
|
191
|
+
/**
|
|
192
|
+
* @param {number} ch
|
|
193
|
+
* @returns {boolean}
|
|
194
|
+
*/
|
|
131
195
|
isDefaultIgnorable(ch) {
|
|
132
196
|
// From DerivedCoreProperties.txt in the Unicode database,
|
|
133
197
|
// minus U+115F, U+1160, U+3164 and U+FFA0, which is what
|
|
@@ -156,7 +220,13 @@ export default class LayoutEngine {
|
|
|
156
220
|
}
|
|
157
221
|
}
|
|
158
222
|
|
|
223
|
+
/**
|
|
224
|
+
* @param {ScriptTag | string[] | null | undefined} [script]
|
|
225
|
+
* @param {LanguageTag | null | undefined} [language]
|
|
226
|
+
* @returns {string[]}
|
|
227
|
+
*/
|
|
159
228
|
getAvailableFeatures(script, language) {
|
|
229
|
+
/** @type {string[]} */
|
|
160
230
|
let features = [];
|
|
161
231
|
|
|
162
232
|
if (this.engine) {
|
|
@@ -170,6 +240,10 @@ export default class LayoutEngine {
|
|
|
170
240
|
return features;
|
|
171
241
|
}
|
|
172
242
|
|
|
243
|
+
/**
|
|
244
|
+
* @param {number} gid
|
|
245
|
+
* @returns {string[]}
|
|
246
|
+
*/
|
|
173
247
|
stringsForGlyph(gid) {
|
|
174
248
|
let result = new Set();
|
|
175
249
|
|
package/src/layout/Script.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { getScript } from '../packages/unicode-properties/index.js';
|
|
2
2
|
|
|
3
|
+
/** @typedef {import('../../types/fontkit').TextDirection} TextDirection */
|
|
4
|
+
|
|
3
5
|
// This maps the Unicode Script property to an OpenType script tag
|
|
4
6
|
// Data from http://www.microsoft.com/typography/otspec/scripttags.htm
|
|
5
7
|
// and http://www.unicode.org/Public/UNIDATA/PropertyValueAliases.txt.
|
|
8
|
+
/** @type {Record<string, string | string[]>} */
|
|
6
9
|
const UNICODE_SCRIPTS = {
|
|
7
10
|
Caucasian_Albanian: 'aghb',
|
|
8
11
|
Arabic: 'arab',
|
|
@@ -133,6 +136,7 @@ const UNICODE_SCRIPTS = {
|
|
|
133
136
|
Unknown: 'zzzz'
|
|
134
137
|
};
|
|
135
138
|
|
|
139
|
+
/** @type {Record<string, string>} */
|
|
136
140
|
const OPENTYPE_SCRIPTS = {};
|
|
137
141
|
for (let script in UNICODE_SCRIPTS) {
|
|
138
142
|
let tag = UNICODE_SCRIPTS[script];
|
|
@@ -145,14 +149,26 @@ for (let script in UNICODE_SCRIPTS) {
|
|
|
145
149
|
}
|
|
146
150
|
}
|
|
147
151
|
|
|
152
|
+
/**
|
|
153
|
+
* @param {string} script
|
|
154
|
+
* @returns {string | string[] | undefined}
|
|
155
|
+
*/
|
|
148
156
|
export function fromUnicode(script) {
|
|
149
157
|
return UNICODE_SCRIPTS[script];
|
|
150
158
|
}
|
|
151
159
|
|
|
160
|
+
/**
|
|
161
|
+
* @param {string} tag
|
|
162
|
+
* @returns {string | undefined}
|
|
163
|
+
*/
|
|
152
164
|
export function fromOpenType(tag) {
|
|
153
165
|
return OPENTYPE_SCRIPTS[tag];
|
|
154
166
|
}
|
|
155
167
|
|
|
168
|
+
/**
|
|
169
|
+
* @param {string} string
|
|
170
|
+
* @returns {string | string[]}
|
|
171
|
+
*/
|
|
156
172
|
export function forString(string) {
|
|
157
173
|
let len = string.length;
|
|
158
174
|
let idx = 0;
|
|
@@ -179,6 +195,10 @@ export function forString(string) {
|
|
|
179
195
|
return UNICODE_SCRIPTS.Unknown;
|
|
180
196
|
}
|
|
181
197
|
|
|
198
|
+
/**
|
|
199
|
+
* @param {number[]} codePoints
|
|
200
|
+
* @returns {string | string[]}
|
|
201
|
+
*/
|
|
182
202
|
export function forCodePoints(codePoints) {
|
|
183
203
|
for (let i = 0; i < codePoints.length; i++) {
|
|
184
204
|
let codePoint = codePoints[i];
|
|
@@ -192,6 +212,7 @@ export function forCodePoints(codePoints) {
|
|
|
192
212
|
}
|
|
193
213
|
|
|
194
214
|
// The scripts in this map are written from right to left
|
|
215
|
+
/** @type {Record<string, boolean>} */
|
|
195
216
|
const RTL = {
|
|
196
217
|
arab: true, // Arabic
|
|
197
218
|
hebr: true, // Hebrew
|
|
@@ -222,8 +243,13 @@ const RTL = {
|
|
|
222
243
|
phlp: true // Psalter Pahlavi
|
|
223
244
|
};
|
|
224
245
|
|
|
246
|
+
/**
|
|
247
|
+
* @param {string | string[] | null | undefined} script
|
|
248
|
+
* @returns {TextDirection}
|
|
249
|
+
*/
|
|
225
250
|
export function direction(script) {
|
|
226
|
-
|
|
251
|
+
let tag = Array.isArray(script) ? script[0] : script;
|
|
252
|
+
if (tag && RTL[tag]) {
|
|
227
253
|
return 'rtl';
|
|
228
254
|
}
|
|
229
255
|
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { getCombiningClass } from '../packages/unicode-properties/index.js';
|
|
2
2
|
|
|
3
|
+
/** @typedef {import('../../types/fontkit').LayoutFont} LayoutFont */
|
|
4
|
+
/** @typedef {import('../../types/fontkit').LayoutGlyph} LayoutGlyph */
|
|
5
|
+
/** @typedef {import('../../types/fontkit').GlyphInfoLike} GlyphInfoLike */
|
|
6
|
+
/** @typedef {import('../../types/fontkit').GlyphPositionLike} GlyphPositionLike */
|
|
7
|
+
|
|
3
8
|
/**
|
|
4
9
|
* This class is used when GPOS does not define 'mark' or 'mkmk' features
|
|
5
10
|
* for positioning marks relative to base glyphs. It uses the unicode
|
|
@@ -9,10 +14,19 @@ import { getCombiningClass } from '../packages/unicode-properties/index.js';
|
|
|
9
14
|
* https://github.com/behdad/harfbuzz/blob/master/src/hb-ot-shape-fallback.cc
|
|
10
15
|
*/
|
|
11
16
|
export default class UnicodeLayoutEngine {
|
|
17
|
+
/**
|
|
18
|
+
* @param {LayoutFont} font
|
|
19
|
+
*/
|
|
12
20
|
constructor(font) {
|
|
21
|
+
/** @type {LayoutFont} */
|
|
13
22
|
this.font = font;
|
|
14
23
|
}
|
|
15
24
|
|
|
25
|
+
/**
|
|
26
|
+
* @param {Array<LayoutGlyph | GlyphInfoLike & { cbox?: import('../../types/fontkit').BBoxLike }>} glyphs
|
|
27
|
+
* @param {GlyphPositionLike[]} positions
|
|
28
|
+
* @returns {GlyphPositionLike[]}
|
|
29
|
+
*/
|
|
16
30
|
positionGlyphs(glyphs, positions) {
|
|
17
31
|
// find each base + mark cluster, and position the marks relative to the base
|
|
18
32
|
let clusterStart = 0;
|
|
@@ -37,9 +51,16 @@ export default class UnicodeLayoutEngine {
|
|
|
37
51
|
return positions;
|
|
38
52
|
}
|
|
39
53
|
|
|
54
|
+
/**
|
|
55
|
+
* @param {Array<LayoutGlyph | (GlyphInfoLike & { cbox?: import('../../types/fontkit').BBoxLike, advanceWidth?: number })>} glyphs
|
|
56
|
+
* @param {GlyphPositionLike[]} positions
|
|
57
|
+
* @param {number} clusterStart
|
|
58
|
+
* @param {number} clusterEnd
|
|
59
|
+
* @returns {void}
|
|
60
|
+
*/
|
|
40
61
|
positionCluster(glyphs, positions, clusterStart, clusterEnd) {
|
|
41
|
-
let base = glyphs[clusterStart];
|
|
42
|
-
let baseBox = base.cbox.copy();
|
|
62
|
+
let base = /** @type {LayoutGlyph} */ (glyphs[clusterStart]);
|
|
63
|
+
let baseBox = /** @type {import('../../types/fontkit').BBoxLike} */ (base.cbox).copy();
|
|
43
64
|
|
|
44
65
|
// adjust bounding box for ligature glyphs
|
|
45
66
|
if (base.codePoints.length > 1) {
|
|
@@ -53,8 +74,8 @@ export default class UnicodeLayoutEngine {
|
|
|
53
74
|
|
|
54
75
|
// position each of the mark glyphs relative to the base glyph
|
|
55
76
|
for (let index = clusterStart + 1; index <= clusterEnd; index++) {
|
|
56
|
-
let mark = glyphs[index];
|
|
57
|
-
let markBox = mark.cbox;
|
|
77
|
+
let mark = /** @type {LayoutGlyph} */ (glyphs[index]);
|
|
78
|
+
let markBox = /** @type {import('../../types/fontkit').BBoxLike} */ (mark.cbox);
|
|
58
79
|
let position = positions[index];
|
|
59
80
|
|
|
60
81
|
let combiningClass = this.getCombiningClass(mark.codePoints[0]);
|
|
@@ -134,6 +155,10 @@ export default class UnicodeLayoutEngine {
|
|
|
134
155
|
return;
|
|
135
156
|
}
|
|
136
157
|
|
|
158
|
+
/**
|
|
159
|
+
* @param {number} codePoint
|
|
160
|
+
* @returns {string}
|
|
161
|
+
*/
|
|
137
162
|
getCombiningClass(codePoint) {
|
|
138
163
|
let combiningClass = getCombiningClass(codePoint);
|
|
139
164
|
|