diff --git a/hbjs.js b/hbjs.js index cd52586..21f6e90 100644 --- a/hbjs.js +++ b/hbjs.js @@ -1139,17 +1139,10 @@ function hbjs(Module) { var infosArray = Module.HEAPU32.subarray(infosPtr32, infosPtr32 + this.getLength() * 5); var infos = []; for (var i = 0; i < infosArray.length; i += 5) { - var info = { + infos.push({ codepoint: infosArray[i], cluster: infosArray[i + 2], - }; - for (var [name, idx] of [['mask', 1], ['var1', 3], ['var2', 4]]) { - Object.defineProperty(info, name, { - value: infosArray[i + idx], - enumerable: false - }); - } - infos.push(info); + }); } return infos; }, @@ -1174,21 +1167,56 @@ function hbjs(Module) { var positionsArray = Module.HEAP32.subarray(positionsPtr32, positionsPtr32 + this.getLength() * 5); var positions = []; for (var i = 0; i < positionsArray.length; i += 5) { - var position = { + positions.push({ x_advance: positionsArray[i], y_advance: positionsArray[i + 1], x_offset: positionsArray[i + 2], y_offset: positionsArray[i + 3], - }; - Object.defineProperty(position, 'var', { - value: positionsArray[i + 4], - enumerable: false }); - positions.push(position); } return positions; }, /** + * Get the glyph information and positions from the buffer. + * @returns {object[]} The glyph information and positions. + * + * The glyph information is returned as an array of objects with the + * properties from getGlyphInfos and getGlyphPositions combined. + */ + getGlyphInfosAndPositions: function () { + var infosPtr32 = exports.hb_buffer_get_glyph_infos(ptr, 0) / 4; + var infosArray = Module.HEAPU32.subarray(infosPtr32, infosPtr32 + this.getLength() * 5); + + var positionsPtr32 = exports.hb_buffer_get_glyph_positions(ptr, 0) / 4; + var positionsArray = positionsPtr32 ? Module.HEAP32.subarray(positionsPtr32, positionsPtr32 + this.getLength() * 5) : null; + + var out = []; + for (var i = 0; i < infosArray.length; i += 5) { + var info = { + codepoint: infosArray[i], + cluster: infosArray[i + 2], + }; + for (var [name, idx] of [['mask', 1], ['var1', 3], ['var2', 4]]) { + Object.defineProperty(info, name, { + value: infosArray[i + idx], + enumerable: false + }); + } + if (positionsArray) { + info.x_advance = positionsArray[i]; + info.y_advance = positionsArray[i + 1]; + info.x_offset = positionsArray[i + 2]; + info.y_offset = positionsArray[i + 3]; + Object.defineProperty(info, 'var', { + value: positionsArray[i + 4], + enumerable: false + }); + } + out.push(info); + } + return out; + }, + /** * Update the glyph positions in the buffer. * @param {object[]} positions The new glyph positions. * diff --git a/test/index.js b/test/index.js index 1d27221..2c7699c 100644 --- a/test/index.js +++ b/test/index.js @@ -659,6 +659,7 @@ describe('Buffer', function () { buffer = hb.createBuffer(); expect(buffer.getGlyphInfos()).to.deep.equal([]); expect(buffer.getGlyphPositions()).to.deep.equal([]); + expect(buffer.getGlyphInfosAndPositions()).to.deep.equal([]); }); it('getInfos and getPositions return non empty arrays for non empty buffer', function () { @@ -670,31 +671,46 @@ describe('Buffer', function () { buffer.guessSegmentProperties(); // before shaping - expect(buffer.getGlyphInfos()).to.deep.equal([ + let infos = buffer.getGlyphInfos(); + let positions = buffer.getGlyphPositions(); + let infosAndPositions = buffer.getGlyphInfosAndPositions(); + + expect(infos).to.deep.equal([ { codepoint: 120, cluster: 0 }, { codepoint: 768, cluster: 1 }, { codepoint: 102, cluster: 2 }, { codepoint: 105, cluster: 3 } ]); - expect(buffer.getGlyphPositions()).to.deep.equal([ + expect(positions).to.deep.equal([ { x_advance: 0, y_advance: 0, x_offset: 0, y_offset: 0 }, { x_advance: 0, y_advance: 0, x_offset: 0, y_offset: 0 }, { x_advance: 0, y_advance: 0, x_offset: 0, y_offset: 0 }, { x_advance: 0, y_advance: 0, x_offset: 0, y_offset: 0 } ]); + for (let i = 0; i < infosAndPositions.length; i++) { + expect(infosAndPositions[i]).to.deep.equal({ ...infos[i], ...positions[i] }); + } + hb.shape(font, buffer); // after shaping - expect(buffer.getGlyphInfos()).to.deep.equal([ + infos = buffer.getGlyphInfos(); + positions = buffer.getGlyphPositions(); + infosAndPositions = buffer.getGlyphInfosAndPositions(); + + expect(infos).to.deep.equal([ { codepoint: 91, cluster: 0 }, { codepoint: 2662, cluster: 0 }, { codepoint: 1652, cluster: 2 } ]); - expect(buffer.getGlyphPositions()).to.deep.equal([ + expect(positions).to.deep.equal([ { x_advance: 529, y_advance: 0, x_offset: 0, y_offset: 0 }, { x_advance: 0, y_advance: 0, x_offset: 97, y_offset: 0 }, { x_advance: 602, y_advance: 0, x_offset: 0, y_offset: 0 } ]); + for (let i = 0; i < infosAndPositions.length; i++) { + expect(infosAndPositions[i]).to.deep.equal({ ...infos[i], ...positions[i] }); + } }); it('glyph infos and positions have private properties', function () { @@ -705,17 +721,14 @@ describe('Buffer', function () { buffer.addText('fi'); buffer.guessSegmentProperties(); hb.shape(font, buffer); - const infos = buffer.getGlyphInfos(); - const positions = buffer.getGlyphPositions(); - - expect(infos.length).to.equal(1); - expect(positions.length).to.equal(1); - expect(Object.keys(infos[0])).to.deep.equal(['codepoint', 'cluster']); - expect(Object.keys(positions[0])).to.deep.equal(['x_advance', 'y_advance', 'x_offset', 'y_offset']); - expect(infos[0].mask).to.not.be.undefined; - expect(infos[0].var1).to.not.be.undefined; - expect(infos[0].var2).to.not.be.undefined; - expect(positions[0].var).to.not.be.undefined; + const infosAndPositions = buffer.getGlyphInfosAndPositions(); + + expect(infosAndPositions.length).to.equal(1); + expect(Object.keys(infosAndPositions[0])).to.deep.equal(['codepoint', 'cluster', 'x_advance', 'y_advance', 'x_offset', 'y_offset']); + expect(infosAndPositions[0].mask).to.not.be.undefined; + expect(infosAndPositions[0].var1).to.not.be.undefined; + expect(infosAndPositions[0].var2).to.not.be.undefined; + expect(infosAndPositions[0].var).to.not.be.undefined; }); it('getPositions returns empty array for buffer without positions', function () {