From 5209ec8032ceb61b60852dd51b25afa0b9b9934f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Wed, 21 Aug 2024 19:24:23 -0700 Subject: [PATCH] Fixed ligatures in Sinhala Replace zero-width joiners with temporary strip markers to prevent ICU from stripping them. --- src/symbol/shaping.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/symbol/shaping.ts b/src/symbol/shaping.ts index b82875e1ad6..eb802b9dcdd 100644 --- a/src/symbol/shaping.ts +++ b/src/symbol/shaping.ts @@ -272,11 +272,14 @@ function shapeText( lines = []; // ICU operates on code units. lineBreaks = lineBreaks.map(index => logicalInput.toCodeUnitIndex(index)); + // Replace zero-width joiners with temporary strip markers (from the Private Use Area) to prevent ICU from stripping them out. + const markedInput = logicalInput.toString().replace(/\u200D/g, '\uF8FF'); const untaggedLines = - processBidirectionalText(logicalInput.toString(), lineBreaks); + processBidirectionalText(markedInput, lineBreaks); for (const line of untaggedLines) { const taggedLine = new TaggedString(); - taggedLine.text = line; + // Restore zero-width joiners from temporary strip markers. + taggedLine.text = line.replace(/\uF8FF/g, '\u200D'); taggedLine.sections = logicalInput.sections; // eslint-disable-next-line @typescript-eslint/no-unused-vars for (const char of splitByGraphemeCluster(line)) { @@ -290,20 +293,23 @@ function shapeText( lines = []; // ICU operates on code units. lineBreaks = lineBreaks.map(index => logicalInput.toCodeUnitIndex(index)); + // Replace zero-width joiners with temporary strip markers (from the Private Use Area) to prevent ICU from stripping them out. + const markedInput = logicalInput.toString().replace(/\u200D/g, '\uF8FF'); // Convert grapheme cluster–based section index to be based on code units. let i = 0; const sectionIndex = []; - for (const grapheme of splitByGraphemeCluster(logicalInput.text)) { + for (const grapheme of splitByGraphemeCluster(markedInput)) { sectionIndex.push(...Array(grapheme.length).fill(logicalInput.sectionIndex[i])); i++; } const processedLines = - processStyledBidirectionalText(logicalInput.text, sectionIndex, lineBreaks); + processStyledBidirectionalText(markedInput, sectionIndex, lineBreaks); for (const line of processedLines) { const taggedLine = new TaggedString(); - taggedLine.text = line[0]; + // Restore zero-width joiners from temporary strip markers. + taggedLine.text = line[0].replace(/\uF8FF/g, '\u200D'); taggedLine.sectionIndex = line[1]; taggedLine.sections = logicalInput.sections; lines.push(taggedLine);