diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index 37bfa467466c6a..2935a8bbb12259 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -210,6 +210,10 @@ class MinimapLayout { * used space beween the lines in line data */ public readonly emptySpaceBetweenLines: number; + /** + * how many lines to skip per line rendered + */ + public readonly skipLines: number; /** * used fontScaling for rendering characters */ @@ -241,6 +245,7 @@ class MinimapLayout { usedRenderMinimap: RenderMinimap, usedRenderLineHeight: RenderMinimap, emptySpaceBetweenLines: number, + skipLines: number, fontScale: number, coversAllLines: boolean, lineCount: number, @@ -258,6 +263,7 @@ class MinimapLayout { this.renderMinimap = usedRenderMinimap; this.renderLineHeight = usedRenderLineHeight; this.emptySpaceBetweenLines = emptySpaceBetweenLines; + this.skipLines = skipLines; this.fontScale = fontScale; this.coversAllLines = coversAllLines; this.lineCount = lineCount; @@ -280,6 +286,7 @@ class MinimapLayout { this.endLineNumber, this.displayLineHeight, this.emptySpaceBetweenLines, + this.skipLines, this.fontScale, this.renderMinimap, this.renderLineHeight, @@ -404,7 +411,7 @@ class MinimapLayout { return new MinimapLayout(scrollTop, scrollHeight , computedSliderRatio, sliderTop, maxMinimapSliderTop, sliderHeight , startLineNumber, endLineNumber, minimapLineHeight - , renderMinimap, renderLineHeight, emptySpaceBetweenLines, fontScale + , renderMinimap, renderLineHeight, emptySpaceBetweenLines, 0, fontScale , coversAllLines, lineCount, options); } else { let startLineNumber = Math.max(1, Math.floor(viewportStartLineNumber - sliderTop * pixelRatio / minimapLineHeight)); @@ -423,11 +430,12 @@ class MinimapLayout { } const endLineNumber = Math.min(lineCount, startLineNumber + minimapLinesFitting - 1); + const skipLines = Math.max(0, Math.floor(1 / minimapLineHeight) - 1); return new MinimapLayout(scrollTop, scrollHeight , computedSliderRatio, sliderTop, maxMinimapSliderTop, sliderHeight , startLineNumber, endLineNumber, minimapLineHeight - , renderMinimap, renderLineHeight, emptySpaceBetweenLines, fontScale + , renderMinimap, renderLineHeight, emptySpaceBetweenLines, skipLines, fontScale , coversAllLines, lineCount, options); } } @@ -545,9 +553,8 @@ class MinimapBuffers { this._lastUsedBuffer = 0; } - public hasSameSize(WIDTH: number, HEIGHT: number): boolean { - return (this._buffers[0].width === WIDTH) && (this._buffers[0].height === HEIGHT); - } + public getWidth(): number { return this._buffers[1 - this._lastUsedBuffer].width; } + public getHeight(): number { return this._buffers[1 - this._lastUsedBuffer].height; } public getBuffer(): ImageData { // rotate buffers @@ -799,11 +806,13 @@ export class Minimap extends ViewPart { } private _getBuffer(WIDTH: number, HEIGHT: number): ImageData { - if (!this._buffers || !this._buffers.hasSameSize(WIDTH, HEIGHT)) { + if (!this._buffers + || (this._buffers.getWidth() !== WIDTH) + || (this._buffers.getHeight() < HEIGHT)) { this._buffers = new MinimapBuffers( this._canvas.domNode.getContext('2d')!, WIDTH, - HEIGHT, + HEIGHT + 64, // overallocate so, chances are we won't need a new buffer soon this._tokensColorTracker.getColor(ColorId.DefaultBackground) ); } @@ -1038,8 +1047,8 @@ export class Minimap extends ViewPart { private renderLines(layout: MinimapLayout): RenderData { const renderMinimap = layout.renderMinimap; - const startLineNumber = layout.startLineNumber; - const endLineNumber = layout.endLineNumber; + const startLineNumber2 = Math.max(1, Math.floor(layout.startLineNumber / (1 + layout.skipLines))); + const endLineNumber2 = Math.floor(layout.endLineNumber / (1 + layout.skipLines)); const minimapLineHeight = layout.renderLineHeight; if (this._lastRenderData @@ -1062,20 +1071,32 @@ export class Minimap extends ViewPart { // Oh well!! We need to repaint some lines... const width = this._options.canvasInnerWidth; - const height = layout.options.entireDocument ? layout.lineCount * (minimapLineHeight + layout.emptySpaceBetweenLines) : this._options.canvasInnerHeight; + let height = this._options.canvasInnerHeight; + if (layout.options.entireDocument) { + height = Math.floor(layout.lineCount * (minimapLineHeight + layout.emptySpaceBetweenLines) / (1 + layout.skipLines)); + } const imageData = this._getBuffer(width, height); // Render untouched lines by using last rendered data. let [_dirtyY1, _dirtyY2, needed] = Minimap._renderUntouchedLines( imageData, - startLineNumber, - endLineNumber, + startLineNumber2, + endLineNumber2, minimapLineHeight + layout.emptySpaceBetweenLines, this._lastRenderData ); + const needed2: boolean[] = []; + for (let i = 0; i < needed.length; ++i) { + let i2 = i * (1 + layout.skipLines); + needed2[i2] = needed[i]; + for (let j = 1; j <= layout.skipLines; ++j) { + needed2[i2 + j] = false; + } + } + // Fetch rendering info from view model for rest of lines that need rendering. - const lineInfo = this._context.model.getMinimapLinesRenderingData(startLineNumber, endLineNumber, needed); + const lineInfo = this._context.model.getMinimapLinesRenderingData(layout.startLineNumber, layout.endLineNumber, needed2); const tabSize = lineInfo.tabSize; const background = this._tokensColorTracker.getColor(ColorId.DefaultBackground); const useLighterFont = this._tokensColorTracker.backgroundIsLight(); @@ -1084,7 +1105,7 @@ export class Minimap extends ViewPart { // Render the rest of lines let dy = 0; const renderedLines: MinimapLine[] = []; - for (let lineIndex = 0, lineCount = endLineNumber - startLineNumber + 1; lineIndex < lineCount; lineIndex++) { + for (let lineIndex = 0, lineCount = endLineNumber2 - startLineNumber2 + 1; lineIndex < lineCount; lineIndex++) { if (needed[lineIndex]) { Minimap._renderLine( imageData, @@ -1096,7 +1117,7 @@ export class Minimap extends ViewPart { dy + layout.emptySpaceBetweenLines, tabSize, oneline, - lineInfo.data[lineIndex]!, + lineInfo.data[lineIndex * (1 + layout.skipLines)]!, layout.fontScale ); } @@ -1112,15 +1133,17 @@ export class Minimap extends ViewPart { // this fill rect could be reduced to only the empty part below the minimap // and droped completely if "Scroll Beyond Last Line" is disabled ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); - let bitmap = createImageBitmap(imageData); - bitmap.then((bitmap: ImageBitmap) => + let bitmap = createImageBitmap(imageData, 0, 0, width, height); + bitmap.then((bitmap: ImageBitmap) => { ctx.drawImage(bitmap, 0, 0, width, height, 0, 0, width, - Math.min(this._options.canvasInnerHeight, layout.displayLineHeight * layout.endLineNumber))); + Math.min(this._options.canvasInnerHeight, layout.displayLineHeight * layout.endLineNumber)); + bitmap.close(); + }); } else { const dirtyY1 = (_dirtyY1 === -1 ? 0 : _dirtyY1); const dirtyY2 = (_dirtyY2 === -1 ? imageData.height : _dirtyY2);