@xterm/addon-image 0.10.0-beta.300 → 0.10.0-beta.301
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/lib/addon-image.js +1 -1
- package/lib/addon-image.js.map +1 -1
- package/lib/addon-image.mjs +1 -1
- package/lib/addon-image.mjs.map +4 -4
- package/package.json +3 -3
- package/src/ImageStorage.ts +57 -142
- package/src/Types.ts +2 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xterm/addon-image",
|
|
3
|
-
"version": "0.10.0-beta.
|
|
3
|
+
"version": "0.10.0-beta.301",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "The xterm.js authors",
|
|
6
6
|
"url": "https://xtermjs.org/"
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"sixel": "^0.16.0",
|
|
28
28
|
"xterm-wasm-parts": "^0.4.1"
|
|
29
29
|
},
|
|
30
|
-
"commit": "
|
|
30
|
+
"commit": "c58ea3637f3968e0e6e79cd92cf9aace7ef89ee2",
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@xterm/xterm": "^6.1.0-beta.
|
|
32
|
+
"@xterm/xterm": "^6.1.0-beta.304"
|
|
33
33
|
}
|
|
34
34
|
}
|
package/src/ImageStorage.ts
CHANGED
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
import { IDisposable } from '@xterm/xterm';
|
|
7
7
|
import { ImageRenderer } from './ImageRenderer';
|
|
8
|
-
import {
|
|
9
|
-
ITerminalExt,
|
|
10
|
-
IBufferLineExt, BgFlags, Cell, Content, ICellSize, ExtFlags, Attributes,
|
|
11
|
-
UnderlineStyle, IAddImageOpts
|
|
8
|
+
import type {
|
|
9
|
+
ITerminalExt, IImageAddonOptions, IImageSpec, ICellSize, IAddImageOpts
|
|
12
10
|
} from './Types';
|
|
13
|
-
|
|
11
|
+
import type { IBufferLine } from 'common/buffer/Types';
|
|
12
|
+
import { CellData } from 'common/buffer/CellData';
|
|
14
13
|
|
|
15
14
|
// fallback default cell size
|
|
16
15
|
export const CELL_SIZE_DEFAULT: ICellSize = {
|
|
@@ -18,93 +17,12 @@ export const CELL_SIZE_DEFAULT: ICellSize = {
|
|
|
18
17
|
height: 14
|
|
19
18
|
};
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
* Extend extended attribute to also hold image tile information.
|
|
23
|
-
*
|
|
24
|
-
* Object definition is copied from base repo to fully mimick its behavior.
|
|
25
|
-
* Image data is added as additional public properties `imageId` and `tileId`.
|
|
26
|
-
*/
|
|
27
|
-
class ExtendedAttrsImage implements IExtendedAttrsImage {
|
|
28
|
-
private _ext: number = 0;
|
|
29
|
-
public get ext(): number {
|
|
30
|
-
if (this._urlId) {
|
|
31
|
-
return (
|
|
32
|
-
(this._ext & ~ExtFlags.UNDERLINE_STYLE) |
|
|
33
|
-
(this.underlineStyle << 26)
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
return this._ext;
|
|
37
|
-
}
|
|
38
|
-
public set ext(value: number) { this._ext = value; }
|
|
39
|
-
|
|
40
|
-
public get underlineStyle(): UnderlineStyle {
|
|
41
|
-
// Always return the URL style if it has one
|
|
42
|
-
if (this._urlId) {
|
|
43
|
-
return UnderlineStyle.DASHED;
|
|
44
|
-
}
|
|
45
|
-
return (this._ext & ExtFlags.UNDERLINE_STYLE) >> 26;
|
|
46
|
-
}
|
|
47
|
-
public set underlineStyle(value: UnderlineStyle) {
|
|
48
|
-
this._ext &= ~ExtFlags.UNDERLINE_STYLE;
|
|
49
|
-
this._ext |= (value << 26) & ExtFlags.UNDERLINE_STYLE;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
public get underlineColor(): number {
|
|
53
|
-
return this._ext & (Attributes.CM_MASK | Attributes.RGB_MASK);
|
|
54
|
-
}
|
|
55
|
-
public set underlineColor(value: number) {
|
|
56
|
-
this._ext &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
|
|
57
|
-
this._ext |= value & (Attributes.CM_MASK | Attributes.RGB_MASK);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
public get underlineVariantOffset(): number {
|
|
61
|
-
const val = (this._ext & ExtFlags.VARIANT_OFFSET) >> 29;
|
|
62
|
-
if (val < 0) {
|
|
63
|
-
return val ^ 0xFFFFFFF8;
|
|
64
|
-
}
|
|
65
|
-
return val;
|
|
66
|
-
}
|
|
67
|
-
public set underlineVariantOffset(value: number) {
|
|
68
|
-
this._ext &= ~ExtFlags.VARIANT_OFFSET;
|
|
69
|
-
this._ext |= (value << 29) & ExtFlags.VARIANT_OFFSET;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
private _urlId: number = 0;
|
|
73
|
-
public get urlId(): number {
|
|
74
|
-
return this._urlId;
|
|
75
|
-
}
|
|
76
|
-
public set urlId(value: number) {
|
|
77
|
-
this._urlId = value;
|
|
78
|
-
}
|
|
79
|
-
|
|
20
|
+
class ImageTileInfo {
|
|
80
21
|
constructor(
|
|
81
|
-
ext: number = 0,
|
|
82
|
-
urlId: number = 0,
|
|
83
22
|
public imageId = -1,
|
|
84
|
-
public tileId = -1
|
|
85
|
-
) {
|
|
86
|
-
this._ext = ext;
|
|
87
|
-
this._urlId = urlId;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
public clone(): IExtendedAttrsImage {
|
|
91
|
-
/**
|
|
92
|
-
* Technically we dont need a clone variant of ExtendedAttrsImage,
|
|
93
|
-
* as we never clone a cell holding image data.
|
|
94
|
-
* Note: Clone is only meant to be used by the InputHandler for
|
|
95
|
-
* sticky attributes, which is never the case for image data.
|
|
96
|
-
* We still provide a proper clone method to reflect the full ext attr
|
|
97
|
-
* state in case there are future use cases for clone.
|
|
98
|
-
*/
|
|
99
|
-
return new ExtendedAttrsImage(this._ext, this._urlId, this.imageId, this.tileId);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
public isEmpty(): boolean {
|
|
103
|
-
return this.underlineStyle === UnderlineStyle.NONE && this._urlId === 0 && this.imageId === -1;
|
|
23
|
+
public tileId = -1) {
|
|
104
24
|
}
|
|
105
25
|
}
|
|
106
|
-
const EMPTY_ATTRS = new ExtendedAttrsImage();
|
|
107
|
-
|
|
108
26
|
|
|
109
27
|
/**
|
|
110
28
|
* ImageStorage - extension of CoreTerminal:
|
|
@@ -126,6 +44,7 @@ export class ImageStorage implements IDisposable {
|
|
|
126
44
|
private _needsFullClear = false;
|
|
127
45
|
// hard limit of stored pixels (fallback limit of 10 MB)
|
|
128
46
|
private _pixelLimit: number = 2500000;
|
|
47
|
+
private _workCell: CellData = new CellData();
|
|
129
48
|
|
|
130
49
|
private _viewportMetrics: { cols: number, rows: number };
|
|
131
50
|
public onImageAdded: (() => void) | undefined;
|
|
@@ -277,10 +196,10 @@ export class ImageStorage implements IDisposable {
|
|
|
277
196
|
|
|
278
197
|
this._terminal._core._inputHandler._dirtyRowTracker.markDirty(buffer.y);
|
|
279
198
|
for (let row = 0; row < rows; ++row) {
|
|
280
|
-
const line = buffer.lines.get(buffer.y + buffer.ybase)
|
|
199
|
+
const line = buffer.lines.get(buffer.y + buffer.ybase)!;
|
|
281
200
|
for (let col = 0; col < cols; ++col) {
|
|
282
201
|
if (offset + col >= termCols) break;
|
|
283
|
-
this._writeToCell(line
|
|
202
|
+
this._writeToCell(line, offset + col, imageId, row * cols + col);
|
|
284
203
|
tileCount++;
|
|
285
204
|
}
|
|
286
205
|
if (opts.scrolling) {
|
|
@@ -428,11 +347,11 @@ export class ImageStorage implements IDisposable {
|
|
|
428
347
|
|
|
429
348
|
// walk all cells in viewport and collect tiles found
|
|
430
349
|
for (let row = start; row <= end; ++row) {
|
|
431
|
-
const line = buffer.lines.get(row + buffer.ydisp)
|
|
350
|
+
const line = buffer.lines.get(row + buffer.ydisp);
|
|
432
351
|
if (!line) return;
|
|
433
352
|
for (let col = 0; col < cols; ++col) {
|
|
434
|
-
|
|
435
|
-
|
|
353
|
+
const e = line.getExtended(col)?.payload;
|
|
354
|
+
if (e instanceof ImageTileInfo) {
|
|
436
355
|
const imageId = e.imageId;
|
|
437
356
|
if (imageId === undefined || imageId === -1) {
|
|
438
357
|
continue;
|
|
@@ -448,13 +367,11 @@ export class ImageStorage implements IDisposable {
|
|
|
448
367
|
* - cell has same image id
|
|
449
368
|
* - cell has consecutive tile id
|
|
450
369
|
*/
|
|
451
|
-
while (
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
&& (e.tileId === startTile + count)
|
|
457
|
-
) {
|
|
370
|
+
while (++col < cols) {
|
|
371
|
+
const nextE = line.getExtended(col)?.payload;
|
|
372
|
+
if (!(nextE instanceof ImageTileInfo) || nextE.imageId !== imageId || nextE.tileId !== startTile + count) {
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
458
375
|
count++;
|
|
459
376
|
}
|
|
460
377
|
col--;
|
|
@@ -504,9 +421,9 @@ export class ImageStorage implements IDisposable {
|
|
|
504
421
|
const rows = buffer.lines.length;
|
|
505
422
|
const oldCol = this._viewportMetrics.cols - 1;
|
|
506
423
|
for (let row = 0; row < rows; ++row) {
|
|
507
|
-
const line = buffer.lines.get(row)
|
|
508
|
-
|
|
509
|
-
|
|
424
|
+
const line = buffer.lines.get(row)!;
|
|
425
|
+
const e = line.getExtended(oldCol)?.payload;
|
|
426
|
+
if (e instanceof ImageTileInfo) {
|
|
510
427
|
const imageId = e.imageId;
|
|
511
428
|
if (imageId === undefined || imageId === -1) {
|
|
512
429
|
continue;
|
|
@@ -523,7 +440,7 @@ export class ImageStorage implements IDisposable {
|
|
|
523
440
|
// expand only if right side is empty (nothing got wrapped from below)
|
|
524
441
|
let hasData = false;
|
|
525
442
|
for (let rightCol = oldCol + 1; rightCol > metrics.cols; ++rightCol) {
|
|
526
|
-
if (line.
|
|
443
|
+
if (line.hasContent(rightCol)) {
|
|
527
444
|
hasData = true;
|
|
528
445
|
break;
|
|
529
446
|
}
|
|
@@ -535,7 +452,7 @@ export class ImageStorage implements IDisposable {
|
|
|
535
452
|
const end = Math.min(metrics.cols, tilesPerRow - (e.tileId % tilesPerRow) + oldCol);
|
|
536
453
|
let lastTile = e.tileId;
|
|
537
454
|
for (let expandCol = oldCol + 1; expandCol < end; ++expandCol) {
|
|
538
|
-
this._writeToCell(line
|
|
455
|
+
this._writeToCell(line, expandCol, imageId, ++lastTile);
|
|
539
456
|
imgSpec.tileCount++;
|
|
540
457
|
}
|
|
541
458
|
}
|
|
@@ -549,10 +466,10 @@ export class ImageStorage implements IDisposable {
|
|
|
549
466
|
*/
|
|
550
467
|
public getImageAtBufferCell(x: number, y: number): HTMLCanvasElement | undefined {
|
|
551
468
|
const buffer = this._terminal._core.buffer;
|
|
552
|
-
const line = buffer.lines.get(y)
|
|
553
|
-
if (line
|
|
554
|
-
const e
|
|
555
|
-
if (e.imageId && e.imageId !== -1) {
|
|
469
|
+
const line = buffer.lines.get(y);
|
|
470
|
+
if (line) {
|
|
471
|
+
const e = line.getExtended(x)?.payload;
|
|
472
|
+
if (e instanceof ImageTileInfo && e.imageId && e.imageId !== -1) {
|
|
556
473
|
const orig = this._images.get(e.imageId)?.orig;
|
|
557
474
|
if (window.ImageBitmap && orig instanceof ImageBitmap) {
|
|
558
475
|
const canvas = ImageRenderer.createCanvas(window.document, orig.width, orig.height);
|
|
@@ -569,10 +486,10 @@ export class ImageStorage implements IDisposable {
|
|
|
569
486
|
*/
|
|
570
487
|
public extractTileAtBufferCell(x: number, y: number): HTMLCanvasElement | undefined {
|
|
571
488
|
const buffer = this._terminal._core.buffer;
|
|
572
|
-
const line = buffer.lines.get(y)
|
|
573
|
-
if (line
|
|
574
|
-
const e
|
|
575
|
-
if (e.imageId && e.imageId !== -1 && e.tileId !== -1) {
|
|
489
|
+
const line = buffer.lines.get(y);
|
|
490
|
+
if (line) {
|
|
491
|
+
const e = line.getExtended(x)?.payload;
|
|
492
|
+
if (e instanceof ImageTileInfo && e.imageId && e.imageId !== -1 && e.tileId !== -1) {
|
|
576
493
|
const spec = this._images.get(e.imageId);
|
|
577
494
|
if (spec) {
|
|
578
495
|
return this._renderer.extractTile(spec, e.tileId);
|
|
@@ -600,31 +517,31 @@ export class ImageStorage implements IDisposable {
|
|
|
600
517
|
return used - current;
|
|
601
518
|
}
|
|
602
519
|
|
|
603
|
-
private _writeToCell(line:
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
old.imageId = imageId;
|
|
617
|
-
old.tileId = tileId;
|
|
618
|
-
return;
|
|
520
|
+
private _writeToCell(line: IBufferLine, x: number, imageId: number, tileId: number): void {
|
|
521
|
+
const workCell = this._workCell;
|
|
522
|
+
line.loadCell(x, workCell);
|
|
523
|
+
if (this._workCell.hasExtendedAttrs()) {
|
|
524
|
+
const old = workCell.extended.payload;
|
|
525
|
+
if (old instanceof ImageTileInfo) {
|
|
526
|
+
// found an old ExtendedAttrsImage, since we know that
|
|
527
|
+
// they are always isolated instances (single cell usage),
|
|
528
|
+
// we can re-use it and just update their id entries
|
|
529
|
+
const oldSpec = this._images.get(old.imageId);
|
|
530
|
+
if (oldSpec) {
|
|
531
|
+
// early eviction for in-viewport overwrites
|
|
532
|
+
oldSpec.tileCount--;
|
|
619
533
|
}
|
|
620
|
-
|
|
621
|
-
|
|
534
|
+
old.imageId = imageId;
|
|
535
|
+
old.tileId = tileId;
|
|
622
536
|
return;
|
|
623
537
|
}
|
|
624
538
|
}
|
|
625
|
-
// fall-through: always create new
|
|
626
|
-
|
|
627
|
-
|
|
539
|
+
// fall-through: always create new ExtendedAttrs entry
|
|
540
|
+
const extattr = workCell.extended.clone();
|
|
541
|
+
extattr.payload = new ImageTileInfo(imageId, tileId);
|
|
542
|
+
workCell.extended = extattr;
|
|
543
|
+
workCell.updateExtended();
|
|
544
|
+
line.setCell(x, workCell);
|
|
628
545
|
}
|
|
629
546
|
|
|
630
547
|
private _evictOnAlternate(): void {
|
|
@@ -637,18 +554,16 @@ export class ImageStorage implements IDisposable {
|
|
|
637
554
|
// re-count tiles on whole buffer
|
|
638
555
|
const buffer = this._terminal._core.buffer;
|
|
639
556
|
for (let y = 0; y < this._terminal.rows; ++y) {
|
|
640
|
-
const line = buffer.lines.get(y)
|
|
557
|
+
const line = buffer.lines.get(y);
|
|
641
558
|
if (!line) {
|
|
642
559
|
continue;
|
|
643
560
|
}
|
|
644
561
|
for (let x = 0; x < this._terminal.cols; ++x) {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
spec.tileCount++;
|
|
651
|
-
}
|
|
562
|
+
const payload = line.getExtended(x)?.payload;
|
|
563
|
+
if (payload instanceof ImageTileInfo) {
|
|
564
|
+
const spec = this._images.get(payload.imageId);
|
|
565
|
+
if (spec) {
|
|
566
|
+
spec.tileCount++;
|
|
652
567
|
}
|
|
653
568
|
}
|
|
654
569
|
}
|
package/src/Types.ts
CHANGED
|
@@ -10,7 +10,6 @@ import { Attributes, BgFlags, Content, ExtFlags, UnderlineStyle } from 'common/b
|
|
|
10
10
|
import type { AttributeData } from 'common/buffer/AttributeData';
|
|
11
11
|
import type { IParams, IDcsHandler, IOscHandler, IApcHandler, IEscapeSequenceParser } from 'common/parser/Types';
|
|
12
12
|
import type { IInputHandler } from 'common/Types';
|
|
13
|
-
import type { IBufferLine, IExtendedAttrs } from 'common/buffer/Types';
|
|
14
13
|
import type { ITerminal, ReadonlyColorSet } from 'browser/Types';
|
|
15
14
|
import type { IRenderDimensions } from 'browser/renderer/shared/Types';
|
|
16
15
|
import type { ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
|
|
@@ -48,6 +47,7 @@ export interface IResetHandler {
|
|
|
48
47
|
reset(): void;
|
|
49
48
|
}
|
|
50
49
|
|
|
50
|
+
/* eslint-disable */
|
|
51
51
|
/**
|
|
52
52
|
* Stub into private interfaces.
|
|
53
53
|
* This should be kept in line with common libs.
|
|
@@ -55,19 +55,6 @@ export interface IResetHandler {
|
|
|
55
55
|
* have a somewhat reliable testing against code changes in the core repo.
|
|
56
56
|
*/
|
|
57
57
|
|
|
58
|
-
// overloaded IExtendedAttrs to hold image refs
|
|
59
|
-
export interface IExtendedAttrsImage extends IExtendedAttrs {
|
|
60
|
-
imageId: number;
|
|
61
|
-
tileId: number;
|
|
62
|
-
clone(): IExtendedAttrsImage;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/* eslint-disable */
|
|
66
|
-
export interface IBufferLineExt extends IBufferLine {
|
|
67
|
-
_extendedAttrs: {[index: number]: IExtendedAttrsImage | undefined};
|
|
68
|
-
_data: Uint32Array;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
58
|
interface IInputHandlerExt extends IInputHandler {
|
|
72
59
|
_parser: IEscapeSequenceParser;
|
|
73
60
|
_curAttrData: AttributeData;
|
|
@@ -78,6 +65,7 @@ interface IInputHandlerExt extends IInputHandler {
|
|
|
78
65
|
};
|
|
79
66
|
onRequestReset(handler: () => void): IDisposable;
|
|
80
67
|
}
|
|
68
|
+
/* eslint-enable */
|
|
81
69
|
|
|
82
70
|
export interface ICoreTerminalExt extends ITerminal {
|
|
83
71
|
_themeService: IThemeService | undefined;
|
|
@@ -89,8 +77,6 @@ export interface ICoreTerminalExt extends ITerminal {
|
|
|
89
77
|
export interface ITerminalExt extends Terminal {
|
|
90
78
|
_core: ICoreTerminalExt;
|
|
91
79
|
}
|
|
92
|
-
/* eslint-enable */
|
|
93
|
-
|
|
94
80
|
|
|
95
81
|
/**
|
|
96
82
|
* Some storage definitions.
|