提交 329261c8 编写于 作者: A Alex Dima

Towards refactoring view line rendering

上级 1d5d1b1a
......@@ -9,9 +9,8 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { IModel } from 'vs/editor/common/editorCommon';
import { TokenizationRegistry, ITokenizationSupport } from 'vs/editor/common/modes';
import { IModeService } from 'vs/editor/common/services/modeService';
import { renderLine, RenderLineInput } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { ViewLineToken } from 'vs/editor/common/core/viewLineToken';
import { LineParts } from 'vs/editor/common/core/lineParts';
import { render2, RenderLineInput2 } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { ViewLineToken, ViewLineTokens } from 'vs/editor/common/core/viewLineToken';
import { LineTokens } from 'vs/editor/common/core/lineTokens';
import * as strings from 'vs/base/common/strings';
import { IStandaloneColorService } from 'vs/editor/common/services/standaloneColorService';
......@@ -96,14 +95,15 @@ export class Colorizer {
}
public static colorizeLine(line: string, tokens: ViewLineToken[], tabSize: number = 4): string {
let renderResult = renderLine(new RenderLineInput(
let renderResult = render2(new RenderLineInput2(
line,
new ViewLineTokens(tokens, 0, line.length),
[],
tabSize,
0,
-1,
'none',
false,
new LineParts(tokens, line.length + 1)
false
));
return renderResult.output;
}
......@@ -126,14 +126,15 @@ function _fakeColorize(lines: string[], tabSize: number): string {
for (let i = 0, length = lines.length; i < length; i++) {
let line = lines[i];
let renderResult = renderLine(new RenderLineInput(
let renderResult = render2(new RenderLineInput2(
line,
new ViewLineTokens([], 0, line.length),
[],
tabSize,
0,
-1,
'none',
false,
new LineParts([], line.length + 1)
false
));
html = html.concat(renderResult.output);
......@@ -152,14 +153,15 @@ function _actualColorize(lines: string[], tabSize: number, tokenizationSupport:
let line = lines[i];
let tokenizeResult = tokenizationSupport.tokenize2(line, state, 0);
let lineTokens = new LineTokens(colorMap, tokenizeResult.tokens, line);
let renderResult = renderLine(new RenderLineInput(
let renderResult = render2(new RenderLineInput2(
line,
new ViewLineTokens(lineTokens.inflate(), 0, line.length),
[],
tabSize,
0,
-1,
'none',
false,
new LineParts(lineTokens.inflate(), line.length + 1)
false
));
html = html.concat(renderResult.output);
......
......@@ -7,8 +7,8 @@
import * as browser from 'vs/base/browser/browser';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/styleMutator';
import { IConfigurationChangedEvent } from 'vs/editor/common/editorCommon';
import { createLineParts, Decoration } from 'vs/editor/common/viewLayout/viewLineParts';
import { renderLine, RenderLineInput, RenderLineOutput, CharacterMapping } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { Decoration } from 'vs/editor/common/viewLayout/viewLineParts';
import { render2, RenderLineInput2, RenderLineOutput, CharacterMapping } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { ClassNames } from 'vs/editor/browser/editorBrowser';
import { IVisibleLineData } from 'vs/editor/browser/view/viewLayer';
import { RangeUtil } from 'vs/editor/browser/viewParts/lines/rangeUtil';
......@@ -97,24 +97,18 @@ export class ViewLine implements IVisibleLineData {
}
this._isMaybeInvalid = false;
let actualInlineDecorations = Decoration.filter(inlineDecorations, lineNumber, this._context.model.getLineMinColumn(lineNumber), this._context.model.getLineMaxColumn(lineNumber));
const model = this._context.model;
const actualInlineDecorations = Decoration.filter(inlineDecorations, lineNumber, model.getLineMinColumn(lineNumber), model.getLineMaxColumn(lineNumber));
let newLineParts = createLineParts(
this._context.model.getLineContent(lineNumber),
this._context.model.getTabSize(),
this._context.model.getLineTokens(lineNumber),
let renderLineInput = new RenderLineInput2(
model.getLineContent(lineNumber),
model.getLineTokens(lineNumber),
actualInlineDecorations,
this._renderWhitespace
);
let renderLineInput = new RenderLineInput(
this._context.model.getLineContent(lineNumber),
this._context.model.getTabSize(),
model.getTabSize(),
this._spaceWidth,
this._stopRenderingLineAfter,
this._renderWhitespace,
this._renderControlCharacters,
newLineParts
this._renderControlCharacters
);
if (this._renderedViewLine && this._renderedViewLine.input.equals(renderLineInput)) {
......@@ -129,7 +123,7 @@ export class ViewLine implements IVisibleLineData {
renderLineInput,
this._context.model.mightContainRTL(),
isWhitespaceOnly,
renderLine(renderLineInput)
render2(renderLineInput)
);
return true;
}
......@@ -174,7 +168,7 @@ export class ViewLine implements IVisibleLineData {
class RenderedViewLine {
public domNode: FastDomNode;
public readonly input: RenderLineInput;
public readonly input: RenderLineInput2;
public readonly html: string;
protected readonly _characterMapping: CharacterMapping;
......@@ -186,7 +180,7 @@ class RenderedViewLine {
*/
private _pixelOffsetCache: number[];
constructor(domNode: FastDomNode, renderLineInput: RenderLineInput, modelContainsRTL: boolean, isWhitespaceOnly: boolean, renderLineOutput: RenderLineOutput) {
constructor(domNode: FastDomNode, renderLineInput: RenderLineInput2, modelContainsRTL: boolean, isWhitespaceOnly: boolean, renderLineOutput: RenderLineOutput) {
this.domNode = domNode;
this.input = renderLineInput;
this.html = renderLineOutput.output;
......@@ -197,7 +191,7 @@ class RenderedViewLine {
this._pixelOffsetCache = null;
if (!modelContainsRTL) {
this._pixelOffsetCache = [];
for (let column = 0, maxLineColumn = this.input.lineParts.maxLineColumn; column <= maxLineColumn; column++) {
for (let column = 0, len = this._characterMapping.length; column <= len; column++) {
this._pixelOffsetCache[column] = -1;
}
}
......@@ -379,17 +373,17 @@ class WebKitRenderedViewLine extends RenderedViewLine {
}
}
const createRenderedLine: (domNode: FastDomNode, renderLineInput: RenderLineInput, modelContainsRTL: boolean, isWhitespaceOnly: boolean, renderLineOutput: RenderLineOutput) => RenderedViewLine = (function () {
const createRenderedLine: (domNode: FastDomNode, renderLineInput: RenderLineInput2, modelContainsRTL: boolean, isWhitespaceOnly: boolean, renderLineOutput: RenderLineOutput) => RenderedViewLine = (function () {
if (browser.isWebKit) {
return createWebKitRenderedLine;
}
return createNormalRenderedLine;
})();
function createWebKitRenderedLine(domNode: FastDomNode, renderLineInput: RenderLineInput, modelContainsRTL: boolean, isWhitespaceOnly: boolean, renderLineOutput: RenderLineOutput): RenderedViewLine {
function createWebKitRenderedLine(domNode: FastDomNode, renderLineInput: RenderLineInput2, modelContainsRTL: boolean, isWhitespaceOnly: boolean, renderLineOutput: RenderLineOutput): RenderedViewLine {
return new WebKitRenderedViewLine(domNode, renderLineInput, modelContainsRTL, isWhitespaceOnly, renderLineOutput);
}
function createNormalRenderedLine(domNode: FastDomNode, renderLineInput: RenderLineInput, modelContainsRTL: boolean, isWhitespaceOnly: boolean, renderLineOutput: RenderLineOutput): RenderedViewLine {
function createNormalRenderedLine(domNode: FastDomNode, renderLineInput: RenderLineInput2, modelContainsRTL: boolean, isWhitespaceOnly: boolean, renderLineOutput: RenderLineOutput): RenderedViewLine {
return new RenderedViewLine(domNode, renderLineInput, modelContainsRTL, isWhitespaceOnly, renderLineOutput);
}
......@@ -19,8 +19,8 @@ import { DefaultConfig } from 'vs/editor/common/config/defaultConfig';
import { Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { createLineParts, Decoration } from 'vs/editor/common/viewLayout/viewLineParts';
import { renderLine, RenderLineInput } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { Decoration } from 'vs/editor/common/viewLayout/viewLineParts';
import { render2, RenderLineInput2 } from 'vs/editor/common/viewLayout/viewLineRenderer';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { CodeEditor } from 'vs/editor/browser/codeEditor';
import { ViewLineToken, ViewLineTokens } from 'vs/editor/common/core/viewLineToken';
......@@ -1887,16 +1887,16 @@ class InlineViewZonesComputer extends ViewZonesComputer {
let lineTokens = new ViewLineTokens([new ViewLineToken(0, '')], 0, lineContent.length);
let actualDecorations = Decoration.filter(decorations, lineNumber, 1, lineContent.length + 1);
let parts = createLineParts(lineContent, tabSize, lineTokens, actualDecorations, config.viewInfo.renderWhitespace);
let r = renderLine(new RenderLineInput(
let r = render2(new RenderLineInput2(
lineContent,
lineTokens,
actualDecorations,
tabSize,
config.fontInfo.spaceWidth,
config.viewInfo.stopRenderingLineAfter,
config.viewInfo.renderWhitespace,
config.viewInfo.renderControlCharacters,
parts
config.viewInfo.renderControlCharacters
));
let myResult: string[] = [];
......
......@@ -24,6 +24,28 @@ export class Decoration {
this.className = className;
}
private static _equals(a: Decoration, b: Decoration): boolean {
return (
a.startColumn === b.startColumn
&& a.endColumn === b.endColumn
&& a.className === b.className
);
}
public static equalsArr(a: Decoration[], b: Decoration[]): boolean {
let aLen = a.length;
let bLen = b.length;
if (aLen !== bLen) {
return false;
}
for (let i = 0; i < aLen; i++) {
if (!Decoration._equals(a[i], b[i])) {
return false;
}
}
return true;
}
public static filter(lineDecorations: InlineDecoration[], lineNumber: number, minLineColumn: number, maxLineColumn: number): Decoration[] {
if (lineDecorations.length === 0) {
return [];
......
......@@ -4,40 +4,43 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ViewLineToken } from 'vs/editor/common/core/viewLineToken';
import { ViewLineToken, ViewLineTokens } from 'vs/editor/common/core/viewLineToken';
import { CharCode } from 'vs/base/common/charCode';
import { LineParts } from 'vs/editor/common/core/lineParts';
import { createLineParts, Decoration } from 'vs/editor/common/viewLayout/viewLineParts';
export class RenderLineInput {
_renderLineInputBrand: void;
export class RenderLineInput2 {
lineContent: string;
tabSize: number;
spaceWidth: number;
stopRenderingLineAfter: number;
renderWhitespace: 'none' | 'boundary' | 'all';
renderControlCharacters: boolean;
lineParts: LineParts;
public readonly lineContent: string;
public readonly lineTokens: ViewLineTokens;
public readonly lineDecorations: Decoration[];
public readonly tabSize: number;
public readonly spaceWidth: number;
public readonly stopRenderingLineAfter: number;
public readonly renderWhitespace: 'none' | 'boundary' | 'all';
public readonly renderControlCharacters: boolean;
constructor(
lineContent: string,
lineTokens: ViewLineTokens,
lineDecorations: Decoration[],
tabSize: number,
spaceWidth: number,
stopRenderingLineAfter: number,
renderWhitespace: 'none' | 'boundary' | 'all',
renderControlCharacters: boolean,
lineParts: LineParts
) {
this.lineContent = lineContent;
this.lineTokens = lineTokens;
this.lineDecorations = lineDecorations;
this.tabSize = tabSize;
this.spaceWidth = spaceWidth;
this.stopRenderingLineAfter = stopRenderingLineAfter;
this.renderWhitespace = renderWhitespace;
this.renderControlCharacters = renderControlCharacters;
this.lineParts = lineParts;
}
public equals(other: RenderLineInput): boolean {
public equals(other: RenderLineInput2): boolean {
return (
this.lineContent === other.lineContent
&& this.tabSize === other.tabSize
......@@ -45,11 +48,64 @@ export class RenderLineInput {
&& this.stopRenderingLineAfter === other.stopRenderingLineAfter
&& this.renderWhitespace === other.renderWhitespace
&& this.renderControlCharacters === other.renderControlCharacters
&& this.lineParts.equals(other.lineParts)
&& Decoration.equalsArr(this.lineDecorations, other.lineDecorations)
&& this.lineTokens.equals(other.lineTokens)
);
}
}
export function render2(input: RenderLineInput2): RenderLineOutput {
let newLineParts = createLineParts(
input.lineContent,
input.tabSize,
input.lineTokens,
input.lineDecorations,
input.renderWhitespace
);
let renderLineInput = new RenderLineInput(
input.lineContent,
input.tabSize,
input.spaceWidth,
input.stopRenderingLineAfter,
input.renderWhitespace,
input.renderControlCharacters,
newLineParts
);
return renderLine(renderLineInput);
}
class RenderLineInput {
_renderLineInputBrand: void;
lineContent: string;
tabSize: number;
spaceWidth: number;
stopRenderingLineAfter: number;
renderWhitespace: 'none' | 'boundary' | 'all';
renderControlCharacters: boolean;
lineParts: LineParts;
constructor(
lineContent: string,
tabSize: number,
spaceWidth: number,
stopRenderingLineAfter: number,
renderWhitespace: 'none' | 'boundary' | 'all',
renderControlCharacters: boolean,
lineParts: LineParts
) {
this.lineContent = lineContent;
this.tabSize = tabSize;
this.spaceWidth = spaceWidth;
this.stopRenderingLineAfter = stopRenderingLineAfter;
this.renderWhitespace = renderWhitespace;
this.renderControlCharacters = renderControlCharacters;
this.lineParts = lineParts;
}
}
export const enum CharacterMappingConstants {
PART_INDEX_MASK = 0b11111111111111110000000000000000,
CHAR_INDEX_MASK = 0b00000000000000001111111111111111,
......@@ -173,7 +229,7 @@ export class RenderLineOutput {
}
}
export function renderLine(input: RenderLineInput): RenderLineOutput {
function renderLine(input: RenderLineInput): RenderLineOutput {
const lineText = input.lineContent;
const lineTextLength = lineText.length;
const tabSize = input.tabSize;
......
......@@ -7,10 +7,9 @@
import * as assert from 'assert';
import { DecorationSegment, LineDecorationsNormalizer, createLineParts, Decoration } from 'vs/editor/common/viewLayout/viewLineParts';
import { Range } from 'vs/editor/common/core/range';
import { RenderLineInput, renderLine } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { RenderLineInput2, render2 } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { ViewLineToken, ViewLineTokens } from 'vs/editor/common/core/viewLineToken';
import { InlineDecoration } from 'vs/editor/common/viewModel/viewModel';
import { LineParts } from 'vs/editor/common/core/lineParts';
suite('Editor ViewLayout - ViewLineParts', () => {
......@@ -337,7 +336,16 @@ suite('Editor ViewLayout - ViewLineParts', () => {
});
function createTestGetColumnOfLinePartOffset(lineContent: string, tabSize: number, parts: ViewLineToken[]): (partIndex: number, partLength: number, offset: number, expected: number) => void {
let renderLineOutput = renderLine(new RenderLineInput(lineContent, tabSize, 10, -1, 'none', false, new LineParts(parts, lineContent.length + 1)));
let renderLineOutput = render2(new RenderLineInput2(
lineContent,
new ViewLineTokens(parts, 0, lineContent.length),
[],
tabSize,
10,
-1,
'none',
false
));
return (partIndex: number, partLength: number, offset: number, expected: number) => {
let charOffset = renderLineOutput.characterMapping.partDataToCharOffset(partIndex, partLength, offset);
......
......@@ -5,10 +5,9 @@
'use strict';
import * as assert from 'assert';
import { renderLine, RenderLineInput, CharacterMapping } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { ViewLineToken } from 'vs/editor/common/core/viewLineToken';
import { render2, RenderLineInput2, CharacterMapping } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { ViewLineToken, ViewLineTokens } from 'vs/editor/common/core/viewLineToken';
import { CharCode } from 'vs/base/common/charCode';
import { LineParts } from 'vs/editor/common/core/lineParts';
suite('viewLineRenderer.renderLine', () => {
......@@ -17,14 +16,15 @@ suite('viewLineRenderer.renderLine', () => {
}
function assertCharacterReplacement(lineContent: string, tabSize: number, expected: string, expectedCharOffsetInPart: number[][]): void {
let _actual = renderLine(new RenderLineInput(
let _actual = render2(new RenderLineInput2(
lineContent,
new ViewLineTokens([new ViewLineToken(0, '')], 0, lineContent.length),
[],
tabSize,
0,
-1,
'none',
false,
new LineParts([createPart(0, '')], lineContent.length + 1)
false
));
assert.equal(_actual.output, '<span><span class="">' + expected + '</span></span>');
......@@ -59,14 +59,15 @@ suite('viewLineRenderer.renderLine', () => {
});
function assertParts(lineContent: string, tabSize: number, parts: ViewLineToken[], expected: string, expectedCharOffsetInPart: number[][]): void {
let _actual = renderLine(new RenderLineInput(
let _actual = render2(new RenderLineInput2(
lineContent,
new ViewLineTokens(parts, 0, lineContent.length),
[],
tabSize,
0,
-1,
'none',
false,
new LineParts(parts, lineContent.length + 1)
false
));
assert.equal(_actual.output, '<span>' + expected + '</span>');
......@@ -90,30 +91,28 @@ suite('viewLineRenderer.renderLine', () => {
});
test('overflow', () => {
let _actual = renderLine(new RenderLineInput(
let _actual = render2(new RenderLineInput2(
'Hello world!',
new ViewLineTokens([
createPart(0, '0'),
createPart(1, '1'),
createPart(2, '2'),
createPart(3, '3'),
createPart(4, '4'),
createPart(5, '5'),
createPart(6, '6'),
createPart(7, '7'),
createPart(8, '8'),
createPart(9, '9'),
createPart(10, '10'),
createPart(11, '11'),
], 0, 'Hello world!'.length),
[],
4,
10,
6,
'boundary',
false,
new LineParts(
[
createPart(0, '0'),
createPart(1, '1'),
createPart(2, '2'),
createPart(3, '3'),
createPart(4, '4'),
createPart(5, '5'),
createPart(6, '6'),
createPart(7, '7'),
createPart(8, '8'),
createPart(9, '9'),
createPart(10, '10'),
createPart(11, '11'),
],
'Hello world!'.length + 1
)
false
));
let expectedOutput = [
......@@ -139,7 +138,7 @@ suite('viewLineRenderer.renderLine', () => {
test('typical line', () => {
let lineText = '\t export class Game { // http://test.com ';
let lineParts = [
createPart(0, 'block meta ts vs-whitespace'),
createPart(0, 'block meta ts'),
createPart(5, 'block declaration meta modifier object storage ts'),
createPart(11, 'block declaration meta object ts'),
createPart(12, 'block declaration meta object storage type ts'),
......@@ -150,10 +149,11 @@ suite('viewLineRenderer.renderLine', () => {
createPart(24, 'block body declaration meta object ts'),
createPart(25, 'block body comment declaration line meta object ts'),
createPart(28, 'block body comment declaration line meta object ts detected-link'),
createPart(43, 'block body comment declaration line meta object ts vs-whitespace'),
createPart(43, 'block body comment declaration line meta object ts'),
];
let expectedOutput = [
'<span class="block meta ts vs-whitespace" style="width:80px">&rarr;&nbsp;&nbsp;&nbsp;&middot;&middot;&middot;&middot;</span>',
'<span class="block meta ts vs-whitespace" style="width:40px">&rarr;&nbsp;&nbsp;&nbsp;</span>',
'<span class="block meta ts vs-whitespace" style="width:40px">&middot;&middot;&middot;&middot;</span>',
'<span class="block declaration meta modifier object storage ts">export</span>',
'<span class="block declaration meta object ts">&nbsp;</span>',
'<span class="block declaration meta object storage type ts">class</span>',
......@@ -164,10 +164,12 @@ suite('viewLineRenderer.renderLine', () => {
'<span class="block body declaration meta object ts">&nbsp;</span>',
'<span class="block body comment declaration line meta object ts">//&nbsp;</span>',
'<span class="block body comment declaration line meta object ts detected-link">http://test.com</span>',
'<span class="block body comment declaration line meta object ts vs-whitespace" style="width:50px">&middot;&middot;&middot;&middot;&middot;</span>'
'<span class="block body comment declaration line meta object ts vs-whitespace" style="width:20px">&middot;&middot;</span>',
'<span class="block body comment declaration line meta object ts vs-whitespace" style="width:30px">&middot;&middot;&middot;</span>'
].join('');
let expectedOffsetsArr = [
[0, 4, 5, 6, 7],
[0],
[0, 1, 2, 3],
[0, 1, 2, 3, 4, 5],
[0],
[0, 1, 2, 3, 4],
......@@ -178,17 +180,19 @@ suite('viewLineRenderer.renderLine', () => {
[0],
[0, 1, 2],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
[0, 1, 2, 3, 4, 5],
[0, 1],
[0, 1, 2, 3],
];
let _actual = renderLine(new RenderLineInput(
let _actual = render2(new RenderLineInput2(
lineText,
new ViewLineTokens(lineParts, 0, lineText.length),
[],
4,
10,
-1,
'boundary',
false,
new LineParts(lineParts, lineText.length + 1)
false
));
assert.equal(_actual.output, '<span>' + expectedOutput + '</span>');
......@@ -235,14 +239,15 @@ suite('viewLineRenderer.renderLine', () => {
[0, 1] // 2 chars
];
let _actual = renderLine(new RenderLineInput(
let _actual = render2(new RenderLineInput2(
lineText,
new ViewLineTokens(lineParts, 0, lineText.length),
[],
4,
10,
-1,
'none',
false,
new LineParts(lineParts, lineText.length + 1)
false
));
assert.equal(_actual.output, '<span>' + expectedOutput + '</span>');
......@@ -289,14 +294,15 @@ suite('viewLineRenderer.renderLine', () => {
[0, 1] // 2 chars
];
let _actual = renderLine(new RenderLineInput(
let _actual = render2(new RenderLineInput2(
lineText,
new ViewLineTokens(lineParts, 0, lineText.length),
[],
4,
10,
-1,
'none',
false,
new LineParts(lineParts, lineText.length + 1)
false
));
assert.equal(_actual.output, '<span>' + expectedOutput + '</span>');
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册