diff --git a/src/vs/editor/common/viewLayout/viewLineRenderer.ts b/src/vs/editor/common/viewLayout/viewLineRenderer.ts index 3c5dea532b5fdff7a102931e843f3823572c7ecf..5336254f3df882dc5ed44bd29a0acd12197a2ee1 100644 --- a/src/vs/editor/common/viewLayout/viewLineRenderer.ts +++ b/src/vs/editor/common/viewLayout/viewLineRenderer.ts @@ -298,7 +298,7 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput containsRTL = strings.containsRTL(lineContent); } if (!containsRTL) { - tokens = splitLargeTokens(tokens); + tokens = splitLargeTokens(lineContent, tokens); } return new ResolvedRenderLineInput( @@ -347,7 +347,7 @@ const enum Constants { * It appears that having very large spans causes very slow reading of character positions. * So here we try to avoid that. */ -function splitLargeTokens(tokens: LinePart[]): LinePart[] { +function splitLargeTokens(lineContent: string, tokens: LinePart[]): LinePart[] { let lastTokenEndIndex = 0; let result: LinePart[] = [], resultLen = 0; for (let i = 0, len = tokens.length; i < len; i++) { @@ -359,6 +359,11 @@ function splitLargeTokens(tokens: LinePart[]): LinePart[] { const piecesCount = Math.ceil(diff / Constants.LongToken); for (let j = 1; j < piecesCount; j++) { let pieceEndIndex = lastTokenEndIndex + (j * Constants.LongToken); + let lastCharInPiece = lineContent.charCodeAt(pieceEndIndex - 1); + if (strings.isHighSurrogate(lastCharInPiece)) { + // Don't cut in the middle of a surrogate pair + pieceEndIndex--; + } result[resultLen++] = new LinePart(pieceEndIndex, tokenType); } result[resultLen++] = new LinePart(tokenEndIndex, tokenType); diff --git a/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts b/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts index 74ce4e38139efd3f51799e5626b8aa7c0813deb5..c75de5998fadb8f122673f347206754898bdf79f 100644 --- a/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts +++ b/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts @@ -468,6 +468,33 @@ suite('viewLineRenderer.renderLine', () => { } }); + test('issue #20624: Unaligned surrogate pairs are corrupted at multiples of 50 columns', () => { + let lineText = 'a𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷'; + + let lineParts = [createPart(lineText.length, 1)]; + let actual = renderViewLine(new RenderLineInput( + false, + lineText, + false, + 0, + lineParts, + [], + 4, + 10, + -1, + 'none', + false + )); + let expectedOutput = [ + 'a𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷', + '𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷', + '𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷', + '𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷', + '𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷', + ]; + assert.equal(actual.html, '' + expectedOutput.join('') + ''); + }); + test('issue #6885: Does not split large tokens in RTL text', () => { let lineText = 'את גרמנית בהתייחסות שמו, שנתי המשפט אל חפש, אם כתב אחרים ולחבר. של התוכן אודות בויקיפדיה כלל, של עזרה כימיה היא. על עמוד יוצרים מיתולוגיה סדר, אם שכל שתפו לעברית שינויים, אם שאלות אנגלית עזה. שמות בקלות מה סדר.'; let lineParts = [createPart(lineText.length, 1)];