@@ -68,7 +68,8 @@ export class RenderLineInput {
6868 public readonly tabSize : number ;
6969 public readonly startVisibleColumn : number ;
7070 public readonly spaceWidth : number ;
71- public readonly middotWidth : number ;
71+ public readonly renderSpaceWidth : number ;
72+ public readonly renderSpaceCharCode : number ;
7273 public readonly stopRenderingLineAfter : number ;
7374 public readonly renderWhitespace : RenderWhitespace ;
7475 public readonly renderControlCharacters : boolean ;
@@ -94,6 +95,7 @@ export class RenderLineInput {
9495 startVisibleColumn : number ,
9596 spaceWidth : number ,
9697 middotWidth : number ,
98+ wsmiddotWidth : number ,
9799 stopRenderingLineAfter : number ,
98100 renderWhitespace : 'none' | 'boundary' | 'selection' | 'all' ,
99101 renderControlCharacters : boolean ,
@@ -112,7 +114,6 @@ export class RenderLineInput {
112114 this . tabSize = tabSize ;
113115 this . startVisibleColumn = startVisibleColumn ;
114116 this . spaceWidth = spaceWidth ;
115- this . middotWidth = middotWidth ;
116117 this . stopRenderingLineAfter = stopRenderingLineAfter ;
117118 this . renderWhitespace = (
118119 renderWhitespace === 'all'
@@ -126,6 +127,16 @@ export class RenderLineInput {
126127 this . renderControlCharacters = renderControlCharacters ;
127128 this . fontLigatures = fontLigatures ;
128129 this . selectionsOnLine = selectionsOnLine && selectionsOnLine . sort ( ( a , b ) => a . startOffset < b . startOffset ? - 1 : 1 ) ;
130+
131+ const wsmiddotDiff = Math . abs ( wsmiddotWidth - spaceWidth ) ;
132+ const middotDiff = Math . abs ( middotWidth - spaceWidth ) ;
133+ if ( wsmiddotDiff < middotDiff ) {
134+ this . renderSpaceWidth = wsmiddotWidth ;
135+ this . renderSpaceCharCode = 0x2E31 ; // U+2E31 - WORD SEPARATOR MIDDLE DOT
136+ } else {
137+ this . renderSpaceWidth = middotWidth ;
138+ this . renderSpaceCharCode = 0xB7 ; // U+00B7 - MIDDLE DOT
139+ }
129140 }
130141
131142 private sameSelection ( otherSelections : LineRange [ ] | null ) : boolean {
@@ -162,6 +173,8 @@ export class RenderLineInput {
162173 && this . tabSize === other . tabSize
163174 && this . startVisibleColumn === other . startVisibleColumn
164175 && this . spaceWidth === other . spaceWidth
176+ && this . renderSpaceWidth === other . renderSpaceWidth
177+ && this . renderSpaceCharCode === other . renderSpaceCharCode
165178 && this . stopRenderingLineAfter === other . stopRenderingLineAfter
166179 && this . renderWhitespace === other . renderWhitespace
167180 && this . renderControlCharacters === other . renderControlCharacters
@@ -383,7 +396,7 @@ class ResolvedRenderLineInput {
383396 public readonly startVisibleColumn : number ,
384397 public readonly containsRTL : boolean ,
385398 public readonly spaceWidth : number ,
386- public readonly middotWidth : number ,
399+ public readonly renderSpaceCharCode : number ,
387400 public readonly renderWhitespace : RenderWhitespace ,
388401 public readonly renderControlCharacters : boolean ,
389402 ) {
@@ -392,7 +405,6 @@ class ResolvedRenderLineInput {
392405}
393406
394407function resolveRenderLineInput ( input : RenderLineInput ) : ResolvedRenderLineInput {
395- const useMonospaceOptimizations = input . useMonospaceOptimizations ;
396408 const lineContent = input . lineContent ;
397409
398410 let isOverflowing : boolean ;
@@ -408,7 +420,7 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput
408420
409421 let tokens = transformAndRemoveOverflowing ( input . lineTokens , input . fauxIndentLength , len ) ;
410422 if ( input . renderWhitespace === RenderWhitespace . All || input . renderWhitespace === RenderWhitespace . Boundary || ( input . renderWhitespace === RenderWhitespace . Selection && ! ! input . selectionsOnLine ) ) {
411- tokens = _applyRenderWhitespace ( lineContent , len , input . continuesWithWrappedLine , tokens , input . fauxIndentLength , input . tabSize , input . startVisibleColumn , useMonospaceOptimizations , input . selectionsOnLine , input . renderWhitespace === RenderWhitespace . Boundary ) ;
423+ tokens = _applyRenderWhitespace ( input , lineContent , len , tokens ) ;
412424 }
413425 let containsForeignElements = ForeignElementType . None ;
414426 if ( input . lineDecorations . length > 0 ) {
@@ -431,7 +443,7 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput
431443 }
432444
433445 return new ResolvedRenderLineInput (
434- useMonospaceOptimizations ,
446+ input . useMonospaceOptimizations ,
435447 input . canUseHalfwidthRightwardsArrow ,
436448 lineContent ,
437449 len ,
@@ -443,7 +455,7 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput
443455 input . startVisibleColumn ,
444456 input . containsRTL ,
445457 input . spaceWidth ,
446- input . middotWidth ,
458+ input . renderSpaceCharCode ,
447459 input . renderWhitespace ,
448460 input . renderControlCharacters
449461 ) ;
@@ -553,7 +565,16 @@ function splitLargeTokens(lineContent: string, tokens: LinePart[], onlyAtSpaces:
553565 * Moreover, a token is created for every visual indent because on some fonts the glyphs used for rendering whitespace (→ or ·) do not have the same width as .
554566 * The rendering phase will generate `style="width:..."` for these tokens.
555567 */
556- function _applyRenderWhitespace ( lineContent : string , len : number , continuesWithWrappedLine : boolean , tokens : LinePart [ ] , fauxIndentLength : number , tabSize : number , startVisibleColumn : number , useMonospaceOptimizations : boolean , selections : LineRange [ ] | null , onlyBoundary : boolean ) : LinePart [ ] {
568+ function _applyRenderWhitespace ( input : RenderLineInput , lineContent : string , len : number , tokens : LinePart [ ] ) : LinePart [ ] {
569+
570+ const continuesWithWrappedLine = input . continuesWithWrappedLine ;
571+ const fauxIndentLength = input . fauxIndentLength ;
572+ const tabSize = input . tabSize ;
573+ const startVisibleColumn = input . startVisibleColumn ;
574+ const useMonospaceOptimizations = input . useMonospaceOptimizations ;
575+ const selections = input . selectionsOnLine ;
576+ const onlyBoundary = ( input . renderWhitespace === RenderWhitespace . Boundary ) ;
577+ const generateLinePartForEachWhitespace = ( input . renderSpaceWidth !== input . spaceWidth ) ;
557578
558579 let result : LinePart [ ] = [ ] , resultLen = 0 ;
559580 let tokenIndex = 0 ;
@@ -616,7 +637,14 @@ function _applyRenderWhitespace(lineContent: string, len: number, continuesWithW
616637 // was in whitespace token
617638 if ( ! isInWhitespace || ( ! useMonospaceOptimizations && tmpIndent >= tabSize ) ) {
618639 // leaving whitespace token or entering a new indent
619- result [ resultLen ++ ] = new LinePart ( charIndex , 'mtkw' ) ;
640+ if ( generateLinePartForEachWhitespace ) {
641+ const lastEndIndex = ( resultLen > 0 ? result [ resultLen - 1 ] . endIndex : fauxIndentLength ) ;
642+ for ( let i = lastEndIndex + 1 ; i <= charIndex ; i ++ ) {
643+ result [ resultLen ++ ] = new LinePart ( i , 'mtkw' ) ;
644+ }
645+ } else {
646+ result [ resultLen ++ ] = new LinePart ( charIndex , 'mtkw' ) ;
647+ }
620648 tmpIndent = tmpIndent % tabSize ;
621649 }
622650 } else {
@@ -661,7 +689,18 @@ function _applyRenderWhitespace(lineContent: string, len: number, continuesWithW
661689 }
662690 }
663691
664- result [ resultLen ++ ] = new LinePart ( len , generateWhitespace ? 'mtkw' : tokenType ) ;
692+ if ( generateWhitespace ) {
693+ if ( generateLinePartForEachWhitespace ) {
694+ const lastEndIndex = ( resultLen > 0 ? result [ resultLen - 1 ] . endIndex : fauxIndentLength ) ;
695+ for ( let i = lastEndIndex + 1 ; i <= len ; i ++ ) {
696+ result [ resultLen ++ ] = new LinePart ( i , 'mtkw' ) ;
697+ }
698+ } else {
699+ result [ resultLen ++ ] = new LinePart ( len , 'mtkw' ) ;
700+ }
701+ } else {
702+ result [ resultLen ++ ] = new LinePart ( len , tokenType ) ;
703+ }
665704
666705 return result ;
667706}
@@ -739,13 +778,10 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render
739778 const startVisibleColumn = input . startVisibleColumn ;
740779 const containsRTL = input . containsRTL ;
741780 const spaceWidth = input . spaceWidth ;
742- const middotWidth = input . middotWidth ;
781+ const renderSpaceCharCode = input . renderSpaceCharCode ;
743782 const renderWhitespace = input . renderWhitespace ;
744783 const renderControlCharacters = input . renderControlCharacters ;
745784
746- // use U+2E31 - WORD SEPARATOR MIDDLE DOT or U+00B7 - MIDDLE DOT
747- const spaceRenderWhitespaceCharacter = ( middotWidth > spaceWidth ? 0x2E31 : 0xB7 ) ;
748-
749785 const characterMapping = new CharacterMapping ( len + 1 , parts . length ) ;
750786
751787 let charIndex = 0 ;
@@ -815,7 +851,7 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render
815851 } else { // must be CharCode.Space
816852 charWidth = 1 ;
817853
818- sb . write1 ( spaceRenderWhitespaceCharacter ) ; // · or word separator middle dot
854+ sb . write1 ( renderSpaceCharCode ) ; // · or word separator middle dot
819855 }
820856
821857 charOffsetInPart += charWidth ;
0 commit comments