From a0529cc4bd2e787e248d3ad4863a47df6a258d55 Mon Sep 17 00:00:00 2001 From: Farnabaz Date: Fri, 11 Nov 2016 14:21:41 +0330 Subject: [PATCH 1/6] fix text selection and cursor position in lines with rtl text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit assume a line contain both english text and persian (rtl) text, like this ``` Sample Text متن نمونه sample text ``` atom always look at first rect size of Text Element and calculate position, this cause cursor to place in wrong position in our example `Range.getClientRects()` return three rects, look at this pen http://codepen.io/farnabaz/pen/rWxrGW --- src/lines-yardstick.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lines-yardstick.coffee b/src/lines-yardstick.coffee index d4979865c..6c42a2f3e 100644 --- a/src/lines-yardstick.coffee +++ b/src/lines-yardstick.coffee @@ -126,4 +126,4 @@ class LinesYardstick clientRectForRange: (textNode, startIndex, endIndex) -> @rangeForMeasurement.setStart(textNode, startIndex) @rangeForMeasurement.setEnd(textNode, endIndex) - @rangeForMeasurement.getClientRects()[0] ? @rangeForMeasurement.getBoundingClientRect() + @rangeForMeasurement.getBoundingClientRect() From bd1919bbe4ef152c0dfc0feee7f5366affd39d86 Mon Sep 17 00:00:00 2001 From: Farnabaz Date: Sat, 12 Nov 2016 05:17:51 +0330 Subject: [PATCH 2/6] add test: cursor position in bidirectional lines --- spec/fixtures/sample-bidirectional.txt | 1 + spec/lines-yardstick-spec.coffee | 70 ++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 spec/fixtures/sample-bidirectional.txt diff --git a/spec/fixtures/sample-bidirectional.txt b/spec/fixtures/sample-bidirectional.txt new file mode 100644 index 000000000..d74de4f6c --- /dev/null +++ b/spec/fixtures/sample-bidirectional.txt @@ -0,0 +1 @@ +Persian, locally known as Parsi or Farsi (زبان فارسی), the predominant modern descendant of Old Persian. diff --git a/spec/lines-yardstick-spec.coffee b/spec/lines-yardstick-spec.coffee index 2172267db..d718f3aae 100644 --- a/spec/lines-yardstick-spec.coffee +++ b/spec/lines-yardstick-spec.coffee @@ -202,3 +202,73 @@ describe "LinesYardstick", -> 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] + +describe "In bidirectional lines", -> + [editor, linesYardstick, createdLineNodes, mockLineNodesProvider] = [] + beforeEach -> + waitsForPromise -> + atom.workspace.open('sample-bidirectional.txt').then (o) -> editor = o + + runs -> + createdLineNodes = [] + + buildLineNode = (screenRow) -> + startIndex = 0 + scopes = [] + screenLine = editor.screenLineForScreenRow(screenRow) + lineNode = document.createElement("div") + lineNode.style.whiteSpace = "pre" + for tagCode in screenLine.tagCodes when tagCode isnt 0 + if editor.displayLayer.isCloseTagCode(tagCode) + scopes.pop() + else if editor.displayLayer.isOpenTagCode(tagCode) + scopes.push(editor.displayLayer.tagForCode(tagCode)) + else + text = screenLine.lineText.substr(startIndex, tagCode) + startIndex += tagCode + + span = document.createElement("span") + span.className = scopes.join(' ').replace(/\.+/g, ' ') + span.textContent = text + lineNode.appendChild(span) + jasmine.attachToDOM(lineNode) + createdLineNodes.push(lineNode) + lineNode + + mockLineNodesProvider = + lineNodesById: {} + + lineIdForScreenRow: (screenRow) -> + editor.screenLineForScreenRow(screenRow)?.id + + lineNodeForScreenRow: (screenRow) -> + if id = @lineIdForScreenRow(screenRow) + @lineNodesById[id] ?= buildLineNode(screenRow) + + textNodesForScreenRow: (screenRow) -> + lineNode = @lineNodeForScreenRow(screenRow) + iterator = document.createNodeIterator(lineNode, NodeFilter.SHOW_TEXT) + textNodes = [] + textNodes.push(textNode) while textNode = iterator.nextNode() + textNodes + + editor.setLineHeightInPixels(14) + lineTopIndex = new LineTopIndex({defaultLineHeight: editor.getLineHeightInPixels()}) + linesYardstick = new LinesYardstick(editor, mockLineNodesProvider, lineTopIndex, atom.grammars) + + afterEach -> + lineNode.remove() for lineNode in createdLineNodes + atom.themes.removeStylesheet('test') + + describe "LinesYardstick::pixelPositionForScreenPosition(screenPosition)", -> + it "should converts screen positions to correct pixel positions", -> + atom.styles.addStyleSheet """ + * { + font-size: 14px; + font-family: monospace; + } + """ + 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.703125, top: 0}) From 4d88a9783e671ae1b4ba5453de65a98477031505 Mon Sep 17 00:00:00 2001 From: Farnabaz Date: Sat, 12 Nov 2016 06:04:01 +0330 Subject: [PATCH 3/6] add test: remove inconsistent indentations --- spec/lines-yardstick-spec.coffee | 116 +++++++++++++++---------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/spec/lines-yardstick-spec.coffee b/spec/lines-yardstick-spec.coffee index d718f3aae..dc3935590 100644 --- a/spec/lines-yardstick-spec.coffee +++ b/spec/lines-yardstick-spec.coffee @@ -204,71 +204,71 @@ describe "LinesYardstick", -> expect(linesYardstick.screenPositionForPixelPosition(top: 1 * 14, left: -10)).toEqual [1, 0] describe "In bidirectional lines", -> - [editor, linesYardstick, createdLineNodes, mockLineNodesProvider] = [] - beforeEach -> - waitsForPromise -> - atom.workspace.open('sample-bidirectional.txt').then (o) -> editor = o + [editor, linesYardstick, createdLineNodes, mockLineNodesProvider] = [] + beforeEach -> + waitsForPromise -> + atom.workspace.open('sample-bidirectional.txt').then (o) -> editor = o - runs -> - createdLineNodes = [] + runs -> + createdLineNodes = [] - buildLineNode = (screenRow) -> - startIndex = 0 - scopes = [] - screenLine = editor.screenLineForScreenRow(screenRow) - lineNode = document.createElement("div") - lineNode.style.whiteSpace = "pre" - for tagCode in screenLine.tagCodes when tagCode isnt 0 - if editor.displayLayer.isCloseTagCode(tagCode) - scopes.pop() - else if editor.displayLayer.isOpenTagCode(tagCode) - scopes.push(editor.displayLayer.tagForCode(tagCode)) - else - text = screenLine.lineText.substr(startIndex, tagCode) - startIndex += tagCode + buildLineNode = (screenRow) -> + startIndex = 0 + scopes = [] + screenLine = editor.screenLineForScreenRow(screenRow) + lineNode = document.createElement("div") + lineNode.style.whiteSpace = "pre" + for tagCode in screenLine.tagCodes when tagCode isnt 0 + if editor.displayLayer.isCloseTagCode(tagCode) + scopes.pop() + else if editor.displayLayer.isOpenTagCode(tagCode) + scopes.push(editor.displayLayer.tagForCode(tagCode)) + else + text = screenLine.lineText.substr(startIndex, tagCode) + startIndex += tagCode - span = document.createElement("span") - span.className = scopes.join(' ').replace(/\.+/g, ' ') - span.textContent = text - lineNode.appendChild(span) - jasmine.attachToDOM(lineNode) - createdLineNodes.push(lineNode) - lineNode + span = document.createElement("span") + span.className = scopes.join(' ').replace(/\.+/g, ' ') + span.textContent = text + lineNode.appendChild(span) + jasmine.attachToDOM(lineNode) + createdLineNodes.push(lineNode) + lineNode - mockLineNodesProvider = - lineNodesById: {} + mockLineNodesProvider = + lineNodesById: {} - lineIdForScreenRow: (screenRow) -> - editor.screenLineForScreenRow(screenRow)?.id + lineIdForScreenRow: (screenRow) -> + editor.screenLineForScreenRow(screenRow)?.id - lineNodeForScreenRow: (screenRow) -> - if id = @lineIdForScreenRow(screenRow) - @lineNodesById[id] ?= buildLineNode(screenRow) + lineNodeForScreenRow: (screenRow) -> + if id = @lineIdForScreenRow(screenRow) + @lineNodesById[id] ?= buildLineNode(screenRow) - textNodesForScreenRow: (screenRow) -> - lineNode = @lineNodeForScreenRow(screenRow) - iterator = document.createNodeIterator(lineNode, NodeFilter.SHOW_TEXT) - textNodes = [] - textNodes.push(textNode) while textNode = iterator.nextNode() - textNodes + textNodesForScreenRow: (screenRow) -> + lineNode = @lineNodeForScreenRow(screenRow) + iterator = document.createNodeIterator(lineNode, NodeFilter.SHOW_TEXT) + textNodes = [] + textNodes.push(textNode) while textNode = iterator.nextNode() + textNodes - editor.setLineHeightInPixels(14) - lineTopIndex = new LineTopIndex({defaultLineHeight: editor.getLineHeightInPixels()}) - linesYardstick = new LinesYardstick(editor, mockLineNodesProvider, lineTopIndex, atom.grammars) + editor.setLineHeightInPixels(14) + lineTopIndex = new LineTopIndex({defaultLineHeight: editor.getLineHeightInPixels()}) + linesYardstick = new LinesYardstick(editor, mockLineNodesProvider, lineTopIndex, atom.grammars) - afterEach -> - lineNode.remove() for lineNode in createdLineNodes - atom.themes.removeStylesheet('test') + afterEach -> + lineNode.remove() for lineNode in createdLineNodes + atom.themes.removeStylesheet('test') - describe "LinesYardstick::pixelPositionForScreenPosition(screenPosition)", -> - it "should converts screen positions to correct pixel positions", -> - atom.styles.addStyleSheet """ - * { - font-size: 14px; - font-family: monospace; - } - """ - 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.703125, top: 0}) + describe "LinesYardstick::pixelPositionForScreenPosition(screenPosition)", -> + it "should converts screen positions to correct pixel positions", -> + atom.styles.addStyleSheet """ + * { + font-size: 14px; + font-family: monospace; + } + """ + 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.703125, top: 0}) From 95edf2f174fdaeecb39e353b1d4b8b90a8325826 Mon Sep 17 00:00:00 2001 From: Farnabaz Date: Sun, 11 Dec 2016 01:13:19 +0330 Subject: [PATCH 4/6] Handle ranges with multiple rect in LineYardstick --- src/lines-yardstick.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lines-yardstick.coffee b/src/lines-yardstick.coffee index 6c42a2f3e..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.getBoundingClientRect() + clientRects = @rangeForMeasurement.getClientRects() + if clientRects.length == 1 + clientRects[0] + else + @rangeForMeasurement.getBoundingClientRect() From 4e7d13b2279273292870313fa0dade03249290c5 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Dec 2016 13:30:34 -0700 Subject: [PATCH 5/6] Clean up tests --- spec/fixtures/sample-bidirectional.txt | 1 - spec/lines-yardstick-spec.coffee | 201 +++++++++---------------- 2 files changed, 74 insertions(+), 128 deletions(-) delete mode 100644 spec/fixtures/sample-bidirectional.txt diff --git a/spec/fixtures/sample-bidirectional.txt b/spec/fixtures/sample-bidirectional.txt deleted file mode 100644 index d74de4f6c..000000000 --- a/spec/fixtures/sample-bidirectional.txt +++ /dev/null @@ -1 +0,0 @@ -Persian, locally known as Parsi or Farsi (زبان فارسی), the predominant modern descendant of Old Persian. diff --git a/spec/lines-yardstick-spec.coffee b/spec/lines-yardstick-spec.coffee index dc3935590..a0100f35f 100644 --- a/spec/lines-yardstick-spec.coffee +++ b/spec/lines-yardstick-spec.coffee @@ -137,138 +137,85 @@ 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", -> - atom.styles.addStyleSheet """ - * { - font-size: 12px; - font-family: monospace; - } - .syntax--function { - font-size: 16px - } - """ + 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') - 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: 224.2365234375})).toEqual([5, 29]) - expect(linesYardstick.screenPositionForPixelPosition({top: 70, left: 225})).toEqual([5, 30]) - 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-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") - - 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] - -describe "In bidirectional lines", -> - [editor, linesYardstick, createdLineNodes, mockLineNodesProvider] = [] - beforeEach -> - waitsForPromise -> - atom.workspace.open('sample-bidirectional.txt').then (o) -> editor = o - - runs -> - createdLineNodes = [] - - buildLineNode = (screenRow) -> - startIndex = 0 - scopes = [] - screenLine = editor.screenLineForScreenRow(screenRow) - lineNode = document.createElement("div") - lineNode.style.whiteSpace = "pre" - for tagCode in screenLine.tagCodes when tagCode isnt 0 - if editor.displayLayer.isCloseTagCode(tagCode) - scopes.pop() - else if editor.displayLayer.isOpenTagCode(tagCode) - scopes.push(editor.displayLayer.tagForCode(tagCode)) - else - text = screenLine.lineText.substr(startIndex, tagCode) - startIndex += tagCode - - span = document.createElement("span") - span.className = scopes.join(' ').replace(/\.+/g, ' ') - span.textContent = text - lineNode.appendChild(span) - jasmine.attachToDOM(lineNode) - createdLineNodes.push(lineNode) - lineNode - - mockLineNodesProvider = - lineNodesById: {} - - lineIdForScreenRow: (screenRow) -> - editor.screenLineForScreenRow(screenRow)?.id - - lineNodeForScreenRow: (screenRow) -> - if id = @lineIdForScreenRow(screenRow) - @lineNodesById[id] ?= buildLineNode(screenRow) - - textNodesForScreenRow: (screenRow) -> - lineNode = @lineNodeForScreenRow(screenRow) - iterator = document.createNodeIterator(lineNode, NodeFilter.SHOW_TEXT) - textNodes = [] - textNodes.push(textNode) while textNode = iterator.nextNode() - textNodes - - editor.setLineHeightInPixels(14) - lineTopIndex = new LineTopIndex({defaultLineHeight: editor.getLineHeightInPixels()}) - linesYardstick = new LinesYardstick(editor, mockLineNodesProvider, lineTopIndex, atom.grammars) - - afterEach -> - lineNode.remove() for lineNode in createdLineNodes - atom.themes.removeStylesheet('test') - - describe "LinesYardstick::pixelPositionForScreenPosition(screenPosition)", -> - it "should converts screen positions to correct pixel positions", -> atom.styles.addStyleSheet """ * { - font-size: 14px; - font-family: monospace; + font-size: 14px; + font-family: monospace; } """ + + 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.703125, top: 0}) + expect(linesYardstick.pixelPositionForScreenPosition(Point(0, Infinity))).toEqual({left: 873.625, top: 0}) + + describe "::screenPositionForPixelPosition(pixelPosition)", -> + it "converts pixel positions to screen positions", -> + 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: 224.2365234375})).toEqual([5, 29]) + expect(linesYardstick.screenPositionForPixelPosition({top: 70, left: 225})).toEqual([5, 30]) + 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-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") + + 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] From b087ab27345e3d31c1f2b3a8b178c96308ebf8de Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 15 Dec 2016 03:16:21 -0700 Subject: [PATCH 6/6] Disable measurement tests for RTL text on Windows @damieng This is unlike the other tests in this file in that none of the assertions pass. Maybe you could take a look at some point to enable at least some coverage on Windows for this? --- spec/lines-yardstick-spec.coffee | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/spec/lines-yardstick-spec.coffee b/spec/lines-yardstick-spec.coffee index 64ac6b569..2112589bc 100644 --- a/spec/lines-yardstick-spec.coffee +++ b/spec/lines-yardstick-spec.coffee @@ -139,22 +139,23 @@ describe "LinesYardstick", -> expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 36)).left).toBe 237.5 expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 37)).left).toBe 244.09375 - 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') + 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: 14px; - font-family: monospace; - } - """ + atom.styles.addStyleSheet """ + * { + font-size: 14px; + font-family: monospace; + } + """ - 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}) + 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}) describe "::screenPositionForPixelPosition(pixelPosition)", -> it "converts pixel positions to screen positions", ->