diff --git a/spec/lines-yardstick-spec.coffee b/spec/lines-yardstick-spec.coffee index 224dea614..2112589bc 100644 --- a/spec/lines-yardstick-spec.coffee +++ b/spec/lines-yardstick-spec.coffee @@ -139,70 +139,87 @@ describe "LinesYardstick", -> expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 36)).left).toBe 237.5 expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 37)).left).toBe 244.09375 - describe "::screenPositionForPixelPosition(pixelPosition)", -> - it "converts pixel positions to screen positions", -> + if process.platform is 'darwin' # Expectations fail on win32 + it "handles lines containing a mix of left-to-right and right-to-left characters", -> + editor.setText('Persian, locally known as Parsi or Farsi (زبان فارسی), the predominant modern descendant of Old Persian.\n') + atom.styles.addStyleSheet """ * { - font-size: 12px; - font-family: monospace; - } - .syntax--function { - font-size: 16px - } - """ - - expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 12.5})).toEqual([0, 2]) - expect(linesYardstick.screenPositionForPixelPosition({top: 14, left: 18.8})).toEqual([1, 3]) - expect(linesYardstick.screenPositionForPixelPosition({top: 28, left: 100})).toEqual([2, 14]) - expect(linesYardstick.screenPositionForPixelPosition({top: 32, left: 24.3})).toEqual([2, 3]) - expect(linesYardstick.screenPositionForPixelPosition({top: 46, left: 66.5})).toEqual([3, 9]) - expect(linesYardstick.screenPositionForPixelPosition({top: 70, left: 99.9})).toEqual([5, 14]) - expect(linesYardstick.screenPositionForPixelPosition({top: 70, left: 225})).toEqual([5, 30]) - - return unless process.platform is 'darwin' # Following tests are 1 pixel off on Win32 - expect(linesYardstick.screenPositionForPixelPosition({top: 70, left: 224.2365234375})).toEqual([5, 29]) - expect(linesYardstick.screenPositionForPixelPosition({top: 84, left: 247.1})).toEqual([6, 33]) - - it "overshoots to the nearest character when text nodes are not spatially contiguous", -> - atom.styles.addStyleSheet """ - * { - font-size: 12px; + font-size: 14px; font-family: monospace; } """ - buildLineNode = (screenRow) -> - lineNode = document.createElement("div") - lineNode.style.whiteSpace = "pre" - lineNode.innerHTML = 'foobar' - jasmine.attachToDOM(lineNode) - createdLineNodes.push(lineNode) - lineNode - editor.setText("foobar") + lineTopIndex = new LineTopIndex({defaultLineHeight: editor.getLineHeightInPixels()}) + linesYardstick = new LinesYardstick(editor, mockLineNodesProvider, lineTopIndex, atom.grammars) + expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 15))).toEqual({left: 126, top: 0}) + expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 62))).toEqual({left: 521, top: 0}) + expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 58))).toEqual({left: 487, top: 0}) + expect(linesYardstick.pixelPositionForScreenPosition(Point(0, Infinity))).toEqual({left: 873.625, top: 0}) - expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 7})).toEqual([0, 1]) - expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 14})).toEqual([0, 2]) - expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 21})).toEqual([0, 3]) - expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 30})).toEqual([0, 3]) - expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 50})).toEqual([0, 3]) - expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 62})).toEqual([0, 3]) - expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 69})).toEqual([0, 4]) - expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 76})).toEqual([0, 5]) - expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 100})).toEqual([0, 6]) - expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 200})).toEqual([0, 6]) + describe "::screenPositionForPixelPosition(pixelPosition)", -> + it "converts pixel positions to screen positions", -> + atom.styles.addStyleSheet """ + * { + font-size: 12px; + font-family: monospace; + } + .syntax--function { + font-size: 16px + } + """ - it "clips pixel positions above buffer start", -> - expect(linesYardstick.screenPositionForPixelPosition(top: -Infinity, left: -Infinity)).toEqual [0, 0] - expect(linesYardstick.screenPositionForPixelPosition(top: -Infinity, left: Infinity)).toEqual [0, 0] - expect(linesYardstick.screenPositionForPixelPosition(top: -1, left: Infinity)).toEqual [0, 0] - expect(linesYardstick.screenPositionForPixelPosition(top: 0, left: Infinity)).toEqual [0, 29] + expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 12.5})).toEqual([0, 2]) + expect(linesYardstick.screenPositionForPixelPosition({top: 14, left: 18.8})).toEqual([1, 3]) + expect(linesYardstick.screenPositionForPixelPosition({top: 28, left: 100})).toEqual([2, 14]) + expect(linesYardstick.screenPositionForPixelPosition({top: 32, left: 24.3})).toEqual([2, 3]) + expect(linesYardstick.screenPositionForPixelPosition({top: 46, left: 66.5})).toEqual([3, 9]) + expect(linesYardstick.screenPositionForPixelPosition({top: 70, left: 99.9})).toEqual([5, 14]) + expect(linesYardstick.screenPositionForPixelPosition({top: 70, left: 225})).toEqual([5, 30]) + return unless process.platform is 'darwin' # Following tests are 1 pixel off on Win32 + expect(linesYardstick.screenPositionForPixelPosition({top: 70, left: 224.2365234375})).toEqual([5, 29]) + expect(linesYardstick.screenPositionForPixelPosition({top: 84, left: 247.1})).toEqual([6, 33]) - it "clips pixel positions below buffer end", -> - expect(linesYardstick.screenPositionForPixelPosition(top: Infinity, left: -Infinity)).toEqual [12, 2] - expect(linesYardstick.screenPositionForPixelPosition(top: Infinity, left: Infinity)).toEqual [12, 2] - expect(linesYardstick.screenPositionForPixelPosition(top: (editor.getLastScreenRow() + 1) * 14, left: 0)).toEqual [12, 2] - expect(linesYardstick.screenPositionForPixelPosition(top: editor.getLastScreenRow() * 14, left: 0)).toEqual [12, 0] + it "overshoots to the nearest character when text nodes are not spatially contiguous", -> + atom.styles.addStyleSheet """ + * { + font-size: 12px; + font-family: monospace; + } + """ - it "clips negative horizontal pixel positions", -> - expect(linesYardstick.screenPositionForPixelPosition(top: 0, left: -10)).toEqual [0, 0] - expect(linesYardstick.screenPositionForPixelPosition(top: 1 * 14, left: -10)).toEqual [1, 0] + buildLineNode = (screenRow) -> + lineNode = document.createElement("div") + lineNode.style.whiteSpace = "pre" + lineNode.innerHTML = 'foobar' + jasmine.attachToDOM(lineNode) + createdLineNodes.push(lineNode) + lineNode + editor.setText("foobar") + + expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 7})).toEqual([0, 1]) + expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 14})).toEqual([0, 2]) + expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 21})).toEqual([0, 3]) + expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 30})).toEqual([0, 3]) + expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 50})).toEqual([0, 3]) + expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 62})).toEqual([0, 3]) + expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 69})).toEqual([0, 4]) + expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 76})).toEqual([0, 5]) + expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 100})).toEqual([0, 6]) + expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 200})).toEqual([0, 6]) + + it "clips pixel positions above buffer start", -> + expect(linesYardstick.screenPositionForPixelPosition(top: -Infinity, left: -Infinity)).toEqual [0, 0] + expect(linesYardstick.screenPositionForPixelPosition(top: -Infinity, left: Infinity)).toEqual [0, 0] + expect(linesYardstick.screenPositionForPixelPosition(top: -1, left: Infinity)).toEqual [0, 0] + expect(linesYardstick.screenPositionForPixelPosition(top: 0, left: Infinity)).toEqual [0, 29] + + it "clips pixel positions below buffer end", -> + expect(linesYardstick.screenPositionForPixelPosition(top: Infinity, left: -Infinity)).toEqual [12, 2] + expect(linesYardstick.screenPositionForPixelPosition(top: Infinity, left: Infinity)).toEqual [12, 2] + expect(linesYardstick.screenPositionForPixelPosition(top: (editor.getLastScreenRow() + 1) * 14, left: 0)).toEqual [12, 2] + expect(linesYardstick.screenPositionForPixelPosition(top: editor.getLastScreenRow() * 14, left: 0)).toEqual [12, 0] + + it "clips negative horizontal pixel positions", -> + expect(linesYardstick.screenPositionForPixelPosition(top: 0, left: -10)).toEqual [0, 0] + expect(linesYardstick.screenPositionForPixelPosition(top: 1 * 14, left: -10)).toEqual [1, 0] diff --git a/src/lines-yardstick.coffee b/src/lines-yardstick.coffee index d4979865c..4ea0b4e8d 100644 --- a/src/lines-yardstick.coffee +++ b/src/lines-yardstick.coffee @@ -126,4 +126,8 @@ class LinesYardstick clientRectForRange: (textNode, startIndex, endIndex) -> @rangeForMeasurement.setStart(textNode, startIndex) @rangeForMeasurement.setEnd(textNode, endIndex) - @rangeForMeasurement.getClientRects()[0] ? @rangeForMeasurement.getBoundingClientRect() + clientRects = @rangeForMeasurement.getClientRects() + if clientRects.length == 1 + clientRects[0] + else + @rangeForMeasurement.getBoundingClientRect()