@wendongfly/myhi 1.0.2 → 1.0.3
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/dist/index.js +1 -1
- package/dist/lib/xterm/LICENSE +21 -0
- package/dist/lib/xterm/README.md +225 -0
- package/dist/lib/xterm/css/xterm.css +190 -0
- package/dist/lib/xterm/lib/xterm.js +2 -0
- package/dist/lib/xterm/lib/xterm.js.map +1 -0
- package/dist/lib/xterm/package.json +90 -0
- package/dist/lib/xterm/src/browser/AccessibilityManager.ts +301 -0
- package/dist/lib/xterm/src/browser/Clipboard.ts +99 -0
- package/dist/lib/xterm/src/browser/ColorContrastCache.ts +39 -0
- package/dist/lib/xterm/src/browser/ColorManager.ts +268 -0
- package/dist/lib/xterm/src/browser/Dom.ts +10 -0
- package/dist/lib/xterm/src/browser/Lifecycle.ts +30 -0
- package/dist/lib/xterm/src/browser/Linkifier.ts +356 -0
- package/dist/lib/xterm/src/browser/Linkifier2.ts +397 -0
- package/dist/lib/xterm/src/browser/LocalizableStrings.ts +10 -0
- package/dist/lib/xterm/src/browser/MouseZoneManager.ts +236 -0
- package/dist/lib/xterm/src/browser/RenderDebouncer.ts +82 -0
- package/dist/lib/xterm/src/browser/ScreenDprMonitor.ts +69 -0
- package/dist/lib/xterm/src/browser/Terminal.ts +1447 -0
- package/dist/lib/xterm/src/browser/TimeBasedDebouncer.ts +86 -0
- package/dist/lib/xterm/src/browser/Types.d.ts +317 -0
- package/dist/lib/xterm/src/browser/Viewport.ts +276 -0
- package/dist/lib/xterm/src/browser/decorations/BufferDecorationRenderer.ts +131 -0
- package/dist/lib/xterm/src/browser/decorations/ColorZoneStore.ts +117 -0
- package/dist/lib/xterm/src/browser/decorations/OverviewRulerRenderer.ts +228 -0
- package/dist/lib/xterm/src/browser/input/CompositionHelper.ts +237 -0
- package/dist/lib/xterm/src/browser/input/Mouse.ts +64 -0
- package/dist/lib/xterm/src/browser/input/MoveToCell.ts +249 -0
- package/dist/lib/xterm/src/browser/public/Terminal.ts +298 -0
- package/dist/lib/xterm/src/browser/renderer/BaseRenderLayer.ts +582 -0
- package/dist/lib/xterm/src/browser/renderer/CursorRenderLayer.ts +378 -0
- package/dist/lib/xterm/src/browser/renderer/CustomGlyphs.ts +632 -0
- package/dist/lib/xterm/src/browser/renderer/GridCache.ts +33 -0
- package/dist/lib/xterm/src/browser/renderer/LinkRenderLayer.ts +84 -0
- package/dist/lib/xterm/src/browser/renderer/Renderer.ts +219 -0
- package/dist/lib/xterm/src/browser/renderer/RendererUtils.ts +26 -0
- package/dist/lib/xterm/src/browser/renderer/SelectionRenderLayer.ts +131 -0
- package/dist/lib/xterm/src/browser/renderer/TextRenderLayer.ts +344 -0
- package/dist/lib/xterm/src/browser/renderer/Types.d.ts +109 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/BaseCharAtlas.ts +58 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/CharAtlasCache.ts +95 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/CharAtlasUtils.ts +54 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/Constants.ts +15 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/DynamicCharAtlas.ts +404 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/LRUMap.ts +136 -0
- package/dist/lib/xterm/src/browser/renderer/atlas/Types.d.ts +29 -0
- package/dist/lib/xterm/src/browser/renderer/dom/DomRenderer.ts +403 -0
- package/dist/lib/xterm/src/browser/renderer/dom/DomRendererRowFactory.ts +344 -0
- package/dist/lib/xterm/src/browser/selection/SelectionModel.ts +144 -0
- package/dist/lib/xterm/src/browser/selection/Types.d.ts +15 -0
- package/dist/lib/xterm/src/browser/services/CharSizeService.ts +87 -0
- package/dist/lib/xterm/src/browser/services/CharacterJoinerService.ts +339 -0
- package/dist/lib/xterm/src/browser/services/CoreBrowserService.ts +20 -0
- package/dist/lib/xterm/src/browser/services/MouseService.ts +36 -0
- package/dist/lib/xterm/src/browser/services/RenderService.ts +237 -0
- package/dist/lib/xterm/src/browser/services/SelectionService.ts +1027 -0
- package/dist/lib/xterm/src/browser/services/Services.ts +123 -0
- package/dist/lib/xterm/src/browser/services/SoundService.ts +63 -0
- package/dist/lib/xterm/src/common/CircularList.ts +239 -0
- package/dist/lib/xterm/src/common/Clone.ts +23 -0
- package/dist/lib/xterm/src/common/Color.ts +285 -0
- package/dist/lib/xterm/src/common/CoreTerminal.ts +300 -0
- package/dist/lib/xterm/src/common/EventEmitter.ts +69 -0
- package/dist/lib/xterm/src/common/InputHandler.ts +3230 -0
- package/dist/lib/xterm/src/common/Lifecycle.ts +68 -0
- package/dist/lib/xterm/src/common/Platform.ts +31 -0
- package/dist/lib/xterm/src/common/SortedList.ts +88 -0
- package/dist/lib/xterm/src/common/TypedArrayUtils.ts +50 -0
- package/dist/lib/xterm/src/common/Types.d.ts +489 -0
- package/dist/lib/xterm/src/common/WindowsMode.ts +27 -0
- package/dist/lib/xterm/src/common/buffer/AttributeData.ts +148 -0
- package/dist/lib/xterm/src/common/buffer/Buffer.ts +711 -0
- package/dist/lib/xterm/src/common/buffer/BufferLine.ts +441 -0
- package/dist/lib/xterm/src/common/buffer/BufferRange.ts +13 -0
- package/dist/lib/xterm/src/common/buffer/BufferReflow.ts +220 -0
- package/dist/lib/xterm/src/common/buffer/BufferSet.ts +131 -0
- package/dist/lib/xterm/src/common/buffer/CellData.ts +94 -0
- package/dist/lib/xterm/src/common/buffer/Constants.ts +139 -0
- package/dist/lib/xterm/src/common/buffer/Marker.ts +37 -0
- package/dist/lib/xterm/src/common/buffer/Types.d.ts +64 -0
- package/dist/lib/xterm/src/common/data/Charsets.ts +256 -0
- package/dist/lib/xterm/src/common/data/EscapeSequences.ts +153 -0
- package/dist/lib/xterm/src/common/input/Keyboard.ts +398 -0
- package/dist/lib/xterm/src/common/input/TextDecoder.ts +346 -0
- package/dist/lib/xterm/src/common/input/UnicodeV6.ts +133 -0
- package/dist/lib/xterm/src/common/input/WriteBuffer.ts +229 -0
- package/dist/lib/xterm/src/common/input/XParseColor.ts +80 -0
- package/dist/lib/xterm/src/common/parser/Constants.ts +58 -0
- package/dist/lib/xterm/src/common/parser/DcsParser.ts +192 -0
- package/dist/lib/xterm/src/common/parser/EscapeSequenceParser.ts +796 -0
- package/dist/lib/xterm/src/common/parser/OscParser.ts +238 -0
- package/dist/lib/xterm/src/common/parser/Params.ts +229 -0
- package/dist/lib/xterm/src/common/parser/Types.d.ts +274 -0
- package/dist/lib/xterm/src/common/public/AddonManager.ts +56 -0
- package/dist/lib/xterm/src/common/public/BufferApiView.ts +35 -0
- package/dist/lib/xterm/src/common/public/BufferLineApiView.ts +29 -0
- package/dist/lib/xterm/src/common/public/BufferNamespaceApi.ts +33 -0
- package/dist/lib/xterm/src/common/public/ParserApi.ts +37 -0
- package/dist/lib/xterm/src/common/public/UnicodeApi.ts +27 -0
- package/dist/lib/xterm/src/common/services/BufferService.ts +185 -0
- package/dist/lib/xterm/src/common/services/CharsetService.ts +34 -0
- package/dist/lib/xterm/src/common/services/CoreMouseService.ts +309 -0
- package/dist/lib/xterm/src/common/services/CoreService.ts +92 -0
- package/dist/lib/xterm/src/common/services/DecorationService.ts +139 -0
- package/dist/lib/xterm/src/common/services/DirtyRowService.ts +53 -0
- package/dist/lib/xterm/src/common/services/InstantiationService.ts +83 -0
- package/dist/lib/xterm/src/common/services/LogService.ts +88 -0
- package/dist/lib/xterm/src/common/services/OptionsService.ts +178 -0
- package/dist/lib/xterm/src/common/services/ServiceRegistry.ts +49 -0
- package/dist/lib/xterm/src/common/services/Services.ts +323 -0
- package/dist/lib/xterm/src/common/services/UnicodeService.ts +82 -0
- package/dist/lib/xterm/src/headless/Terminal.ts +170 -0
- package/dist/lib/xterm/src/headless/Types.d.ts +31 -0
- package/dist/lib/xterm/src/headless/public/Terminal.ts +216 -0
- package/dist/lib/xterm/typings/xterm.d.ts +1872 -0
- package/dist/lib/xterm-fit/LICENSE +19 -0
- package/dist/lib/xterm-fit/README.md +24 -0
- package/dist/lib/xterm-fit/lib/xterm-addon-fit.js +2 -0
- package/dist/lib/xterm-fit/lib/xterm-addon-fit.js.map +1 -0
- package/dist/lib/xterm-fit/out/FitAddon.js +58 -0
- package/dist/lib/xterm-fit/out/FitAddon.js.map +1 -0
- package/dist/lib/xterm-fit/out-test/FitAddon.api.js.map +1 -0
- package/dist/lib/xterm-fit/package.json +21 -0
- package/dist/lib/xterm-fit/src/FitAddon.ts +86 -0
- package/dist/lib/xterm-fit/typings/xterm-addon-fit.d.ts +55 -0
- package/dist/lib/xterm-links/LICENSE +19 -0
- package/dist/lib/xterm-links/README.md +21 -0
- package/dist/lib/xterm-links/lib/xterm-addon-web-links.js +2 -0
- package/dist/lib/xterm-links/lib/xterm-addon-web-links.js.map +1 -0
- package/dist/lib/xterm-links/package.json +26 -0
- package/dist/lib/xterm-links/src/WebLinkProvider.ts +145 -0
- package/dist/lib/xterm-links/src/WebLinksAddon.ts +77 -0
- package/dist/lib/xterm-links/typings/xterm-addon-web-links.d.ts +58 -0
- package/package.json +1 -1
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR, TEXT_BASELINE } from 'browser/renderer/atlas/Constants';
|
|
7
|
+
import { IGlyphIdentifier, ICharAtlasConfig } from 'browser/renderer/atlas/Types';
|
|
8
|
+
import { BaseCharAtlas } from 'browser/renderer/atlas/BaseCharAtlas';
|
|
9
|
+
import { DEFAULT_ANSI_COLORS } from 'browser/ColorManager';
|
|
10
|
+
import { LRUMap } from 'browser/renderer/atlas/LRUMap';
|
|
11
|
+
import { isFirefox, isSafari } from 'common/Platform';
|
|
12
|
+
import { IColor } from 'common/Types';
|
|
13
|
+
import { throwIfFalsy } from 'browser/renderer/RendererUtils';
|
|
14
|
+
import { color } from 'common/Color';
|
|
15
|
+
|
|
16
|
+
// In practice we're probably never going to exhaust a texture this large. For debugging purposes,
|
|
17
|
+
// however, it can be useful to set this to a really tiny value, to verify that LRU eviction works.
|
|
18
|
+
const TEXTURE_WIDTH = 1024;
|
|
19
|
+
const TEXTURE_HEIGHT = 1024;
|
|
20
|
+
|
|
21
|
+
const TRANSPARENT_COLOR = {
|
|
22
|
+
css: 'rgba(0, 0, 0, 0)',
|
|
23
|
+
rgba: 0
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Drawing to the cache is expensive: If we have to draw more than this number of glyphs to the
|
|
27
|
+
// cache in a single frame, give up on trying to cache anything else, and try to finish the current
|
|
28
|
+
// frame ASAP.
|
|
29
|
+
//
|
|
30
|
+
// This helps to limit the amount of damage a program can do when it would otherwise thrash the
|
|
31
|
+
// cache.
|
|
32
|
+
const FRAME_CACHE_DRAW_LIMIT = 100;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The number of milliseconds to wait before generating the ImageBitmap, this is to debounce/batch
|
|
36
|
+
* the operation as window.createImageBitmap is asynchronous.
|
|
37
|
+
*/
|
|
38
|
+
const GLYPH_BITMAP_COMMIT_DELAY = 100;
|
|
39
|
+
|
|
40
|
+
interface IGlyphCacheValue {
|
|
41
|
+
index: number;
|
|
42
|
+
isEmpty: boolean;
|
|
43
|
+
inBitmap: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function getGlyphCacheKey(glyph: IGlyphIdentifier): number {
|
|
47
|
+
// Note that this only returns a valid key when code < 256
|
|
48
|
+
// Layout:
|
|
49
|
+
// 0b00000000000000000000000000000001: italic (1)
|
|
50
|
+
// 0b00000000000000000000000000000010: dim (1)
|
|
51
|
+
// 0b00000000000000000000000000000100: bold (1)
|
|
52
|
+
// 0b00000000000000000000111111111000: fg (9)
|
|
53
|
+
// 0b00000000000111111111000000000000: bg (9)
|
|
54
|
+
// 0b00011111111000000000000000000000: code (8)
|
|
55
|
+
// 0b11100000000000000000000000000000: unused (3)
|
|
56
|
+
return glyph.code << 21 | glyph.bg << 12 | glyph.fg << 3 | (glyph.bold ? 0 : 4) + (glyph.dim ? 0 : 2) + (glyph.italic ? 0 : 1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class DynamicCharAtlas extends BaseCharAtlas {
|
|
60
|
+
// An ordered map that we're using to keep track of where each glyph is in the atlas texture.
|
|
61
|
+
// It's ordered so that we can determine when to remove the old entries.
|
|
62
|
+
private _cacheMap: LRUMap<IGlyphCacheValue>;
|
|
63
|
+
|
|
64
|
+
// The texture that the atlas is drawn to
|
|
65
|
+
private _cacheCanvas: HTMLCanvasElement;
|
|
66
|
+
private _cacheCtx: CanvasRenderingContext2D;
|
|
67
|
+
|
|
68
|
+
// A temporary context that glyphs are drawn to before being transfered to the atlas.
|
|
69
|
+
private _tmpCtx: CanvasRenderingContext2D;
|
|
70
|
+
|
|
71
|
+
// The number of characters stored in the atlas by width/height
|
|
72
|
+
private _width: number;
|
|
73
|
+
private _height: number;
|
|
74
|
+
|
|
75
|
+
private _drawToCacheCount: number = 0;
|
|
76
|
+
|
|
77
|
+
// An array of glyph keys that are waiting on the bitmap to be generated.
|
|
78
|
+
private _glyphsWaitingOnBitmap: IGlyphCacheValue[] = [];
|
|
79
|
+
|
|
80
|
+
// The timeout that is used to batch bitmap generation so it's not requested for every new glyph.
|
|
81
|
+
private _bitmapCommitTimeout: number | null = null;
|
|
82
|
+
|
|
83
|
+
// The bitmap to draw from, this is much faster on other browsers than others.
|
|
84
|
+
private _bitmap: ImageBitmap | null = null;
|
|
85
|
+
|
|
86
|
+
constructor(document: Document, private _config: ICharAtlasConfig) {
|
|
87
|
+
super();
|
|
88
|
+
this._cacheCanvas = document.createElement('canvas');
|
|
89
|
+
this._cacheCanvas.width = TEXTURE_WIDTH;
|
|
90
|
+
this._cacheCanvas.height = TEXTURE_HEIGHT;
|
|
91
|
+
// The canvas needs alpha because we use clearColor to convert the background color to alpha.
|
|
92
|
+
// It might also contain some characters with transparent backgrounds if allowTransparency is
|
|
93
|
+
// set.
|
|
94
|
+
this._cacheCtx = throwIfFalsy(this._cacheCanvas.getContext('2d', { alpha: true }));
|
|
95
|
+
|
|
96
|
+
const tmpCanvas = document.createElement('canvas');
|
|
97
|
+
tmpCanvas.width = this._config.scaledCharWidth;
|
|
98
|
+
tmpCanvas.height = this._config.scaledCharHeight;
|
|
99
|
+
this._tmpCtx = throwIfFalsy(tmpCanvas.getContext('2d', { alpha: this._config.allowTransparency }));
|
|
100
|
+
|
|
101
|
+
this._width = Math.floor(TEXTURE_WIDTH / this._config.scaledCharWidth);
|
|
102
|
+
this._height = Math.floor(TEXTURE_HEIGHT / this._config.scaledCharHeight);
|
|
103
|
+
const capacity = this._width * this._height;
|
|
104
|
+
this._cacheMap = new LRUMap(capacity);
|
|
105
|
+
this._cacheMap.prealloc(capacity);
|
|
106
|
+
|
|
107
|
+
// This is useful for debugging
|
|
108
|
+
// document.body.appendChild(this._cacheCanvas);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public dispose(): void {
|
|
112
|
+
if (this._bitmapCommitTimeout !== null) {
|
|
113
|
+
window.clearTimeout(this._bitmapCommitTimeout);
|
|
114
|
+
this._bitmapCommitTimeout = null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public beginFrame(): void {
|
|
119
|
+
this._drawToCacheCount = 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
public clear(): void {
|
|
123
|
+
if (this._cacheMap.size > 0) {
|
|
124
|
+
const capacity = this._width * this._height;
|
|
125
|
+
this._cacheMap = new LRUMap(capacity);
|
|
126
|
+
this._cacheMap.prealloc(capacity);
|
|
127
|
+
}
|
|
128
|
+
this._cacheCtx.clearRect(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
|
|
129
|
+
this._tmpCtx.clearRect(0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public draw(
|
|
133
|
+
ctx: CanvasRenderingContext2D,
|
|
134
|
+
glyph: IGlyphIdentifier,
|
|
135
|
+
x: number,
|
|
136
|
+
y: number
|
|
137
|
+
): boolean {
|
|
138
|
+
// Space is always an empty cell, special case this as it's so common
|
|
139
|
+
if (glyph.code === 32) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Exit early for uncachable glyphs
|
|
144
|
+
if (!this._canCache(glyph)) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const glyphKey = getGlyphCacheKey(glyph);
|
|
149
|
+
const cacheValue = this._cacheMap.get(glyphKey);
|
|
150
|
+
if (cacheValue !== null && cacheValue !== undefined) {
|
|
151
|
+
this._drawFromCache(ctx, cacheValue, x, y);
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
if (this._drawToCacheCount < FRAME_CACHE_DRAW_LIMIT) {
|
|
155
|
+
let index;
|
|
156
|
+
if (this._cacheMap.size < this._cacheMap.capacity) {
|
|
157
|
+
index = this._cacheMap.size;
|
|
158
|
+
} else {
|
|
159
|
+
// we're out of space, so our call to set will delete this item
|
|
160
|
+
index = this._cacheMap.peek()!.index;
|
|
161
|
+
}
|
|
162
|
+
const cacheValue = this._drawToCache(glyph, index);
|
|
163
|
+
this._cacheMap.set(glyphKey, cacheValue);
|
|
164
|
+
this._drawFromCache(ctx, cacheValue, x, y);
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private _canCache(glyph: IGlyphIdentifier): boolean {
|
|
171
|
+
// Only cache ascii and extended characters for now, to be safe. In the future, we could do
|
|
172
|
+
// something more complicated to determine the expected width of a character.
|
|
173
|
+
//
|
|
174
|
+
// If we switch the renderer over to webgl at some point, we may be able to use blending modes
|
|
175
|
+
// to draw overlapping glyphs from the atlas:
|
|
176
|
+
// https://github.com/servo/webrender/issues/464#issuecomment-255632875
|
|
177
|
+
// https://webglfundamentals.org/webgl/lessons/webgl-text-texture.html
|
|
178
|
+
return glyph.code < 256;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private _toCoordinateX(index: number): number {
|
|
182
|
+
return (index % this._width) * this._config.scaledCharWidth;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private _toCoordinateY(index: number): number {
|
|
186
|
+
return Math.floor(index / this._width) * this._config.scaledCharHeight;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private _drawFromCache(
|
|
190
|
+
ctx: CanvasRenderingContext2D,
|
|
191
|
+
cacheValue: IGlyphCacheValue,
|
|
192
|
+
x: number,
|
|
193
|
+
y: number
|
|
194
|
+
): void {
|
|
195
|
+
// We don't actually need to do anything if this is whitespace.
|
|
196
|
+
if (cacheValue.isEmpty) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const cacheX = this._toCoordinateX(cacheValue.index);
|
|
200
|
+
const cacheY = this._toCoordinateY(cacheValue.index);
|
|
201
|
+
ctx.drawImage(
|
|
202
|
+
cacheValue.inBitmap ? this._bitmap! : this._cacheCanvas,
|
|
203
|
+
cacheX,
|
|
204
|
+
cacheY,
|
|
205
|
+
this._config.scaledCharWidth,
|
|
206
|
+
this._config.scaledCharHeight,
|
|
207
|
+
x,
|
|
208
|
+
y,
|
|
209
|
+
this._config.scaledCharWidth,
|
|
210
|
+
this._config.scaledCharHeight
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private _getColorFromAnsiIndex(idx: number): IColor {
|
|
215
|
+
if (idx < this._config.colors.ansi.length) {
|
|
216
|
+
return this._config.colors.ansi[idx];
|
|
217
|
+
}
|
|
218
|
+
return DEFAULT_ANSI_COLORS[idx];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private _getBackgroundColor(glyph: IGlyphIdentifier): IColor {
|
|
222
|
+
if (this._config.allowTransparency) {
|
|
223
|
+
// The background color might have some transparency, so we need to render it as fully
|
|
224
|
+
// transparent in the atlas. Otherwise we'd end up drawing the transparent background twice
|
|
225
|
+
// around the anti-aliased edges of the glyph, and it would look too dark.
|
|
226
|
+
return TRANSPARENT_COLOR;
|
|
227
|
+
}
|
|
228
|
+
if (glyph.bg === INVERTED_DEFAULT_COLOR) {
|
|
229
|
+
return this._config.colors.foreground;
|
|
230
|
+
}
|
|
231
|
+
if (glyph.bg < 256) {
|
|
232
|
+
return this._getColorFromAnsiIndex(glyph.bg);
|
|
233
|
+
}
|
|
234
|
+
return this._config.colors.background;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
private _getForegroundColor(glyph: IGlyphIdentifier): IColor {
|
|
238
|
+
if (glyph.fg === INVERTED_DEFAULT_COLOR) {
|
|
239
|
+
return color.opaque(this._config.colors.background);
|
|
240
|
+
}
|
|
241
|
+
if (glyph.fg < 256) {
|
|
242
|
+
// 256 color support
|
|
243
|
+
return this._getColorFromAnsiIndex(glyph.fg);
|
|
244
|
+
}
|
|
245
|
+
return this._config.colors.foreground;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// TODO: We do this (or something similar) in multiple places. We should split this off
|
|
249
|
+
// into a shared function.
|
|
250
|
+
private _drawToCache(glyph: IGlyphIdentifier, index: number): IGlyphCacheValue {
|
|
251
|
+
this._drawToCacheCount++;
|
|
252
|
+
|
|
253
|
+
this._tmpCtx.save();
|
|
254
|
+
|
|
255
|
+
// draw the background
|
|
256
|
+
const backgroundColor = this._getBackgroundColor(glyph);
|
|
257
|
+
// Use a 'copy' composite operation to clear any existing glyph out of _tmpCtxWithAlpha, regardless of
|
|
258
|
+
// transparency in backgroundColor
|
|
259
|
+
this._tmpCtx.globalCompositeOperation = 'copy';
|
|
260
|
+
this._tmpCtx.fillStyle = backgroundColor.css;
|
|
261
|
+
this._tmpCtx.fillRect(0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight);
|
|
262
|
+
this._tmpCtx.globalCompositeOperation = 'source-over';
|
|
263
|
+
|
|
264
|
+
// draw the foreground/glyph
|
|
265
|
+
const fontWeight = glyph.bold ? this._config.fontWeightBold : this._config.fontWeight;
|
|
266
|
+
const fontStyle = glyph.italic ? 'italic' : '';
|
|
267
|
+
this._tmpCtx.font =
|
|
268
|
+
`${fontStyle} ${fontWeight} ${this._config.fontSize * this._config.devicePixelRatio}px ${this._config.fontFamily}`;
|
|
269
|
+
this._tmpCtx.textBaseline = TEXT_BASELINE;
|
|
270
|
+
|
|
271
|
+
this._tmpCtx.fillStyle = this._getForegroundColor(glyph).css;
|
|
272
|
+
|
|
273
|
+
// Apply alpha to dim the character
|
|
274
|
+
if (glyph.dim) {
|
|
275
|
+
this._tmpCtx.globalAlpha = DIM_OPACITY;
|
|
276
|
+
}
|
|
277
|
+
// Draw the character
|
|
278
|
+
this._tmpCtx.fillText(glyph.chars, 0, this._config.scaledCharHeight);
|
|
279
|
+
|
|
280
|
+
// clear the background from the character to avoid issues with drawing over the previous
|
|
281
|
+
// character if it extends past it's bounds
|
|
282
|
+
let imageData = this._tmpCtx.getImageData(
|
|
283
|
+
0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight
|
|
284
|
+
);
|
|
285
|
+
let isEmpty = false;
|
|
286
|
+
if (!this._config.allowTransparency) {
|
|
287
|
+
isEmpty = clearColor(imageData, backgroundColor);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// If this charcater is underscore and empty, shift it up until it is visible, try for a maximum
|
|
291
|
+
// of 5 pixels.
|
|
292
|
+
if (isEmpty && glyph.chars === '_' && !this._config.allowTransparency) {
|
|
293
|
+
for (let offset = 1; offset <= 5; offset++) {
|
|
294
|
+
// Draw the character
|
|
295
|
+
this._tmpCtx.fillText(glyph.chars, 0, this._config.scaledCharHeight - offset);
|
|
296
|
+
|
|
297
|
+
// clear the background from the character to avoid issues with drawing over the previous
|
|
298
|
+
// character if it extends past it's bounds
|
|
299
|
+
imageData = this._tmpCtx.getImageData(
|
|
300
|
+
0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight
|
|
301
|
+
);
|
|
302
|
+
isEmpty = clearColor(imageData, backgroundColor);
|
|
303
|
+
if (!isEmpty) {
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
this._tmpCtx.restore();
|
|
310
|
+
|
|
311
|
+
// copy the data from imageData to _cacheCanvas
|
|
312
|
+
const x = this._toCoordinateX(index);
|
|
313
|
+
const y = this._toCoordinateY(index);
|
|
314
|
+
// putImageData doesn't do any blending, so it will overwrite any existing cache entry for us
|
|
315
|
+
this._cacheCtx.putImageData(imageData, x, y);
|
|
316
|
+
|
|
317
|
+
// Add the glyph and queue it to the bitmap (if the browser supports it)
|
|
318
|
+
const cacheValue = {
|
|
319
|
+
index,
|
|
320
|
+
isEmpty,
|
|
321
|
+
inBitmap: false
|
|
322
|
+
};
|
|
323
|
+
this._addGlyphToBitmap(cacheValue);
|
|
324
|
+
|
|
325
|
+
return cacheValue;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
private _addGlyphToBitmap(cacheValue: IGlyphCacheValue): void {
|
|
329
|
+
// Support is patchy for createImageBitmap at the moment, pass a canvas back
|
|
330
|
+
// if support is lacking as drawImage works there too. Firefox is also
|
|
331
|
+
// included here as ImageBitmap appears both buggy and has horrible
|
|
332
|
+
// performance (tested on v55).
|
|
333
|
+
if (!('createImageBitmap' in window) || isFirefox || isSafari) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Add the glyph to the queue
|
|
338
|
+
this._glyphsWaitingOnBitmap.push(cacheValue);
|
|
339
|
+
|
|
340
|
+
// Check if bitmap generation timeout already exists
|
|
341
|
+
if (this._bitmapCommitTimeout !== null) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
this._bitmapCommitTimeout = window.setTimeout(() => this._generateBitmap(), GLYPH_BITMAP_COMMIT_DELAY);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
private _generateBitmap(): void {
|
|
349
|
+
const glyphsMovingToBitmap = this._glyphsWaitingOnBitmap;
|
|
350
|
+
this._glyphsWaitingOnBitmap = [];
|
|
351
|
+
window.createImageBitmap(this._cacheCanvas).then(bitmap => {
|
|
352
|
+
// Set bitmap
|
|
353
|
+
this._bitmap = bitmap;
|
|
354
|
+
|
|
355
|
+
// Mark all new glyphs as in bitmap, excluding glyphs that came in after
|
|
356
|
+
// the bitmap was requested
|
|
357
|
+
for (let i = 0; i < glyphsMovingToBitmap.length; i++) {
|
|
358
|
+
const value = glyphsMovingToBitmap[i];
|
|
359
|
+
// It doesn't matter if the value was already evicted, it will be
|
|
360
|
+
// released from memory after this block if so.
|
|
361
|
+
value.inBitmap = true;
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
this._bitmapCommitTimeout = null;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// This is used for debugging the renderer, just swap out `new DynamicCharAtlas` with
|
|
369
|
+
// `new NoneCharAtlas`.
|
|
370
|
+
export class NoneCharAtlas extends BaseCharAtlas {
|
|
371
|
+
constructor(document: Document, config: ICharAtlasConfig) {
|
|
372
|
+
super();
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
public draw(
|
|
376
|
+
ctx: CanvasRenderingContext2D,
|
|
377
|
+
glyph: IGlyphIdentifier,
|
|
378
|
+
x: number,
|
|
379
|
+
y: number
|
|
380
|
+
): boolean {
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Makes a partiicular rgb color in an ImageData completely transparent.
|
|
387
|
+
* @returns True if the result is "empty", meaning all pixels are fully transparent.
|
|
388
|
+
*/
|
|
389
|
+
function clearColor(imageData: ImageData, color: IColor): boolean {
|
|
390
|
+
let isEmpty = true;
|
|
391
|
+
const r = color.rgba >>> 24;
|
|
392
|
+
const g = color.rgba >>> 16 & 0xFF;
|
|
393
|
+
const b = color.rgba >>> 8 & 0xFF;
|
|
394
|
+
for (let offset = 0; offset < imageData.data.length; offset += 4) {
|
|
395
|
+
if (imageData.data[offset] === r &&
|
|
396
|
+
imageData.data[offset + 1] === g &&
|
|
397
|
+
imageData.data[offset + 2] === b) {
|
|
398
|
+
imageData.data[offset + 3] = 0;
|
|
399
|
+
} else {
|
|
400
|
+
isEmpty = false;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return isEmpty;
|
|
404
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
interface ILinkedListNode<T> {
|
|
7
|
+
prev: ILinkedListNode<T> | null;
|
|
8
|
+
next: ILinkedListNode<T> | null;
|
|
9
|
+
key: number | null;
|
|
10
|
+
value: T | null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class LRUMap<T> {
|
|
14
|
+
private _map: { [key: number]: ILinkedListNode<T> } = {};
|
|
15
|
+
private _head: ILinkedListNode<T> | null = null;
|
|
16
|
+
private _tail: ILinkedListNode<T> | null = null;
|
|
17
|
+
private _nodePool: ILinkedListNode<T>[] = [];
|
|
18
|
+
public size: number = 0;
|
|
19
|
+
|
|
20
|
+
constructor(public capacity: number) { }
|
|
21
|
+
|
|
22
|
+
private _unlinkNode(node: ILinkedListNode<T>): void {
|
|
23
|
+
const prev = node.prev;
|
|
24
|
+
const next = node.next;
|
|
25
|
+
if (node === this._head) {
|
|
26
|
+
this._head = next;
|
|
27
|
+
}
|
|
28
|
+
if (node === this._tail) {
|
|
29
|
+
this._tail = prev;
|
|
30
|
+
}
|
|
31
|
+
if (prev !== null) {
|
|
32
|
+
prev.next = next;
|
|
33
|
+
}
|
|
34
|
+
if (next !== null) {
|
|
35
|
+
next.prev = prev;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private _appendNode(node: ILinkedListNode<T>): void {
|
|
40
|
+
const tail = this._tail;
|
|
41
|
+
if (tail !== null) {
|
|
42
|
+
tail.next = node;
|
|
43
|
+
}
|
|
44
|
+
node.prev = tail;
|
|
45
|
+
node.next = null;
|
|
46
|
+
this._tail = node;
|
|
47
|
+
if (this._head === null) {
|
|
48
|
+
this._head = node;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Preallocate a bunch of linked-list nodes. Allocating these nodes ahead of time means that
|
|
54
|
+
* they're more likely to live next to each other in memory, which seems to improve performance.
|
|
55
|
+
*
|
|
56
|
+
* Each empty object only consumes about 60 bytes of memory, so this is pretty cheap, even for
|
|
57
|
+
* large maps.
|
|
58
|
+
*/
|
|
59
|
+
public prealloc(count: number): void {
|
|
60
|
+
const nodePool = this._nodePool;
|
|
61
|
+
for (let i = 0; i < count; i++) {
|
|
62
|
+
nodePool.push({
|
|
63
|
+
prev: null,
|
|
64
|
+
next: null,
|
|
65
|
+
key: null,
|
|
66
|
+
value: null
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public get(key: number): T | null {
|
|
72
|
+
// This is unsafe: We're assuming our keyspace doesn't overlap with Object.prototype. However,
|
|
73
|
+
// it's faster than calling hasOwnProperty, and in our case, it would never overlap.
|
|
74
|
+
const node = this._map[key];
|
|
75
|
+
if (node !== undefined) {
|
|
76
|
+
this._unlinkNode(node);
|
|
77
|
+
this._appendNode(node);
|
|
78
|
+
return node.value;
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Gets a value from a key without marking it as the most recently used item.
|
|
85
|
+
*/
|
|
86
|
+
public peekValue(key: number): T | null {
|
|
87
|
+
const node = this._map[key];
|
|
88
|
+
if (node !== undefined) {
|
|
89
|
+
return node.value;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public peek(): T | null {
|
|
95
|
+
const head = this._head;
|
|
96
|
+
return head === null ? null : head.value;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public set(key: number, value: T): void {
|
|
100
|
+
// This is unsafe: See note above.
|
|
101
|
+
let node = this._map[key];
|
|
102
|
+
if (node !== undefined) {
|
|
103
|
+
// already exists, we just need to mutate it and move it to the end of the list
|
|
104
|
+
node = this._map[key];
|
|
105
|
+
this._unlinkNode(node);
|
|
106
|
+
node.value = value;
|
|
107
|
+
} else if (this.size >= this.capacity) {
|
|
108
|
+
// we're out of space: recycle the head node, move it to the tail
|
|
109
|
+
node = this._head!;
|
|
110
|
+
this._unlinkNode(node);
|
|
111
|
+
delete this._map[node.key!];
|
|
112
|
+
node.key = key;
|
|
113
|
+
node.value = value;
|
|
114
|
+
this._map[key] = node;
|
|
115
|
+
} else {
|
|
116
|
+
// make a new element
|
|
117
|
+
const nodePool = this._nodePool;
|
|
118
|
+
if (nodePool.length > 0) {
|
|
119
|
+
// use a preallocated node if we can
|
|
120
|
+
node = nodePool.pop()!;
|
|
121
|
+
node.key = key;
|
|
122
|
+
node.value = value;
|
|
123
|
+
} else {
|
|
124
|
+
node = {
|
|
125
|
+
prev: null,
|
|
126
|
+
next: null,
|
|
127
|
+
key,
|
|
128
|
+
value
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
this._map[key] = node;
|
|
132
|
+
this.size++;
|
|
133
|
+
}
|
|
134
|
+
this._appendNode(node);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FontWeight } from 'common/services/Services';
|
|
7
|
+
import { IPartialColorSet } from 'browser/Types';
|
|
8
|
+
|
|
9
|
+
export interface IGlyphIdentifier {
|
|
10
|
+
chars: string;
|
|
11
|
+
code: number;
|
|
12
|
+
bg: number;
|
|
13
|
+
fg: number;
|
|
14
|
+
bold: boolean;
|
|
15
|
+
dim: boolean;
|
|
16
|
+
italic: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ICharAtlasConfig {
|
|
20
|
+
devicePixelRatio: number;
|
|
21
|
+
fontSize: number;
|
|
22
|
+
fontFamily: string;
|
|
23
|
+
fontWeight: FontWeight;
|
|
24
|
+
fontWeightBold: FontWeight;
|
|
25
|
+
scaledCharWidth: number;
|
|
26
|
+
scaledCharHeight: number;
|
|
27
|
+
allowTransparency: boolean;
|
|
28
|
+
colors: IPartialColorSet;
|
|
29
|
+
}
|