Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exploration: implementing variable line heights #233110

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
2 changes: 2 additions & 0 deletions src/vs/editor/browser/observableCodeEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ export class ObservableCodeEditor extends Disposable {
}

public setDecorations(decorations: IObservable<IModelDeltaDecoration[]>): IDisposable {
console.log('setDecorations of ObservableCodeEditor');
console.log('decorations : ', decorations);
const d = new DisposableStore();
const decorationsCollection = this.editor.createDecorationsCollection();
d.add(autorunOpts({ owner: this, debugName: () => `Apply decorations from ${decorations.debugName}` }, reader => {
Expand Down
7 changes: 7 additions & 0 deletions src/vs/editor/browser/services/abstractCodeEditorService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,8 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider {
public afterContentClassName: string | undefined;
public glyphMarginClassName: string | undefined;
public isWholeLine: boolean;
public lineHeight?: number;
public fontSize?: number;
public overviewRuler: IModelDecorationOverviewRulerOptions | undefined;
public stickiness: TrackedRangeStickiness | undefined;
public beforeInjectedText: InjectedTextOptions | undefined;
Expand Down Expand Up @@ -517,6 +519,9 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider {

const options = providerArgs.options;
this.isWholeLine = Boolean(options.isWholeLine);
console.log('options.lineHeight : ', options.lineHeight);
this.lineHeight = options.lineHeight;
this.fontSize = options.fontSize;
this.stickiness = options.rangeBehavior;

const lightOverviewRulerColor = options.light && options.light.overviewRulerColor || options.overviewRulerColor;
Expand Down Expand Up @@ -546,6 +551,8 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider {
className: this.className,
glyphMarginClassName: this.glyphMarginClassName,
isWholeLine: this.isWholeLine,
lineHeight: this.lineHeight,
fontSize: this.fontSize,
overviewRuler: this.overviewRuler,
stickiness: this.stickiness,
before: this.beforeInjectedText,
Expand Down
29 changes: 23 additions & 6 deletions src/vs/editor/browser/view/domLineBreaksComputer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ const ttPolicy = createTrustedTypesPolicy('domLineBreaksComputer', { createHTML:

export class DOMLineBreaksComputerFactory implements ILineBreaksComputerFactory {

private readonly maxLogsIndex = 10;
private currentIndex = 0;

public static create(targetWindow: Window): DOMLineBreaksComputerFactory {
return new DOMLineBreaksComputerFactory(new WeakRef(targetWindow));
}
Expand All @@ -33,15 +36,17 @@ export class DOMLineBreaksComputerFactory implements ILineBreaksComputerFactory
addRequest: (lineText: string, injectedText: LineInjectedText[] | null, previousLineBreakData: ModelLineProjectionData | null) => {
requests.push(lineText);
injectedTexts.push(injectedText);
this.currentIndex++;
},
finalize: () => {
return createLineBreaks(assertIsDefined(this.targetWindow.deref()), requests, fontInfo, tabSize, wrappingColumn, wrappingIndent, wordBreak, injectedTexts);
this.currentIndex++;
return createLineBreaks(assertIsDefined(this.targetWindow.deref()), requests, fontInfo, tabSize, wrappingColumn, wrappingIndent, wordBreak, injectedTexts, this.maxLogsIndex, this.currentIndex);
}
};
}
}

function createLineBreaks(targetWindow: Window, requests: string[], fontInfo: FontInfo, tabSize: number, firstLineBreakColumn: number, wrappingIndent: WrappingIndent, wordBreak: 'normal' | 'keepAll', injectedTextsPerLine: (LineInjectedText[] | null)[]): (ModelLineProjectionData | null)[] {
function createLineBreaks(targetWindow: Window, requests: string[], fontInfo: FontInfo, tabSize: number, firstLineBreakColumn: number, wrappingIndent: WrappingIndent, wordBreak: 'normal' | 'keepAll', injectedTextsPerLine: (LineInjectedText[] | null)[], maxLogsIndex: number, currentIndex: number): (ModelLineProjectionData | null)[] {
function createEmptyLineBreakWithPossiblyInjectedText(requestIdx: number): ModelLineProjectionData | null {
const injectedTexts = injectedTextsPerLine[requestIdx];
if (injectedTexts) {
Expand Down Expand Up @@ -81,6 +86,11 @@ function createLineBreaks(targetWindow: Window, requests: string[], fontInfo: Fo
const allCharOffsets: number[][] = [];
const allVisibleColumns: number[][] = [];
for (let i = 0; i < requests.length; i++) {
if (currentIndex < maxLogsIndex) {
console.log('createLineBreaks');
console.log('requests[i] : ', requests[i]);
console.log('LineInjectedText.applyInjectedText(requests[i], injectedTextsPerLine[i]) : ', LineInjectedText.applyInjectedText(requests[i], injectedTextsPerLine[i]));
}
const lineContent = LineInjectedText.applyInjectedText(requests[i], injectedTextsPerLine[i]);

let firstNonWhitespaceIndex = 0;
Expand Down Expand Up @@ -118,7 +128,7 @@ function createLineBreaks(targetWindow: Window, requests: string[], fontInfo: Fo
}

const renderLineContent = lineContent.substr(firstNonWhitespaceIndex);
const tmp = renderLine(renderLineContent, wrappedTextIndentLength, tabSize, width, sb, additionalIndentLength);
const tmp = renderLine(renderLineContent, wrappedTextIndentLength, tabSize, width, sb, additionalIndentLength, maxLogsIndex, currentIndex);
firstNonWhitespaceIndices[i] = firstNonWhitespaceIndex;
wrappedTextIndentLengths[i] = wrappedTextIndentLength;
renderLineContents[i] = renderLineContent;
Expand Down Expand Up @@ -148,7 +158,7 @@ function createLineBreaks(targetWindow: Window, requests: string[], fontInfo: Fo
const result: (ModelLineProjectionData | null)[] = [];
for (let i = 0; i < requests.length; i++) {
const lineDomNode = lineDomNodes[i];
const breakOffsets: number[] | null = readLineBreaks(range, lineDomNode, renderLineContents[i], allCharOffsets[i]);
const breakOffsets: number[] | null = readLineBreaks(range, lineDomNode, renderLineContents[i], allCharOffsets[i], maxLogsIndex, currentIndex);
if (breakOffsets === null) {
result[i] = createEmptyLineBreakWithPossiblyInjectedText(i);
continue;
Expand Down Expand Up @@ -192,7 +202,8 @@ const enum Constants {
SPAN_MODULO_LIMIT = 16384
}

function renderLine(lineContent: string, initialVisibleColumn: number, tabSize: number, width: number, sb: StringBuilder, wrappingIndentLength: number): [number[], number[]] {
// --
function renderLine(lineContent: string, initialVisibleColumn: number, tabSize: number, width: number, sb: StringBuilder, wrappingIndentLength: number, maxLogsIndex: number, currentIndex: number): [number[], number[]] {

if (wrappingIndentLength !== 0) {
const hangingOffset = String(wrappingIndentLength);
Expand Down Expand Up @@ -293,10 +304,16 @@ function renderLine(lineContent: string, initialVisibleColumn: number, tabSize:

sb.appendString('</div>');

if (currentIndex < maxLogsIndex) {
console.log('sb.build() : ', sb.build());
}
return [charOffsets, visibleColumns];
}

function readLineBreaks(range: Range, lineDomNode: HTMLDivElement, lineContent: string, charOffsets: number[]): number[] | null {
function readLineBreaks(range: Range, lineDomNode: HTMLDivElement, lineContent: string, charOffsets: number[], maxLogsIndex: number, currentIndex: number): number[] | null {
if (currentIndex < maxLogsIndex) {
console.log('lineContent : ', lineContent);
}
if (lineContent.length <= 1) {
return null;
}
Expand Down
42 changes: 39 additions & 3 deletions src/vs/editor/browser/view/viewLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ interface IRendererContext<T extends IVisibleLine> {
class ViewLayerRenderer<T extends IVisibleLine> {

private static _ttPolicy = createTrustedTypesPolicy('editorViewLayer', { createHTML: value => value });
private readonly maxLogsIndex = 10;
private currentIndex = 0;

constructor(
private readonly _domNode: HTMLElement,
Expand All @@ -392,6 +394,7 @@ class ViewLayerRenderer<T extends IVisibleLine> {
ctx.lines[x - startLineNumber] = this._lineFactory.createLine();
}
this._finishRendering(ctx, true, deltaTop);
this.currentIndex++;
return ctx;
}

Expand Down Expand Up @@ -447,16 +450,34 @@ class ViewLayerRenderer<T extends IVisibleLine> {

this._finishRendering(ctx, false, deltaTop);

this.currentIndex++;
return ctx;
}

private _renderUntouchedLines(ctx: IRendererContext<T>, startIndex: number, endIndex: number, deltaTop: number[], deltaLN: number): void {
if (this.currentIndex < this.maxLogsIndex) {
console.log('_renderUntouchedLines');
console.log('startIndex ', startIndex);
console.log('endIndex ', endIndex);
console.log('deltaTop ', deltaTop);
console.log('deltaLN ', deltaLN);
}
const rendLineNumberStart = ctx.rendLineNumberStart;
const lines = ctx.lines;

for (let i = startIndex; i <= endIndex; i++) {
const lineNumber = rendLineNumberStart + i;
lines[i].layoutLine(lineNumber, deltaTop[lineNumber - deltaLN], this._viewportData.lineHeight);
const deltaIndex = lineNumber - deltaLN;
const lineHeight = deltaTop[deltaIndex + 1] - deltaTop[deltaIndex];
if (this.currentIndex < this.maxLogsIndex) {
console.log('i ', i);
console.log('deltaTop : ', deltaTop);
console.log('lineNumber ', lineNumber);
console.log('deltaLN : ', deltaLN);
console.log('deltaIndex ', deltaIndex);
console.log('lineHeight ', lineHeight);
}
lines[i].layoutLine(lineNumber, deltaTop[deltaIndex], lineHeight);
}
}

Expand Down Expand Up @@ -539,6 +560,9 @@ class ViewLayerRenderer<T extends IVisibleLine> {
private static readonly _sb = new StringBuilder(100000);

private _finishRendering(ctx: IRendererContext<T>, domNodeIsEmpty: boolean, deltaTop: number[]): void {
if (this.currentIndex < this.maxLogsIndex) {
console.log('_finishRendering');
}

const sb = ViewLayerRenderer._sb;
const linesLength = ctx.linesLength;
Expand All @@ -560,7 +584,13 @@ class ViewLayerRenderer<T extends IVisibleLine> {
continue;
}

const renderResult = line.renderLine(i + rendLineNumberStart, deltaTop[i], this._viewportData.lineHeight, this._viewportData, sb);
const lineHeight = deltaTop[i + 1] - deltaTop[i];
if (this.currentIndex < this.maxLogsIndex) {
console.log('i : ', i);
console.log('deltaTop : ', deltaTop);
console.log('lineHeight : ', lineHeight);
}
const renderResult = line.renderLine(i + rendLineNumberStart, deltaTop[i], lineHeight, this._viewportData, sb);
if (!renderResult) {
// line does not need rendering
continue;
Expand Down Expand Up @@ -590,7 +620,13 @@ class ViewLayerRenderer<T extends IVisibleLine> {
continue;
}

const renderResult = line.renderLine(i + rendLineNumberStart, deltaTop[i], this._viewportData.lineHeight, this._viewportData, sb);
const lineHeight = deltaTop[i + 1] - deltaTop[i];
if (this.currentIndex < this.maxLogsIndex) {
console.log('i : ', i);
console.log('deltaTop : ', deltaTop);
console.log('lineHeight : ', lineHeight);
}
const renderResult = line.renderLine(i + rendLineNumberStart, deltaTop[i], lineHeight, this._viewportData, sb);
if (!renderResult) {
// line does not need rendering
continue;
Expand Down
9 changes: 9 additions & 0 deletions src/vs/editor/browser/viewParts/selections/selections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ export class SelectionsOverlay extends DynamicViewOverlay {
private _selections: Range[];
private _renderResult: string[] | null;

private readonly maxLogsIndex = 10;
private currentIndex = 0;

constructor(context: ViewContext) {
super();
this._context = context;
Expand Down Expand Up @@ -286,6 +289,11 @@ export class SelectionsOverlay extends DynamicViewOverlay {
const top = hasMultipleSelections ? (lineNumber === firstLineNumber ? 1 : 0) : 0;
const bottom = hasMultipleSelections ? (lineNumber !== firstLineNumber && lineNumber === lastLineNumber ? 1 : 0) : 0;

if (this.currentIndex < this.maxLogsIndex) {
console.log('top ', top);
console.log('bottom ', bottom);
}

let innerCornerOutput = '';
let restOfSelectionOutput = '';

Expand Down Expand Up @@ -352,6 +360,7 @@ export class SelectionsOverlay extends DynamicViewOverlay {
output2[lineIndex][0] += innerCornerOutput;
output2[lineIndex][1] += restOfSelectionOutput;
}
this.currentIndex++;
}

private _previousFrameVisibleRangesWithStyle: (LineVisibleRangesWithStyle[] | null)[] = [];
Expand Down
14 changes: 13 additions & 1 deletion src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ export class ViewCursor {
private _lastRenderedContent: string;
private _renderData: ViewCursorRenderData | null;

private readonly maxLogsIndex = 10;
private currentIndex = 0;

constructor(context: ViewContext, plurality: CursorPlurality) {
this._context = context;
const options = this._context.configuration.options;
Expand Down Expand Up @@ -193,7 +196,16 @@ export class ViewCursor {
}

const top = ctx.getVerticalOffsetForLineNumber(position.lineNumber) - ctx.bigNumbersDelta;
return new ViewCursorRenderData(top, left, paddingLeft, width, this._lineHeight, textContent, textContentClassName);
const bottom = ctx.getVerticalOffsetForLineNumber(position.lineNumber + 1) - ctx.bigNumbersDelta;

if (this.currentIndex < this.maxLogsIndex) {
console.log('top : ', top);
console.log('bottom : ', bottom);
console.log('this._lineHeight : ', this._lineHeight);
console.log('bottom - top : ', bottom - top);
}
this.currentIndex++;
return new ViewCursorRenderData(top, left, paddingLeft, width, bottom - top, textContent, textContentClassName);
}

const visibleRangeForCharacter = ctx.linesVisibleRangesForRange(new Range(position.lineNumber, position.column, position.lineNumber, position.column + nextGrapheme.length), false);
Expand Down
5 changes: 4 additions & 1 deletion src/vs/editor/browser/viewParts/viewLines/viewLine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export class ViewLine implements IVisibleLine {
return false;
}

//
public renderLine(lineNumber: number, deltaTop: number, lineHeight: number, viewportData: ViewportData, sb: StringBuilder): boolean {
if (this._options.useGpu && ViewGpuContext.canRender(this._options, viewportData, lineNumber)) {
this._renderedViewLine?.domNode?.domNode.remove();
Expand Down Expand Up @@ -144,7 +145,7 @@ export class ViewLine implements IVisibleLine {
}
}

const renderLineInput = new RenderLineInput(
const renderLineInput = new RenderLineInput( //
options.useMonospaceOptimizations,
options.canUseHalfwidthRightwardsArrow,
lineData.content,
Expand Down Expand Up @@ -174,6 +175,8 @@ export class ViewLine implements IVisibleLine {
sb.appendString('<div style="top:');
sb.appendString(String(deltaTop));
sb.appendString('px;height:');
// sb.appendString(String(lineHeight));
// sb.appendString('px;line-height:');
sb.appendString(String(lineHeight));
sb.appendString('px;" class="');
sb.appendString(ViewLine.CLASS_NAME);
Expand Down
2 changes: 1 addition & 1 deletion src/vs/editor/browser/viewParts/viewLines/viewLines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export class ViewLines extends ViewPart implements IViewLines {
this._stickyScrollEnabled = options.get(EditorOption.stickyScroll).enabled;
this._maxNumberStickyLines = options.get(EditorOption.stickyScroll).maxLineCount;

applyFontInfo(this.domNode, fontInfo);
applyFontInfo(this.domNode, fontInfo); // applying font info, but this needs to be overridden

this._onOptionsMaybeChanged();

Expand Down
3 changes: 3 additions & 0 deletions src/vs/editor/browser/widget/codeEditor/codeEditorWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE

// update all decorations
const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || [];
//
this.changeDecorations(accessor => this._decorationTypeKeysToIds[decorationTypeKey] = accessor.deltaDecorations(oldDecorationsIds, newModelDecorations));
}

Expand Down Expand Up @@ -1906,6 +1907,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
return model;
}

//
private _registerDecorationType(description: string, key: string, options: editorCommon.IDecorationRenderOptions, parentTypeKey?: string): void {
this._codeEditorService.registerDecorationType(description, key, options, parentTypeKey, this);
}
Expand All @@ -1914,6 +1916,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
this._codeEditorService.removeDecorationType(key);
}

//
private _resolveDecorationOptions(typeKey: string, writable: boolean): IModelDecorationOptions {
return this._codeEditorService.resolveDecorationOptions(typeKey, writable);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,9 @@ export class DiffEditorViewZones extends Disposable {
decorations.push(new InlineDecoration(
i.originalRange.delta(-(a.diff.original.startLineNumber - 1)),
diffDeleteDecoration.className!,
InlineDecorationType.Regular
InlineDecorationType.Regular,
diffDeleteDecoration.lineHeight,
diffDeleteDecoration.fontSize
));
}
const result = renderLines(source, renderOptions, decorations, deletedCodeDomNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ function renderOriginalLine(
const lineContent = lineTokens.getLineContent();
const isBasicASCII = ViewLineRenderingData.isBasicASCII(lineContent, mightContainNonBasicASCII);
const containsRTL = ViewLineRenderingData.containsRTL(lineContent, isBasicASCII, mightContainRTL);
const output = renderViewLine(new RenderLineInput(
const output = renderViewLine(new RenderLineInput( //
(options.fontInfo.isMonospace && !options.disableMonospaceOptimizations),
options.fontInfo.canUseHalfwidthRightwardsArrow,
lineContent,
Expand Down
8 changes: 4 additions & 4 deletions src/vs/editor/common/config/editorOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1878,7 +1878,7 @@ class EditorFontInfo extends ComputedEditorOption<EditorOption.fontInfo, FontInf
class EditorFontSize extends SimpleEditorOption<EditorOption.fontSize, number> {

constructor() {
super(
super(//
EditorOption.fontSize, 'fontSize', EDITOR_FONT_DEFAULTS.fontSize,
{
type: 'number',
Expand All @@ -1900,7 +1900,7 @@ class EditorFontSize extends SimpleEditorOption<EditorOption.fontSize, number> {
public override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: number): number {
// The final fontSize respects the editor zoom level.
// So take the result from env.fontInfo
return env.fontInfo.fontSize;
return env.fontInfo.fontSize; //
}
}

Expand Down Expand Up @@ -2401,7 +2401,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
outerWidth: env.outerWidth,
outerHeight: env.outerHeight,
isDominatedByLongLines: env.isDominatedByLongLines,
lineHeight: env.fontInfo.lineHeight,
lineHeight: env.fontInfo.lineHeight, //
viewLineCount: env.viewLineCount,
lineNumbersDigitCount: env.lineNumbersDigitCount,
typicalHalfwidthCharacterWidth: env.fontInfo.typicalHalfwidthCharacterWidth,
Expand Down Expand Up @@ -3080,7 +3080,7 @@ class EditorLineHeight extends EditorFloatOption<EditorOption.lineHeight> {
// The lineHeight is computed from the fontSize if it is 0.
// Moreover, the final lineHeight respects the editor zoom level.
// So take the result from env.fontInfo
return env.fontInfo.lineHeight;
return env.fontInfo.lineHeight; //
}
}

Expand Down
Loading
Loading