Skip to content

Commit 6f2b8ba

Browse files
committed
Ligatures: Refactor findInternal() for clarity
1 parent d92928e commit 6f2b8ba

File tree

1 file changed

+27
-123
lines changed
  • packages/extraterm-font-ligatures/src

1 file changed

+27
-123
lines changed

packages/extraterm-font-ligatures/src/index.ts

Lines changed: 27 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class FontImpl implements Font {
104104
};
105105
}
106106

107-
const result = this._fastFindInternal(glyphIds.slice());
107+
const result = this._findInternal(glyphIds.slice());
108108
const finalResult: LigatureData = {
109109
inputGlyphs: glyphIds,
110110
outputGlyphs: result.sequence,
@@ -134,7 +134,7 @@ class FontImpl implements Font {
134134
glyphIds.push(this._font.charToGlyphIndex(char));
135135
}
136136

137-
const result = this._fastFindInternal(glyphIds);
137+
const result = this._findInternal(glyphIds);
138138
if (this._cache) {
139139
this._cache.set(text, result.ranges);
140140
}
@@ -144,117 +144,6 @@ class FontImpl implements Font {
144144

145145
private _findInternal(sequence: number[]): { sequence: number[]; ranges: [number, number][]; } {
146146
const ranges: [number, number][] = [];
147-
148-
let nextLookup = this._getNextLookup(sequence, 0);
149-
while (nextLookup.index !== null) {
150-
const lookup = this._lookupTrees[nextLookup.index];
151-
if (lookup.processForward) {
152-
let lastGlyphIndex = nextLookup.last;
153-
for (let i = nextLookup.first; i < lastGlyphIndex; i++) {
154-
const result = walkTree(lookup.tree, sequence, i, i);
155-
if (result) {
156-
let didSubstitute = false;
157-
for (let j = 0; j < result.substitutions.length; j++) {
158-
const sub = result.substitutions[j];
159-
if (sub !== null) {
160-
sequence[i + j] = sub;
161-
didSubstitute = true;
162-
}
163-
}
164-
if (didSubstitute) {
165-
mergeRange(
166-
ranges,
167-
result.contextRange[0] + i,
168-
result.contextRange[1] + i
169-
);
170-
171-
// Substitutions can end up extending the search range
172-
if (i + result.length >= lastGlyphIndex) {
173-
lastGlyphIndex = i + result.length + 1;
174-
}
175-
}
176-
i += result.length - 1;
177-
}
178-
}
179-
} else {
180-
// We don't need to do the lastGlyphIndex tracking here because
181-
// reverse processing isn't allowed to replace more than one
182-
// character at a time.
183-
for (let i = nextLookup.last - 1; i >= nextLookup.first; i--) {
184-
const result = walkTree(lookup.tree, sequence, i, i);
185-
if (result) {
186-
for (let j = 0; j < result.substitutions.length; j++) {
187-
const sub = result.substitutions[j];
188-
if (sub !== null) {
189-
sequence[i + j] = sub;
190-
}
191-
}
192-
193-
mergeRange(
194-
ranges,
195-
result.contextRange[0] + i,
196-
result.contextRange[1] + i
197-
);
198-
199-
i -= result.length - 1;
200-
}
201-
}
202-
}
203-
204-
nextLookup = this._getNextLookup(sequence, nextLookup.index + 1);
205-
}
206-
207-
return { sequence, ranges };
208-
}
209-
210-
/**
211-
* Returns the lookup and glyph range for the first lookup that might
212-
* contain a match.
213-
*
214-
* @param sequence Input glyph sequence
215-
* @param start The first input to try
216-
*/
217-
private _getNextLookup(sequence: number[], start: number): { index: number | null; first: number; last: number; } {
218-
const result: { index: number | null; first: number; last: number; } = {
219-
index: null,
220-
first: Infinity,
221-
last: -1
222-
};
223-
const glyphLookups = this._glyphLookups;
224-
225-
// Loop through each glyph and find the first valid lookup for it
226-
for (let i = 0; i < sequence.length; i++) {
227-
const lookups = glyphLookups.get(sequence[i]);
228-
if (!lookups) {
229-
continue;
230-
}
231-
232-
for (let j = 0; j < lookups.length; j++) {
233-
const lookupIndex = lookups[j];
234-
if (lookupIndex >= start) {
235-
// Update the lookup information if it's the one we're
236-
// storing or earlier than it.
237-
if (result.index === null || lookupIndex <= result.index) {
238-
result.index = lookupIndex;
239-
240-
if (result.first > i) {
241-
result.first = i;
242-
}
243-
244-
result.last = i + 1;
245-
}
246-
247-
break;
248-
}
249-
}
250-
}
251-
252-
return result;
253-
}
254-
255-
private _fastFindInternal(sequence: number[]): { sequence: number[]; ranges: [number, number][]; } {
256-
const ranges: [number, number][] = [];
257-
258147
const orderedLookups = this._findRelevantLookupsForSequence(sequence);
259148
for (let orderedLookupIndex = 0; orderedLookupIndex < orderedLookups.length; orderedLookupIndex++) {
260149
this._applyLookupToSequence(orderedLookups[orderedLookupIndex], sequence, ranges);
@@ -268,22 +157,37 @@ class FontImpl implements Font {
268157
const glyphLookups = this._glyphLookups;
269158
const currentLookup = this._lookupTrees[currentLookupIndex];
270159

271-
for (let i = 0; i < sequenceLength; i++) {
272-
const currentLookups = glyphLookups.get(sequence[i]);
273-
if (currentLookups == null || currentLookups.indexOf(currentLookupIndex) === -1) {
274-
continue;
160+
if (currentLookup.processForward) {
161+
for (let i = 0; i < sequenceLength; i++) {
162+
const currentLookups = glyphLookups.get(sequence[i]);
163+
if (currentLookups == null || currentLookups.indexOf(currentLookupIndex) === -1) {
164+
continue;
165+
}
166+
167+
const result = walkTree(currentLookup.tree, sequence, i, i);
168+
if (result && this._applySubstitutionsToSequence(sequence, result.substitutions, i)) {
169+
mergeRange(ranges, result.contextRange[0] + i, result.contextRange[1] + i);
170+
i += result.length - 1;
171+
}
275172
}
173+
} else {
174+
for (let i = sequenceLength-1; i >= 0; i--) {
175+
const currentLookups = glyphLookups.get(sequence[i]);
176+
if (currentLookups == null || currentLookups.indexOf(currentLookupIndex) === -1) {
177+
continue;
178+
}
276179

277-
const result = walkTree(currentLookup.tree, sequence, i, i);
278-
if (result && this._applySubstitutionsToSequence(sequence, result.substitutions, i)) {
279-
mergeRange(ranges, result.contextRange[0] + i, result.contextRange[1] + i);
280-
i+= result.length - 1;
180+
const result = walkTree(currentLookup.tree, sequence, i, i);
181+
if (result && this._applySubstitutionsToSequence(sequence, result.substitutions, i)) {
182+
mergeRange(ranges, result.contextRange[0] + i, result.contextRange[1] + i);
183+
i -= result.length - 1;
184+
}
281185
}
282186
}
283187
}
284188

285189
private _findRelevantLookupsForSequence(sequence: number[]): number[] {
286-
// Determine which lookups we should extamine.
190+
// Determine which lookups we should examine.
287191
const glyphLookups = this._glyphLookups;
288192
const sequenceLength = sequence.length;
289193
const seenLookups = new Set<number>();
@@ -333,7 +237,7 @@ class FontImpl implements Font {
333237
glyphIds.push(glyphIndex);
334238
}
335239

336-
const result = this._fastFindInternal(glyphIds);
240+
const result = this._findInternal(glyphIds);
337241
let i = 0;
338242
for (const range of result.ranges) {
339243
while (i < range[0]) {

0 commit comments

Comments
 (0)