Skip to content

Commit a4df29e

Browse files
committed
Bind hb_ot_layout_feature_get_lookups()
1 parent f9f1f63 commit a4df29e

3 files changed

Lines changed: 50 additions & 0 deletions

File tree

harfbuzz.symbols

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ _hb_ot_layout_table_get_script_tags
7878
_hb_ot_layout_table_get_feature_tags
7979
_hb_ot_layout_script_get_language_tags
8080
_hb_ot_layout_language_get_feature_tags
81+
_hb_ot_layout_feature_get_lookups
8182
_hb_ot_layout_get_glyph_class
8283
_hb_ot_layout_feature_get_name_ids
8384
_hb_ot_name_list_names

src/face.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,43 @@ export class Face {
244244
return tags;
245245
}
246246

247+
/**
248+
* Fetches a list of all lookups enumerated for the specified feature, in
249+
* the specified face's GSUB table or GPOS table.
250+
* @param table The table to query, either "GSUB" or "GPOS".
251+
* @param featureIndex The index of the requested feature.
252+
* @returns An array of lookup indexes.
253+
*/
254+
getFeatureLookups(table: string, featureIndex: number): number[] {
255+
const sp = Module.stackSave();
256+
const tableTag = hb_tag(table);
257+
let startOffset = 0;
258+
let lookupCount = STATIC_ARRAY_SIZE;
259+
const lookupCountPtr = Module.stackAlloc(4);
260+
const lookupIndexesPtr = Module.stackAlloc(STATIC_ARRAY_SIZE * 4);
261+
const lookups: number[] = [];
262+
while (lookupCount == STATIC_ARRAY_SIZE) {
263+
Module.HEAPU32[lookupCountPtr / 4] = lookupCount;
264+
exports.hb_ot_layout_feature_get_lookups(
265+
this.ptr,
266+
tableTag,
267+
featureIndex,
268+
startOffset,
269+
lookupCountPtr,
270+
lookupIndexesPtr,
271+
);
272+
lookupCount = Module.HEAPU32[lookupCountPtr / 4];
273+
const lookupIndexes = Module.HEAPU32.subarray(
274+
lookupIndexesPtr / 4,
275+
lookupIndexesPtr / 4 + lookupCount,
276+
);
277+
lookups.push(...Array.from(lookupIndexes as Uint32Array));
278+
startOffset += lookupCount;
279+
}
280+
Module.stackRestore(sp);
281+
return lookups;
282+
}
283+
247284
/**
248285
* Get the GDEF class of the requested glyph.
249286
* @param glyph The glyph to get the class of.

test/index.test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,18 @@ describe("Face", function () {
246246
});
247247
});
248248

249+
it("getFeatureLookups returns the lookups for a feature", function () {
250+
let blob = new hb.Blob(
251+
fs.readFileSync(path.join(__dirname, "fonts/noto/NotoSans-Regular.ttf")),
252+
);
253+
let face = new hb.Face(blob);
254+
const ligaIndex = face.getTableFeatureTags("GSUB").indexOf("liga");
255+
expect(face.getFeatureLookups("GSUB", ligaIndex)).to.deep.equal([39]);
256+
const kernIndex = face.getTableFeatureTags("GPOS").indexOf("kern");
257+
expect(face.getFeatureLookups("GPOS", kernIndex)).to.deep.equal([0, 2]);
258+
expect(face.getFeatureLookups("GSUB", 9999)).to.deep.equal([]);
259+
});
260+
249261
it("getGlyphClass returns the class of a glyph", function () {
250262
let blob = new hb.Blob(
251263
fs.readFileSync(path.join(__dirname, "fonts/noto/NotoSans-Regular.ttf")),

0 commit comments

Comments
 (0)