From 72fe8f51b7ab3cec581d9ad1c6ffdd0be3a9349f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 23 Feb 2017 10:25:39 +0100 Subject: [PATCH] Fixes #20624: Unaligned surrogate pairs are corrupted at multiples of 50 columns --- .../common/viewLayout/viewLineRenderer.ts | 9 +++++-- .../viewLayout/viewLineRenderer.test.ts | 27 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/common/viewLayout/viewLineRenderer.ts b/src/vs/editor/common/viewLayout/viewLineRenderer.ts index 3c5dea532b5..5336254f3df 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 74ce4e38139..c75de5998fa 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)]; -- GitLab