Skip to content

Commit eb93054

Browse files
committed
Add face.getGlyphInfosAndPositions()
Fixes #169
1 parent ad0ace2 commit eb93054

File tree

2 files changed

+67
-4
lines changed

2 files changed

+67
-4
lines changed

hbjs.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,46 @@ function hbjs(Module) {
11891189
return positions;
11901190
},
11911191
/**
1192+
* Get the glyph information and positions from the buffer.
1193+
* @returns {object[]} The glyph information and positions.
1194+
*
1195+
* The glyph information is returned as an array of objects with the
1196+
* properties from getGlyphInfos and getGlyphPositions combined.
1197+
*/
1198+
getGlyphInfosAndPositions: function () {
1199+
var infosPtr32 = exports.hb_buffer_get_glyph_infos(ptr, 0) / 4;
1200+
var infosArray = Module.HEAPU32.subarray(infosPtr32, infosPtr32 + this.getLength() * 5);
1201+
1202+
var positionsPtr32 = exports.hb_buffer_get_glyph_positions(ptr, 0) / 4;
1203+
var positionsArray = positionsPtr32 ? Module.HEAP32.subarray(positionsPtr32, positionsPtr32 + this.getLength() * 5) : null;
1204+
1205+
var out = [];
1206+
for (var i = 0; i < infosArray.length; i += 5) {
1207+
var info = {
1208+
codepoint: infosArray[i],
1209+
cluster: infosArray[i + 2],
1210+
};
1211+
for (var [name, idx] of [['mask', 1], ['var1', 3], ['var2', 4]]) {
1212+
Object.defineProperty(info, name, {
1213+
value: infosArray[i + idx],
1214+
enumerable: false
1215+
});
1216+
}
1217+
if (positionsArray) {
1218+
info.x_advance = positionsArray[i];
1219+
info.y_advance = positionsArray[i + 1];
1220+
info.x_offset = positionsArray[i + 2];
1221+
info.y_offset = positionsArray[i + 3];
1222+
Object.defineProperty(info, 'var', {
1223+
value: positionsArray[i + 4],
1224+
enumerable: false
1225+
});
1226+
}
1227+
out.push(info);
1228+
}
1229+
return out;
1230+
},
1231+
/**
11921232
* Update the glyph positions in the buffer.
11931233
* @param {object[]} positions The new glyph positions.
11941234
*

test/index.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,7 @@ describe('Buffer', function () {
659659
buffer = hb.createBuffer();
660660
expect(buffer.getGlyphInfos()).to.deep.equal([]);
661661
expect(buffer.getGlyphPositions()).to.deep.equal([]);
662+
expect(buffer.getGlyphInfosAndPositions()).to.deep.equal([]);
662663
});
663664

664665
it('getInfos and getPositions return non empty arrays for non empty buffer', function () {
@@ -670,31 +671,46 @@ describe('Buffer', function () {
670671
buffer.guessSegmentProperties();
671672

672673
// before shaping
673-
expect(buffer.getGlyphInfos()).to.deep.equal([
674+
let infos = buffer.getGlyphInfos();
675+
let positions = buffer.getGlyphPositions();
676+
let infosAndPositions = buffer.getGlyphInfosAndPositions();
677+
678+
expect(infos).to.deep.equal([
674679
{ codepoint: 120, cluster: 0 },
675680
{ codepoint: 768, cluster: 1 },
676681
{ codepoint: 102, cluster: 2 },
677682
{ codepoint: 105, cluster: 3 }
678683
]);
679-
expect(buffer.getGlyphPositions()).to.deep.equal([
684+
expect(positions).to.deep.equal([
680685
{ x_advance: 0, y_advance: 0, x_offset: 0, y_offset: 0 },
681686
{ x_advance: 0, y_advance: 0, x_offset: 0, y_offset: 0 },
682687
{ x_advance: 0, y_advance: 0, x_offset: 0, y_offset: 0 },
683688
{ x_advance: 0, y_advance: 0, x_offset: 0, y_offset: 0 }
684689
]);
685690

691+
for (let i = 0; i < infosAndPositions.length; i++) {
692+
expect(infosAndPositions[i]).to.deep.equal({ ...infos[i], ...positions[i] });
693+
}
694+
686695
hb.shape(font, buffer);
687696
// after shaping
688-
expect(buffer.getGlyphInfos()).to.deep.equal([
697+
infos = buffer.getGlyphInfos();
698+
positions = buffer.getGlyphPositions();
699+
infosAndPositions = buffer.getGlyphInfosAndPositions();
700+
701+
expect(infos).to.deep.equal([
689702
{ codepoint: 91, cluster: 0 },
690703
{ codepoint: 2662, cluster: 0 },
691704
{ codepoint: 1652, cluster: 2 }
692705
]);
693-
expect(buffer.getGlyphPositions()).to.deep.equal([
706+
expect(positions).to.deep.equal([
694707
{ x_advance: 529, y_advance: 0, x_offset: 0, y_offset: 0 },
695708
{ x_advance: 0, y_advance: 0, x_offset: 97, y_offset: 0 },
696709
{ x_advance: 602, y_advance: 0, x_offset: 0, y_offset: 0 }
697710
]);
711+
for (let i = 0; i < infosAndPositions.length; i++) {
712+
expect(infosAndPositions[i]).to.deep.equal({ ...infos[i], ...positions[i] });
713+
}
698714
});
699715

700716
it('glyph infos and positions have private properties', function () {
@@ -707,15 +723,22 @@ describe('Buffer', function () {
707723
hb.shape(font, buffer);
708724
const infos = buffer.getGlyphInfos();
709725
const positions = buffer.getGlyphPositions();
726+
const infosAndPositions = buffer.getGlyphInfosAndPositions();
710727

711728
expect(infos.length).to.equal(1);
712729
expect(positions.length).to.equal(1);
730+
expect(infosAndPositions.length).to.equal(1);
713731
expect(Object.keys(infos[0])).to.deep.equal(['codepoint', 'cluster']);
714732
expect(Object.keys(positions[0])).to.deep.equal(['x_advance', 'y_advance', 'x_offset', 'y_offset']);
733+
expect(Object.keys(infosAndPositions[0])).to.deep.equal(['codepoint', 'cluster', 'x_advance', 'y_advance', 'x_offset', 'y_offset']);
715734
expect(infos[0].mask).to.not.be.undefined;
716735
expect(infos[0].var1).to.not.be.undefined;
717736
expect(infos[0].var2).to.not.be.undefined;
718737
expect(positions[0].var).to.not.be.undefined;
738+
expect(infosAndPositions[0].mask).to.equal(infos[0].mask);
739+
expect(infosAndPositions[0].var1).to.equal(infos[0].var1);
740+
expect(infosAndPositions[0].var2).to.equal(infos[0].var2);
741+
expect(infosAndPositions[0].var).to.equal(positions[0].var);
719742
});
720743

721744
it('getPositions returns empty array for buffer without positions', function () {

0 commit comments

Comments
 (0)