harfbuzzjs 0.4.14 → 0.5.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/hbjs.js CHANGED
@@ -3,6 +3,7 @@ function hbjs(Module) {
3
3
 
4
4
  var exports = Module.wasmExports;
5
5
  var utf8Decoder = new TextDecoder("utf8");
6
+ var utf8Encoder = new TextEncoder("utf8");
6
7
  let addFunction = Module.addFunction;
7
8
  let removeFunction = Module.removeFunction;
8
9
 
@@ -15,24 +16,28 @@ function hbjs(Module) {
15
16
  var GSUB_PHASE = 1;
16
17
  var GPOS_PHASE = 2;
17
18
 
19
+ const STATIC_ARRAY_SIZE = 128
20
+
18
21
  function hb_tag(s) {
19
22
  return (
20
23
  (s.charCodeAt(0) & 0xFF) << 24 |
21
24
  (s.charCodeAt(1) & 0xFF) << 16 |
22
- (s.charCodeAt(2) & 0xFF) << 8 |
23
- (s.charCodeAt(3) & 0xFF) << 0
25
+ (s.charCodeAt(2) & 0xFF) << 8 |
26
+ (s.charCodeAt(3) & 0xFF) << 0
24
27
  );
25
28
  }
26
29
 
27
- var HB_BUFFER_SERIALIZE_FORMAT_JSON = hb_tag('JSON');
28
- var HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 4;
30
+ var HB_BUFFER_SERIALIZE_FORMAT_JSON = hb_tag('JSON');
31
+ var HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 4;
32
+
33
+ const HB_OT_NAME_ID_INVALID = 0xFFFF;
29
34
 
30
35
  function _hb_untag(tag) {
31
36
  return [
32
37
  String.fromCharCode((tag >> 24) & 0xFF),
33
38
  String.fromCharCode((tag >> 16) & 0xFF),
34
- String.fromCharCode((tag >> 8) & 0xFF),
35
- String.fromCharCode((tag >> 0) & 0xFF)
39
+ String.fromCharCode((tag >> 8) & 0xFF),
40
+ String.fromCharCode((tag >> 0) & 0xFF)
36
41
  ].join('');
37
42
  }
38
43
 
@@ -46,6 +51,19 @@ function hbjs(Module) {
46
51
  return 0x0;
47
52
  }
48
53
 
54
+ function _language_to_string(language) {
55
+ var ptr = exports.hb_language_to_string(language);
56
+ var str = utf8Decoder.decode(Module.HEAPU8.subarray(ptr, Module.HEAPU8.indexOf(0, ptr)));
57
+ return str;
58
+ }
59
+
60
+ function _language_from_string(str) {
61
+ var languageStr = createAsciiString(str);
62
+ var languagePtr = exports.hb_language_from_string(languageStr.ptr, -1);
63
+ languageStr.free();
64
+ return languagePtr;
65
+ }
66
+
49
67
  /**
50
68
  * Create an object representing a Harfbuzz blob.
51
69
  * @param {string} blob A blob of binary data (usually the contents of a font file).
@@ -94,18 +112,18 @@ function hbjs(Module) {
94
112
  * Return the binary contents of an OpenType table.
95
113
  * @param {string} table Table name
96
114
  */
97
- reference_table: function(table) {
115
+ reference_table: function (table) {
98
116
  var blob = exports.hb_face_reference_table(ptr, hb_tag(table));
99
117
  var length = exports.hb_blob_get_length(blob);
100
118
  if (!length) { return; }
101
119
  var blobptr = exports.hb_blob_get_data(blob, null);
102
- var table_string = Module.HEAPU8.subarray(blobptr, blobptr+length);
120
+ var table_string = Module.HEAPU8.subarray(blobptr, blobptr + length);
103
121
  return table_string;
104
122
  },
105
123
  /**
106
124
  * Return variation axis infos
107
125
  */
108
- getAxisInfos: function() {
126
+ getAxisInfos: function () {
109
127
  var axis = exports.malloc(64 * 32);
110
128
  var c = exports.malloc(4);
111
129
  Module.HEAPU32[c / 4] = 64;
@@ -125,13 +143,180 @@ function hbjs(Module) {
125
143
  /**
126
144
  * Return unicodes the face supports
127
145
  */
128
- collectUnicodes: function() {
146
+ collectUnicodes: function () {
129
147
  var unicodeSetPtr = exports.hb_set_create();
130
148
  exports.hb_face_collect_unicodes(ptr, unicodeSetPtr);
131
149
  var result = typedArrayFromSet(unicodeSetPtr);
132
150
  exports.hb_set_destroy(unicodeSetPtr);
133
151
  return result;
134
152
  },
153
+ /**
154
+ * Return all scripts enumerated in the specified face's
155
+ * GSUB table or GPOS table.
156
+ * @param {string} table: The table to query, either "GSUB" or "GPOS".
157
+ **/
158
+ getTableScriptTags: function (table) {
159
+ var tableTag = hb_tag(table);
160
+ var startOffset = 0;
161
+ var scriptCount = STATIC_ARRAY_SIZE;
162
+ var scriptCountPtr = Module.stackAlloc(4);
163
+ var scriptTagsPtr = Module.stackAlloc(STATIC_ARRAY_SIZE * 4);
164
+ var tags = [];
165
+ while (scriptCount == STATIC_ARRAY_SIZE) {
166
+ Module.HEAPU32[scriptCountPtr / 4] = scriptCount;
167
+ exports.hb_ot_layout_table_get_script_tags(ptr, tableTag, startOffset,
168
+ scriptCountPtr, scriptTagsPtr);
169
+ scriptCount = Module.HEAPU32[scriptCountPtr / 4];
170
+ var scriptTags = Module.HEAPU32.subarray(scriptTagsPtr / 4,
171
+ scriptTagsPtr / 4 + scriptCount);
172
+ tags.push(...Array.from(scriptTags).map(_hb_untag));
173
+ startOffset += scriptCount;
174
+ }
175
+ return tags;
176
+ },
177
+ /**
178
+ * Return all features enumerated in the specified face's
179
+ * GSUB table or GPOS table.
180
+ * @param {string} table: The table to query, either "GSUB" or "GPOS".
181
+ **/
182
+ getTableFeatureTags: function (table) {
183
+ var tableTag = hb_tag(table);
184
+ var startOffset = 0;
185
+ var featureCount = STATIC_ARRAY_SIZE;
186
+ var featureCountPtr = Module.stackAlloc(4);
187
+ var featureTagsPtr = Module.stackAlloc(STATIC_ARRAY_SIZE * 4);
188
+ var tags = [];
189
+ while (featureCount == STATIC_ARRAY_SIZE) {
190
+ Module.HEAPU32[featureCountPtr / 4] = featureCount;
191
+ exports.hb_ot_layout_table_get_feature_tags(ptr, tableTag, startOffset,
192
+ featureCountPtr, featureTagsPtr);
193
+ featureCount = Module.HEAPU32[featureCountPtr / 4];
194
+ var scriptTags = Module.HEAPU32.subarray(featureTagsPtr / 4,
195
+ featureTagsPtr / 4 + featureCount);
196
+ tags.push(...Array.from(scriptTags).map(_hb_untag));
197
+ startOffset += featureCount;
198
+ }
199
+ return tags;
200
+ },
201
+ /**
202
+ * Return language tags in the given face's GSUB or GPOS table, underneath
203
+ * the specified script index.
204
+ * @param {string} table: The table to query, either "GSUB" or "GPOS".
205
+ * @param {number} scriptIndex: The index of the script to query.
206
+ **/
207
+ getScriptLanguageTags: function (table, scriptIndex) {
208
+ var tableTag = hb_tag(table);
209
+ var startOffset = 0;
210
+ var languageCount = STATIC_ARRAY_SIZE;
211
+ var languageCountPtr = Module.stackAlloc(4);
212
+ var languageTagsPtr = Module.stackAlloc(STATIC_ARRAY_SIZE * 4);
213
+ var tags = [];
214
+ while (languageCount == STATIC_ARRAY_SIZE) {
215
+ Module.HEAPU32[languageCountPtr / 4] = languageCount;
216
+ exports.hb_ot_layout_script_get_language_tags(ptr, tableTag, scriptIndex, startOffset,
217
+ languageCountPtr, languageTagsPtr);
218
+ languageCount = Module.HEAPU32[languageCountPtr / 4];
219
+ var languageTags = Module.HEAPU32.subarray(languageTagsPtr / 4,
220
+ languageTagsPtr / 4 + languageCount);
221
+ tags.push(...Array.from(languageTags).map(_hb_untag));
222
+ startOffset += languageCount;
223
+ }
224
+ return tags;
225
+ },
226
+ /**
227
+ * Return all features in the specified face's GSUB table or GPOS table,
228
+ * underneath the specified script and language.
229
+ * @param {string} table: The table to query, either "GSUB" or "GPOS".
230
+ * @param {number} scriptIndex: The index of the script to query.
231
+ * @param {number} languageIndex: The index of the language to query.
232
+ **/
233
+ getLanguageFeatureTags: function (table, scriptIndex, languageIndex) {
234
+ var tableTag = hb_tag(table);
235
+ var startOffset = 0;
236
+ var featureCount = STATIC_ARRAY_SIZE;
237
+ var featureCountPtr = Module.stackAlloc(4);
238
+ var featureTagsPtr = Module.stackAlloc(STATIC_ARRAY_SIZE * 4);
239
+ var tags = [];
240
+ while (featureCount == STATIC_ARRAY_SIZE) {
241
+ Module.HEAPU32[featureCountPtr / 4] = featureCount;
242
+ exports.hb_ot_layout_language_get_feature_tags(ptr, tableTag, scriptIndex, languageIndex, startOffset,
243
+ featureCountPtr, featureTagsPtr);
244
+ featureCount = Module.HEAPU32[featureCountPtr / 4];
245
+ var featureTags = Module.HEAPU32.subarray(featureTagsPtr / 4,
246
+ featureTagsPtr / 4 + featureCount);
247
+ tags.push(...Array.from(featureTags).map(_hb_untag));
248
+ startOffset += featureCount;
249
+ }
250
+ return tags;
251
+ },
252
+ /**
253
+ * Return all names in the specified face's name table.
254
+ **/
255
+ listNames: function () {
256
+ var numEntriesPtr = Module.stackAlloc(4);
257
+ var entriesPtr = exports.hb_ot_name_list_names(ptr, numEntriesPtr);
258
+ var numEntries = Module.HEAPU32[numEntriesPtr / 4];
259
+ var entries = [];
260
+ for (var i = 0; i < numEntries; i++) {
261
+ // FIXME: this depends on the struct memory layout.
262
+ // A more robust way would involve ading helper C functions to access
263
+ // the struct and use them here.
264
+ entries.push({
265
+ nameId: Module.HEAPU32[(entriesPtr / 4) + (i * 3)],
266
+ language: _language_to_string(Module.HEAPU32[(entriesPtr / 4) + (i * 3) + 2])
267
+ });
268
+ }
269
+ return entries;
270
+ },
271
+ /**
272
+ * Get the name of the specified face.
273
+ * @param {number} nameId The ID of the name to get.
274
+ * @param {string} language The language of the name to get.
275
+ **/
276
+ getName: function (nameId, language) {
277
+ var languagePtr = _language_from_string(language);
278
+ var nameLen = exports.hb_ot_name_get_utf16(ptr, nameId, languagePtr, 0, 0) + 1;
279
+ var textSizePtr = Module.stackAlloc(4);
280
+ var textPtr = exports.malloc(nameLen * 2);
281
+ Module.HEAPU32[textSizePtr / 4] = nameLen;
282
+ exports.hb_ot_name_get_utf16(ptr, nameId, languagePtr, textSizePtr, textPtr);
283
+ var name = String.fromCharCode.apply(null, Module.HEAPU16.subarray(textPtr / 2, textPtr / 2 + nameLen - 1));
284
+ exports.free(textPtr);
285
+ return name;
286
+ },
287
+ /**
288
+ * Get the name IDs of the specified feature.
289
+ * @param {string} table The table to query, either "GSUB" or "GPOS".
290
+ * @param {number} featureIndex The index of the feature to query.
291
+ **/
292
+ getFeatureNameIds: function (table, featureIndex) {
293
+ var tableTag = hb_tag(table);
294
+ var labelIdPtr = Module.stackAlloc(4);
295
+ var tooltipIdPtr = Module.stackAlloc(4);
296
+ var sampleIdPtr = Module.stackAlloc(4);
297
+ var numNamedParametersPtr = Module.stackAlloc(4);
298
+ var firstParameterIdPtr = Module.stackAlloc(4);
299
+
300
+ var found = exports.hb_ot_layout_feature_get_name_ids(ptr, tableTag, featureIndex,
301
+ labelIdPtr, tooltipIdPtr, sampleIdPtr, numNamedParametersPtr, firstParameterIdPtr);
302
+
303
+ if (found) {
304
+ let uiLabelNameId = Module.HEAPU32[labelIdPtr / 4];
305
+ let uiTooltipTextNameId = Module.HEAPU32[tooltipIdPtr / 4];
306
+ let sampleTextNameId = Module.HEAPU32[sampleIdPtr / 4];
307
+ let numNamedParameters = Module.HEAPU32[numNamedParametersPtr / 4];
308
+ let firstParameterId = Module.HEAPU32[firstParameterIdPtr / 4];
309
+ let paramUiLabelNameIds = Array(numNamedParameters).fill().map((_, i) => firstParameterId + i);
310
+ return {
311
+ uiLabelNameId: uiLabelNameId == HB_OT_NAME_ID_INVALID ? null : uiLabelNameId,
312
+ uiTooltipTextNameId: uiTooltipTextNameId == HB_OT_NAME_ID_INVALID ? null : uiTooltipTextNameId,
313
+ sampleTextNameId: sampleTextNameId == HB_OT_NAME_ID_INVALID ? null : sampleTextNameId,
314
+ paramUiLabelNameIds: paramUiLabelNameIds
315
+ };
316
+ }
317
+
318
+ return null;
319
+ },
135
320
  /**
136
321
  * Free the object.
137
322
  */
@@ -149,9 +334,10 @@ function hbjs(Module) {
149
334
  /**
150
335
  * Create an object representing a Harfbuzz font.
151
336
  * @param {object} blob An object returned from `createFace`.
337
+ * @param {number} ptr Optional pointer to an existing font.
152
338
  **/
153
- function createFont(face) {
154
- var ptr = exports.hb_font_create(face.ptr);
339
+ function createFont(face, ptr) {
340
+ var ptr = ptr ? exports.hb_font_reference(ptr) : exports.hb_font_create(face.ptr);
155
341
  var drawFuncsPtr = null;
156
342
  var moveToPtr = null;
157
343
  var lineToPtr = null;
@@ -216,8 +402,110 @@ function hbjs(Module) {
216
402
 
217
403
  return {
218
404
  ptr: ptr,
405
+ /**
406
+ * Create a sub font.
407
+ * @returns {object} Object representing the sub font.
408
+ **/
409
+ subFont: function () {
410
+ return createFont(null, exports.hb_font_create_sub_font(ptr));
411
+ },
412
+ /**
413
+ * Return font horizontal extents.
414
+ * @returns {object} Object with ascender, descender, and lineGap properties.
415
+ **/
416
+ hExtents: function () {
417
+ var extentsPtr = Module.stackAlloc(12);
418
+ exports.hb_font_get_h_extents(ptr, extentsPtr);
419
+ return {
420
+ ascender: Module.HEAP32[extentsPtr / 4],
421
+ descender: Module.HEAP32[extentsPtr / 4 + 1],
422
+ lineGap: Module.HEAP32[extentsPtr / 4 + 2],
423
+ };
424
+ },
425
+ /**
426
+ * Return font vertical extents.
427
+ * @returns {object} Object with ascender, descender, and lineGap properties.
428
+ **/
429
+ vExtents: function () {
430
+ var extentsPtr = Module.stackAlloc(12);
431
+ exports.hb_font_get_v_extents(ptr, extentsPtr);
432
+ return {
433
+ ascender: Module.HEAP32[extentsPtr / 4],
434
+ descender: Module.HEAP32[extentsPtr / 4 + 1],
435
+ lineGap: Module.HEAP32[extentsPtr / 4 + 2],
436
+ };
437
+ },
219
438
  glyphName: glyphName,
220
439
  glyphToPath: glyphToPath,
440
+ /**
441
+ * Return glyph horizontal advance.
442
+ * @param {number} glyphId ID of the requested glyph in the font.
443
+ **/
444
+ glyphHAdvance: function (glyphId) {
445
+ return exports.hb_font_get_glyph_h_advance(ptr, glyphId);
446
+ },
447
+ /**
448
+ * Return glyph vertical advance.
449
+ * @param {number} glyphId ID of the requested glyph in the font.
450
+ **/
451
+ glyphVAdvance: function (glyphId) {
452
+ return exports.hb_font_get_glyph_v_advance(ptr, glyphId);
453
+ },
454
+ /**
455
+ * Return glyph horizontal origin.
456
+ * @param {number} glyphId ID of the requested glyph in the font.
457
+ **/
458
+ glyphHOrigin: function (glyphId) {
459
+ let xPtr = Module.stackAlloc(4);
460
+ let yPtr = Module.stackAlloc(4);
461
+ if (exports.hb_font_get_glyph_h_origin(ptr, glyphId, xPtr, yPtr)) {
462
+ return [Module.HEAP32[xPtr / 4], Module.HEAP32[yPtr / 4]];
463
+ }
464
+ return null;
465
+ },
466
+ /**
467
+ * Return glyph vertical origin.
468
+ * @param {number} glyphId ID of the requested glyph in the font.
469
+ **/
470
+ glyphVOrigin: function (glyphId) {
471
+ let xPtr = Module.stackAlloc(4);
472
+ let yPtr = Module.stackAlloc(4);
473
+ if (exports.hb_font_get_glyph_v_origin(ptr, glyphId, xPtr, yPtr)) {
474
+ return [Module.HEAP32[xPtr / 4], Module.HEAP32[yPtr / 4]];
475
+ }
476
+ return null;
477
+ },
478
+ /**
479
+ * Return glyph extents.
480
+ * @param {number} glyphId ID of the requested glyph in the font.
481
+ **/
482
+ glyphExtents: function (glyphId) {
483
+ var extentsPtr = Module.stackAlloc(16);
484
+ if (exports.hb_font_get_glyph_extents(ptr, glyphId, extentsPtr)) {
485
+ return {
486
+ xBearing: Module.HEAP32[extentsPtr / 4],
487
+ yBearing: Module.HEAP32[extentsPtr / 4 + 1],
488
+ width: Module.HEAP32[extentsPtr / 4 + 2],
489
+ height: Module.HEAP32[extentsPtr / 4 + 3]
490
+ };
491
+ }
492
+ return null;
493
+ },
494
+ /**
495
+ * Return glyph ID from name.
496
+ * @param {string} name Name of the requested glyph in the font.
497
+ **/
498
+ glyphFromName: function (name) {
499
+ var glyphId = null;
500
+ var glyphIdPtr = Module.stackAlloc(4);
501
+ var namePtr = exports.malloc(name.length + 1);
502
+ utf8Encoder.encodeInto(name, Module.HEAPU8.subarray(namePtr, namePtr + name.length));
503
+ if (exports.hb_font_get_glyph_from_name(ptr, namePtr, name.length, glyphIdPtr)) {
504
+ glyphId = Module.HEAPU32[glyphIdPtr / 4];
505
+ }
506
+ exports.free(namePtr);
507
+ return glyphId;
508
+ },
221
509
  /**
222
510
  * Return a glyph as a JSON path string
223
511
  * based on format described on https://svgwg.org/specs/paths/#InterfaceSVGPathSegment
@@ -254,6 +542,13 @@ function hbjs(Module) {
254
542
  exports.free(vars);
255
543
  },
256
544
  /**
545
+ * Set the font's font functions.
546
+ * @param {object} fontFuncs The font functions.
547
+ **/
548
+ setFuncs: function (fontFuncs) {
549
+ exports.hb_font_set_funcs(ptr, fontFuncs.ptr);
550
+ },
551
+ /**
257
552
  * Free the object.
258
553
  */
259
554
  destroy: function () {
@@ -271,6 +566,304 @@ function hbjs(Module) {
271
566
  };
272
567
  }
273
568
 
569
+ /**
570
+ * Create a object representing a HarfBuzz font functions.
571
+ **/
572
+ function createFontFuncs() {
573
+ var ptr = exports.hb_font_funcs_create();
574
+ return {
575
+ ptr: ptr,
576
+ /**
577
+ * Set the font's glyph extents function.
578
+ * @param {function} func The function to set.
579
+ *
580
+ * The function takes the following arguments:
581
+ * @param {object} font The font.
582
+ * @param {number} glyph The glyph ID.
583
+ *
584
+ * The function should return an object with the following properties, or null on failure:
585
+ * @param {number} xBearing The x bearing of the glyph.
586
+ * @param {number} yBearing The y bearing of the glyph.
587
+ * @param {number} width The width of the glyph.
588
+ * @param {number} height The height of the glyph.
589
+ **/
590
+ setGlyphExtentsFunc: function (func) {
591
+ let funcPtr = addFunction(function (fontPtr, font_data, glyph, extentsPtr, user_data) {
592
+ let font = createFont(null, fontPtr);
593
+ let extents = func(font, glyph);
594
+ font.destroy();
595
+ if (extents) {
596
+ Module.HEAP32[extentsPtr / 4] = extents.xBearing;
597
+ Module.HEAP32[extentsPtr / 4 + 1] = extents.yBearing;
598
+ Module.HEAP32[extentsPtr / 4 + 2] = extents.width;
599
+ Module.HEAP32[extentsPtr / 4 + 3] = extents.height;
600
+ return 1;
601
+ }
602
+ return 0;
603
+ }, 'ippipp');
604
+ exports.hb_font_funcs_set_glyph_extents_func(ptr, funcPtr, 0, 0);
605
+ },
606
+ /**
607
+ * Set the font's glyph from name function.
608
+ * @param {function} func The function to set.
609
+ *
610
+ * The function takes the following arguments:
611
+ * @param {object} font The font.
612
+ * @param {string} name The glyph name.
613
+ *
614
+ * The function should return an object with the following properties, or null on failure:
615
+ * @param {number} glyph The glyph ID.
616
+ **/
617
+ setGlyphFromNameFunc: function (func) {
618
+ let funcPtr = addFunction(function (fontPtr, font_data, namePtr, len, glyphPtr, user_data) {
619
+ let font = createFont(null, fontPtr);
620
+ let name = utf8Decoder.decode(Module.HEAPU8.subarray(namePtr, namePtr + len));
621
+ let glyph = func(font, name);
622
+ font.destroy();
623
+ if (glyph) {
624
+ Module.HEAPU32[glyphPtr / 4] = glyph;
625
+ return 1;
626
+ }
627
+ return 0;
628
+ }, 'ipppipp');
629
+ exports.hb_font_funcs_set_glyph_from_name_func(ptr, funcPtr, 0, 0);
630
+ },
631
+ /**
632
+ * Set the font's glyph horizontal advance function.
633
+ * @param {function} func The function to set.
634
+ *
635
+ * The function takes the following arguments:
636
+ * @param {object} font The font.
637
+ * @param {number} glyph The glyph ID.
638
+ *
639
+ * The function should return the horizontal advance of the glyph.
640
+ **/
641
+ setGlyphHAdvanceFunc: function (func) {
642
+ let funcPtr = addFunction(function (fontPtr, font_data, glyph, user_data) {
643
+ let font = createFont(null, fontPtr);
644
+ let advance = func(font, glyph);
645
+ font.destroy();
646
+ return advance;
647
+ }, 'ippip');
648
+ exports.hb_font_funcs_set_glyph_h_advance_func(ptr, funcPtr, 0, 0);
649
+ },
650
+ /**
651
+ * Set the font's glyph vertical advance function.
652
+ * @param {function} func The function to set.
653
+ *
654
+ * The function takes the following arguments:
655
+ * @param {object} font The font.
656
+ * @param {number} glyph The glyph ID.
657
+ *
658
+ * The function should return the vertical advance of the glyph.
659
+ **/
660
+ setGlyphVAdvanceFunc: function (func) {
661
+ let funcPtr = addFunction(function (fontPtr, font_data, glyph, user_data) {
662
+ let font = createFont(null, fontPtr);
663
+ let advance = func(font, glyph);
664
+ font.destroy();
665
+ return advance;
666
+ }, 'ippip');
667
+ exports.hb_font_funcs_set_glyph_v_advance_func(ptr, funcPtr, 0, 0);
668
+ },
669
+ /**
670
+ * Set the font's glyph horizontal origin function.
671
+ * @param {function} func The function to set.
672
+ *
673
+ * The function takes the following arguments:
674
+ * @param {object} font The font.
675
+ * @param {number} glyph The glyph ID.
676
+ *
677
+ * The function should return the x and y horizontal origin of the glyph, or null on failure.
678
+ **/
679
+ setGlyphHOriginFunc: function (func) {
680
+ let funcPtr = addFunction(function (fontPtr, font_data, glyph, xPtr, yPtr, user_data) {
681
+ let font = createFont(null, fontPtr);
682
+ let origin = func(font, glyph);
683
+ font.destroy();
684
+ if (origin) {
685
+ Module.HEAP32[xPtr / 4] = origin[0];
686
+ Module.HEAP32[yPtr / 4] = origin[1];
687
+ return 1;
688
+ }
689
+ return 0;
690
+ }, 'ippippp');
691
+ exports.hb_font_funcs_set_glyph_h_origin_func(ptr, funcPtr, 0, 0);
692
+ },
693
+ /**
694
+ * Set the font's glyph vertical origin function.
695
+ * @param {function} func The function to set.
696
+ *
697
+ * The function takes the following arguments:
698
+ * @param {object} font The font.
699
+ * @param {number} glyph The glyph ID.
700
+ *
701
+ * The function should return the x and y vertical origin of the glyph, or null on failure.
702
+ **/
703
+ setGlyphVOriginFunc: function (func) {
704
+ let funcPtr = addFunction(function (fontPtr, font_data, glyph, xPtr, yPtr, user_data) {
705
+ let font = createFont(null, fontPtr);
706
+ let origin = func(font, glyph);
707
+ font.destroy();
708
+ if (origin) {
709
+ Module.HEAP32[xPtr / 4] = origin[0];
710
+ Module.HEAP32[yPtr / 4] = origin[1];
711
+ return 1;
712
+ }
713
+ return 0;
714
+ }, 'ippippp');
715
+ exports.hb_font_funcs_set_glyph_v_origin_func(ptr, funcPtr, 0, 0);
716
+ },
717
+ /**
718
+ * Set the font's glyph horizontal kerning function.
719
+ * @param {function} func The function to set.
720
+ *
721
+ * The function takes the following arguments:
722
+ * @param {object} font The font.
723
+ * @param {number} firstGlyph The first glyph ID.
724
+ * @param {number} secondGlyph The second glyph ID.
725
+ *
726
+ * The function should return the horizontal kerning of the glyphs.
727
+ **/
728
+ setGlyphHKerningFunc: function (func) {
729
+ let funcPtr = addFunction(function (fontPtr, font_data, firstGlyph, secondGlyph, user_data) {
730
+ let font = createFont(null, fontPtr);
731
+ let kerning = func(font, firstGlyph, secondGlyph);
732
+ font.destroy();
733
+ return kerning;
734
+ }, 'ippiip');
735
+ exports.hb_font_funcs_set_glyph_h_kerning_func(ptr, funcPtr, 0, 0);
736
+ },
737
+ /**
738
+ * Set the font's glyph name function.
739
+ * @param {function} func The function to set.
740
+ *
741
+ * The function takes the following arguments:
742
+ * @param {object} font The font.
743
+ * @param {number} glyph The glyph ID.
744
+ *
745
+ * The function should return the name of the glyph, or null on failure.
746
+ **/
747
+ setGlyphNameFunc: function (func) {
748
+ let funcPtr = addFunction(function (fontPtr, font_data, glyph, namePtr, size, user_data) {
749
+ let font = createFont(null, fontPtr);
750
+ let name = func(font, glyph);
751
+ font.destroy();
752
+ if (name) {
753
+ utf8Encoder.encodeInto(name, Module.HEAPU8.subarray(namePtr, namePtr + size));
754
+ return 1;
755
+ }
756
+ return 0;
757
+ }, 'ippipip');
758
+ exports.hb_font_funcs_set_glyph_name_func(ptr, funcPtr, 0, 0);
759
+ },
760
+ /**
761
+ * Set the font's nominal glyph function.
762
+ * @param {function} func The function to set.
763
+ *
764
+ * The function takes the following arguments:
765
+ * @param {object} font The font.
766
+ * @param {number} unicode The unicode.
767
+ *
768
+ * The function should return the nominal glyph of the unicode, or null on failure.
769
+ **/
770
+ setNominalGlyphFunc: function (func) {
771
+ let funcPtr = addFunction(function (fontPtr, font_data, unicode, glyphPtr, user_data) {
772
+ let font = createFont(null, fontPtr);
773
+ let glyph = func(font, unicode);
774
+ font.destroy();
775
+ if (glyph) {
776
+ Module.HEAPU32[glyphPtr / 4] = glyph;
777
+ return 1;
778
+ }
779
+ return 0;
780
+ }, 'ippipp');
781
+ exports.hb_font_funcs_set_nominal_glyph_func(ptr, funcPtr, 0, 0);
782
+ },
783
+ /**
784
+ * Set the font's variation glyph function.
785
+ * @param {function} func The function to set.
786
+ *
787
+ * The function takes the following arguments:
788
+ * @param {object} font The font.
789
+ * @param {number} unicode The unicode.
790
+ * @param {number} variationSelector The variation selector.
791
+ *
792
+ * The function should return the variation glyph of the unicode, or null on failure.
793
+ **/
794
+ setVariationGlyphFunc: function (func) {
795
+ let funcPtr = addFunction(function (fontPtr, font_data, unicode, variationSelector, glyphPtr, user_data) {
796
+ let font = createFont(null, fontPtr);
797
+ let glyph = func(font, unicode, variationSelector);
798
+ font.destroy();
799
+ if (glyph) {
800
+ Module.HEAPU32[glyphPtr / 4] = glyph;
801
+ return 1;
802
+ }
803
+ return 0;
804
+ }, 'ippiipp');
805
+ exports.hb_font_funcs_set_variation_glyph_func(ptr, funcPtr, 0, 0);
806
+ },
807
+ /**
808
+ * Set the font's horizontal extents function.
809
+ * @param {function} func The function to set.
810
+ *
811
+ * The function takes the following arguments:
812
+ * @param {object} font The font.
813
+ *
814
+ * The function should return an object with the following properties, or null on failure:
815
+ * @param {number} ascender The ascender of the font.
816
+ * @param {number} descender The descender of the font.
817
+ * @param {number} lineGap The line gap of the font.
818
+ **/
819
+ setFontHExtentsFunc: function (func) {
820
+ let funcPtr = addFunction(function (fontPtr, font_data, extentsPtr, user_data) {
821
+ let font = createFont(null, fontPtr);
822
+ let extents = func(font);
823
+ font.destroy();
824
+ if (extents) {
825
+ Module.HEAP32[extentsPtr / 4] = extents.ascender;
826
+ Module.HEAP32[extentsPtr / 4 + 1] = extents.descender;
827
+ Module.HEAP32[extentsPtr / 4 + 2] = extents.lineGap;
828
+ return 1;
829
+ }
830
+ return 0;
831
+ }, 'ipppp');
832
+ exports.hb_font_funcs_set_font_h_extents_func(ptr, funcPtr, 0, 0);
833
+ },
834
+ /**
835
+ * Set the font's vertical extents function.
836
+ * @param {function} func The function to set.
837
+ *
838
+ * The function takes the following arguments:
839
+ * @param {object} font The font.
840
+ *
841
+ * The function should return an object with the following properties, or null on failure:
842
+ * @param {number} ascender The ascender of the font.
843
+ * @param {number} descender The descender of the font.
844
+ * @param {number} lineGap The line gap of the font.
845
+ **/
846
+ setFontVExtentsFunc: function (func) {
847
+ let funcPtr = addFunction(function (fontPtr, font_data, extentsPtr, user_data) {
848
+ let font = createFont(null, fontPtr);
849
+ let extents = func(font);
850
+ font.destroy();
851
+ if (extents) {
852
+ Module.HEAP32[extentsPtr / 4] = extents.ascender;
853
+ Module.HEAP32[extentsPtr / 4 + 1] = extents.descender;
854
+ Module.HEAP32[extentsPtr / 4 + 2] = extents.lineGap;
855
+ return 1;
856
+ }
857
+ return 0;
858
+ }, 'ipppp');
859
+ exports.hb_font_funcs_set_font_v_extents_func(ptr, funcPtr, 0, 0);
860
+ },
861
+ destroy: function () {
862
+ exports.hb_font_funcs_destroy(ptr);
863
+ }
864
+ };
865
+ }
866
+
274
867
  /**
275
868
  * Use when you know the input range should be ASCII.
276
869
  * Faster than encoding to UTF-8
@@ -353,7 +946,7 @@ function hbjs(Module) {
353
946
  flagValue |= _buffer_flag(s);
354
947
  })
355
948
 
356
- exports.hb_buffer_set_flags(ptr,flagValue);
949
+ exports.hb_buffer_set_flags(ptr, flagValue);
357
950
  },
358
951
  /**
359
952
  * Set buffer language explicitly.
@@ -361,7 +954,7 @@ function hbjs(Module) {
361
954
  */
362
955
  setLanguage: function (language) {
363
956
  var str = createAsciiString(language);
364
- exports.hb_buffer_set_language(ptr, exports.hb_language_from_string(str.ptr,-1));
957
+ exports.hb_buffer_set_language(ptr, exports.hb_language_from_string(str.ptr, -1));
365
958
  str.free();
366
959
  },
367
960
  /**
@@ -370,7 +963,7 @@ function hbjs(Module) {
370
963
  */
371
964
  setScript: function (script) {
372
965
  var str = createAsciiString(script);
373
- exports.hb_buffer_set_script(ptr, exports.hb_script_from_string(str.ptr,-1));
966
+ exports.hb_buffer_set_script(ptr, exports.hb_script_from_string(str.ptr, -1));
374
967
  str.free();
375
968
  },
376
969
 
@@ -548,6 +1141,7 @@ function hbjs(Module) {
548
1141
  createBlob: createBlob,
549
1142
  createFace: createFace,
550
1143
  createFont: createFont,
1144
+ createFontFuncs: createFontFuncs,
551
1145
  createBuffer: createBuffer,
552
1146
  shape: shape,
553
1147
  shapeWithTrace: shapeWithTrace,
@@ -559,4 +1153,4 @@ function hbjs(Module) {
559
1153
  // Should be replaced with something more reliable
560
1154
  try {
561
1155
  module.exports = hbjs;
562
- } catch (e) {}
1156
+ } catch (e) { }