Move atlas parts into webgl/

This commit is contained in:
Daniel Imms
2019-05-18 23:30:10 -07:00
parent f42e53f15a
commit 6922156d07
18 changed files with 642 additions and 25 deletions
+8 -4
View File
@@ -47,7 +47,6 @@ import { removeTerminalFromCache } from './renderer/atlas/CharAtlasCache';
import { DomRenderer } from './renderer/dom/DomRenderer';
import { IKeyboardEvent } from './common/Types';
import { evaluateKeyboardEvent } from './core/input/Keyboard';
import { WebglRenderer } from './renderer/webgl/WebglRenderer';
import { KeyboardResultType, ICharset, IBufferLine, IAttributeData } from './core/Types';
import { clone } from './common/Clone';
import { EventEmitter2, IEvent } from './common/EventEmitter2';
@@ -818,11 +817,16 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
}
public setRenderer(renderer: IRenderer): void {
this._renderCoordinator.setRenderer(renderer);
// this._renderCoordinator.onOptionsChanged();
this.refresh(0, this.rows - 1);
}
private _createRenderer(): IRenderer {
switch (this.options.rendererType) {
case 'canvas': return new Renderer(this, this._colorManager.colors); break;
case 'dom': return new DomRenderer(this, this._colorManager.colors); break;
case 'webgl': return new WebglRenderer(this, this._colorManager.colors); break;
case 'canvas': return new Renderer(this, this._colorManager.colors);
case 'dom': return new DomRenderer(this, this._colorManager.colors);
default: throw new Error(`Unrecognized rendererType "${this.options.rendererType}"`);
}
}
+3
View File
@@ -22,6 +22,9 @@ export class TestTerminal extends Terminal {
}
export class MockTerminal implements ITerminal {
setRenderer(renderer: any): void {
throw new Error('Method not implemented.');
}
onCursorMove: IEvent<void>;
onLineFeed: IEvent<void>;
onSelectionChange: IEvent<void>;
+1
View File
@@ -270,6 +270,7 @@ export interface IPublicTerminal extends IDisposable, IEventEmitter {
setOption(key: string, value: any): void;
refresh(start: number, end: number): void;
reset(): void;
setRenderer(renderer: any): void;
}
export interface IBufferAccessor {
+7
View File
@@ -10,6 +10,7 @@ import { Terminal as TerminalCore } from '../Terminal';
import * as Strings from '../Strings';
import { IEvent } from '../common/EventEmitter2';
import { AddonManager } from './AddonManager';
import { WebglRendererAddon } from '../renderer/webgl/WebglRendererAddon';
export class Terminal implements ITerminalApi {
private _core: ITerminal;
@@ -183,6 +184,12 @@ export class Terminal implements ITerminalApi {
public loadAddon(addon: ITerminalAddon): void {
return this._addonManager.loadAddon(this, addon);
}
public setRenderer(renderer: any): void {
this._core.setRenderer(renderer);
}
public loadWebgl(): void {
this.loadAddon(new WebglRendererAddon());
}
public static get strings(): ILocalizableStrings {
return Strings;
}
+1 -3
View File
@@ -9,15 +9,13 @@ import BaseCharAtlas from './BaseCharAtlas';
import DynamicCharAtlas from './DynamicCharAtlas';
import NoneCharAtlas from './NoneCharAtlas';
import StaticCharAtlas from './StaticCharAtlas';
import WebglCharAtlas from '../webgl/WebglCharAtlas';
import { ICharAtlasConfig } from './Types';
import { IColorSet } from '../../ui/Types';
const charAtlasImplementations = {
'none': NoneCharAtlas,
'static': StaticCharAtlas,
'dynamic': DynamicCharAtlas,
'webgl': WebglCharAtlas
'dynamic': DynamicCharAtlas
};
interface ICharAtlasCacheEntry {
+1 -1
View File
@@ -6,7 +6,7 @@
import { createProgram, PROJECTION_MATRIX } from './WebglUtils';
import { IRenderDimensions } from '../Types';
import { ITerminal } from '../../Types';
import WebglCharAtlas from './WebglCharAtlas';
import WebglCharAtlas from './atlas/WebglCharAtlas';
import { IWebGL2RenderingContext, IWebGLVertexArrayObject, IRenderModel, IRasterizedGlyph } from './Types';
import { INDICIES_PER_CELL } from './WebglRenderer';
import { COMBINED_CHAR_BIT_MASK } from './RenderModel';
+2 -2
View File
@@ -8,8 +8,8 @@ import { IRenderDimensions } from '../Types';
import { createProgram, expandFloat32Array, PROJECTION_MATRIX } from './WebglUtils';
import { IRenderModel, IWebGLVertexArrayObject, IWebGL2RenderingContext, ISelectionRenderModel } from './Types';
import { fill } from '../../common/TypedArrayUtils';
import { INVERTED_DEFAULT_COLOR } from '../atlas/Types';
import { is256Color } from '../atlas/CharAtlasUtils';
import { INVERTED_DEFAULT_COLOR } from './atlas/Types';
import { is256Color } from './atlas/CharAtlasUtils';
import { DEFAULT_COLOR } from '../../common/Types';
import { IColorSet, IColor } from '../../ui/Types';
+3 -3
View File
@@ -8,11 +8,11 @@ import { CharacterJoinerHandler, ITerminal } from '../../Types';
import { GlyphRenderer } from './GlyphRenderer';
import { LinkRenderLayer } from '../LinkRenderLayer';
import { CursorRenderLayer } from '../CursorRenderLayer';
import { acquireCharAtlas } from '../atlas/CharAtlasCache';
import WebglCharAtlas from './WebglCharAtlas';
import { acquireCharAtlas } from './atlas/CharAtlasCache';
import WebglCharAtlas from './atlas/WebglCharAtlas';
import { RectangleRenderer } from './RectangleRenderer';
import { IWebGL2RenderingContext } from './Types';
import { INVERTED_DEFAULT_COLOR } from '../atlas/Types';
import { INVERTED_DEFAULT_COLOR } from './atlas/Types';
import { RenderModel, COMBINED_CHAR_BIT_MASK } from './RenderModel';
import { Disposable } from '../../common/Lifecycle';
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_ATTR_INDEX, NULL_CELL_CODE } from '../../core/buffer/BufferLine';
+26
View File
@@ -0,0 +1,26 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal, ITerminalAddon } from 'xterm';
import { WebglRenderer } from './WebglRenderer';
export class WebglRendererAddon implements ITerminalAddon {
private _terminal: Terminal | undefined;
constructor() {}
public activate(terminal: Terminal): void {
if (!terminal.element) {
throw new Error('Cannot activate WebglRendererAddon before Terminal.open');
}
this._terminal = terminal;
const core = (terminal as any)._core;
this._terminal.setRenderer(new WebglRenderer(core, core._colorManager.colors));
}
public dispose(): void {
throw new Error('WebglRendererAddon.dispose Not yet implemented');
}
}
+56
View File
@@ -0,0 +1,56 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IGlyphIdentifier } from './Types';
import { IDisposable } from 'xterm';
export default abstract class BaseCharAtlas implements IDisposable {
private _didWarmUp: boolean = false;
public dispose(): void { }
/**
* Perform any work needed to warm the cache before it can be used. May be called multiple times.
* Implement _doWarmUp instead if you only want to get called once.
*/
public warmUp(): void {
if (!this._didWarmUp) {
this._doWarmUp();
this._didWarmUp = true;
}
}
/**
* Perform any work needed to warm the cache before it can be used. Used by the default
* implementation of warmUp(), and will only be called once.
*/
protected _doWarmUp(): void { }
/**
* Called when we start drawing a new frame.
*
* TODO: We rely on this getting called by TextRenderLayer. This should really be called by
* Renderer instead, but we need to make Renderer the source-of-truth for the char atlas, instead
* of BaseRenderLayer.
*/
public beginFrame(): void { }
/**
* May be called before warmUp finishes, however it is okay for the implementation to
* do nothing and return false in that case.
*
* @param ctx Where to draw the character onto.
* @param glyph Information about what to draw
* @param x The position on the context to start drawing at
* @param y The position on the context to start drawing at
* @returns The success state. True if we drew the character.
*/
public abstract draw(
ctx: CanvasRenderingContext2D,
glyph: IGlyphIdentifier,
x: number,
y: number
): boolean;
}
@@ -0,0 +1,94 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ITerminal } from '../../../Types';
import { generateConfig, configEquals } from './CharAtlasUtils';
import BaseCharAtlas from './BaseCharAtlas';
import WebglCharAtlas from './WebglCharAtlas';
import { ICharAtlasConfig } from './Types';
import { IColorSet } from '../../../ui/Types';
interface ICharAtlasCacheEntry {
atlas: BaseCharAtlas;
config: ICharAtlasConfig;
// N.B. This implementation potentially holds onto copies of the terminal forever, so
// this may cause memory leaks.
ownedBy: ITerminal[];
}
const charAtlasCache: ICharAtlasCacheEntry[] = [];
/**
* Acquires a char atlas, either generating a new one or returning an existing
* one that is in use by another terminal.
* @param terminal The terminal.
* @param colors The colors to use.
*/
export function acquireCharAtlas(
terminal: ITerminal,
colors: IColorSet,
scaledCharWidth: number,
scaledCharHeight: number
): BaseCharAtlas {
const newConfig = generateConfig(scaledCharWidth, scaledCharHeight, terminal, colors);
// Check to see if the terminal already owns this config
for (let i = 0; i < charAtlasCache.length; i++) {
const entry = charAtlasCache[i];
const ownedByIndex = entry.ownedBy.indexOf(terminal);
if (ownedByIndex >= 0) {
if (configEquals(entry.config, newConfig)) {
return entry.atlas;
}
// The configs differ, release the terminal from the entry
if (entry.ownedBy.length === 1) {
entry.atlas.dispose();
charAtlasCache.splice(i, 1);
} else {
entry.ownedBy.splice(ownedByIndex, 1);
}
break;
}
}
// Try match a char atlas from the cache
for (let i = 0; i < charAtlasCache.length; i++) {
const entry = charAtlasCache[i];
if (configEquals(entry.config, newConfig)) {
// Add the terminal to the cache entry and return
entry.ownedBy.push(terminal);
return entry.atlas;
}
}
const newEntry: ICharAtlasCacheEntry = {
atlas: new WebglCharAtlas(document, newConfig),
config: newConfig,
ownedBy: [terminal]
};
charAtlasCache.push(newEntry);
return newEntry.atlas;
}
/**
* Removes a terminal reference from the cache, allowing its memory to be freed.
* @param terminal The terminal to remove.
*/
export function removeTerminalFromCache(terminal: ITerminal): void {
for (let i = 0; i < charAtlasCache.length; i++) {
const index = charAtlasCache[i].ownedBy.indexOf(terminal);
if (index !== -1) {
if (charAtlasCache[i].ownedBy.length === 1) {
// Remove the cache entry if it's the only terminal
charAtlasCache[i].atlas.dispose();
charAtlasCache.splice(i, 1);
} else {
// Remove the reference from the cache entry
charAtlasCache[i].ownedBy.splice(index, 1);
}
break;
}
}
}
@@ -0,0 +1,129 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { FontWeight } from 'xterm';
import { isFirefox, isSafari } from '../../../common/Platform';
import { ICharAtlasConfig, CHAR_ATLAS_CELL_SPACING } from './Types';
import { IColor } from '../../../ui/Types';
/**
* Generates a char atlas.
* @param context The window or worker context.
* @param canvasFactory A function to generate a canvas with a width or height.
* @param config The config for the new char atlas.
*/
export function generateStaticCharAtlasTexture(context: Window, canvasFactory: (width: number, height: number) => HTMLCanvasElement, config: ICharAtlasConfig): HTMLCanvasElement | Promise<ImageBitmap> {
const cellWidth = config.scaledCharWidth + CHAR_ATLAS_CELL_SPACING;
const cellHeight = config.scaledCharHeight + CHAR_ATLAS_CELL_SPACING;
const canvas = canvasFactory(
/*255 ascii chars*/255 * cellWidth,
(/*default+default bold*/2 + /*0-15*/16 + /*0-15 bold*/16) * cellHeight
);
const ctx = canvas.getContext('2d', {alpha: config.allowTransparency});
ctx.fillStyle = config.colors.background.css;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.fillStyle = config.colors.foreground.css;
ctx.font = getFont(config.fontWeight, config);
ctx.textBaseline = 'middle';
// Default color
for (let i = 0; i < 256; i++) {
ctx.save();
ctx.beginPath();
ctx.rect(i * cellWidth, 0, cellWidth, cellHeight);
ctx.clip();
ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight / 2);
ctx.restore();
}
// Default color bold
ctx.save();
ctx.font = getFont(config.fontWeightBold, config);
for (let i = 0; i < 256; i++) {
ctx.save();
ctx.beginPath();
ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight);
ctx.clip();
ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight * 1.5);
ctx.restore();
}
ctx.restore();
// Colors 0-15
ctx.font = getFont(config.fontWeight, config);
for (let colorIndex = 0; colorIndex < 16; colorIndex++) {
const y = (colorIndex + 2) * cellHeight;
// Draw ascii characters
for (let i = 0; i < 256; i++) {
ctx.save();
ctx.beginPath();
ctx.rect(i * cellWidth, y, cellWidth, cellHeight);
ctx.clip();
ctx.fillStyle = config.colors.ansi[colorIndex].css;
ctx.fillText(String.fromCharCode(i), i * cellWidth, y + cellHeight / 2);
ctx.restore();
}
}
// Colors 0-15 bold
ctx.font = getFont(config.fontWeightBold, config);
for (let colorIndex = 0; colorIndex < 16; colorIndex++) {
const y = (colorIndex + 2 + 16) * cellHeight;
// Draw ascii characters
for (let i = 0; i < 256; i++) {
ctx.save();
ctx.beginPath();
ctx.rect(i * cellWidth, y, cellWidth, cellHeight);
ctx.clip();
ctx.fillStyle = config.colors.ansi[colorIndex].css;
ctx.fillText(String.fromCharCode(i), i * cellWidth, y + cellHeight / 2);
ctx.restore();
}
}
ctx.restore();
// Support is patchy for createImageBitmap at the moment, pass a canvas back
// if support is lacking as drawImage works there too. Firefox is also
// included here as ImageBitmap appears both buggy and has horrible
// performance (tested on v55).
if (!('createImageBitmap' in context) || isFirefox || isSafari) {
// Don't attempt to clear background colors if createImageBitmap is not supported
return canvas;
}
const charAtlasImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// Remove the background color from the image so characters may overlap
clearColor(charAtlasImageData, config.colors.background);
return context.createImageBitmap(charAtlasImageData);
}
/**
* Makes a partiicular rgb color in an ImageData completely transparent.
* @returns True if the result is "empty", meaning all pixels are fully transparent.
*/
export function clearColor(imageData: ImageData, color: IColor): boolean {
let isEmpty = true;
const r = color.rgba >>> 24;
const g = color.rgba >>> 16 & 0xFF;
const b = color.rgba >>> 8 & 0xFF;
for (let offset = 0; offset < imageData.data.length; offset += 4) {
if (imageData.data[offset] === r &&
imageData.data[offset + 1] === g &&
imageData.data[offset + 2] === b) {
imageData.data[offset + 3] = 0;
} else {
isEmpty = false;
}
}
return isEmpty;
}
function getFont(fontWeight: FontWeight, config: ICharAtlasConfig): string {
return `${fontWeight} ${config.fontSize * config.devicePixelRatio}px ${config.fontFamily}`;
}
@@ -0,0 +1,58 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ITerminal } from '../../../Types';
import { ICharAtlasConfig } from './Types';
import { DEFAULT_COLOR } from '../../../common/Types';
import { IColorSet } from '../../../ui/Types';
export function generateConfig(scaledCharWidth: number, scaledCharHeight: number, terminal: ITerminal, colors: IColorSet): ICharAtlasConfig {
// null out some fields that don't matter
const clonedColors = <IColorSet>{
foreground: colors.foreground,
background: colors.background,
cursor: null,
cursorAccent: null,
selection: null,
// For the static char atlas, we only use the first 16 colors, but we need all 256 for the
// dynamic character atlas.
ansi: colors.ansi.slice(0, 16)
};
return {
type: terminal.options.experimentalCharAtlas,
devicePixelRatio: window.devicePixelRatio,
scaledCharWidth,
scaledCharHeight,
fontFamily: terminal.options.fontFamily,
fontSize: terminal.options.fontSize,
fontWeight: terminal.options.fontWeight,
fontWeightBold: terminal.options.fontWeightBold,
allowTransparency: terminal.options.allowTransparency,
colors: clonedColors
};
}
export function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean {
for (let i = 0; i < a.colors.ansi.length; i++) {
if (a.colors.ansi[i].rgba !== b.colors.ansi[i].rgba) {
return false;
}
}
return a.type === b.type &&
a.devicePixelRatio === b.devicePixelRatio &&
a.fontFamily === b.fontFamily &&
a.fontSize === b.fontSize &&
a.fontWeight === b.fontWeight &&
a.fontWeightBold === b.fontWeightBold &&
a.allowTransparency === b.allowTransparency &&
a.scaledCharWidth === b.scaledCharWidth &&
a.scaledCharHeight === b.scaledCharHeight &&
a.colors.foreground === b.colors.foreground &&
a.colors.background === b.colors.background;
}
export function is256Color(colorCode: number): boolean {
return colorCode < DEFAULT_COLOR;
}
+65
View File
@@ -0,0 +1,65 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai';
import LRUMap from './LRUMap';
describe('LRUMap', () => {
it('can be used to store and retrieve values', () => {
const map = new LRUMap(10);
map.set(1, 'valuea');
map.set(2, 'valueb');
map.set(3, 'valuec');
assert.strictEqual(map.get(1), 'valuea');
assert.strictEqual(map.get(2), 'valueb');
assert.strictEqual(map.get(3), 'valuec');
});
it('maintains a size from insertions', () => {
const map = new LRUMap(10);
assert.strictEqual(map.size, 0);
map.set(1, 'value');
assert.strictEqual(map.size, 1);
map.set(2, 'value');
assert.strictEqual(map.size, 2);
});
it('deletes the oldest entry when the capacity is exceeded', () => {
const map = new LRUMap(4);
map.set(1, 'value');
map.set(2, 'value');
map.set(3, 'value');
map.set(4, 'value');
map.set(5, 'value');
assert.isNull(map.get(1));
assert.isNotNull(map.get(2));
assert.isNotNull(map.get(3));
assert.isNotNull(map.get(4));
assert.isNotNull(map.get(5));
assert.strictEqual(map.size, 4);
});
it('prevents a recently accessed entry from getting deleted', () => {
const map = new LRUMap(2);
map.set(1, 'value');
map.set(2, 'value');
map.get(1);
// a would normally get deleted here, except that we called get()
map.set(3, 'value');
assert.isNotNull(map.get(1));
// b got deleted instead of a
assert.isNull(map.get(2));
assert.isNotNull(map.get(3));
});
it('supports mutation', () => {
const map = new LRUMap(10);
map.set(1, 'oldvalue');
map.set(1, 'newvalue');
// mutation doesn't change the size
assert.strictEqual(map.size, 1);
assert.strictEqual(map.get(1), 'newvalue');
});
});
+136
View File
@@ -0,0 +1,136 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
interface ILinkedListNode<T> {
prev: ILinkedListNode<T>;
next: ILinkedListNode<T>;
key: number;
value: T;
}
export default class LRUMap<T> {
private _map: { [key: number]: ILinkedListNode<T> } = {};
private _head: ILinkedListNode<T> = null;
private _tail: ILinkedListNode<T> = null;
private _nodePool: ILinkedListNode<T>[] = [];
public size: number = 0;
constructor(public capacity: number) { }
private _unlinkNode(node: ILinkedListNode<T>): void {
const prev = node.prev;
const next = node.next;
if (node === this._head) {
this._head = next;
}
if (node === this._tail) {
this._tail = prev;
}
if (prev !== null) {
prev.next = next;
}
if (next !== null) {
next.prev = prev;
}
}
private _appendNode(node: ILinkedListNode<T>): void {
const tail = this._tail;
if (tail !== null) {
tail.next = node;
}
node.prev = tail;
node.next = null;
this._tail = node;
if (this._head === null) {
this._head = node;
}
}
/**
* Preallocate a bunch of linked-list nodes. Allocating these nodes ahead of time means that
* they're more likely to live next to each other in memory, which seems to improve performance.
*
* Each empty object only consumes about 60 bytes of memory, so this is pretty cheap, even for
* large maps.
*/
public prealloc(count: number): void {
const nodePool = this._nodePool;
for (let i = 0; i < count; i++) {
nodePool.push({
prev: null,
next: null,
key: null,
value: null
});
}
}
public get(key: number): T | null {
// This is unsafe: We're assuming our keyspace doesn't overlap with Object.prototype. However,
// it's faster than calling hasOwnProperty, and in our case, it would never overlap.
const node = this._map[key];
if (node !== undefined) {
this._unlinkNode(node);
this._appendNode(node);
return node.value;
}
return null;
}
/**
* Gets a value from a key without marking it as the most recently used item.
*/
public peekValue(key: number): T | null {
const node = this._map[key];
if (node !== undefined) {
return node.value;
}
return null;
}
public peek(): T | null {
const head = this._head;
return head === null ? null : head.value;
}
public set(key: number, value: T): void {
// This is unsafe: See note above.
let node = this._map[key];
if (node !== undefined) {
// already exists, we just need to mutate it and move it to the end of the list
node = this._map[key];
this._unlinkNode(node);
node.value = value;
} else if (this.size >= this.capacity) {
// we're out of space: recycle the head node, move it to the tail
node = this._head;
this._unlinkNode(node);
delete this._map[node.key];
node.key = key;
node.value = value;
this._map[key] = node;
} else {
// make a new element
const nodePool = this._nodePool;
if (nodePool.length > 0) {
// use a preallocated node if we can
node = nodePool.pop();
node.key = key;
node.value = value;
} else {
node = {
prev: null,
next: null,
key,
value
};
}
this._map[key] = node;
this.size++;
}
this._appendNode(node);
}
}
+35
View File
@@ -0,0 +1,35 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { FontWeight } from 'xterm';
import { IColorSet } from '../../../ui/Types';
export const INVERTED_DEFAULT_COLOR = 257;
export const DIM_OPACITY = 0.5;
export const CHAR_ATLAS_CELL_SPACING = 1;
export interface IGlyphIdentifier {
chars: string;
code: number;
bg: number;
fg: number;
bold: boolean;
dim: boolean;
italic: boolean;
}
export interface ICharAtlasConfig {
type: 'none' | 'static' | 'dynamic' | 'webgl';
devicePixelRatio: number;
fontSize: number;
fontFamily: string;
fontWeight: FontWeight;
fontWeightBold: FontWeight;
scaledCharWidth: number;
scaledCharHeight: number;
allowTransparency: boolean;
colors: IColorSet;
}
@@ -3,16 +3,16 @@
* @license MIT
*/
import { DIM_OPACITY, IGlyphIdentifier, INVERTED_DEFAULT_COLOR, ICharAtlasConfig } from '../atlas/Types';
import BaseCharAtlas from '../atlas/BaseCharAtlas';
import { IRasterizedGlyph, IBoundingBox, IRasterizedGlyphSet } from './Types';
import { FLAGS } from '../Types';
import { is256Color } from '../atlas/CharAtlasUtils';
import { clearColor } from '../atlas/CharAtlasGenerator';
import { DEFAULT_ATTR } from '../../core/buffer/BufferLine';
import { DEFAULT_COLOR } from '../../common/Types';
import { IColor } from '../../ui/Types';
import { DEFAULT_ANSI_COLORS } from '../../ui/ColorManager';
import { DIM_OPACITY, IGlyphIdentifier, INVERTED_DEFAULT_COLOR, ICharAtlasConfig } from './Types';
import BaseCharAtlas from './BaseCharAtlas';
import { IRasterizedGlyph, IBoundingBox, IRasterizedGlyphSet } from '../Types';
import { FLAGS } from '../../Types';
import { is256Color } from './CharAtlasUtils';
import { clearColor } from './CharAtlasGenerator';
import { DEFAULT_ATTR } from '../../../core/buffer/BufferLine';
import { DEFAULT_COLOR } from '../../../common/Types';
import { IColor } from '../../../ui/Types';
import { DEFAULT_ANSI_COLORS } from '../../../ui/ColorManager';
// In practice we're probably never going to exhaust a texture this large. For debugging purposes,
// however, it can be useful to set this to a really tiny value, to verify that LRU eviction works.
+7 -2
View File
@@ -18,7 +18,7 @@ declare module 'xterm' {
/**
* A string representing a renderer type.
*/
export type RendererType = 'dom' | 'canvas' | 'webgl';
export type RendererType = 'dom' | 'canvas';
/**
* An object containing start up options for the terminal.
@@ -99,7 +99,7 @@ declare module 'xterm' {
* Currently defaults to 'static'. This option may be removed in the future. If it is, passed
* parameters will be ignored.
*/
experimentalCharAtlas?: 'none' | 'static' | 'dynamic' | 'webgl';
experimentalCharAtlas?: 'none' | 'static' | 'dynamic';
/**
* The font size used to render text.
@@ -890,6 +890,11 @@ declare module 'xterm' {
* @param addon The addon to load.
*/
loadAddon(addon: ITerminalAddon): void;
/**
* (EXPERIMENTAL)
*/
setRenderer(renderer: any): void;
}
/**