@xterm/xterm 5.4.0-beta.17 → 5.4.0-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xterm/xterm",
3
3
  "description": "Full xterm terminal, in your browser",
4
- "version": "5.4.0-beta.17",
4
+ "version": "5.4.0-beta.19",
5
5
  "main": "lib/xterm.js",
6
6
  "style": "css/xterm.css",
7
7
  "types": "typings/xterm.d.ts",
@@ -11,7 +11,7 @@ import { ICoreService, IDecorationService, IOptionsService } from 'common/servic
11
11
  import { color, rgba } from 'common/Color';
12
12
  import { ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
13
13
  import { JoinedCellData } from 'browser/services/CharacterJoinerService';
14
- import { excludeFromContrastRatioDemands } from 'browser/renderer/shared/RendererUtils';
14
+ import { treatGlyphAsBackgroundColor } from 'browser/renderer/shared/RendererUtils';
15
15
  import { AttributeData } from 'common/buffer/AttributeData';
16
16
  import { WidthCache } from 'browser/renderer/dom/WidthCache';
17
17
  import { IColorContrastCache } from 'browser/Types';
@@ -458,7 +458,7 @@ export class DomRendererRowFactory {
458
458
  }
459
459
 
460
460
  private _applyMinimumContrast(element: HTMLElement, bg: IColor, fg: IColor, cell: ICellData, bgOverride: IColor | undefined, fgOverride: IColor | undefined): boolean {
461
- if (this._optionsService.rawOptions.minimumContrastRatio === 1 || excludeFromContrastRatioDemands(cell.getCode())) {
461
+ if (this._optionsService.rawOptions.minimumContrastRatio === 1 || treatGlyphAsBackgroundColor(cell.getCode())) {
462
462
  return false;
463
463
  }
464
464
 
@@ -5,6 +5,8 @@ import { Attributes, BgFlags, ExtFlags, FgFlags, NULL_CELL_CODE, UnderlineStyle
5
5
  import { IDecorationService, IOptionsService } from 'common/services/Services';
6
6
  import { ICellData } from 'common/Types';
7
7
  import { Terminal } from '@xterm/xterm';
8
+ import { rgba } from 'common/Color';
9
+ import { treatGlyphAsBackgroundColor } from 'browser/renderer/shared/RendererUtils';
8
10
 
9
11
  // Work variables to avoid garbage collection
10
12
  let $fg = 0;
@@ -65,11 +67,11 @@ export class CellColorResolver {
65
67
  // Apply decorations on the bottom layer
66
68
  this._decorationService.forEachDecorationAtCell(x, y, 'bottom', d => {
67
69
  if (d.backgroundColorRGB) {
68
- $bg = d.backgroundColorRGB.rgba >> 8 & 0xFFFFFF;
70
+ $bg = d.backgroundColorRGB.rgba >> 8 & Attributes.RGB_MASK;
69
71
  $hasBg = true;
70
72
  }
71
73
  if (d.foregroundColorRGB) {
72
- $fg = d.foregroundColorRGB.rgba >> 8 & 0xFFFFFF;
74
+ $fg = d.foregroundColorRGB.rgba >> 8 & Attributes.RGB_MASK;
73
75
  $hasFg = true;
74
76
  }
75
77
  });
@@ -77,10 +79,94 @@ export class CellColorResolver {
77
79
  // Apply the selection color if needed
78
80
  $isSelected = this._selectionRenderModel.isCellSelected(this._terminal, x, y);
79
81
  if ($isSelected) {
80
- $bg = (this._coreBrowserService.isFocused ? $colors.selectionBackgroundOpaque : $colors.selectionInactiveBackgroundOpaque).rgba >> 8 & 0xFFFFFF;
82
+ // If the cell has a bg color, retain the color by blending it with the selection color
83
+ if (
84
+ (this.result.fg & FgFlags.INVERSE) ||
85
+ (this.result.bg & Attributes.CM_MASK) !== Attributes.CM_DEFAULT
86
+ ) {
87
+ // Resolve the standard bg color
88
+ if (this.result.fg & FgFlags.INVERSE) {
89
+ switch (this.result.fg & Attributes.CM_MASK) {
90
+ case Attributes.CM_P16:
91
+ case Attributes.CM_P256:
92
+ $bg = this._themeService.colors.ansi[this.result.fg & Attributes.PCOLOR_MASK].rgba;
93
+ break;
94
+ case Attributes.CM_RGB:
95
+ $bg = (this.result.fg & Attributes.RGB_MASK) << 8 | 0xFF;
96
+ break;
97
+ case Attributes.CM_DEFAULT:
98
+ default:
99
+ $bg = this._themeService.colors.foreground.rgba;
100
+ }
101
+ } else {
102
+ switch (this.result.bg & Attributes.CM_MASK) {
103
+ case Attributes.CM_P16:
104
+ case Attributes.CM_P256:
105
+ $bg = this._themeService.colors.ansi[this.result.bg & Attributes.PCOLOR_MASK].rgba;
106
+ break;
107
+ case Attributes.CM_RGB:
108
+ $bg = this.result.bg & Attributes.RGB_MASK << 8 | 0xFF;
109
+ break;
110
+ // No need to consider default bg color here as it's not possible
111
+ }
112
+ }
113
+ // Blend with selection bg color
114
+ $bg = rgba.blend(
115
+ $bg,
116
+ ((this._coreBrowserService.isFocused ? $colors.selectionBackgroundOpaque : $colors.selectionInactiveBackgroundOpaque).rgba & 0xFFFFFF00) | 0x80
117
+ ) >> 8 & Attributes.RGB_MASK;
118
+ } else {
119
+ $bg = (this._coreBrowserService.isFocused ? $colors.selectionBackgroundOpaque : $colors.selectionInactiveBackgroundOpaque).rgba >> 8 & Attributes.RGB_MASK;
120
+ }
81
121
  $hasBg = true;
122
+
123
+ // Apply explicit selection foreground if present
82
124
  if ($colors.selectionForeground) {
83
- $fg = $colors.selectionForeground.rgba >> 8 & 0xFFFFFF;
125
+ $fg = $colors.selectionForeground.rgba >> 8 & Attributes.RGB_MASK;
126
+ $hasFg = true;
127
+ }
128
+
129
+ // Overwrite fg as bg if it's a special decorative glyph (eg. powerline)
130
+ if (treatGlyphAsBackgroundColor(cell.getCode())) {
131
+ // Inverse default background should be treated as transparent
132
+ if (
133
+ (this.result.fg & FgFlags.INVERSE) &&
134
+ (this.result.bg & Attributes.CM_MASK) === Attributes.CM_DEFAULT
135
+ ) {
136
+ $fg = (this._coreBrowserService.isFocused ? $colors.selectionBackgroundOpaque : $colors.selectionInactiveBackgroundOpaque).rgba >> 8 & Attributes.RGB_MASK;
137
+ } else {
138
+
139
+ if (this.result.fg & FgFlags.INVERSE) {
140
+ switch (this.result.bg & Attributes.CM_MASK) {
141
+ case Attributes.CM_P16:
142
+ case Attributes.CM_P256:
143
+ $fg = this._themeService.colors.ansi[this.result.bg & Attributes.PCOLOR_MASK].rgba;
144
+ break;
145
+ case Attributes.CM_RGB:
146
+ $fg = this.result.bg & Attributes.RGB_MASK << 8 | 0xFF;
147
+ break;
148
+ // No need to consider default bg color here as it's not possible
149
+ }
150
+ } else {
151
+ switch (this.result.fg & Attributes.CM_MASK) {
152
+ case Attributes.CM_P16:
153
+ case Attributes.CM_P256:
154
+ $fg = this._themeService.colors.ansi[this.result.fg & Attributes.PCOLOR_MASK].rgba;
155
+ break;
156
+ case Attributes.CM_RGB:
157
+ $fg = (this.result.fg & Attributes.RGB_MASK) << 8 | 0xFF;
158
+ break;
159
+ case Attributes.CM_DEFAULT:
160
+ default:
161
+ $fg = this._themeService.colors.foreground.rgba;
162
+ }
163
+ }
164
+
165
+ $fg = rgba.blend(
166
+ $fg,
167
+ ((this._coreBrowserService.isFocused ? $colors.selectionBackgroundOpaque : $colors.selectionInactiveBackgroundOpaque).rgba & 0xFFFFFF00) | 0x80
168
+ ) >> 8 & Attributes.RGB_MASK;
169
+ }
84
170
  $hasFg = true;
85
171
  }
86
172
  }
@@ -88,11 +174,11 @@ export class CellColorResolver {
88
174
  // Apply decorations on the top layer
89
175
  this._decorationService.forEachDecorationAtCell(x, y, 'top', d => {
90
176
  if (d.backgroundColorRGB) {
91
- $bg = d.backgroundColorRGB.rgba >> 8 & 0xFFFFFF;
177
+ $bg = d.backgroundColorRGB.rgba >> 8 & Attributes.RGB_MASK;
92
178
  $hasBg = true;
93
179
  }
94
180
  if (d.foregroundColorRGB) {
95
- $fg = d.foregroundColorRGB.rgba >> 8 & 0xFFFFFF;
181
+ $fg = d.foregroundColorRGB.rgba >> 8 & Attributes.RGB_MASK;
96
182
  $hasFg = true;
97
183
  }
98
184
  });
@@ -119,7 +205,7 @@ export class CellColorResolver {
119
205
  if ($hasBg && !$hasFg) {
120
206
  // Resolve bg color type (default color has a different meaning in fg vs bg)
121
207
  if ((this.result.bg & Attributes.CM_MASK) === Attributes.CM_DEFAULT) {
122
- $fg = (this.result.fg & ~(Attributes.RGB_MASK | FgFlags.INVERSE | Attributes.CM_MASK)) | (($colors.background.rgba >> 8 & 0xFFFFFF) & Attributes.RGB_MASK) | Attributes.CM_RGB;
208
+ $fg = (this.result.fg & ~(Attributes.RGB_MASK | FgFlags.INVERSE | Attributes.CM_MASK)) | (($colors.background.rgba >> 8 & Attributes.RGB_MASK) & Attributes.RGB_MASK) | Attributes.CM_RGB;
123
209
  } else {
124
210
  $fg = (this.result.fg & ~(Attributes.RGB_MASK | FgFlags.INVERSE | Attributes.CM_MASK)) | this.result.bg & (Attributes.RGB_MASK | Attributes.CM_MASK);
125
211
  }
@@ -128,7 +214,7 @@ export class CellColorResolver {
128
214
  if (!$hasBg && $hasFg) {
129
215
  // Resolve bg color type (default color has a different meaning in fg vs bg)
130
216
  if ((this.result.fg & Attributes.CM_MASK) === Attributes.CM_DEFAULT) {
131
- $bg = (this.result.bg & ~(Attributes.RGB_MASK | Attributes.CM_MASK)) | (($colors.foreground.rgba >> 8 & 0xFFFFFF) & Attributes.RGB_MASK) | Attributes.CM_RGB;
217
+ $bg = (this.result.bg & ~(Attributes.RGB_MASK | Attributes.CM_MASK)) | (($colors.foreground.rgba >> 8 & Attributes.RGB_MASK) & Attributes.RGB_MASK) | Attributes.CM_RGB;
132
218
  } else {
133
219
  $bg = (this.result.bg & ~(Attributes.RGB_MASK | Attributes.CM_MASK)) | this.result.fg & (Attributes.RGB_MASK | Attributes.CM_MASK);
134
220
  }
@@ -27,7 +27,7 @@ function isBoxOrBlockGlyph(codepoint: number): boolean {
27
27
  return 0x2500 <= codepoint && codepoint <= 0x259F;
28
28
  }
29
29
 
30
- export function excludeFromContrastRatioDemands(codepoint: number): boolean {
30
+ export function treatGlyphAsBackgroundColor(codepoint: number): boolean {
31
31
  return isPowerlineGlyph(codepoint) || isBoxOrBlockGlyph(codepoint);
32
32
  }
33
33
 
@@ -6,7 +6,7 @@
6
6
  import { IColorContrastCache } from 'browser/Types';
7
7
  import { DIM_OPACITY, TEXT_BASELINE } from 'browser/renderer/shared/Constants';
8
8
  import { tryDrawCustomChar } from 'browser/renderer/shared/CustomGlyphs';
9
- import { computeNextVariantOffset, excludeFromContrastRatioDemands, isPowerlineGlyph, isRestrictedPowerlineGlyph, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
9
+ import { computeNextVariantOffset, treatGlyphAsBackgroundColor, isPowerlineGlyph, isRestrictedPowerlineGlyph, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
10
10
  import { IBoundingBox, ICharAtlasConfig, IRasterizedGlyph, ITextureAtlas } from 'browser/renderer/shared/Types';
11
11
  import { NULL_COLOR, color, rgba } from 'common/Color';
12
12
  import { EventEmitter } from 'common/EventEmitter';
@@ -15,7 +15,6 @@ import { IdleTaskQueue } from 'common/TaskQueue';
15
15
  import { IColor } from 'common/Types';
16
16
  import { AttributeData } from 'common/buffer/AttributeData';
17
17
  import { Attributes, DEFAULT_COLOR, DEFAULT_EXT, UnderlineStyle } from 'common/buffer/Constants';
18
- import { traceCall } from 'common/services/LogService';
19
18
  import { IUnicodeService } from 'common/services/Services';
20
19
 
21
20
  /**
@@ -424,7 +423,6 @@ export class TextureAtlas implements ITextureAtlas {
424
423
  return this._config.colors.contrastCache;
425
424
  }
426
425
 
427
- @traceCall
428
426
  private _drawToCache(codeOrChars: number | string, bg: number, fg: number, ext: number, restrictToCellHeight: boolean = false): IRasterizedGlyph {
429
427
  const chars = typeof codeOrChars === 'number' ? String.fromCharCode(codeOrChars) : codeOrChars;
430
428
 
@@ -492,7 +490,7 @@ export class TextureAtlas implements ITextureAtlas {
492
490
 
493
491
  const powerlineGlyph = chars.length === 1 && isPowerlineGlyph(chars.charCodeAt(0));
494
492
  const restrictedPowerlineGlyph = chars.length === 1 && isRestrictedPowerlineGlyph(chars.charCodeAt(0));
495
- const foregroundColor = this._getForegroundColor(bg, bgColorMode, bgColor, fg, fgColorMode, fgColor, inverse, dim, bold, excludeFromContrastRatioDemands(chars.charCodeAt(0)));
493
+ const foregroundColor = this._getForegroundColor(bg, bgColorMode, bgColor, fg, fgColorMode, fgColor, inverse, dim, bold, treatGlyphAsBackgroundColor(chars.charCodeAt(0)));
496
494
  this._tmpCtx.fillStyle = foregroundColor.css;
497
495
 
498
496
  // For powerline glyphs left/top padding is excluded (https://github.com/microsoft/vscode/issues/120129)
@@ -245,6 +245,23 @@ export namespace rgb {
245
245
  * Helper functions where the source type is "rgba" (number: 0xrrggbbaa).
246
246
  */
247
247
  export namespace rgba {
248
+ export function blend(bg: number, fg: number): number {
249
+ $a = (fg & 0xFF) / 0xFF;
250
+ if ($a === 1) {
251
+ return fg;
252
+ }
253
+ const fgR = (fg >> 24) & 0xFF;
254
+ const fgG = (fg >> 16) & 0xFF;
255
+ const fgB = (fg >> 8) & 0xFF;
256
+ const bgR = (bg >> 24) & 0xFF;
257
+ const bgG = (bg >> 16) & 0xFF;
258
+ const bgB = (bg >> 8) & 0xFF;
259
+ $r = bgR + Math.round((fgR - bgR) * $a);
260
+ $g = bgG + Math.round((fgG - bgG) * $a);
261
+ $b = bgB + Math.round((fgB - bgB) * $a);
262
+ return channels.toRgba($r, $g, $b);
263
+ }
264
+
248
265
  /**
249
266
  * Given a foreground color and a background color, either increase or reduce the luminance of the
250
267
  * foreground color until the specified contrast ratio is met. If pure white or black is hit