Skip to content

Commit

Permalink
feat: add ability to retrieve only the ligature ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
princjef committed May 3, 2018
1 parent 8b5b89c commit f120430
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 17 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ following keys:
be rendered together to produce the ligatures in the output sequence. The
ranges are inclusive on the left and exclusive on the right

#### `findLigatureRanges(text)`

Scans the provided text for font ligatures, returning an array of ranges where
ligatures are located.

**Params**

* `text` [*string*] - text to search for ligatures
Expand Down
16 changes: 8 additions & 8 deletions bench/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,49 +19,49 @@ setup(async () => {

test('Fira Code: code.txt', (context, iteration) => {
const line = code[iteration % code.length];
context.fira.findLigatures(line);
context.fira.findLigatureRanges(line);
return line.length;
});

test('Fira Code: noLigatures.txt', (context, iteration) => {
const line = noLigatures[iteration % noLigatures.length];
context.fira.findLigatures(line);
context.fira.findLigatureRanges(line);
return line.length;
});

test('Iosevka: code.txt', (context, iteration) => {
const line = code[iteration % code.length];
context.iosevka.findLigatures(line);
context.iosevka.findLigatureRanges(line);
return line.length;
});

test('Iosevka: noLigatures.txt', (context, iteration) => {
const line = noLigatures[iteration % noLigatures.length];
context.iosevka.findLigatures(line);
context.iosevka.findLigatureRanges(line);
return line.length;
});

test('Monoid: code.txt', (context, iteration) => {
const line = code[iteration % code.length];
context.monoid.findLigatures(line);
context.monoid.findLigatureRanges(line);
return line.length;
});

test('Monoid: noLigatures.txt', (context, iteration) => {
const line = noLigatures[iteration % noLigatures.length];
context.monoid.findLigatures(line);
context.monoid.findLigatureRanges(line);
return line.length;
});

test('Ubuntu Mono: code.txt', (context, iteration) => {
const line = code[iteration % code.length];
context.ubuntu.findLigatures(line);
context.ubuntu.findLigatureRanges(line);
return line.length;
});

test('Ubuntu Mono: noLigatures.txt', (context, iteration) => {
const line = noLigatures[iteration % noLigatures.length];
context.ubuntu.findLigatures(line);
context.ubuntu.findLigatureRanges(line);
return line.length;
});

Expand Down
8 changes: 7 additions & 1 deletion src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,16 @@ for (const { font, input, glyphs, ranges } of [
...monoidCases,
...otherCases
]) {
test(`${font}: '${input}'`, async t => {
test(`findLigatures() > ${font}: '${input}'`, async t => {
const inst = await load(font);
const result = inst.findLigatures(input);
t.deepEqual(result.outputGlyphs, glyphs);
t.deepEqual(result.contextRanges, ranges);
});

test(`findLigatureRanges() > ${font}: '${input}'`, async t => {
const inst = await load(font);
const result = inst.findLigatureRanges(input);
t.deepEqual(result, ranges);
});
}
42 changes: 34 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,37 +44,63 @@ class FontImpl implements Font {
};
}

let result: number[] = glyphIds.slice();
const result = this._findInternal(glyphIds.slice());

return {
inputGlyphs: glyphIds,
outputGlyphs: result.sequence,
contextRanges: result.ranges
};
}

findLigatureRanges(text: string): [number, number][] {
// Short circuit the process if there are no possible ligatures in the
// font
if (this._lookupGroups.length === 0) {
return [];
}

const glyphIds: number[] = [];
for (const char of text) {
glyphIds.push(this._font.charToGlyphIndex(char));
}

const result = this._findInternal(glyphIds);

return result.ranges;
}

private _findInternal(sequence: number[]): { sequence: number[]; ranges: [number, number][]; } {
const individualContextRanges: [number, number][] = [];

for (const lookup of this._lookupGroups) {
switch (lookup.lookupType) {
// https://docs.microsoft.com/en-us/typography/opentype/spec/gsub#lookuptype-6-chaining-contextual-substitution-subtable
case 6:
for (let index = 0; index < result.length; index++) {
for (let index = 0; index < sequence.length; index++) {
for (const table of lookup.subtables) {
let res: SubstitutionResult | null = null;
switch (table.substFormat) {
case 1:
res = processGsubType6Format1(
table,
result,
sequence,
index,
this._font.tables.gsub.lookups
);
break;
case 2:
res = processGsubType6Format2(
table,
result,
sequence,
index,
this._font.tables.gsub.lookups
);
break;
case 3:
res = processGsubType6Format3(
table,
result,
sequence,
index,
this._font.tables.gsub.lookups
);
Expand All @@ -94,11 +120,11 @@ class FontImpl implements Font {
break;
// https://docs.microsoft.com/en-us/typography/opentype/spec/gsub#lookuptype-8-reverse-chaining-contextual-single-substitution-subtable
case 8:
for (let index = result.length - 1; index >= 0; index--) {
for (let index = sequence.length - 1; index >= 0; index--) {
for (const table of lookup.subtables) {
const res = processGsubType8Format1(
table,
result,
sequence,
index
);

Expand Down Expand Up @@ -137,7 +163,7 @@ class FontImpl implements Font {
}
}

return { inputGlyphs: glyphIds, outputGlyphs: result, contextRanges };
return { sequence, ranges: contextRanges };
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,12 @@ export interface Font {
* @param text String to search for ligatures
*/
findLigatures(text: string): LigatureData;

/**
* Scans the provided text for font ligatures, returning an array of ranges
* where ligatures are located.
*
* @param text String to search for ligatures
*/
findLigatureRanges(text: string): [number, number][];
}

0 comments on commit f120430

Please sign in to comment.