harfbuzzjs 0.10.3 → 1.0.0-beta.2

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 DELETED
@@ -1,1463 +0,0 @@
1
- function hbjs(Module) {
2
- 'use strict';
3
-
4
- var exports = Module.wasmExports;
5
- var utf8Decoder = new TextDecoder("utf8");
6
- var utf8Encoder = new TextEncoder("utf8");
7
- let addFunction = Module.addFunction;
8
- let removeFunction = Module.removeFunction;
9
- let stackSave = Module.stackSave;
10
- let stackRestore = Module.stackRestore;
11
- let stackAlloc = Module.stackAlloc;
12
-
13
- var freeFuncPtr = addFunction(function (ptr) { exports.free(ptr); }, 'vi');
14
-
15
- const TRACE_PHASE_DONT_STOP = 0;
16
- const TRACE_PHASE_GSUB = 1;
17
- const TRACE_PHASE_GPOS = 2;
18
-
19
- const STATIC_ARRAY_SIZE = 128
20
-
21
- const HB_MEMORY_MODE_WRITABLE = 2;
22
- const HB_SET_VALUE_INVALID = -1;
23
- const HB_OT_NAME_ID_INVALID = 0xFFFF;
24
-
25
- const bufferContentType = {
26
- 0: "INVALID",
27
- 1: "UNICODE",
28
- 2: "GLYPHS",
29
- };
30
- const bufferSerializeFlags = {
31
- "DEFAULT": 0x00000000,
32
- "NO_CLUSTERS": 0x00000001,
33
- "NO_POSITIONS": 0x00000002,
34
- "NO_GLYPH_NAMES": 0x00000004,
35
- "GLYPH_EXTENTS": 0x00000008,
36
- "GLYPH_FLAGS": 0x00000010,
37
- "NO_ADVANCES": 0x00000020,
38
- };
39
-
40
- const bufferFlags = {
41
- "DEFAULT": 0x00000000,
42
- "BOT": 0x00000001,
43
- "EOT": 0x00000002,
44
- "PRESERVE_DEFAULT_IGNORABLES": 0x00000004,
45
- "REMOVE_DEFAULT_IGNORABLES": 0x00000008,
46
- "DO_NOT_INSERT_DOTTED_CIRCLE": 0x00000010,
47
- "VERIFY": 0x00000020,
48
- "PRODUCE_UNSAFE_TO_CONCAT": 0x00000040,
49
- "PRODUCE_SAFE_TO_INSERT_TATWEEL": 0x00000080,
50
- };
51
-
52
- function _hb_tag(s) {
53
- return (
54
- (s.charCodeAt(0) & 0xFF) << 24 |
55
- (s.charCodeAt(1) & 0xFF) << 16 |
56
- (s.charCodeAt(2) & 0xFF) << 8 |
57
- (s.charCodeAt(3) & 0xFF) << 0
58
- );
59
- }
60
-
61
- function _hb_untag(tag) {
62
- return [
63
- String.fromCharCode((tag >> 24) & 0xFF),
64
- String.fromCharCode((tag >> 16) & 0xFF),
65
- String.fromCharCode((tag >> 8) & 0xFF),
66
- String.fromCharCode((tag >> 0) & 0xFF)
67
- ].join('');
68
- }
69
-
70
- function _utf8_ptr_to_string(ptr, length) {
71
- let end;
72
- if (length === undefined) end = Module.HEAPU8.indexOf(0, ptr);
73
- else end = ptr + length;
74
- return utf8Decoder.decode(Module.HEAPU8.subarray(ptr, end));
75
- }
76
-
77
- function _utf16_ptr_to_string(ptr, length) {
78
- let end = ptr / 2 + length;
79
- return String.fromCharCode.apply(null, Module.HEAPU16.subarray(ptr / 2, end));
80
- }
81
-
82
- /**
83
- * Use when you know the input range should be ASCII.
84
- * Faster than encoding to UTF-8
85
- **/
86
- function _string_to_ascii_ptr(text) {
87
- const ptr = exports.malloc(text.length + 1);
88
- for (let i = 0; i < text.length; ++i) {
89
- const char = text.charCodeAt(i);
90
- if (char > 127) throw new Error('Expected ASCII text');
91
- Module.HEAPU8[ptr + i] = char;
92
- }
93
- Module.HEAPU8[ptr + text.length] = 0;
94
- return {
95
- ptr: ptr,
96
- length: text.length,
97
- free: function () { exports.free(ptr); }
98
- };
99
- }
100
-
101
- function _string_to_utf8_ptr(text) {
102
- const ptr = exports.malloc(text.length);
103
- utf8Encoder.encodeInto(text, Module.HEAPU8.subarray(ptr, ptr + text.length));
104
- return {
105
- ptr: ptr,
106
- length: text.length,
107
- free: function () { exports.free(ptr); }
108
- };
109
- }
110
-
111
- function _string_to_utf16_ptr(text) {
112
- const ptr = exports.malloc(text.length * 2);
113
- const words = Module.HEAPU16.subarray(ptr / 2, ptr / 2 + text.length);
114
- for (let i = 0; i < words.length; ++i) words[i] = text.charCodeAt(i);
115
- return {
116
- ptr: ptr,
117
- length: words.length,
118
- free: function () { exports.free(ptr); }
119
- };
120
- }
121
-
122
- function _language_to_string(language) {
123
- var ptr = exports.hb_language_to_string(language);
124
- return _utf8_ptr_to_string(ptr);
125
- }
126
-
127
- function _language_from_string(str) {
128
- var languageStr = _string_to_ascii_ptr(str);
129
- var languagePtr = exports.hb_language_from_string(languageStr.ptr, -1);
130
- languageStr.free();
131
- return languagePtr;
132
- }
133
-
134
- /**
135
- * Create an object representing a Harfbuzz blob.
136
- * @param {string} blob A blob of binary data (usually the contents of a font file).
137
- **/
138
- function createBlob(blob) {
139
- var blobPtr = exports.malloc(blob.byteLength);
140
- Module.HEAPU8.set(new Uint8Array(blob), blobPtr);
141
- var ptr = exports.hb_blob_create(blobPtr, blob.byteLength, HB_MEMORY_MODE_WRITABLE, blobPtr, freeFuncPtr);
142
- return {
143
- ptr: ptr,
144
- /**
145
- * Free the object.
146
- */
147
- destroy: function () { exports.hb_blob_destroy(ptr); }
148
- };
149
- }
150
-
151
- /**
152
- * Return the typed array of HarfBuzz set contents.
153
- * @param {number} setPtr Pointer of set
154
- * @returns {Uint32Array} Typed array instance
155
- */
156
- function _typed_array_from_set(setPtr) {
157
- const setCount = exports.hb_set_get_population(setPtr);
158
- const arrayPtr = exports.malloc(setCount << 2);
159
- const arrayOffset = arrayPtr >> 2;
160
- const array = Module.HEAPU32.subarray(arrayOffset, arrayOffset + setCount);
161
- Module.HEAPU32.set(array, arrayOffset);
162
- exports.hb_set_next_many(setPtr, HB_SET_VALUE_INVALID, arrayPtr, setCount);
163
- return array;
164
- }
165
-
166
- /**
167
- * Create an object representing a Harfbuzz face.
168
- * @param {object} blob An object returned from `createBlob`.
169
- * @param {number} index The index of the font in the blob. (0 for most files,
170
- * or a 0-indexed font number if the `blob` came form a TTC/OTC file.)
171
- **/
172
- function createFace(blob, index) {
173
- var ptr = exports.hb_face_create(blob.ptr, index);
174
- const upem = exports.hb_face_get_upem(ptr);
175
- return {
176
- ptr: ptr,
177
- upem,
178
- /**
179
- * Return the binary contents of an OpenType table.
180
- * @param {string} table Table name
181
- */
182
- reference_table: function (table) {
183
- var blob = exports.hb_face_reference_table(ptr, _hb_tag(table));
184
- var length = exports.hb_blob_get_length(blob);
185
- if (!length) { return; }
186
- var blobptr = exports.hb_blob_get_data(blob, null);
187
- var table_string = Module.HEAPU8.subarray(blobptr, blobptr + length);
188
- return table_string;
189
- },
190
- /**
191
- * Return variation axis infos
192
- */
193
- getAxisInfos: function () {
194
- var sp = stackSave();
195
- var axis = stackAlloc(64 * 32);
196
- var c = stackAlloc(4);
197
- Module.HEAPU32[c / 4] = 64;
198
- exports.hb_ot_var_get_axis_infos(ptr, 0, c, axis);
199
- var result = {};
200
- Array.from({ length: Module.HEAPU32[c / 4] }).forEach(function (_, i) {
201
- result[_hb_untag(Module.HEAPU32[axis / 4 + i * 8 + 1])] = {
202
- min: Module.HEAPF32[axis / 4 + i * 8 + 4],
203
- default: Module.HEAPF32[axis / 4 + i * 8 + 5],
204
- max: Module.HEAPF32[axis / 4 + i * 8 + 6]
205
- };
206
- });
207
- stackRestore(sp);
208
- return result;
209
- },
210
- /**
211
- * Return unicodes the face supports
212
- */
213
- collectUnicodes: function () {
214
- var unicodeSetPtr = exports.hb_set_create();
215
- exports.hb_face_collect_unicodes(ptr, unicodeSetPtr);
216
- var result = _typed_array_from_set(unicodeSetPtr);
217
- exports.hb_set_destroy(unicodeSetPtr);
218
- return result;
219
- },
220
- /**
221
- * Return all scripts enumerated in the specified face's
222
- * GSUB table or GPOS table.
223
- * @param {string} table: The table to query, either "GSUB" or "GPOS".
224
- **/
225
- getTableScriptTags: function (table) {
226
- var sp = stackSave();
227
- var tableTag = _hb_tag(table);
228
- var startOffset = 0;
229
- var scriptCount = STATIC_ARRAY_SIZE;
230
- var scriptCountPtr = stackAlloc(4);
231
- var scriptTagsPtr = stackAlloc(STATIC_ARRAY_SIZE * 4);
232
- var tags = [];
233
- while (scriptCount == STATIC_ARRAY_SIZE) {
234
- Module.HEAPU32[scriptCountPtr / 4] = scriptCount;
235
- exports.hb_ot_layout_table_get_script_tags(ptr, tableTag, startOffset,
236
- scriptCountPtr, scriptTagsPtr);
237
- scriptCount = Module.HEAPU32[scriptCountPtr / 4];
238
- var scriptTags = Module.HEAPU32.subarray(scriptTagsPtr / 4,
239
- scriptTagsPtr / 4 + scriptCount);
240
- tags.push(...Array.from(scriptTags).map(_hb_untag));
241
- startOffset += scriptCount;
242
- }
243
- stackRestore(sp);
244
- return tags;
245
- },
246
- /**
247
- * Return all features enumerated in the specified face's
248
- * GSUB table or GPOS table.
249
- * @param {string} table: The table to query, either "GSUB" or "GPOS".
250
- **/
251
- getTableFeatureTags: function (table) {
252
- var sp = stackSave();
253
- var tableTag = _hb_tag(table);
254
- var startOffset = 0;
255
- var featureCount = STATIC_ARRAY_SIZE;
256
- var featureCountPtr = stackAlloc(4);
257
- var featureTagsPtr = stackAlloc(STATIC_ARRAY_SIZE * 4);
258
- var tags = [];
259
- while (featureCount == STATIC_ARRAY_SIZE) {
260
- Module.HEAPU32[featureCountPtr / 4] = featureCount;
261
- exports.hb_ot_layout_table_get_feature_tags(ptr, tableTag, startOffset,
262
- featureCountPtr, featureTagsPtr);
263
- featureCount = Module.HEAPU32[featureCountPtr / 4];
264
- var scriptTags = Module.HEAPU32.subarray(featureTagsPtr / 4,
265
- featureTagsPtr / 4 + featureCount);
266
- tags.push(...Array.from(scriptTags).map(_hb_untag));
267
- startOffset += featureCount;
268
- }
269
- stackRestore(sp);
270
- return tags;
271
-
272
- },
273
- /**
274
- * Return language tags in the given face's GSUB or GPOS table, underneath
275
- * the specified script index.
276
- * @param {string} table: The table to query, either "GSUB" or "GPOS".
277
- * @param {number} scriptIndex: The index of the script to query.
278
- **/
279
- getScriptLanguageTags: function (table, scriptIndex) {
280
- var sp = stackSave();
281
- var tableTag = _hb_tag(table);
282
- var startOffset = 0;
283
- var languageCount = STATIC_ARRAY_SIZE;
284
- var languageCountPtr = stackAlloc(4);
285
- var languageTagsPtr = stackAlloc(STATIC_ARRAY_SIZE * 4);
286
- var tags = [];
287
- while (languageCount == STATIC_ARRAY_SIZE) {
288
- Module.HEAPU32[languageCountPtr / 4] = languageCount;
289
- exports.hb_ot_layout_script_get_language_tags(ptr, tableTag, scriptIndex, startOffset,
290
- languageCountPtr, languageTagsPtr);
291
- languageCount = Module.HEAPU32[languageCountPtr / 4];
292
- var languageTags = Module.HEAPU32.subarray(languageTagsPtr / 4,
293
- languageTagsPtr / 4 + languageCount);
294
- tags.push(...Array.from(languageTags).map(_hb_untag));
295
- startOffset += languageCount;
296
- }
297
- stackRestore(sp);
298
- return tags;
299
- },
300
- /**
301
- * Return all features in the specified face's GSUB table or GPOS table,
302
- * underneath the specified script and language.
303
- * @param {string} table: The table to query, either "GSUB" or "GPOS".
304
- * @param {number} scriptIndex: The index of the script to query.
305
- * @param {number} languageIndex: The index of the language to query.
306
- **/
307
- getLanguageFeatureTags: function (table, scriptIndex, languageIndex) {
308
- var sp = stackSave();
309
- var tableTag = _hb_tag(table);
310
- var startOffset = 0;
311
- var featureCount = STATIC_ARRAY_SIZE;
312
- var featureCountPtr = stackAlloc(4);
313
- var featureTagsPtr = stackAlloc(STATIC_ARRAY_SIZE * 4);
314
- var tags = [];
315
- while (featureCount == STATIC_ARRAY_SIZE) {
316
- Module.HEAPU32[featureCountPtr / 4] = featureCount;
317
- exports.hb_ot_layout_language_get_feature_tags(ptr, tableTag, scriptIndex, languageIndex, startOffset,
318
- featureCountPtr, featureTagsPtr);
319
- featureCount = Module.HEAPU32[featureCountPtr / 4];
320
- var featureTags = Module.HEAPU32.subarray(featureTagsPtr / 4,
321
- featureTagsPtr / 4 + featureCount);
322
- tags.push(...Array.from(featureTags).map(_hb_untag));
323
- startOffset += featureCount;
324
- }
325
- stackRestore(sp);
326
- return tags;
327
- },
328
- /**
329
- * Get the GDEF class of the requested glyph.
330
- * @param {number} glyph The glyph to get the class of.
331
- * @returns {string} The class of the glyph. Which can be either
332
- * UNCLASSIFIED, BASE_GLYPH, LIGATURE, MARK, or COMPONENT.
333
- **/
334
- getGlyphClass: function (glyph) {
335
- const gclass = exports.hb_ot_layout_get_glyph_class(ptr, glyph);
336
- switch (gclass) {
337
- case 0:
338
- return 'UNCLASSIFIED';
339
- case 1:
340
- return 'BASE_GLYPH';
341
- case 2:
342
- return 'LIGATURE';
343
- case 3:
344
- return 'MARK';
345
- case 4:
346
- return 'COMPONENT';
347
- }
348
- },
349
- /**
350
- * Return all names in the specified face's name table.
351
- **/
352
- listNames: function () {
353
- var sp = stackSave();
354
- var numEntriesPtr = stackAlloc(4);
355
- var entriesPtr = exports.hb_ot_name_list_names(ptr, numEntriesPtr);
356
- var numEntries = Module.HEAPU32[numEntriesPtr / 4];
357
- var entries = [];
358
- for (var i = 0; i < numEntries; i++) {
359
- // FIXME: this depends on the struct memory layout.
360
- // A more robust way would involve ading helper C functions to access
361
- // the struct and use them here.
362
- entries.push({
363
- nameId: Module.HEAPU32[(entriesPtr / 4) + (i * 3)],
364
- language: _language_to_string(Module.HEAPU32[(entriesPtr / 4) + (i * 3) + 2])
365
- });
366
- }
367
- stackRestore(sp);
368
- return entries;
369
- },
370
- /**
371
- * Get the name of the specified face.
372
- * @param {number} nameId The ID of the name to get.
373
- * @param {string} language The language of the name to get.
374
- **/
375
- getName: function (nameId, language) {
376
- var sp = stackSave();
377
- var languagePtr = _language_from_string(language);
378
- var nameLen = exports.hb_ot_name_get_utf16(ptr, nameId, languagePtr, 0, 0) + 1;
379
- var textSizePtr = stackAlloc(4);
380
- var textPtr = exports.malloc(nameLen * 2);
381
- Module.HEAPU32[textSizePtr / 4] = nameLen;
382
- exports.hb_ot_name_get_utf16(ptr, nameId, languagePtr, textSizePtr, textPtr);
383
- var name = _utf16_ptr_to_string(textPtr, nameLen - 1);
384
- exports.free(textPtr);
385
- stackRestore(sp);
386
- return name;
387
- },
388
- /**
389
- * Get the name IDs of the specified feature.
390
- * @param {string} table The table to query, either "GSUB" or "GPOS".
391
- * @param {number} featureIndex The index of the feature to query.
392
- **/
393
- getFeatureNameIds: function (table, featureIndex) {
394
- var sp = stackSave();
395
- var tableTag = _hb_tag(table);
396
- var labelIdPtr = stackAlloc(4);
397
- var tooltipIdPtr = stackAlloc(4);
398
- var sampleIdPtr = stackAlloc(4);
399
- var numNamedParametersPtr = stackAlloc(4);
400
- var firstParameterIdPtr = stackAlloc(4);
401
-
402
- var found = exports.hb_ot_layout_feature_get_name_ids(ptr, tableTag, featureIndex,
403
- labelIdPtr, tooltipIdPtr, sampleIdPtr, numNamedParametersPtr, firstParameterIdPtr);
404
-
405
- var names = null;
406
- if (found) {
407
- let uiLabelNameId = Module.HEAPU32[labelIdPtr / 4];
408
- let uiTooltipTextNameId = Module.HEAPU32[tooltipIdPtr / 4];
409
- let sampleTextNameId = Module.HEAPU32[sampleIdPtr / 4];
410
- let numNamedParameters = Module.HEAPU32[numNamedParametersPtr / 4];
411
- let firstParameterId = Module.HEAPU32[firstParameterIdPtr / 4];
412
- let paramUiLabelNameIds = Array(numNamedParameters).fill().map((_, i) => firstParameterId + i);
413
- names = {
414
- uiLabelNameId: uiLabelNameId == HB_OT_NAME_ID_INVALID ? null : uiLabelNameId,
415
- uiTooltipTextNameId: uiTooltipTextNameId == HB_OT_NAME_ID_INVALID ? null : uiTooltipTextNameId,
416
- sampleTextNameId: sampleTextNameId == HB_OT_NAME_ID_INVALID ? null : sampleTextNameId,
417
- paramUiLabelNameIds: paramUiLabelNameIds
418
- };
419
- }
420
-
421
- stackRestore(sp);
422
- return names;
423
- },
424
- /**
425
- * Free the object.
426
- */
427
- destroy: function () {
428
- exports.hb_face_destroy(ptr);
429
- },
430
- };
431
- }
432
-
433
- var pathBuffer = "";
434
-
435
- /**
436
- * Create an object representing a Harfbuzz font.
437
- * @param {object} blob An object returned from `createFace`.
438
- * @param {number} ptr Optional pointer to an existing font.
439
- **/
440
- function createFont(face, ptr) {
441
- var ptr = ptr ? exports.hb_font_reference(ptr) : exports.hb_font_create(face.ptr);
442
- var drawFuncsPtr = null;
443
- var moveToPtr = null;
444
- var lineToPtr = null;
445
- var cubicToPtr = null;
446
- var quadToPtr = null;
447
- var closePathPtr = null;
448
-
449
- /**
450
- * Return a glyph as an SVG path string.
451
- * @param {number} glyphId ID of the requested glyph in the font.
452
- **/
453
- function glyphToPath(glyphId) {
454
- if (!drawFuncsPtr) {
455
- var moveTo = function (dfuncs, draw_data, draw_state, to_x, to_y, user_data) {
456
- pathBuffer += `M${to_x},${to_y}`;
457
- }
458
- var lineTo = function (dfuncs, draw_data, draw_state, to_x, to_y, user_data) {
459
- pathBuffer += `L${to_x},${to_y}`;
460
- }
461
- var cubicTo = function (dfuncs, draw_data, draw_state, c1_x, c1_y, c2_x, c2_y, to_x, to_y, user_data) {
462
- pathBuffer += `C${c1_x},${c1_y} ${c2_x},${c2_y} ${to_x},${to_y}`;
463
- }
464
- var quadTo = function (dfuncs, draw_data, draw_state, c_x, c_y, to_x, to_y, user_data) {
465
- pathBuffer += `Q${c_x},${c_y} ${to_x},${to_y}`;
466
- }
467
- var closePath = function (dfuncs, draw_data, draw_state, user_data) {
468
- pathBuffer += 'Z';
469
- }
470
-
471
- moveToPtr = addFunction(moveTo, 'viiiffi');
472
- lineToPtr = addFunction(lineTo, 'viiiffi');
473
- cubicToPtr = addFunction(cubicTo, 'viiiffffffi');
474
- quadToPtr = addFunction(quadTo, 'viiiffffi');
475
- closePathPtr = addFunction(closePath, 'viiii');
476
- drawFuncsPtr = exports.hb_draw_funcs_create();
477
- exports.hb_draw_funcs_set_move_to_func(drawFuncsPtr, moveToPtr, 0, 0);
478
- exports.hb_draw_funcs_set_line_to_func(drawFuncsPtr, lineToPtr, 0, 0);
479
- exports.hb_draw_funcs_set_cubic_to_func(drawFuncsPtr, cubicToPtr, 0, 0);
480
- exports.hb_draw_funcs_set_quadratic_to_func(drawFuncsPtr, quadToPtr, 0, 0);
481
- exports.hb_draw_funcs_set_close_path_func(drawFuncsPtr, closePathPtr, 0, 0);
482
- }
483
-
484
- pathBuffer = "";
485
- exports.hb_font_draw_glyph(ptr, glyphId, drawFuncsPtr, 0);
486
- return pathBuffer;
487
- }
488
-
489
- /**
490
- * Return glyph name.
491
- * @param {number} glyphId ID of the requested glyph in the font.
492
- **/
493
- function glyphName(glyphId) {
494
- var sp = stackSave();
495
- var strSize = 256;
496
- var strPtr = stackAlloc(strSize);
497
- exports.hb_font_glyph_to_string(ptr, glyphId, strPtr, strSize);
498
- var name = _utf8_ptr_to_string(strPtr);
499
- stackRestore(sp);
500
- return name;
501
- }
502
-
503
- return {
504
- ptr: ptr,
505
- /**
506
- * Create a sub font.
507
- * @returns {object} Object representing the sub font.
508
- **/
509
- subFont: function () {
510
- return createFont(null, exports.hb_font_create_sub_font(ptr));
511
- },
512
- /**
513
- * Return font horizontal extents.
514
- * @returns {object} Object with ascender, descender, and lineGap properties.
515
- **/
516
- hExtents: function () {
517
- var sp = stackSave();
518
- var extentsPtr = stackAlloc(48);
519
- exports.hb_font_get_h_extents(ptr, extentsPtr);
520
- var extents = {
521
- ascender: Module.HEAP32[extentsPtr / 4],
522
- descender: Module.HEAP32[extentsPtr / 4 + 1],
523
- lineGap: Module.HEAP32[extentsPtr / 4 + 2],
524
- };
525
- stackRestore(sp);
526
- return extents;
527
- },
528
- /**
529
- * Return font vertical extents.
530
- * @returns {object} Object with ascender, descender, and lineGap properties.
531
- **/
532
- vExtents: function () {
533
- var sp = stackSave();
534
- var extentsPtr = stackAlloc(48);
535
- exports.hb_font_get_v_extents(ptr, extentsPtr);
536
- var extents = {
537
- ascender: Module.HEAP32[extentsPtr / 4],
538
- descender: Module.HEAP32[extentsPtr / 4 + 1],
539
- lineGap: Module.HEAP32[extentsPtr / 4 + 2],
540
- };
541
- stackRestore(sp);
542
- return extents;
543
- },
544
- glyphName: glyphName,
545
- glyphToPath: glyphToPath,
546
- /**
547
- * Return glyph horizontal advance.
548
- * @param {number} glyphId ID of the requested glyph in the font.
549
- **/
550
- glyphHAdvance: function (glyphId) {
551
- return exports.hb_font_get_glyph_h_advance(ptr, glyphId);
552
- },
553
- /**
554
- * Return glyph vertical advance.
555
- * @param {number} glyphId ID of the requested glyph in the font.
556
- **/
557
- glyphVAdvance: function (glyphId) {
558
- return exports.hb_font_get_glyph_v_advance(ptr, glyphId);
559
- },
560
- /**
561
- * Return glyph horizontal origin.
562
- * @param {number} glyphId ID of the requested glyph in the font.
563
- **/
564
- glyphHOrigin: function (glyphId) {
565
- var sp = stackSave();
566
- let xPtr = stackAlloc(4);
567
- let yPtr = stackAlloc(4);
568
- let origin = null;
569
- if (exports.hb_font_get_glyph_h_origin(ptr, glyphId, xPtr, yPtr)) {
570
- origin = [Module.HEAP32[xPtr / 4], Module.HEAP32[yPtr / 4]];
571
- }
572
- stackRestore(sp);
573
- return origin;
574
- },
575
- /**
576
- * Return glyph vertical origin.
577
- * @param {number} glyphId ID of the requested glyph in the font.
578
- **/
579
- glyphVOrigin: function (glyphId) {
580
- var sp = stackSave();
581
- let xPtr = stackAlloc(4);
582
- let yPtr = stackAlloc(4);
583
- let origin = null;
584
- if (exports.hb_font_get_glyph_v_origin(ptr, glyphId, xPtr, yPtr)) {
585
- origin = [Module.HEAP32[xPtr / 4], Module.HEAP32[yPtr / 4]];
586
- }
587
- stackRestore(sp);
588
- return origin;
589
- },
590
- /**
591
- * Return glyph extents.
592
- * @param {number} glyphId ID of the requested glyph in the font.
593
- **/
594
- glyphExtents: function (glyphId) {
595
- var sp = stackSave();
596
- var extentsPtr = stackAlloc(16);
597
- var extents = null;
598
- if (exports.hb_font_get_glyph_extents(ptr, glyphId, extentsPtr)) {
599
- extents = {
600
- xBearing: Module.HEAP32[extentsPtr / 4],
601
- yBearing: Module.HEAP32[extentsPtr / 4 + 1],
602
- width: Module.HEAP32[extentsPtr / 4 + 2],
603
- height: Module.HEAP32[extentsPtr / 4 + 3]
604
- };
605
- }
606
- stackRestore(sp);
607
- return extents;
608
- },
609
- /**
610
- * Return glyph ID from name.
611
- * @param {string} name Name of the requested glyph in the font.
612
- **/
613
- glyphFromName: function (name) {
614
- var sp = stackSave();
615
- var glyphIdPtr = stackAlloc(4);
616
- var namePtr = _string_to_utf8_ptr(name);
617
- var glyphId = null;
618
- if (exports.hb_font_get_glyph_from_name(ptr, namePtr.ptr, namePtr.length, glyphIdPtr)) {
619
- glyphId = Module.HEAPU32[glyphIdPtr / 4];
620
- }
621
- namePtr.free();
622
- stackRestore(sp);
623
- return glyphId;
624
- },
625
- /**
626
- * Return a glyph as a JSON path string
627
- * based on format described on https://svgwg.org/specs/paths/#InterfaceSVGPathSegment
628
- * @param {number} glyphId ID of the requested glyph in the font.
629
- **/
630
- glyphToJson: function (glyphId) {
631
- var path = glyphToPath(glyphId);
632
- return path.replace(/([MLQCZ])/g, '|$1 ').split('|').filter(function (x) { return x.length; }).map(function (x) {
633
- var row = x.split(/[ ,]/g);
634
- return { type: row[0], values: row.slice(1).filter(function (x) { return x.length; }).map(function (x) { return +x; }) };
635
- });
636
- },
637
- /**
638
- * Set the font's scale factor, affecting the position values returned from
639
- * shaping.
640
- * @param {number} xScale Units to scale in the X dimension.
641
- * @param {number} yScale Units to scale in the Y dimension.
642
- **/
643
- setScale: function (xScale, yScale) {
644
- exports.hb_font_set_scale(ptr, xScale, yScale);
645
- },
646
- /**
647
- * Set the font's variations.
648
- * @param {object} variations Dictionary of variations to set
649
- **/
650
- setVariations: function (variations) {
651
- var entries = Object.entries(variations);
652
- var vars = exports.malloc(8 * entries.length);
653
- entries.forEach(function (entry, i) {
654
- Module.HEAPU32[vars / 4 + i * 2 + 0] = _hb_tag(entry[0]);
655
- Module.HEAPF32[vars / 4 + i * 2 + 1] = entry[1];
656
- });
657
- exports.hb_font_set_variations(ptr, vars, entries.length);
658
- exports.free(vars);
659
- },
660
- /**
661
- * Set the font's font functions.
662
- * @param {object} fontFuncs The font functions.
663
- **/
664
- setFuncs: function (fontFuncs) {
665
- exports.hb_font_set_funcs(ptr, fontFuncs.ptr);
666
- },
667
- /**
668
- * Free the object.
669
- */
670
- destroy: function () {
671
- exports.hb_font_destroy(ptr);
672
- if (drawFuncsPtr) {
673
- exports.hb_draw_funcs_destroy(drawFuncsPtr);
674
- drawFuncsPtr = null;
675
- removeFunction(moveToPtr);
676
- removeFunction(lineToPtr);
677
- removeFunction(cubicToPtr);
678
- removeFunction(quadToPtr);
679
- removeFunction(closePathPtr);
680
- }
681
- }
682
- };
683
- }
684
-
685
- /**
686
- * Create a object representing a HarfBuzz font functions.
687
- **/
688
- function createFontFuncs() {
689
- var ptr = exports.hb_font_funcs_create();
690
- return {
691
- ptr: ptr,
692
- /**
693
- * Set the font's glyph extents function.
694
- * @param {function} func The function to set.
695
- *
696
- * The function takes the following arguments:
697
- * @param {object} font The font.
698
- * @param {number} glyph The glyph ID.
699
- *
700
- * The function should return an object with the following properties, or null on failure:
701
- * @param {number} xBearing The x bearing of the glyph.
702
- * @param {number} yBearing The y bearing of the glyph.
703
- * @param {number} width The width of the glyph.
704
- * @param {number} height The height of the glyph.
705
- **/
706
- setGlyphExtentsFunc: function (func) {
707
- let funcPtr = addFunction(function (fontPtr, font_data, glyph, extentsPtr, user_data) {
708
- let font = createFont(null, fontPtr);
709
- let extents = func(font, glyph);
710
- font.destroy();
711
- if (extents) {
712
- Module.HEAP32[extentsPtr / 4] = extents.xBearing;
713
- Module.HEAP32[extentsPtr / 4 + 1] = extents.yBearing;
714
- Module.HEAP32[extentsPtr / 4 + 2] = extents.width;
715
- Module.HEAP32[extentsPtr / 4 + 3] = extents.height;
716
- return 1;
717
- }
718
- return 0;
719
- }, 'ippipp');
720
- exports.hb_font_funcs_set_glyph_extents_func(ptr, funcPtr, 0, 0);
721
- },
722
- /**
723
- * Set the font's glyph from name function.
724
- * @param {function} func The function to set.
725
- *
726
- * The function takes the following arguments:
727
- * @param {object} font The font.
728
- * @param {string} name The glyph name.
729
- *
730
- * The function should return an object with the following properties, or null on failure:
731
- * @param {number} glyph The glyph ID.
732
- **/
733
- setGlyphFromNameFunc: function (func) {
734
- let funcPtr = addFunction(function (fontPtr, font_data, namePtr, len, glyphPtr, user_data) {
735
- let font = createFont(null, fontPtr);
736
- let name = _utf8_ptr_to_string(namePtr, len);
737
- let glyph = func(font, name);
738
- font.destroy();
739
- if (glyph) {
740
- Module.HEAPU32[glyphPtr / 4] = glyph;
741
- return 1;
742
- }
743
- return 0;
744
- }, 'ipppipp');
745
- exports.hb_font_funcs_set_glyph_from_name_func(ptr, funcPtr, 0, 0);
746
- },
747
- /**
748
- * Set the font's glyph horizontal advance function.
749
- * @param {function} func The function to set.
750
- *
751
- * The function takes the following arguments:
752
- * @param {object} font The font.
753
- * @param {number} glyph The glyph ID.
754
- *
755
- * The function should return the horizontal advance of the glyph.
756
- **/
757
- setGlyphHAdvanceFunc: function (func) {
758
- let funcPtr = addFunction(function (fontPtr, font_data, glyph, user_data) {
759
- let font = createFont(null, fontPtr);
760
- let advance = func(font, glyph);
761
- font.destroy();
762
- return advance;
763
- }, 'ippip');
764
- exports.hb_font_funcs_set_glyph_h_advance_func(ptr, funcPtr, 0, 0);
765
- },
766
- /**
767
- * Set the font's glyph vertical advance function.
768
- * @param {function} func The function to set.
769
- *
770
- * The function takes the following arguments:
771
- * @param {object} font The font.
772
- * @param {number} glyph The glyph ID.
773
- *
774
- * The function should return the vertical advance of the glyph.
775
- **/
776
- setGlyphVAdvanceFunc: function (func) {
777
- let funcPtr = addFunction(function (fontPtr, font_data, glyph, user_data) {
778
- let font = createFont(null, fontPtr);
779
- let advance = func(font, glyph);
780
- font.destroy();
781
- return advance;
782
- }, 'ippip');
783
- exports.hb_font_funcs_set_glyph_v_advance_func(ptr, funcPtr, 0, 0);
784
- },
785
- /**
786
- * Set the font's glyph horizontal origin function.
787
- * @param {function} func The function to set.
788
- *
789
- * The function takes the following arguments:
790
- * @param {object} font The font.
791
- * @param {number} glyph The glyph ID.
792
- *
793
- * The function should return the x and y horizontal origin of the glyph, or null on failure.
794
- **/
795
- setGlyphHOriginFunc: function (func) {
796
- let funcPtr = addFunction(function (fontPtr, font_data, glyph, xPtr, yPtr, user_data) {
797
- let font = createFont(null, fontPtr);
798
- let origin = func(font, glyph);
799
- font.destroy();
800
- if (origin) {
801
- Module.HEAP32[xPtr / 4] = origin[0];
802
- Module.HEAP32[yPtr / 4] = origin[1];
803
- return 1;
804
- }
805
- return 0;
806
- }, 'ippippp');
807
- exports.hb_font_funcs_set_glyph_h_origin_func(ptr, funcPtr, 0, 0);
808
- },
809
- /**
810
- * Set the font's glyph vertical origin function.
811
- * @param {function} func The function to set.
812
- *
813
- * The function takes the following arguments:
814
- * @param {object} font The font.
815
- * @param {number} glyph The glyph ID.
816
- *
817
- * The function should return the x and y vertical origin of the glyph, or null on failure.
818
- **/
819
- setGlyphVOriginFunc: function (func) {
820
- let funcPtr = addFunction(function (fontPtr, font_data, glyph, xPtr, yPtr, user_data) {
821
- let font = createFont(null, fontPtr);
822
- let origin = func(font, glyph);
823
- font.destroy();
824
- if (origin) {
825
- Module.HEAP32[xPtr / 4] = origin[0];
826
- Module.HEAP32[yPtr / 4] = origin[1];
827
- return 1;
828
- }
829
- return 0;
830
- }, 'ippippp');
831
- exports.hb_font_funcs_set_glyph_v_origin_func(ptr, funcPtr, 0, 0);
832
- },
833
- /**
834
- * Set the font's glyph horizontal kerning function.
835
- * @param {function} func The function to set.
836
- *
837
- * The function takes the following arguments:
838
- * @param {object} font The font.
839
- * @param {number} firstGlyph The first glyph ID.
840
- * @param {number} secondGlyph The second glyph ID.
841
- *
842
- * The function should return the horizontal kerning of the glyphs.
843
- **/
844
- setGlyphHKerningFunc: function (func) {
845
- let funcPtr = addFunction(function (fontPtr, font_data, firstGlyph, secondGlyph, user_data) {
846
- let font = createFont(null, fontPtr);
847
- let kerning = func(font, firstGlyph, secondGlyph);
848
- font.destroy();
849
- return kerning;
850
- }, 'ippiip');
851
- exports.hb_font_funcs_set_glyph_h_kerning_func(ptr, funcPtr, 0, 0);
852
- },
853
- /**
854
- * Set the font's glyph name function.
855
- * @param {function} func The function to set.
856
- *
857
- * The function takes the following arguments:
858
- * @param {object} font The font.
859
- * @param {number} glyph The glyph ID.
860
- *
861
- * The function should return the name of the glyph, or null on failure.
862
- **/
863
- setGlyphNameFunc: function (func) {
864
- let funcPtr = addFunction(function (fontPtr, font_data, glyph, namePtr, size, user_data) {
865
- let font = createFont(null, fontPtr);
866
- let name = func(font, glyph);
867
- font.destroy();
868
- if (name) {
869
- utf8Encoder.encodeInto(name, Module.HEAPU8.subarray(namePtr, namePtr + size));
870
- return 1;
871
- }
872
- return 0;
873
- }, 'ippipip');
874
- exports.hb_font_funcs_set_glyph_name_func(ptr, funcPtr, 0, 0);
875
- },
876
- /**
877
- * Set the font's nominal glyph function.
878
- * @param {function} func The function to set.
879
- *
880
- * The function takes the following arguments:
881
- * @param {object} font The font.
882
- * @param {number} unicode The unicode.
883
- *
884
- * The function should return the nominal glyph of the unicode, or null on failure.
885
- **/
886
- setNominalGlyphFunc: function (func) {
887
- let funcPtr = addFunction(function (fontPtr, font_data, unicode, glyphPtr, user_data) {
888
- let font = createFont(null, fontPtr);
889
- let glyph = func(font, unicode);
890
- font.destroy();
891
- if (glyph) {
892
- Module.HEAPU32[glyphPtr / 4] = glyph;
893
- return 1;
894
- }
895
- return 0;
896
- }, 'ippipp');
897
- exports.hb_font_funcs_set_nominal_glyph_func(ptr, funcPtr, 0, 0);
898
- },
899
- /**
900
- * Set the font's variation glyph function.
901
- * @param {function} func The function to set.
902
- *
903
- * The function takes the following arguments:
904
- * @param {object} font The font.
905
- * @param {number} unicode The unicode.
906
- * @param {number} variationSelector The variation selector.
907
- *
908
- * The function should return the variation glyph of the unicode, or null on failure.
909
- **/
910
- setVariationGlyphFunc: function (func) {
911
- let funcPtr = addFunction(function (fontPtr, font_data, unicode, variationSelector, glyphPtr, user_data) {
912
- let font = createFont(null, fontPtr);
913
- let glyph = func(font, unicode, variationSelector);
914
- font.destroy();
915
- if (glyph) {
916
- Module.HEAPU32[glyphPtr / 4] = glyph;
917
- return 1;
918
- }
919
- return 0;
920
- }, 'ippiipp');
921
- exports.hb_font_funcs_set_variation_glyph_func(ptr, funcPtr, 0, 0);
922
- },
923
- /**
924
- * Set the font's horizontal extents function.
925
- * @param {function} func The function to set.
926
- *
927
- * The function takes the following arguments:
928
- * @param {object} font The font.
929
- *
930
- * The function should return an object with the following properties, or null on failure:
931
- * @param {number} ascender The ascender of the font.
932
- * @param {number} descender The descender of the font.
933
- * @param {number} lineGap The line gap of the font.
934
- **/
935
- setFontHExtentsFunc: function (func) {
936
- let funcPtr = addFunction(function (fontPtr, font_data, extentsPtr, user_data) {
937
- let font = createFont(null, fontPtr);
938
- let extents = func(font);
939
- font.destroy();
940
- if (extents) {
941
- Module.HEAP32[extentsPtr / 4] = extents.ascender;
942
- Module.HEAP32[extentsPtr / 4 + 1] = extents.descender;
943
- Module.HEAP32[extentsPtr / 4 + 2] = extents.lineGap;
944
- return 1;
945
- }
946
- return 0;
947
- }, 'ipppp');
948
- exports.hb_font_funcs_set_font_h_extents_func(ptr, funcPtr, 0, 0);
949
- },
950
- /**
951
- * Set the font's vertical extents function.
952
- * @param {function} func The function to set.
953
- *
954
- * The function takes the following arguments:
955
- * @param {object} font The font.
956
- *
957
- * The function should return an object with the following properties, or null on failure:
958
- * @param {number} ascender The ascender of the font.
959
- * @param {number} descender The descender of the font.
960
- * @param {number} lineGap The line gap of the font.
961
- **/
962
- setFontVExtentsFunc: function (func) {
963
- let funcPtr = addFunction(function (fontPtr, font_data, extentsPtr, user_data) {
964
- let font = createFont(null, fontPtr);
965
- let extents = func(font);
966
- font.destroy();
967
- if (extents) {
968
- Module.HEAP32[extentsPtr / 4] = extents.ascender;
969
- Module.HEAP32[extentsPtr / 4 + 1] = extents.descender;
970
- Module.HEAP32[extentsPtr / 4 + 2] = extents.lineGap;
971
- return 1;
972
- }
973
- return 0;
974
- }, 'ipppp');
975
- exports.hb_font_funcs_set_font_v_extents_func(ptr, funcPtr, 0, 0);
976
- },
977
- destroy: function () {
978
- exports.hb_font_funcs_destroy(ptr);
979
- }
980
- };
981
- }
982
-
983
- /**
984
- * Create an object representing a Harfbuzz buffer.
985
- * @param {number} ptr Optional. The pointer to the buffer.
986
- **/
987
- function createBuffer(ptr) {
988
- var ptr = ptr ? exports.hb_buffer_reference(ptr) : exports.hb_buffer_create();
989
- return {
990
- ptr: ptr,
991
- /**
992
- * Add text to the buffer.
993
- * @param {string} text Text to be added to the buffer.
994
- * @param {number} itemOffset Optional. The offset of the first character to add to the buffer.
995
- * @param {number} itemLength Optional. The number of characters to add to the buffer, or null for the end of text.
996
- **/
997
- addText: function (text, itemOffset = 0, itemLength = null) {
998
- const str = _string_to_utf16_ptr(text);
999
- if (itemLength == null) itemLength = str.length;
1000
- exports.hb_buffer_add_utf16(ptr, str.ptr, str.length, itemOffset, itemLength);
1001
- str.free();
1002
- },
1003
- /**
1004
- * Add code points to the buffer.
1005
- * @param {number[]} codePoints Array of code points to be added to the buffer.
1006
- * @param {number} itemOffset Optional. The offset of the first code point to add to the buffer.
1007
- * @param {number} itemLength Optional. The number of code points to add to the buffer, or null for the end of the array.
1008
- */
1009
- addCodePoints: function (codePoints, itemOffset = 0, itemLength = null) {
1010
- let codePointsPtr = exports.malloc(codePoints.length * 4);
1011
- let codePointsArray = Module.HEAPU32.subarray(codePointsPtr / 4, codePointsPtr / 4 + codePoints.length);
1012
- codePointsArray.set(codePoints);
1013
- if (itemLength == null) itemLength = codePoints.length;
1014
- exports.hb_buffer_add_codepoints(ptr, codePointsPtr, codePoints.length, itemOffset, itemLength);
1015
- exports.free(codePointsPtr);
1016
- },
1017
- /**
1018
- * Set buffer script, language and direction.
1019
- *
1020
- * This needs to be done before shaping.
1021
- **/
1022
- guessSegmentProperties: function () {
1023
- return exports.hb_buffer_guess_segment_properties(ptr);
1024
- },
1025
- /**
1026
- * Set buffer direction explicitly.
1027
- * @param {string} direction: One of "ltr", "rtl", "ttb" or "btt"
1028
- */
1029
- setDirection: function (dir) {
1030
- exports.hb_buffer_set_direction(ptr, {
1031
- ltr: 4,
1032
- rtl: 5,
1033
- ttb: 6,
1034
- btt: 7
1035
- }[dir] || 0);
1036
- },
1037
- /**
1038
- * Set buffer flags explicitly.
1039
- * @param {string[]} flags: A list of strings which may be either:
1040
- * "DEFAULT"
1041
- * "BOT"
1042
- * "EOT"
1043
- * "PRESERVE_DEFAULT_IGNORABLES"
1044
- * "REMOVE_DEFAULT_IGNORABLES"
1045
- * "DO_NOT_INSERT_DOTTED_CIRCLE"
1046
- * "VERIFY"
1047
- * "PRODUCE_UNSAFE_TO_CONCAT"
1048
- * "PRODUCE_SAFE_TO_INSERT_TATWEEL"
1049
- */
1050
- setFlags: function (flags) {
1051
- var flagsValue = 0
1052
- flags.forEach(s => flagsValue |= bufferFlags[s] || 0);
1053
- exports.hb_buffer_set_flags(ptr, flagsValue);
1054
- },
1055
- /**
1056
- * Set buffer language explicitly.
1057
- * @param {string} language: The buffer language
1058
- */
1059
- setLanguage: function (language) {
1060
- var str = _string_to_ascii_ptr(language);
1061
- exports.hb_buffer_set_language(ptr, exports.hb_language_from_string(str.ptr, -1));
1062
- str.free();
1063
- },
1064
- /**
1065
- * Set buffer script explicitly.
1066
- * @param {string} script: The buffer script
1067
- */
1068
- setScript: function (script) {
1069
- var str = _string_to_ascii_ptr(script);
1070
- exports.hb_buffer_set_script(ptr, exports.hb_script_from_string(str.ptr, -1));
1071
- str.free();
1072
- },
1073
- /**
1074
- * Set the Harfbuzz clustering level.
1075
- *
1076
- * Affects the cluster values returned from shaping.
1077
- * @param {number} level: Clustering level. See the Harfbuzz manual chapter
1078
- * on Clusters.
1079
- **/
1080
- setClusterLevel: function (level) {
1081
- exports.hb_buffer_set_cluster_level(ptr, level)
1082
- },
1083
- /**
1084
- * Reset the buffer to its initial status.
1085
- **/
1086
- reset: function () {
1087
- exports.hb_buffer_reset(ptr);
1088
- },
1089
- /**
1090
- * Similar to reset(), but does not clear the Unicode functions and the
1091
- * replacement code point.
1092
- **/
1093
- clearContents: function () {
1094
- exports.hb_buffer_clear_contents(ptr);
1095
- },
1096
- /**
1097
- * Set message func.
1098
- * @param {function} func The function to set.
1099
- *
1100
- * The function should accept three arguments:
1101
- * @param {object} buffer The buffer
1102
- * @param {object} font The font
1103
- * @param {string} message The message
1104
- *
1105
- * Returning false from this function will skip this shaping step and move to the next one.
1106
- */
1107
- setMessageFunc: function (func) {
1108
- var traceFunc = function (bufferPtr, fontPtr, messagePtr, user_data) {
1109
- var message = _utf8_ptr_to_string(messagePtr);
1110
- var buffer = createBuffer(bufferPtr);
1111
- var font = createFont(null, fontPtr);
1112
- var result = func(buffer, font, message);
1113
- buffer.destroy();
1114
- font.destroy();
1115
- return result ? 1 : 0;
1116
- }
1117
- var traceFuncPtr = addFunction(traceFunc, 'iiiii');
1118
- exports.hb_buffer_set_message_func(ptr, traceFuncPtr, 0, 0);
1119
- },
1120
- /**
1121
- * Get the the number of items in the buffer.
1122
- * @returns {number} The buffer length.
1123
- */
1124
- getLength: function () {
1125
- return exports.hb_buffer_get_length(ptr);
1126
- },
1127
- /**
1128
- * Get the glyph information from the buffer.
1129
- * @returns {object[]} The glyph information.
1130
- *
1131
- * The glyph information is returned as an array of objects with the
1132
- * following properties:
1133
- * @param {number} codepoint either a Unicode code point (before shaping) or a glyph index (after shaping).
1134
- * @param {number} cluster The cluster index of the glyph.
1135
- */
1136
- getGlyphInfos: function () {
1137
- var infosPtr32 = exports.hb_buffer_get_glyph_infos(ptr, 0) / 4;
1138
- // hb_glyph_info_t struct: { codepoint, mask, cluster, var1, var2 } (5 uint32s)
1139
- var infosArray = Module.HEAPU32.subarray(infosPtr32, infosPtr32 + this.getLength() * 5);
1140
- var infos = [];
1141
- for (var i = 0; i < infosArray.length; i += 5) {
1142
- infos.push({
1143
- codepoint: infosArray[i],
1144
- cluster: infosArray[i + 2],
1145
- });
1146
- }
1147
- return infos;
1148
- },
1149
- /**
1150
- * Get the glyph positions from the buffer.
1151
- * @returns {object[]} The glyph positions.
1152
- *
1153
- * The glyph positions are returned as an array of objects with the
1154
- * following properties:
1155
- * @param {number} x_advance The x advance of the glyph.
1156
- * @param {number} y_advance The y advance of the glyph.
1157
- * @param {number} x_offset The x offset of the glyph.
1158
- * @param {number} y_offset The y offset of the glyph.
1159
- *
1160
- */
1161
- getGlyphPositions: function () {
1162
- var positionsPtr32 = exports.hb_buffer_get_glyph_positions(ptr, 0) / 4;
1163
- if (positionsPtr32 == 0) {
1164
- return [];
1165
- }
1166
- // hb_glyph_position_t struct: { x_advance, y_advance, x_offset, y_offset, var } (5 int32s)
1167
- var positionsArray = Module.HEAP32.subarray(positionsPtr32, positionsPtr32 + this.getLength() * 5);
1168
- var positions = [];
1169
- for (var i = 0; i < positionsArray.length; i += 5) {
1170
- positions.push({
1171
- x_advance: positionsArray[i],
1172
- y_advance: positionsArray[i + 1],
1173
- x_offset: positionsArray[i + 2],
1174
- y_offset: positionsArray[i + 3],
1175
- });
1176
- }
1177
- return positions;
1178
- },
1179
- /**
1180
- * Get the glyph information and positions from the buffer.
1181
- * @returns {object[]} The glyph information and positions.
1182
- *
1183
- * The glyph information is returned as an array of objects with the
1184
- * properties from getGlyphInfos and getGlyphPositions combined.
1185
- */
1186
- getGlyphInfosAndPositions: function () {
1187
- var infosPtr32 = exports.hb_buffer_get_glyph_infos(ptr, 0) / 4;
1188
- var infosArray = Module.HEAPU32.subarray(infosPtr32, infosPtr32 + this.getLength() * 5);
1189
-
1190
- var positionsPtr32 = exports.hb_buffer_get_glyph_positions(ptr, 0) / 4;
1191
- var positionsArray = positionsPtr32 ? Module.HEAP32.subarray(positionsPtr32, positionsPtr32 + this.getLength() * 5) : null;
1192
-
1193
- var out = [];
1194
- for (var i = 0; i < infosArray.length; i += 5) {
1195
- var info = {
1196
- codepoint: infosArray[i],
1197
- cluster: infosArray[i + 2],
1198
- };
1199
- for (var [name, idx] of [['mask', 1], ['var1', 3], ['var2', 4]]) {
1200
- Object.defineProperty(info, name, {
1201
- value: infosArray[i + idx],
1202
- enumerable: false
1203
- });
1204
- }
1205
- if (positionsArray) {
1206
- info.x_advance = positionsArray[i];
1207
- info.y_advance = positionsArray[i + 1];
1208
- info.x_offset = positionsArray[i + 2];
1209
- info.y_offset = positionsArray[i + 3];
1210
- Object.defineProperty(info, 'var', {
1211
- value: positionsArray[i + 4],
1212
- enumerable: false
1213
- });
1214
- }
1215
- out.push(info);
1216
- }
1217
- return out;
1218
- },
1219
- /**
1220
- * Update the glyph positions in the buffer.
1221
- * @param {object[]} positions The new glyph positions.
1222
- *
1223
- * WARNING: Do not use unless you know what you are doing.
1224
- */
1225
- updateGlyphPositions: function (positions) {
1226
- var positionsPtr32 = exports.hb_buffer_get_glyph_positions(ptr, 0) / 4;
1227
- if (positionsPtr32 == 0) {
1228
- return;
1229
- }
1230
- var len = Math.min(positions.length, this.getLength());
1231
- var positionsArray = Module.HEAP32.subarray(positionsPtr32, positionsPtr32 + len * 5);
1232
- for (var i = 0; i < len; i++) {
1233
- positionsArray[i * 5] = positions[i].x_advance;
1234
- positionsArray[i * 5 + 1] = positions[i].y_advance;
1235
- positionsArray[i * 5 + 2] = positions[i].x_offset;
1236
- positionsArray[i * 5 + 3] = positions[i].y_offset;
1237
- }
1238
- },
1239
- /**
1240
- * Serialize the buffer contents to a string.
1241
- * @param {object} font Optional. The font to use for serialization.
1242
- * @param {number} start Optional. The starting index of the glyphs to serialize.
1243
- * @param {number} end Optional. The ending index of the glyphs to serialize.
1244
- * @param {string} format Optional. The format to serialize the buffer contents to.
1245
- * @param {string[]} flags Optional. The flags to use for serialization. A list of strings which may be either:
1246
- * "DEFAULT"
1247
- * "NO_CLUSTERS"
1248
- * "NO_POSITIONS"
1249
- * "NO_GLYPH_NAMES"
1250
- * "GLYPH_EXTENTS"
1251
- * "GLYPH_FLAGS"
1252
- * "NO_ADVANCES"
1253
- *
1254
- * @returns {string} The serialized buffer contents.
1255
- */
1256
- serialize: function (font, start = 0, end = null, format = "TEXT", flags = []) {
1257
- var sp = stackSave();
1258
- if (end == null) end = this.getLength();
1259
- var bufLen = 32 * 1024;
1260
- var bufPtr = exports.malloc(bufLen);
1261
- var bufConsumedPtr = stackAlloc(4);
1262
- var flagsValue = 0;
1263
- flags.forEach(flag => flagsValue |= bufferSerializeFlags[flag] || 0);
1264
- var result = "";
1265
- while (start < end) {
1266
- start += exports.hb_buffer_serialize(ptr, start, end,
1267
- bufPtr, bufLen, bufConsumedPtr,
1268
- font ? font.ptr : 0, _hb_tag(format), flagsValue);
1269
- var bufConsumed = Module.HEAPU32[bufConsumedPtr / 4];
1270
- if (bufConsumed == 0) break;
1271
- result += _utf8_ptr_to_string(bufPtr, bufConsumed);
1272
- }
1273
- exports.free(bufPtr);
1274
- stackRestore(sp);
1275
- return result;
1276
- },
1277
- /**
1278
- * Return the buffer content type.
1279
- *
1280
- * @returns {string} The buffer content type. One of:
1281
- * "INVALID"
1282
- * "UNICODE"
1283
- * "GLYPHS"
1284
- */
1285
- getContentType: function () {
1286
- return bufferContentType[exports.hb_buffer_get_content_type(ptr)];
1287
- },
1288
- /**
1289
- * Return the buffer contents as a JSON object.
1290
- *
1291
- * After shaping, this function will return an array of glyph information
1292
- * objects. Each object will have the following attributes:
1293
- *
1294
- * - g: The glyph ID
1295
- * - cl: The cluster ID
1296
- * - ax: Advance width (width to advance after this glyph is painted)
1297
- * - ay: Advance height (height to advance after this glyph is painted)
1298
- * - dx: X displacement (adjustment in X dimension when painting this glyph)
1299
- * - dy: Y displacement (adjustment in Y dimension when painting this glyph)
1300
- * - flags: Glyph flags like `HB_GLYPH_FLAG_UNSAFE_TO_BREAK` (0x1)
1301
- **/
1302
- json: function () {
1303
- var buf = this.serialize(null, 0, null, "JSON", ["NO_GLYPH_NAMES", "GLYPH_FLAGS"]);
1304
- var json = JSON.parse(buf);
1305
- // For backward compatibility, as harfbuzz uses 'fl' for flags but earlier
1306
- // we were doing the serialization ourselves and used 'flags'.
1307
- json.forEach(function (glyph) {
1308
- glyph.flags = glyph.fl || 0;
1309
- delete glyph.fl;
1310
- });
1311
- return json;
1312
- },
1313
- /**
1314
- * Free the object.
1315
- */
1316
- destroy: function () { exports.hb_buffer_destroy(ptr); }
1317
- };
1318
- }
1319
-
1320
- /**
1321
- * Shape a buffer with a given font.
1322
- *
1323
- * This returns nothing, but modifies the buffer.
1324
- *
1325
- * @param {object} font: A font returned from `createFont`
1326
- * @param {object} buffer: A buffer returned from `createBuffer` and suitably
1327
- * prepared.
1328
- * @param {object} features: A string of comma-separated OpenType features to apply.
1329
- */
1330
- function shape(font, buffer, features) {
1331
- var featuresPtr = 0;
1332
- var featuresLen = 0;
1333
- if (features) {
1334
- features = features.split(",");
1335
- featuresPtr = exports.malloc(16 * features.length);
1336
- features.forEach(function (feature, i) {
1337
- var str = _string_to_ascii_ptr(feature);
1338
- if (exports.hb_feature_from_string(str.ptr, -1, featuresPtr + featuresLen * 16))
1339
- featuresLen++;
1340
- str.free();
1341
- });
1342
- }
1343
-
1344
- exports.hb_shape(font.ptr, buffer.ptr, featuresPtr, featuresLen);
1345
- if (featuresPtr)
1346
- exports.free(featuresPtr);
1347
- }
1348
-
1349
- /**
1350
- * Shape a buffer with a given font, returning a JSON trace of the shaping process.
1351
- *
1352
- * This function supports "partial shaping", where the shaping process is
1353
- * terminated after a given lookup ID is reached. If the user requests the function
1354
- * to terminate shaping after an ID in the GSUB phase, GPOS table lookups will be
1355
- * processed as normal.
1356
- *
1357
- * @param {object} font: A font returned from `createFont`
1358
- * @param {object} buffer: A buffer returned from `createBuffer` and suitably
1359
- * prepared.
1360
- * @param {object} features: A string of comma-separated OpenType features to apply.
1361
- * @param {number} stop_at: A lookup ID at which to terminate shaping.
1362
- * @param {number} stop_phase: Either 0 (don't terminate shaping), 1 (`stop_at`
1363
- refers to a lookup ID in the GSUB table), 2 (`stop_at` refers to a lookup
1364
- ID in the GPOS table).
1365
- */
1366
- function shapeWithTrace(font, buffer, features, stop_at, stop_phase) {
1367
- var trace = [];
1368
- var currentPhase = TRACE_PHASE_DONT_STOP;
1369
- var stopping = false;
1370
- var failure = false;
1371
-
1372
- buffer.setMessageFunc((buffer, font, message) => {
1373
- if (message.startsWith("start table GSUB"))
1374
- currentPhase = TRACE_PHASE_GSUB;
1375
- else if (message.startsWith("start table GPOS"))
1376
- currentPhase = TRACE_PHASE_GPOS;
1377
-
1378
- if (currentPhase != stop_phase)
1379
- stopping = false;
1380
-
1381
- if (failure)
1382
- return true;
1383
-
1384
- if (stop_phase != TRACE_PHASE_DONT_STOP && currentPhase == stop_phase && message.startsWith("end lookup " + stop_at))
1385
- stopping = true;
1386
-
1387
- if (stopping)
1388
- return false;
1389
-
1390
- var traceBuf = buffer.serialize(font, 0, null, "JSON", ["NO_GLYPH_NAMES"]);
1391
-
1392
- trace.push({
1393
- m: message,
1394
- t: JSON.parse(traceBuf),
1395
- glyphs: buffer.getContentType() == "GLYPHS",
1396
- });
1397
-
1398
- return true;
1399
- });
1400
-
1401
- shape(font, buffer, features, 0);
1402
- return trace;
1403
- }
1404
-
1405
- function version() {
1406
- var sp = stackSave();
1407
- var versionPtr = stackAlloc(12);
1408
- exports.hb_version(versionPtr, versionPtr + 4, versionPtr + 8);
1409
- var version = {
1410
- major: Module.HEAPU32[versionPtr / 4],
1411
- minor: Module.HEAPU32[(versionPtr + 4) / 4],
1412
- micro: Module.HEAPU32[(versionPtr + 8) / 4],
1413
- };
1414
- stackRestore(sp);
1415
- return version;
1416
- }
1417
-
1418
- function version_string() {
1419
- var versionPtr = exports.hb_version_string();
1420
- return _utf8_ptr_to_string(versionPtr);
1421
- }
1422
-
1423
- /**
1424
- * Convert an OpenType script tag to HarfBuzz script.
1425
- * @param {string} tag: The tag to convert.
1426
- * @returns {string}: The script.
1427
- */
1428
- function otTagToScript(tag) {
1429
- var hbTag = _hb_tag(tag);
1430
- var script = exports.hb_ot_tag_to_script(hbTag);
1431
- return _hb_untag(script);
1432
- }
1433
-
1434
- /**
1435
- * Convert an OpenType language tag to HarfBuzz language.
1436
- * @param {string} tag: The tag to convert.
1437
- * @returns {string}: The language.
1438
- */
1439
- function otTagToLanguage(tag) {
1440
- var hbTag = _hb_tag(tag);
1441
- var language = exports.hb_ot_tag_to_language(hbTag);
1442
- return _language_to_string(language);
1443
- }
1444
-
1445
- return {
1446
- createBlob: createBlob,
1447
- createFace: createFace,
1448
- createFont: createFont,
1449
- createFontFuncs: createFontFuncs,
1450
- createBuffer: createBuffer,
1451
- shape: shape,
1452
- shapeWithTrace: shapeWithTrace,
1453
- version: version,
1454
- version_string: version_string,
1455
- otTagToScript: otTagToScript,
1456
- otTagToLanguage: otTagToLanguage,
1457
- };
1458
- }
1459
-
1460
- // Should be replaced with something more reliable
1461
- try {
1462
- module.exports = hbjs;
1463
- } catch (e) { }