Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config-override.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
#undef HB_NO_VAR_COMPOSITES
#undef HB_NO_NAME
#undef HB_NO_LAYOUT_FEATURE_PARAMS
#undef HB_NO_LAYOUT_RARELY_USED
#define HB_BUFFER_MESSAGE_MORE 1
2 changes: 2 additions & 0 deletions harfbuzz.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ _hb_ot_layout_table_get_script_tags
_hb_ot_layout_table_get_feature_tags
_hb_ot_layout_script_get_language_tags
_hb_ot_layout_language_get_feature_tags
_hb_ot_layout_feature_get_lookups
_hb_ot_layout_lookup_get_optical_bound
_hb_ot_layout_get_glyph_class
_hb_ot_layout_feature_get_name_ids
_hb_ot_name_list_names
Expand Down
37 changes: 37 additions & 0 deletions src/face.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,43 @@ export class Face {
return tags;
}

/**
* Fetches a list of all lookups enumerated for the specified feature, in
* the specified face's GSUB table or GPOS table.
* @param table The table to query, either "GSUB" or "GPOS".
* @param featureIndex The index of the requested feature.
* @returns An array of lookup indexes.
*/
getFeatureLookups(table: string, featureIndex: number): number[] {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
getFeatureLookups(table: string, featureIndex: number): number[] {
getFeatureLookups(table: "GSUB" | "GPOS", featureIndex: number): number[] {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const sp = Module.stackSave();
const tableTag = hb_tag(table);
let startOffset = 0;
let lookupCount = STATIC_ARRAY_SIZE;
const lookupCountPtr = Module.stackAlloc(4);
const lookupIndexesPtr = Module.stackAlloc(STATIC_ARRAY_SIZE * 4);
const lookups: number[] = [];
while (lookupCount == STATIC_ARRAY_SIZE) {
Module.HEAPU32[lookupCountPtr / 4] = lookupCount;
exports.hb_ot_layout_feature_get_lookups(
this.ptr,
tableTag,
featureIndex,
startOffset,
lookupCountPtr,
lookupIndexesPtr,
);
lookupCount = Module.HEAPU32[lookupCountPtr / 4];
const lookupIndexes = Module.HEAPU32.subarray(
lookupIndexesPtr / 4,
lookupIndexesPtr / 4 + lookupCount,
);
lookups.push(...Array.from(lookupIndexes as Uint32Array));
startOffset += lookupCount;
}
Module.stackRestore(sp);
return lookups;
}

/**
* Get the GDEF class of the requested glyph.
* @param glyph The glyph to get the class of.
Expand Down
22 changes: 22 additions & 0 deletions src/font.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
string_to_utf8_ptr,
} from "./helpers";
import type { FontExtents, GlyphExtents, SvgPathCommand } from "./types";
import type { Direction } from "./buffer";
import type { Face } from "./face";
import type { FontFuncs } from "./font-funcs";
import type { Variation } from "./variation";
Expand Down Expand Up @@ -453,4 +454,25 @@ export class Font {
setFuncs(fontFuncs: FontFuncs): void {
exports.hb_font_set_funcs(this.ptr, fontFuncs.ptr);
}

/**
* Fetches the optical bound of a glyph positioned at the margin of text.
* The direction identifies which edge of the glyph to query.
* @param lookupIndex Index of the feature lookup to query.
* @param direction Edge of the glyph to query.
* @param glyph A glyph id.
* @returns Adjustment value. Negative values mean the glyph will stick out of the margin.
*/
getLookupOpticalBound(
lookupIndex: number,
direction: Direction,
glyph: number,
): number {
return exports.hb_ot_layout_lookup_get_optical_bound(
this.ptr,
lookupIndex,
direction,
glyph,
);
}
}
29 changes: 29 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,18 @@ describe("Face", function () {
});
});

it("getFeatureLookups returns the lookups for a feature", function () {
let blob = new hb.Blob(
fs.readFileSync(path.join(__dirname, "fonts/noto/NotoSans-Regular.ttf")),
);
let face = new hb.Face(blob);
const ligaIndex = face.getTableFeatureTags("GSUB").indexOf("liga");
expect(face.getFeatureLookups("GSUB", ligaIndex)).to.deep.equal([39]);
const kernIndex = face.getTableFeatureTags("GPOS").indexOf("kern");
expect(face.getFeatureLookups("GPOS", kernIndex)).to.deep.equal([0, 2]);
expect(face.getFeatureLookups("GSUB", 9999)).to.deep.equal([]);
});

it("getGlyphClass returns the class of a glyph", function () {
let blob = new hb.Blob(
fs.readFileSync(path.join(__dirname, "fonts/noto/NotoSans-Regular.ttf")),
Expand Down Expand Up @@ -508,6 +520,23 @@ describe("Font", function () {
expect(font.glyph(0x10ffff)).to.equal(font.nominalGlyph(0x10ffff));
});

it("getLookupOpticalBound returns some value", function () {
let blob = new hb.Blob(
fs.readFileSync(path.join(__dirname, "fonts/noto/NotoSans-Regular.ttf")),
);
let face = new hb.Face(blob);
let font = new hb.Font(face);
const kernIndex = face.getTableFeatureTags("GPOS").indexOf("kern");
const [lookupIndex] = face.getFeatureLookups("GPOS", kernIndex);
const glyph = font.glyphFromName("A");
const opticalBound = font.getLookupOpticalBound(
lookupIndex,
hb.Direction.LTR,
glyph,
);
expect(opticalBound).to.be.a("number");
});

it("setVariations affects advances", function () {
let blob = new hb.Blob(
fs.readFileSync(
Expand Down