diff --git a/lib/mixins/canvas-drawer.js b/lib/mixins/canvas-drawer.js index eb36f528..14960097 100644 --- a/lib/mixins/canvas-drawer.js +++ b/lib/mixins/canvas-drawer.js @@ -122,9 +122,33 @@ export default class CanvasDrawer extends Mixin { const firstRow = this.minimap.getFirstVisibleScreenRow() const lastRow = this.minimap.getLastVisibleScreenRow() - this.updateTokensLayer(firstRow, lastRow) - this.updateBackDecorationsLayer(firstRow, lastRow) - this.updateFrontDecorationsLayer(firstRow, lastRow) + const devicePixelRatio = this.minimap.getDevicePixelRatio() + const lineHeight = this.minimap.getLineHeight() * devicePixelRatio + const charHeight = this.minimap.getCharHeight() * devicePixelRatio + const charWidth = this.minimap.getCharWidth() * devicePixelRatio + const { width: canvasWidth, height: canvasHeight } = this.tokensLayer.getSize() + const editor = this.minimap.getTextEditor() + const editorElement = this.minimap.getTextEditorElement() + + this.updateTokensLayer(firstRow, lastRow, lineHeight, charHeight, charWidth, canvasWidth, this.tokensLayer.context, editor, editorElement, this.displayCodeHighlights, this.ignoreWhitespacesInTokens, this.maxTokensInOneLine) + + const decorations = this.minimap.decorationsByTypeThenRows(firstRow, lastRow) + + const renderData = { + context: this.backLayer.context, + canvasWidth, + canvasHeight, + lineHeight, + charWidth, + charHeight, + orders: Main.getPluginsOrder() + } + + this.updateBackDecorationsLayer(firstRow, lastRow, renderData, lineHeight, editorElement, decorations) + + renderData.context = this.frontLayer.context + + this.updateFrontDecorationsLayer(firstRow, lastRow, renderData, lineHeight, editorElement, decorations) this.pendingChanges = [] this.pendingBackDecorationChanges = [] @@ -149,12 +173,56 @@ export default class CanvasDrawer extends Mixin { * * @param {number} firstRow firstRow the first row of the range to update * @param {number} lastRow lastRow the last row of the range to update + * + * @param {number} lineHeight this.minimap.getLineHeight() * devicePixelRatio + * @param {number} charHeight this.minimap.getCharHeight() * devicePixelRatio + * @param {number} charWidth this.minimap.getCharWidth() * devicePixelRatio + * @param {number} canvasWidth this.tokensLayer.getSize().width + * @param {CanvasRenderingContext2D} context this.tokensLayer.context + * @param {TextEditor} editor this.minimap.getTextEditor() + * @param {TextEditorElement} editorElement this.minimap.getTextEditorElement() + * @param {boolean} displayCodeHighlights this.displayCodeHighlights + * @param {boolean} ignoreWhitespacesInTokens this.ignoreWhitespacesInTokens + * @param {number} maxTokensInOneLine this.maxTokensInOneLine * @access private */ - updateTokensLayer (firstRow, lastRow) { + updateTokensLayer (firstRow, lastRow, lineHeight, charHeight, charWidth, canvasWidth, context, editor, editorElement, displayCodeHighlights, ignoreWhitespacesInTokens, maxTokensInOneLine) { const intactRanges = computeIntactRanges(firstRow, lastRow, this.pendingChanges, this.offscreenFirstRow, this.offscreenLastRow) - this.redrawRangesOnLayer(this.tokensLayer, intactRanges, firstRow, lastRow, this.drawLines) + // NOTE: this method is the hot function of Minimap. Do not refactor. The code is inlined delibarately. + + // redrawRangesOnLayer inlined (this.redrawRangesOnLayer(this.tokensLayer, intactRanges, firstRow, lastRow, this.drawLines)) + + this.tokensLayer.clearCanvas() + + if (intactRanges.length === 0) { + this.drawLines(firstRow, lastRow, 0, lineHeight, charHeight, charWidth, canvasWidth, context, editor, editorElement, displayCodeHighlights, ignoreWhitespacesInTokens, maxTokensInOneLine) + } else { + for (let j = 0, len = intactRanges.length; j < len; j++) { + const intact = intactRanges[j] + + this.tokensLayer.copyPartFromOffscreen( + intact.offscreenRow * lineHeight, + (intact.start - firstRow) * lineHeight, + (intact.end - intact.start) * lineHeight + ) + } + // drawLinesForRanges inlined + let currentRow = firstRow + for (let i = 0, len = intactRanges.length; i < len; i++) { + const range = intactRanges[i] + + this.drawLines(currentRow, range.start, currentRow - firstRow, lineHeight, charHeight, charWidth, canvasWidth, context, editor, editorElement, displayCodeHighlights, ignoreWhitespacesInTokens, maxTokensInOneLine) + + currentRow = range.end + } + if (currentRow <= lastRow) { + this.drawLines(currentRow, lastRow, currentRow - firstRow, lineHeight, charHeight, charWidth, canvasWidth, context, editor, editorElement, displayCodeHighlights, ignoreWhitespacesInTokens, maxTokensInOneLine) + } + } + + this.tokensLayer.resetOffscreenSize() + this.tokensLayer.copyToOffscreen() } /** @@ -163,12 +231,50 @@ export default class CanvasDrawer extends Mixin { * * @param {number} firstRow firstRow the first row of the range to update * @param {number} lastRow lastRow the last row of the range to update + * + * @param {Object} renderData + * @param {number} lineHeight this.minimap.getLineHeight() * devicePixelRatio + * @param {TextEditorElement} editorElement this.minimap.getTextEditorElement() + * @param {Array} decorations * @access private */ - updateBackDecorationsLayer (firstRow, lastRow) { + updateBackDecorationsLayer (firstRow, lastRow, renderData, lineHeight, editorElement, decorations) { const intactRanges = computeIntactRanges(firstRow, lastRow, this.pendingBackDecorationChanges, this.offscreenFirstRow, this.offscreenLastRow) - this.redrawRangesOnLayer(this.backLayer, intactRanges, firstRow, lastRow, this.drawBackDecorationsForLines) + // NOTE: this method is the hot function of Minimap. Do not refactor. The code is inlined delibarately. + + // redrawRangesOnLayer inlined (this.redrawRangesOnLayer(this.backLayer, intactRanges, firstRow, lastRow, this.drawBackDecorationsForLines) + + this.backLayer.clearCanvas() + + if (intactRanges.length === 0) { + this.drawBackDecorationsForLines(firstRow, lastRow, 0, renderData, lineHeight, editorElement, decorations) + } else { + for (let j = 0, len = intactRanges.length; j < len; j++) { + const intact = intactRanges[j] + + this.backLayer.copyPartFromOffscreen( + intact.offscreenRow * lineHeight, + (intact.start - firstRow) * lineHeight, + (intact.end - intact.start) * lineHeight + ) + } + // drawLinesForRanges inlined + let currentRow = firstRow + for (let i = 0, len = intactRanges.length; i < len; i++) { + const range = intactRanges[i] + + this.drawBackDecorationsForLines(currentRow, range.start, currentRow - firstRow, renderData, lineHeight, editorElement, decorations) + + currentRow = range.end + } + if (currentRow <= lastRow) { + this.drawBackDecorationsForLines(currentRow, lastRow, currentRow - firstRow, renderData, lineHeight, editorElement, decorations) + } + } + + this.backLayer.resetOffscreenSize() + this.backLayer.copyToOffscreen() } /** @@ -177,12 +283,50 @@ export default class CanvasDrawer extends Mixin { * * @param {number} firstRow firstRow the first row of the range to update * @param {number} lastRow lastRow the last row of the range to update + * + * @param {Object} renderData + * @param {number} lineHeight this.minimap.getLineHeight() * devicePixelRatio + * @param {TextEditorElement} editorElement this.minimap.getTextEditorElement() + * @param {Array} decorations * @access private */ - updateFrontDecorationsLayer (firstRow, lastRow) { + updateFrontDecorationsLayer (firstRow, lastRow, renderData, lineHeight, editorElement, decorations) { const intactRanges = computeIntactRanges(firstRow, lastRow, this.pendingFrontDecorationChanges, this.offscreenFirstRow, this.offscreenLastRow) - this.redrawRangesOnLayer(this.frontLayer, intactRanges, firstRow, lastRow, this.drawFrontDecorationsForLines) + // NOTE: this method is the hot function of Minimap. Do not refactor. The code is inlined delibarately. + + // redrawRangesOnLayer inlined (this.frontLayer(this.frontLayer, intactRanges, firstRow, lastRow, this.drawFrontDecorationsForLines) + + this.frontLayer.clearCanvas() + + if (intactRanges.length === 0) { + this.drawFrontDecorationsForLines(firstRow, lastRow, 0, renderData, lineHeight, editorElement, decorations) + } else { + for (let j = 0, len = intactRanges.length; j < len; j++) { + const intact = intactRanges[j] + + this.frontLayer.copyPartFromOffscreen( + intact.offscreenRow * lineHeight, + (intact.start - firstRow) * lineHeight, + (intact.end - intact.start) * lineHeight + ) + } + // drawLinesForRanges inlined + let currentRow = firstRow + for (let i = 0, len = intactRanges.length; i < len; i++) { + const range = intactRanges[i] + + this.drawFrontDecorationsForLines(currentRow, range.start, currentRow - firstRow, renderData, lineHeight, editorElement, decorations) + + currentRow = range.end + } + if (currentRow <= lastRow) { + this.drawFrontDecorationsForLines(currentRow, lastRow, currentRow - firstRow, renderData, lineHeight, editorElement, decorations) + } + } + + this.frontLayer.resetOffscreenSize() + this.frontLayer.copyToOffscreen() } // ###### ####### ## ####### ######## ###### @@ -269,31 +413,32 @@ export default class CanvasDrawer extends Mixin { * @param {number} lastRow lastRow the last row of the range to update * @param {Function} method the render method to use for the lines drawing * @access private + * Unused (inlined the code for performance reasons) */ - redrawRangesOnLayer (layer, intactRanges, firstRow, lastRow, method) { - const devicePixelRatio = this.minimap.getDevicePixelRatio() - const lineHeight = this.minimap.getLineHeight() * devicePixelRatio - - layer.clearCanvas() - - if (intactRanges.length === 0) { - method.call(this, firstRow, lastRow, 0) - } else { - for (let j = 0, len = intactRanges.length; j < len; j++) { - const intact = intactRanges[j] - - layer.copyPartFromOffscreen( - intact.offscreenRow * lineHeight, - (intact.start - firstRow) * lineHeight, - (intact.end - intact.start) * lineHeight - ) - } - this.drawLinesForRanges(method, intactRanges, firstRow, lastRow) - } - - layer.resetOffscreenSize() - layer.copyToOffscreen() - } + // redrawRangesOnLayer (layer, intactRanges, firstRow, lastRow, method) { + // const devicePixelRatio = this.minimap.getDevicePixelRatio() + // const lineHeight = this.minimap.getLineHeight() * devicePixelRatio + // + // layer.clearCanvas() + // + // if (intactRanges.length === 0) { + // method.call(this, firstRow, lastRow, 0) + // } else { + // for (let j = 0, len = intactRanges.length; j < len; j++) { + // const intact = intactRanges[j] + // + // layer.copyPartFromOffscreen( + // intact.offscreenRow * lineHeight, + // (intact.start - firstRow) * lineHeight, + // (intact.end - intact.start) * lineHeight + // ) + // } + // this.drawLinesForRanges(method, intactRanges, firstRow, lastRow) + // } + // + // layer.resetOffscreenSize() + // layer.copyToOffscreen() + // } /** * Renders the lines between the intact ranges when an update has pending @@ -304,20 +449,21 @@ export default class CanvasDrawer extends Mixin { * @param {number} firstRow the first row of the rendered region * @param {number} lastRow the last row of the rendered region * @access private + * Unused (inlined the code for performance reasons) */ - drawLinesForRanges (method, ranges, firstRow, lastRow) { - let currentRow = firstRow - for (let i = 0, len = ranges.length; i < len; i++) { - const range = ranges[i] - - method.call(this, currentRow, range.start, currentRow - firstRow) - - currentRow = range.end - } - if (currentRow <= lastRow) { - method.call(this, currentRow, lastRow, currentRow - firstRow) - } - } + // drawLinesForRanges (method, ranges, firstRow, lastRow) { + // let currentRow = firstRow + // for (let i = 0, len = ranges.length; i < len; i++) { + // const range = ranges[i] + // + // method.call(this, currentRow, range.start, currentRow - firstRow) + // + // currentRow = range.end + // } + // if (currentRow <= lastRow) { + // method.call(this, currentRow, lastRow, currentRow - firstRow) + // } + // } /** * Draws back decorations on the corresponding layer. @@ -329,28 +475,16 @@ export default class CanvasDrawer extends Mixin { * @param {number} lastRow the last row to render * @param {number} offsetRow the relative offset to apply to rows when * rendering them + * + * @param {Object} renderData + * @param {number} lineHeight this.minimap.getLineHeight() * devicePixelRatio + * @param {TextEditorElement} editorElement this.minimap.getTextEditorElement() + * @param {Array} decorations * @access private */ - drawBackDecorationsForLines (firstRow, lastRow, offsetRow) { + drawBackDecorationsForLines (firstRow, lastRow, offsetRow, renderData, lineHeight, editorElement, decorations) { if (firstRow > lastRow) { return } - const devicePixelRatio = this.minimap.getDevicePixelRatio() - const lineHeight = this.minimap.getLineHeight() * devicePixelRatio - const charHeight = this.minimap.getCharHeight() * devicePixelRatio - const charWidth = this.minimap.getCharWidth() * devicePixelRatio - const decorations = this.minimap.decorationsByTypeThenRows(firstRow, lastRow) - const { width: canvasWidth, height: canvasHeight } = this.tokensLayer.getSize() - const renderData = { - context: this.backLayer.context, - canvasWidth, - canvasHeight, - lineHeight, - charWidth, - charHeight, - orders: Main.getPluginsOrder() - } - const editorElement = this.minimap.getTextEditorElement() - const drawCustomDecorationLambda = (decoration, data, decorationColor) => drawCustomDecoration(decoration, data, decorationColor, editorElement) backgroundDecorationDispatcher['background-custom'] = drawCustomDecorationLambda @@ -362,7 +496,7 @@ export default class CanvasDrawer extends Mixin { this.drawDecorations(screenRow, decorations, renderData, backgroundDecorationDispatcher, editorElement) } - this.backLayer.context.fill() + renderData.context.fill() } /** @@ -375,29 +509,16 @@ export default class CanvasDrawer extends Mixin { * @param {number} lastRow the last row to render * @param {number} offsetRow the relative offset to apply to rows when * rendering them + * + * @param {Object} renderData + * @param {number} lineHeight this.minimap.getLineHeight() * devicePixelRatio + * @param {TextEditorElement} editorElement this.minimap.getTextEditorElement() + * @param {Array} decorations * @access private */ - drawFrontDecorationsForLines (firstRow, lastRow, offsetRow) { + drawFrontDecorationsForLines (firstRow, lastRow, offsetRow, renderData, lineHeight, editorElement, decorations) { if (firstRow > lastRow) { return } - const devicePixelRatio = this.minimap.getDevicePixelRatio() - const lineHeight = this.minimap.getLineHeight() * devicePixelRatio - const charHeight = this.minimap.getCharHeight() * devicePixelRatio - const charWidth = this.minimap.getCharWidth() * devicePixelRatio - const decorations = this.minimap.decorationsByTypeThenRows(firstRow, lastRow) - const { width: canvasWidth, height: canvasHeight } = this.tokensLayer.getSize() - const renderData = { - context: this.frontLayer.context, - canvasWidth, - canvasHeight, - lineHeight, - charWidth, - charHeight, - orders: Main.getPluginsOrder() - } - - const editorElement = this.minimap.getTextEditorElement() - const drawCustomDecorationLambda = (decoration, data, decorationColor) => drawCustomDecoration(decoration, data, decorationColor, editorElement) frontDecorationDispatcher['foreground-custom'] = drawCustomDecorationLambda @@ -422,25 +543,26 @@ export default class CanvasDrawer extends Mixin { * @param {number} lastRow the last row to render * @param {number} offsetRow the relative offset to apply to rows when * rendering them + * @param {number} lineHeight this.minimap.getLineHeight() * devicePixelRatio + * @param {number} charHeight this.minimap.getCharHeight() * devicePixelRatio + * @param {number} charWidth this.minimap.getCharWidth() * devicePixelRatio + * @param {number} canvasWidth this.tokensLayer.getSize().width + * @param {CanvasRenderingContext2D} context this.tokensLayer.context + * @param {TextEditor} editor this.minimap.getTextEditor() + * @param {TextEditorElement} editorElement this.minimap.getTextEditorElement() + * @param {boolean} displayCodeHighlights this.displayCodeHighlights + * @param {boolean} ignoreWhitespacesInTokens this.ignoreWhitespacesInTokens + * @param {number} maxTokensInOneLine this.maxTokensInOneLine * @access private */ - drawLines (firstRow, lastRow, offsetRow) { - if (firstRow > lastRow) { return } + drawLines (firstRow, lastRow, offsetRow, lineHeight, charHeight, charWidth, canvasWidth, context, editor, editorElement, displayCodeHighlights, ignoreWhitespacesInTokens, maxTokensInOneLine) { + // NOTE: this method is the hot function of Minimap. Do not refactor. The code is inlined delibarately. - const devicePixelRatio = this.minimap.getDevicePixelRatio() - const lineHeight = this.minimap.getLineHeight() * devicePixelRatio - const charHeight = this.minimap.getCharHeight() * devicePixelRatio - const charWidth = this.minimap.getCharWidth() * devicePixelRatio - const displayCodeHighlights = this.displayCodeHighlights - const context = this.tokensLayer.context - const { width: canvasWidth } = this.tokensLayer.getSize() - - const editor = this.minimap.getTextEditor() - const editorElement = this.minimap.getTextEditorElement() + if (firstRow > lastRow) { return } let lastLine, x let y = (offsetRow * lineHeight) - lineHeight - eachTokenForScreenRows(firstRow, lastRow, editor, this.maxTokensInOneLine, (line, token) => { + eachTokenForScreenRows(firstRow, lastRow, editor, maxTokensInOneLine, (line, token) => { if (lastLine !== line) { x = 0 y += lineHeight @@ -457,7 +579,7 @@ export default class CanvasDrawer extends Mixin { : this.getDefaultColor(editorElement) x = drawToken( - context, token.text, color, x, y, charWidth, charHeight, this.ignoreWhitespacesInTokens + context, token.text, color, x, y, charWidth, charHeight, ignoreWhitespacesInTokens ) } })