@@ -196,10 +196,10 @@ export class ViewLine implements IVisibleLineData {
196196 * Visible ranges for a model range
197197 */
198198 public getVisibleRangesForRange ( startColumn :number , endColumn :number , clientRectDeltaLeft :number , endNode :HTMLElement ) : HorizontalRange [ ] {
199- startColumn = + startColumn ; // @perf
200- endColumn = + endColumn ; // @perf
201- clientRectDeltaLeft = + clientRectDeltaLeft ; // @perf
202- let stopRenderingLineAfter = + this . _stopRenderingLineAfter ; // @perf
199+ startColumn = startColumn | 0 ; // @perf
200+ endColumn = endColumn | 0 ; // @perf
201+ clientRectDeltaLeft = clientRectDeltaLeft | 0 ; // @perf
202+ const stopRenderingLineAfter = this . _stopRenderingLineAfter | 0 ; // @perf
203203
204204 if ( stopRenderingLineAfter !== - 1 && startColumn > stopRenderingLineAfter && endColumn > stopRenderingLineAfter ) {
205205 // This range is obviously not visible
@@ -218,36 +218,11 @@ export class ViewLine implements IVisibleLineData {
218218 }
219219
220220 protected _readVisibleRangesForRange ( startColumn :number , endColumn :number , clientRectDeltaLeft :number , endNode :HTMLElement ) : HorizontalRange [ ] {
221-
222- let result : HorizontalRange [ ] ;
223221 if ( startColumn === endColumn ) {
224- result = this . _readRawVisibleRangesForPosition ( startColumn , clientRectDeltaLeft , endNode ) ;
222+ return this . _readRawVisibleRangesForPosition ( startColumn , clientRectDeltaLeft , endNode ) ;
225223 } else {
226- result = this . _readRawVisibleRangesForRange ( startColumn , endColumn , clientRectDeltaLeft , endNode ) ;
227- }
228-
229- if ( ! result || result . length <= 1 ) {
230- return result ;
224+ return this . _readRawVisibleRangesForRange ( startColumn , endColumn , clientRectDeltaLeft , endNode ) ;
231225 }
232-
233- result . sort ( compareVisibleRanges ) ;
234-
235- let output : HorizontalRange [ ] = [ ] ;
236- let prevRange : HorizontalRange = result [ 0 ] ;
237-
238- for ( let i = 1 , len = result . length ; i < len ; i ++ ) {
239- let currRange = result [ i ] ;
240-
241- if ( prevRange . left + prevRange . width + 0.9 /* account for browser's rounding errors*/ >= currRange . left ) {
242- prevRange . width = Math . max ( prevRange . width , currRange . left + currRange . width - prevRange . left ) ;
243- } else {
244- output . push ( prevRange ) ;
245- prevRange = currRange ;
246- }
247- }
248- output . push ( prevRange ) ;
249-
250- return output ;
251226 }
252227
253228 protected _readRawVisibleRangesForPosition ( column :number , clientRectDeltaLeft :number , endNode :HTMLElement ) : HorizontalRange [ ] {
@@ -260,7 +235,7 @@ export class ViewLine implements IVisibleLineData {
260235 let partIndex = findIndexInArrayWithMax ( this . _lineParts , column - 1 , this . _lastRenderedPartIndex ) ;
261236 let charOffsetInPart = this . _charOffsetInPart [ column - 1 ] ;
262237
263- return this . _readRawVisibleRangesFrom ( this . _getReadingTarget ( ) , partIndex , charOffsetInPart , partIndex , charOffsetInPart , clientRectDeltaLeft , endNode ) ;
238+ return RangeUtil . readHorizontalRanges ( this . _getReadingTarget ( ) , partIndex , charOffsetInPart , partIndex , charOffsetInPart , clientRectDeltaLeft , this . _getScaleRatio ( ) , endNode ) ;
264239 }
265240
266241 private _readRawVisibleRangesForRange ( startColumn :number , endColumn :number , clientRectDeltaLeft :number , endNode :HTMLElement ) : HorizontalRange [ ] {
@@ -276,70 +251,15 @@ export class ViewLine implements IVisibleLineData {
276251 let endPartIndex = findIndexInArrayWithMax ( this . _lineParts , endColumn - 1 , this . _lastRenderedPartIndex ) ;
277252 let endCharOffsetInPart = this . _charOffsetInPart [ endColumn - 1 ] ;
278253
279- return this . _readRawVisibleRangesFrom ( this . _getReadingTarget ( ) , startPartIndex , startCharOffsetInPart , endPartIndex , endCharOffsetInPart , clientRectDeltaLeft , endNode ) ;
254+ return RangeUtil . readHorizontalRanges ( this . _getReadingTarget ( ) , startPartIndex , startCharOffsetInPart , endPartIndex , endCharOffsetInPart , clientRectDeltaLeft , this . _getScaleRatio ( ) , endNode ) ;
280255 }
281256
282257 private _readRawVisibleRangeForEntireLine ( ) : HorizontalRange {
283258 return new HorizontalRange ( 0 , this . _getReadingTarget ( ) . offsetWidth ) ;
284259 }
285260
286- private _readRawVisibleRangesFrom ( domNode :HTMLElement , startChildIndex :number , startOffset :number , endChildIndex :number , endOffset :number , clientRectDeltaLeft :number , endNode :HTMLElement ) : HorizontalRange [ ] {
287- let range = RangeUtil . createRange ( ) ;
288-
289- try {
290- // Panic check
291- let min = 0 ;
292- let max = domNode . children . length - 1 ;
293- if ( min > max ) {
294- return null ;
295- }
296- startChildIndex = Math . min ( max , Math . max ( min , startChildIndex ) ) ;
297- endChildIndex = Math . min ( max , Math . max ( min , endChildIndex ) ) ;
298-
299- // If crossing over to a span only to select offset 0, then use the previous span's maximum offset
300- // Chrome is buggy and doesn't handle 0 offsets well sometimes.
301- if ( startChildIndex !== endChildIndex ) {
302- if ( endChildIndex > 0 && endOffset === 0 ) {
303- endChildIndex -- ;
304- endOffset = Number . MAX_VALUE ;
305- }
306- }
307-
308- let startElement = domNode . children [ startChildIndex ] . firstChild ;
309- let endElement = domNode . children [ endChildIndex ] . firstChild ;
310-
311- if ( ! startElement || ! endElement ) {
312- return null ;
313- }
314-
315- startOffset = Math . min ( startElement . textContent . length , Math . max ( 0 , startOffset ) ) ;
316- endOffset = Math . min ( endElement . textContent . length , Math . max ( 0 , endOffset ) ) ;
317-
318- range . setStart ( startElement , startOffset ) ;
319- range . setEnd ( endElement , endOffset ) ;
320-
321- let clientRects = range . getClientRects ( ) ;
322- if ( clientRects . length === 0 ) {
323- return null ;
324- }
325-
326- return this . _createRawVisibleRangesFromClientRects ( clientRects , clientRectDeltaLeft ) ;
327-
328- } catch ( e ) {
329- // This is life ...
330- return null ;
331- } finally {
332- RangeUtil . detachRange ( range , endNode ) ;
333- }
334- }
335-
336- protected _createRawVisibleRangesFromClientRects ( clientRects :ClientRectList , clientRectDeltaLeft :number ) : HorizontalRange [ ] {
337- let result :HorizontalRange [ ] = [ ] ;
338- for ( let i = 0 , len = clientRects . length ; i < len ; i ++ ) {
339- let cR = clientRects [ i ] ;
340- result . push ( new HorizontalRange ( Math . max ( 0 , cR . left - clientRectDeltaLeft ) , cR . width ) ) ;
341- }
342- return result ;
261+ protected _getScaleRatio ( ) : number {
262+ return 1 ;
343263 }
344264
345265 /**
@@ -437,15 +357,8 @@ class IEViewLine extends ViewLine {
437357 super ( context ) ;
438358 }
439359
440- protected _createRawVisibleRangesFromClientRects ( clientRects :ClientRectList , clientRectDeltaLeft :number ) : HorizontalRange [ ] {
441- let ratioX = screen . logicalXDPI / screen . deviceXDPI ;
442- let result :HorizontalRange [ ] = [ ] ;
443- for ( let i = 0 , len = clientRects . length ; i < len ; i ++ ) {
444- let cR = clientRects [ i ] ;
445- result [ i ] = new HorizontalRange ( Math . max ( 0 , cR . left * ratioX - clientRectDeltaLeft ) , cR . width * ratioX ) ;
446- }
447-
448- return result ;
360+ protected _getScaleRatio ( ) : number {
361+ return screen . logicalXDPI / screen . deviceXDPI ;
449362 }
450363}
451364
@@ -508,22 +421,97 @@ class RangeUtil {
508421 */
509422 private static _handyReadyRange :Range ;
510423
511- public static createRange ( ) : Range {
512- if ( ! RangeUtil . _handyReadyRange ) {
513- RangeUtil . _handyReadyRange = document . createRange ( ) ;
424+ private static _createRange ( ) : Range {
425+ if ( ! this . _handyReadyRange ) {
426+ this . _handyReadyRange = document . createRange ( ) ;
514427 }
515- return RangeUtil . _handyReadyRange ;
428+ return this . _handyReadyRange ;
516429 }
517430
518- public static detachRange ( range :Range , endNode :HTMLElement ) : void {
431+ private static _detachRange ( range :Range , endNode :HTMLElement ) : void {
519432 // Move range out of the span node, IE doesn't like having many ranges in
520433 // the same spot and will act badly for lines containing dashes ('-')
521434 range . selectNodeContents ( endNode ) ;
522435 }
523- }
524436
525- function compareVisibleRanges ( a : HorizontalRange , b : HorizontalRange ) : number {
526- return a . left - b . left ;
437+ private static _readClientRects ( startElement :Node , startOffset :number , endElement :Node , endOffset :number , endNode :HTMLElement ) : ClientRectList {
438+ let range = this . _createRange ( ) ;
439+ try {
440+ range . setStart ( startElement , startOffset ) ;
441+ range . setEnd ( endElement , endOffset ) ;
442+
443+ return range . getClientRects ( ) ;
444+ } catch ( e ) {
445+ // This is life ...
446+ return null ;
447+ } finally {
448+ this . _detachRange ( range , endNode ) ;
449+ }
450+ }
451+
452+ private static _createHorizontalRangesFromClientRects ( clientRects :ClientRectList , clientRectDeltaLeft :number , scaleRatio :number ) : HorizontalRange [ ] {
453+ if ( ! clientRects || clientRects . length === 0 ) {
454+ return null ;
455+ }
456+
457+ let result :HorizontalRange [ ] = [ ] ;
458+ let prevLeft = Math . max ( 0 , clientRects [ 0 ] . left * scaleRatio - clientRectDeltaLeft ) ;
459+ let prevWidth = clientRects [ 0 ] . width * scaleRatio ;
460+
461+ for ( let i = 1 , len = clientRects . length ; i < len ; i ++ ) {
462+ let myLeft = Math . max ( 0 , clientRects [ i ] . left * scaleRatio - clientRectDeltaLeft ) ;
463+ let myWidth = clientRects [ i ] . width * scaleRatio ;
464+
465+ if ( myLeft < prevLeft ) {
466+ console . error ( 'Unexpected: RangeUtil._createHorizontalRangesFromClientRects: client rects are not sorted' ) ;
467+ }
468+
469+ if ( prevLeft + prevWidth + 0.9 /* account for browser's rounding errors*/ >= myLeft ) {
470+ prevWidth = Math . max ( prevWidth , myLeft + myWidth - prevLeft ) ;
471+ } else {
472+ result . push ( new HorizontalRange ( prevLeft , prevWidth ) ) ;
473+ prevLeft = myLeft ;
474+ prevWidth = myWidth ;
475+ }
476+ }
477+
478+ result . push ( new HorizontalRange ( prevLeft , prevWidth ) ) ;
479+
480+ return result ;
481+ }
482+
483+ public static readHorizontalRanges ( domNode :HTMLElement , startChildIndex :number , startOffset :number , endChildIndex :number , endOffset :number , clientRectDeltaLeft :number , scaleRatio :number , endNode :HTMLElement ) : HorizontalRange [ ] {
484+ // Panic check
485+ let min = 0 ;
486+ let max = domNode . children . length - 1 ;
487+ if ( min > max ) {
488+ return null ;
489+ }
490+ startChildIndex = Math . min ( max , Math . max ( min , startChildIndex ) ) ;
491+ endChildIndex = Math . min ( max , Math . max ( min , endChildIndex ) ) ;
492+
493+ // If crossing over to a span only to select offset 0, then use the previous span's maximum offset
494+ // Chrome is buggy and doesn't handle 0 offsets well sometimes.
495+ if ( startChildIndex !== endChildIndex ) {
496+ if ( endChildIndex > 0 && endOffset === 0 ) {
497+ endChildIndex -- ;
498+ endOffset = Number . MAX_VALUE ;
499+ }
500+ }
501+
502+ let startElement = domNode . children [ startChildIndex ] . firstChild ;
503+ let endElement = domNode . children [ endChildIndex ] . firstChild ;
504+
505+ if ( ! startElement || ! endElement ) {
506+ return null ;
507+ }
508+
509+ startOffset = Math . min ( startElement . textContent . length , Math . max ( 0 , startOffset ) ) ;
510+ endOffset = Math . min ( endElement . textContent . length , Math . max ( 0 , endOffset ) ) ;
511+
512+ let clientRects = this . _readClientRects ( startElement , startOffset , endElement , endOffset , endNode ) ;
513+ return this . _createHorizontalRangesFromClientRects ( clientRects , clientRectDeltaLeft , scaleRatio ) ;
514+ }
527515}
528516
529517function findIndexInArrayWithMax ( lineParts :ILineParts , desiredIndex : number , maxResult :number ) : number {
0 commit comments