forked from xtermjs/xterm.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
537 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/** | ||
* Copyright (c) 2017 The xterm.js authors. All rights reserved. | ||
* @license MIT | ||
*/ | ||
|
||
import { ITerminal } from '../../Types'; | ||
import { | ||
ICharAtlas, | ||
ICharAtlasConfig, | ||
IGlyphIdentifier, | ||
generateConfig, | ||
configEquals, | ||
} from './CharAtlasUtils'; | ||
import NoneCharAtlas from './NoneCharAtlas'; | ||
import DynamicCharAtlas from './DynamicCharAtlas'; | ||
import { IColorSet } from '../Types'; | ||
|
||
const charAtlasImplementations = { | ||
'none': NoneCharAtlas, | ||
'static': NoneCharAtlas, // TODO: implement | ||
'dynamic': DynamicCharAtlas, | ||
}; | ||
|
||
interface ICharAtlasCacheEntry { | ||
atlas: ICharAtlas; | ||
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, | ||
): ICharAtlas { | ||
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; | ||
} else { | ||
// The configs differ, release the terminal from the entry | ||
if (entry.ownedBy.length === 1) { | ||
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 charAtlasImplementations[terminal.options.experimentalCharAtlas]( | ||
document, | ||
newConfig, | ||
), | ||
config: newConfig, | ||
ownedBy: [terminal], | ||
}; | ||
charAtlasCache.push(newEntry); | ||
return newEntry.atlas; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/** | ||
* Copyright (c) 2017 The xterm.js authors. All rights reserved. | ||
* @license MIT | ||
*/ | ||
|
||
import { ITerminal } from '../../Types'; | ||
import { ITheme } from 'xterm'; | ||
import { IColorSet } from '../Types'; | ||
|
||
export interface IGlyphIdentifier { | ||
char: string; | ||
bg: number; | ||
fg: number; | ||
bold: boolean; | ||
dim: boolean; | ||
} | ||
|
||
export const CHAR_ATLAS_CELL_SPACING = 1; | ||
export const INVERTED_DEFAULT_COLOR = -1; | ||
export const DIM_OPACITY = 0.5; | ||
|
||
export interface ICharAtlasConfig { | ||
type: 'none' | 'static' | 'dynamic'; | ||
devicePixelRatio: number; | ||
fontSize: number; | ||
fontFamily: string; | ||
fontWeight: string; | ||
fontWeightBold: string; | ||
scaledCharWidth: number; | ||
scaledCharHeight: number; | ||
allowTransparency: boolean; | ||
colors: IColorSet; | ||
} | ||
|
||
export interface ICharAtlas { | ||
/** | ||
* Perform any work needed to warm the cache before it can be used. | ||
*/ | ||
warmUp(): Promise<any>; | ||
|
||
/** | ||
* 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. | ||
*/ | ||
draw( | ||
ctx: CanvasRenderingContext2D, | ||
glyph: IGlyphIdentifier, | ||
x: number, | ||
y: number | ||
): boolean; | ||
} | ||
|
||
export function generateConfig(scaledCharWidth: number, scaledCharHeight: number, terminal: ITerminal, colors: IColorSet): ICharAtlasConfig { | ||
const clonedColors = { | ||
foreground: colors.foreground, | ||
background: colors.background, | ||
cursor: null, | ||
cursorAccent: null, | ||
selection: null, | ||
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] !== b.colors.ansi[i]) { | ||
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; | ||
} |
Oops, something went wrong.