2 * Copyright (c) 2017 The xterm.js authors. All rights reserved.
6 import { generateConfig, configEquals } from 'browser/renderer/atlas/CharAtlasUtils';
7 import { BaseCharAtlas } from 'browser/renderer/atlas/BaseCharAtlas';
8 import { DynamicCharAtlas } from 'browser/renderer/atlas/DynamicCharAtlas';
9 import { ICharAtlasConfig } from 'browser/renderer/atlas/Types';
10 import { IColorSet } from 'browser/Types';
11 import { ITerminalOptions } from 'common/services/Services';
13 interface ICharAtlasCacheEntry {
15 config: ICharAtlasConfig;
16 // N.B. This implementation potentially holds onto copies of the terminal forever, so
17 // this may cause memory leaks.
21 const charAtlasCache: ICharAtlasCacheEntry[] = [];
24 * Acquires a char atlas, either generating a new one or returning an existing
25 * one that is in use by another terminal.
27 export function acquireCharAtlas(
28 options: ITerminalOptions,
31 scaledCharWidth: number,
32 scaledCharHeight: number
34 const newConfig = generateConfig(scaledCharWidth, scaledCharHeight, options, colors);
36 // Check to see if the renderer already owns this config
37 for (let i = 0; i < charAtlasCache.length; i++) {
38 const entry = charAtlasCache[i];
39 const ownedByIndex = entry.ownedBy.indexOf(rendererId);
40 if (ownedByIndex >= 0) {
41 if (configEquals(entry.config, newConfig)) {
44 // The configs differ, release the renderer from the entry
45 if (entry.ownedBy.length === 1) {
46 entry.atlas.dispose();
47 charAtlasCache.splice(i, 1);
49 entry.ownedBy.splice(ownedByIndex, 1);
55 // Try match a char atlas from the cache
56 for (let i = 0; i < charAtlasCache.length; i++) {
57 const entry = charAtlasCache[i];
58 if (configEquals(entry.config, newConfig)) {
59 // Add the renderer to the cache entry and return
60 entry.ownedBy.push(rendererId);
65 const newEntry: ICharAtlasCacheEntry = {
66 atlas: new DynamicCharAtlas(
73 charAtlasCache.push(newEntry);
74 return newEntry.atlas;
78 * Removes a terminal reference from the cache, allowing its memory to be freed.
80 export function removeTerminalFromCache(rendererId: number): void {
81 for (let i = 0; i < charAtlasCache.length; i++) {
82 const index = charAtlasCache[i].ownedBy.indexOf(rendererId);
84 if (charAtlasCache[i].ownedBy.length === 1) {
85 // Remove the cache entry if it's the only renderer
86 charAtlasCache[i].atlas.dispose();
87 charAtlasCache.splice(i, 1);
89 // Remove the reference from the cache entry
90 charAtlasCache[i].ownedBy.splice(index, 1);