未验证 提交 bb04e412 编写于 作者: A Alex Dima

Fixes #90391: Split lines into spans of at most 16384 characters

上级 2e3bbc2d
......@@ -149,6 +149,10 @@ function createLineBreaks(requests: string[], fontInfo: FontInfo, tabSize: numbe
return result;
}
const enum Constants {
SPAN_MODULO_LIMIT = 16384
}
function renderLine(lineContent: string, initialVisibleColumn: number, tabSize: number, width: number, sb: IStringBuilder): [number[], number[]] {
sb.appendASCIIString('<div style="width:');
sb.appendASCIIString(String(width));
......@@ -164,7 +168,11 @@ function renderLine(lineContent: string, initialVisibleColumn: number, tabSize:
let visibleColumns: number[] = [];
let nextCharCode = (0 < len ? lineContent.charCodeAt(0) : CharCode.Null);
sb.appendASCIIString('<span>');
for (let charIndex = 0; charIndex < len; charIndex++) {
if (charIndex !== 0 && charIndex % Constants.SPAN_MODULO_LIMIT === 0) {
sb.appendASCIIString('</span><span>');
}
charOffsets[charIndex] = charOffset;
visibleColumns[charIndex] = visibleColumn;
const charCode = nextCharCode;
......@@ -227,6 +235,7 @@ function renderLine(lineContent: string, initialVisibleColumn: number, tabSize:
charOffset += producedCharacters;
visibleColumn += charWidth;
}
sb.appendASCIIString('</span>');
charOffsets[lineContent.length] = charOffset;
visibleColumns[lineContent.length] = visibleColumn;
......@@ -240,10 +249,15 @@ function readLineBreaks(range: Range, lineDomNode: HTMLDivElement, lineContent:
if (lineContent.length <= 1) {
return null;
}
const textContentNode = lineDomNode.firstChild!;
const spans = <HTMLSpanElement[]>Array.prototype.slice.call(lineDomNode.children, 0);
const breakOffsets: number[] = [];
discoverBreaks(range, textContentNode, charOffsets, 0, null, lineContent.length - 1, null, breakOffsets);
try {
discoverBreaks(range, spans, charOffsets, 0, null, lineContent.length - 1, null, breakOffsets);
} catch (err) {
console.log(err);
return null;
}
if (breakOffsets.length === 0) {
return null;
......@@ -255,13 +269,13 @@ function readLineBreaks(range: Range, lineDomNode: HTMLDivElement, lineContent:
type MaybeRects = ClientRectList | DOMRectList | null;
function discoverBreaks(range: Range, textContentNode: Node, charOffsets: number[], low: number, lowRects: MaybeRects, high: number, highRects: MaybeRects, result: number[]): void {
function discoverBreaks(range: Range, spans: HTMLSpanElement[], charOffsets: number[], low: number, lowRects: MaybeRects, high: number, highRects: MaybeRects, result: number[]): void {
if (low === high) {
return;
}
lowRects = lowRects || readClientRect(range, textContentNode, charOffsets[low], charOffsets[low + 1]);
highRects = highRects || readClientRect(range, textContentNode, charOffsets[high], charOffsets[high + 1]);
lowRects = lowRects || readClientRect(range, spans, charOffsets[low], charOffsets[low + 1]);
highRects = highRects || readClientRect(range, spans, charOffsets[high], charOffsets[high + 1]);
if (Math.abs(lowRects[0].top - highRects[0].top) <= 0.1) {
// same line
......@@ -276,13 +290,13 @@ function discoverBreaks(range: Range, textContentNode: Node, charOffsets: number
}
const mid = low + ((high - low) / 2) | 0;
const midRects = readClientRect(range, textContentNode, charOffsets[mid], charOffsets[mid + 1]);
discoverBreaks(range, textContentNode, charOffsets, low, lowRects, mid, midRects, result);
discoverBreaks(range, textContentNode, charOffsets, mid, midRects, high, highRects, result);
const midRects = readClientRect(range, spans, charOffsets[mid], charOffsets[mid + 1]);
discoverBreaks(range, spans, charOffsets, low, lowRects, mid, midRects, result);
discoverBreaks(range, spans, charOffsets, mid, midRects, high, highRects, result);
}
function readClientRect(range: Range, textContentNode: Node, startOffset: number, endOffset: number): ClientRectList | DOMRectList {
range.setStart(textContentNode, startOffset);
range.setEnd(textContentNode, endOffset);
function readClientRect(range: Range, spans: HTMLSpanElement[], startOffset: number, endOffset: number): ClientRectList | DOMRectList {
range.setStart(spans[(startOffset / Constants.SPAN_MODULO_LIMIT) | 0].firstChild!, startOffset % Constants.SPAN_MODULO_LIMIT);
range.setEnd(spans[(endOffset / Constants.SPAN_MODULO_LIMIT) | 0].firstChild!, endOffset % Constants.SPAN_MODULO_LIMIT);
return range.getClientRects();
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册