From bb709f58d91ce08133ed963be7283eb79c7465c8 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 30 Sep 2015 16:15:49 +0200 Subject: [PATCH] :racehorse: Cache pixel positions --- src/lines-yardstick.coffee | 31 ++++++++++++++++++++----------- src/text-editor-component.coffee | 10 +++++++--- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/lines-yardstick.coffee b/src/lines-yardstick.coffee index b445ab643..07fff489a 100644 --- a/src/lines-yardstick.coffee +++ b/src/lines-yardstick.coffee @@ -6,6 +6,10 @@ class LinesYardstick constructor: (@model, @presenter, @lineNodesProvider) -> @tokenIterator = new TokenIterator @rangeForMeasurement = document.createRange() + @invalidateCache() + + invalidateCache: -> + @pixelPositionsByLineIdAndColumn = {} prepareScreenRowsForMeasurement: (screenRows) -> @presenter.setScreenRowsToMeasure(screenRows) @@ -21,15 +25,15 @@ class LinesYardstick row = Math.min(row, @model.getLastScreenRow()) row = Math.max(0, row) - tokenizedLine = @model.tokenizedLineForScreenRow(row) - lineNode = @lineNodesProvider.lineNodeForLineIdAndScreenRow(tokenizedLine.id, row) + line = @model.tokenizedLineForScreenRow(row) + lineNode = @lineNodesProvider.lineNodeForLineIdAndScreenRow(line?.id, row) - return new Point(row, 0) unless lineNode? and tokenizedLine? + return new Point(row, 0) unless lineNode? and line? iterator = document.createNodeIterator(lineNode, NodeFilter.SHOW_TEXT) charIndex = 0 - @tokenIterator.reset(tokenizedLine) + @tokenIterator.reset(line) while @tokenIterator.next() text = @tokenIterator.getText() textIndex = 0 @@ -77,19 +81,19 @@ class LinesYardstick {top, left} leftPixelPositionForScreenPosition: (row, column) -> - tokenizedLine = @model.tokenizedLineForScreenRow(row) - return 0 unless tokenizedLine? + line = @model.tokenizedLineForScreenRow(row) + lineNode = @lineNodesProvider.lineNodeForLineIdAndScreenRow(line?.id, row) - lineNode = - @lineNodesProvider.lineNodeForLineIdAndScreenRow(tokenizedLine.id, row) + return 0 unless line? and lineNode? - return 0 unless lineNode? + if cachedPosition = @pixelPositionsByLineIdAndColumn[line.id]?[column] + return cachedPosition indexWithinTextNode = null iterator = document.createNodeIterator(lineNode, NodeFilter.SHOW_TEXT) charIndex = 0 - @tokenIterator.reset(tokenizedLine) + @tokenIterator.reset(line) while @tokenIterator.next() break if foundIndexWithinTextNode? @@ -126,7 +130,12 @@ class LinesYardstick if textNode? foundIndexWithinTextNode ?= textNode.textContent.length - @leftPixelPositionForCharInTextNode(lineNode, textNode, foundIndexWithinTextNode) + position = @leftPixelPositionForCharInTextNode( + lineNode, textNode, foundIndexWithinTextNode + ) + @pixelPositionsByLineIdAndColumn[line.id] ?= {} + @pixelPositionsByLineIdAndColumn[line.id][column] = position + position else 0 diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 0ed7df25e..235ab4a0e 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -560,7 +560,7 @@ class TextEditorComponent handleStylingChange: => @sampleFontStyling() @sampleBackgroundColors() - @presenter.characterWidthsChanged() + @invalidateCharacterWidths() handleDragUntilMouseUp: (dragHandler) => dragging = false @@ -823,7 +823,7 @@ class TextEditorComponent setFontSize: (fontSize) -> @getTopmostDOMNode().style.fontSize = fontSize + 'px' @sampleFontStyling() - @presenter.characterWidthsChanged() + @invalidateCharacterWidths() getFontFamily: -> getComputedStyle(@getTopmostDOMNode()).fontFamily @@ -831,11 +831,15 @@ class TextEditorComponent setFontFamily: (fontFamily) -> @getTopmostDOMNode().style.fontFamily = fontFamily @sampleFontStyling() - @presenter.characterWidthsChanged() + @invalidateCharacterWidths() setLineHeight: (lineHeight) -> @getTopmostDOMNode().style.lineHeight = lineHeight @sampleFontStyling() + @invalidateCharacterWidths() + + invalidateCharacterWidths: -> + @linesYardstick.invalidateCache() @presenter.characterWidthsChanged() setShowIndentGuide: (showIndentGuide) ->