Skip to content

Commit aac7eb2

Browse files
committed
Add support for pinning variation axes
1 parent 9fb043c commit aac7eb2

File tree

3 files changed

+114
-1
lines changed

3 files changed

+114
-1
lines changed

index.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,20 @@ const loadAndInitializeHarfbuzz = _.once(async () => {
1414
return [exports, heapu8];
1515
});
1616

17+
function HB_TAG(str) {
18+
return str.split('').reduce(function (a, ch) {
19+
return (a << 8) + ch.charCodeAt(0);
20+
}, 0);
21+
}
22+
1723
async function subsetFont(
1824
originalFont,
1925
text,
20-
{ targetFormat = fontverter.detectFormat(originalFont), preserveNameIds } = {}
26+
{
27+
targetFormat = fontverter.detectFormat(originalFont),
28+
preserveNameIds,
29+
variationAxes,
30+
} = {}
2131
) {
2232
if (typeof text !== 'string') {
2333
throw new Error('The subset text must be given as a string');
@@ -72,6 +82,17 @@ async function subsetFont(
7282
exports.hb_set_add(inputUnicodes, c.codePointAt(0));
7383
}
7484

85+
if (variationAxes) {
86+
for (const [axisName, value] of Object.entries(variationAxes)) {
87+
exports.hb_subset_input_pin_axis_location(
88+
input,
89+
face,
90+
HB_TAG(axisName),
91+
value
92+
);
93+
}
94+
}
95+
7596
let subset;
7697
try {
7798
subset = exports.hb_subset_or_fail(face, input);

test/index.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,4 +320,96 @@ describe('subset-font', function () {
320320
});
321321
});
322322
});
323+
324+
describe('with a variable font', function () {
325+
beforeEach(async function () {
326+
this.variableRobotoFont = await readFile(
327+
pathModule.resolve(
328+
__dirname,
329+
'..',
330+
'testdata',
331+
'RobotoFlex-VariableFont_GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght.ttf'
332+
)
333+
);
334+
});
335+
336+
describe('when not instancing the font using axis pinning', function () {
337+
it('should include the original variation axes', async function () {
338+
const result = await subsetFont(this.variableRobotoFont, 'abcd');
339+
340+
expect(fontkit.create(result).variationAxes, 'to satisfy', {
341+
wght: { name: 'wght', min: 100, default: 400, max: 1000 },
342+
wdth: { name: 'wdth', min: 25, default: 100, max: 151 },
343+
opsz: { name: 'opsz', min: 8, default: 14, max: 144 },
344+
GRAD: { name: 'GRAD', min: -200, default: 0, max: 150 },
345+
slnt: { name: 'slnt', min: -10, default: 0, max: 0 },
346+
XTRA: { name: 'XTRA', min: 323, default: 468, max: 603 },
347+
XOPQ: { name: 'XOPQ', min: 27, default: 96, max: 175 },
348+
YOPQ: { name: 'YOPQ', min: 25, default: 79, max: 135 },
349+
YTLC: { name: 'YTLC', min: 416, default: 514, max: 570 },
350+
YTUC: { name: 'YTUC', min: 528, default: 712, max: 760 },
351+
YTAS: { name: 'YTAS', min: 649, default: 750, max: 854 },
352+
YTDE: { name: 'YTDE', min: -305, default: -203, max: -98 },
353+
YTFI: { name: 'YTFI', min: 560, default: 738, max: 788 },
354+
});
355+
});
356+
});
357+
358+
describe('when instancing the font using axis pinning', function () {
359+
describe('when pinning all the axes', function () {
360+
it('should remove the variation axes from the font', async function () {
361+
const result = await subsetFont(this.variableRobotoFont, 'abcd', {
362+
variationAxes: {
363+
wght: 200,
364+
wdth: 120,
365+
opsz: 80,
366+
GRAD: -20,
367+
slnt: -8,
368+
XTRA: 502,
369+
XOPQ: 101,
370+
YOPQ: 79,
371+
YTLC: 420,
372+
YTUC: 600,
373+
YTAS: 810,
374+
YTDE: -90,
375+
YTFI: 660,
376+
},
377+
});
378+
379+
expect(fontkit.create(result).variationAxes, 'to equal', {});
380+
381+
// When not instancing the subset font is about 29 KB
382+
expect(result.length, 'to be less than', 4096);
383+
});
384+
});
385+
});
386+
387+
describe('when pinning only some of the axes', function () {
388+
it('should remove the pinned variation axes from the font', async function () {
389+
const result = await subsetFont(this.variableRobotoFont, 'abcd', {
390+
variationAxes: {
391+
wght: 200,
392+
wdth: 120,
393+
opsz: 80,
394+
XTRA: 502,
395+
XOPQ: 101,
396+
YOPQ: 79,
397+
YTLC: 420,
398+
YTUC: 600,
399+
YTAS: 810,
400+
YTDE: -90,
401+
YTFI: 660,
402+
},
403+
});
404+
405+
expect(fontkit.create(result).variationAxes, 'to equal', {
406+
GRAD: { name: 'GRAD', min: -200, default: 0, max: 150 },
407+
slnt: { name: 'slnt', min: -10, default: 0, max: 0 },
408+
});
409+
410+
// When not instancing the subset font is about 29 KB
411+
expect(result.length, 'to be less than', 25000);
412+
});
413+
});
414+
});
323415
});
Binary file not shown.

0 commit comments

Comments
 (0)