From a2414ca4cb5548d70c0d69f7756061fcebb7a00d Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Fri, 8 May 2026 15:02:28 +0300 Subject: [PATCH] Bind hb_font_get_glyph() and friends Bind hb_font_get_glyph(), hb_font_get_nominal_glyph(), and hb_font_get_variation_glyph(). --- harfbuzz.symbols | 3 ++ src/font.ts | 82 ++++++++++++++++++++++++++++++++++++++++++++++ test/index.test.js | 17 ++++++++++ 3 files changed, 102 insertions(+) diff --git a/harfbuzz.symbols b/harfbuzz.symbols index 93638ef..605a969 100644 --- a/harfbuzz.symbols +++ b/harfbuzz.symbols @@ -38,7 +38,10 @@ _hb_font_set_variations _hb_font_get_h_extents _hb_font_get_v_extents _hb_font_get_glyph_extents +_hb_font_get_glyph _hb_font_get_glyph_from_name +_hb_font_get_nominal_glyph +_hb_font_get_variation_glyph _hb_font_get_glyph_h_advance _hb_font_get_glyph_v_advance _hb_font_get_glyph_h_origin diff --git a/src/font.ts b/src/font.ts index 08427d5..3e83cdd 100644 --- a/src/font.ts +++ b/src/font.ts @@ -295,6 +295,88 @@ export class Font { return extents; } + /** + * Fetches the glyph ID for a Unicode code point in the specified + * font, with an optional variation selector. + * + * If `variationSelector` is 0, it is equivalent to + * {@link Font.nominalGlyph}; otherwise it is equivalent to + * {@link Font.variationGlyph}. + * + * @param unicode The Unicode code point to query. + * @param variationSelector A variation-selector code point. + * @returns The glyph ID, or undefined if not found. + */ + glyph(unicode: number, variationSelector: number = 0): number | undefined { + const sp = Module.stackSave(); + const glyphIdPtr = Module.stackAlloc(4); + let glyphId: number | undefined; + if ( + exports.hb_font_get_glyph( + this.ptr, + unicode, + variationSelector, + glyphIdPtr, + ) + ) { + glyphId = Module.HEAPU32[glyphIdPtr / 4]; + } + Module.stackRestore(sp); + return glyphId; + } + + /** + * Fetches the nominal glyph ID for a Unicode code point in the + * specified font. + * + * This version of the function should not be used to fetch glyph IDs + * for code points modified by variation selectors. For variation-selector + * support, use {@link Font.variationGlyph} or {@link Font.glyph}. + * + * @param unicode The Unicode code point to query. + * @returns The glyph ID, or undefined if not found. + */ + nominalGlyph(unicode: number): number | undefined { + const sp = Module.stackSave(); + const glyphIdPtr = Module.stackAlloc(4); + let glyphId: number | undefined; + if (exports.hb_font_get_nominal_glyph(this.ptr, unicode, glyphIdPtr)) { + glyphId = Module.HEAPU32[glyphIdPtr / 4]; + } + Module.stackRestore(sp); + return glyphId; + } + + /** + * Fetches the glyph ID for a Unicode code point when followed by + * by the specified variation-selector code point, in the specified + * font. + * + * @param unicode The Unicode code point to query. + * @param variationSelector The variation-selector code point to query. + * @returns The glyph ID, or undefined if not found. + */ + variationGlyph( + unicode: number, + variationSelector: number, + ): number | undefined { + const sp = Module.stackSave(); + const glyphIdPtr = Module.stackAlloc(4); + let glyphId: number | undefined; + if ( + exports.hb_font_get_variation_glyph( + this.ptr, + unicode, + variationSelector, + glyphIdPtr, + ) + ) { + glyphId = Module.HEAPU32[glyphIdPtr / 4]; + } + Module.stackRestore(sp); + return glyphId; + } + /** * Return glyph ID from name. * @param name Name of the requested glyph in the font. diff --git a/test/index.test.js b/test/index.test.js index ef2a763..ce86ae2 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -491,6 +491,23 @@ describe("Font", function () { expect(font.glyphFromName("NonExistentGlyph")).to.equal(undefined); }); + it("glyph/nominalGlyph/variationGlyph return ids for code points", 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 codepoint = "A".codePointAt(0); + expect(font.nominalGlyph(codepoint)).to.equal(36); + expect(font.nominalGlyph(0x10ffff)).to.equal(undefined); + expect(font.variationGlyph(codepoint, 0xfe00)).to.equal(undefined); + expect(font.glyph(codepoint)).to.equal(font.nominalGlyph(codepoint)); + expect(font.glyph(codepoint, 0xfe00)).to.equal( + font.variationGlyph(codepoint, 0xfe00), + ); + expect(font.glyph(0x10ffff)).to.equal(font.nominalGlyph(0x10ffff)); + }); + it("setVariations affects advances", function () { let blob = new hb.Blob( fs.readFileSync(