Skip to content

Commit

Permalink
Fixed grapheme–section mapping during bidi processing
Browse files Browse the repository at this point in the history
  • Loading branch information
1ec5 committed Aug 21, 2024
1 parent 17ebe56 commit 711c33e
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 10 deletions.
12 changes: 6 additions & 6 deletions src/symbol/shaping.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ describe('TaggedString', () => {
test('splits surrogate pairs', () => {
const tagged = new TaggedString();
tagged.text = '𰻞𰻞麵𪚥𪚥';
expect(tagged.codeUnitIndex(0)).toBe(0);
expect(tagged.codeUnitIndex(1)).toBe(2);
expect(tagged.codeUnitIndex(2)).toBe(4);
expect(tagged.codeUnitIndex(3)).toBe(5);
expect(tagged.codeUnitIndex(4)).toBe(7);
expect(tagged.codeUnitIndex(5)).toBe(9);
expect(tagged.toCodeUnitIndex(0)).toBe(0);
expect(tagged.toCodeUnitIndex(1)).toBe(2);
expect(tagged.toCodeUnitIndex(2)).toBe(4);
expect(tagged.toCodeUnitIndex(3)).toBe(5);
expect(tagged.toCodeUnitIndex(4)).toBe(7);
expect(tagged.toCodeUnitIndex(5)).toBe(9);
});
});
});
Expand Down
19 changes: 15 additions & 4 deletions src/symbol/shaping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export class TaggedString {
/**
* Converts a grapheme cluster index to a UTF-16 code unit (JavaScript character index).
*/
codeUnitIndex(unicodeIndex: number): number {
toCodeUnitIndex(unicodeIndex: number): number {
return splitByGraphemeCluster(this.text).slice(0, unicodeIndex).join('').length;
}

Expand Down Expand Up @@ -271,7 +271,7 @@ function shapeText(
// Bidi doesn't have to be style-aware
lines = [];
// ICU operates on code units.
lineBreaks = lineBreaks.map(index => logicalInput.codeUnitIndex(index));
lineBreaks = lineBreaks.map(index => logicalInput.toCodeUnitIndex(index));
const untaggedLines =
processBidirectionalText(logicalInput.toString(), lineBreaks);
for (const line of untaggedLines) {
Expand All @@ -289,9 +289,20 @@ function shapeText(
// with formatting
lines = [];
// ICU operates on code units.
lineBreaks = lineBreaks.map(index => logicalInput.codeUnitIndex(index));
lineBreaks = lineBreaks.map(index => logicalInput.toCodeUnitIndex(index));

// Convert grapheme cluster–based section index to be based on code units.
let i = 0;
let elapsedCodeUnits = 0;
let sectionIndex = [];
for (const grapheme of splitByGraphemeCluster(logicalInput.text)) {
sectionIndex.push(...Array(grapheme.length).fill(logicalInput.sectionIndex[i]));
i++;
elapsedCodeUnits += grapheme.length;
}

const processedLines =
processStyledBidirectionalText(logicalInput.text, logicalInput.sectionIndex, lineBreaks);
processStyledBidirectionalText(logicalInput.text, sectionIndex, lineBreaks);
for (const line of processedLines) {
const taggedLine = new TaggedString();
taggedLine.text = line[0];
Expand Down

0 comments on commit 711c33e

Please sign in to comment.