@termaxjs/editor-canvas 0.1.1
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/LICENSE +201 -0
- package/README.md +9 -0
- package/dist/CanvasViewportRenderer.d.ts +22 -0
- package/dist/CanvasViewportRenderer.d.ts.map +1 -0
- package/dist/CanvasViewportRenderer.js +215 -0
- package/dist/CanvasViewportRenderer.js.map +1 -0
- package/dist/GlyphAtlas.d.ts +42 -0
- package/dist/GlyphAtlas.d.ts.map +1 -0
- package/dist/GlyphAtlas.js +158 -0
- package/dist/GlyphAtlas.js.map +1 -0
- package/dist/KineticScroller.d.ts +39 -0
- package/dist/KineticScroller.d.ts.map +1 -0
- package/dist/KineticScroller.js +102 -0
- package/dist/KineticScroller.js.map +1 -0
- package/dist/LigatureEngine.d.ts +27 -0
- package/dist/LigatureEngine.d.ts.map +1 -0
- package/dist/LigatureEngine.js +105 -0
- package/dist/LigatureEngine.js.map +1 -0
- package/dist/WebGLGlyphAtlas.d.ts +34 -0
- package/dist/WebGLGlyphAtlas.d.ts.map +1 -0
- package/dist/WebGLGlyphAtlas.js +99 -0
- package/dist/WebGLGlyphAtlas.js.map +1 -0
- package/dist/WebGLViewportRenderer.d.ts +26 -0
- package/dist/WebGLViewportRenderer.d.ts.map +1 -0
- package/dist/WebGLViewportRenderer.js +297 -0
- package/dist/WebGLViewportRenderer.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Measure width and height for a monospace font in the browser.
|
|
3
|
+
*/
|
|
4
|
+
export function measureMonospaceFont(fontFamily, fontSize, lineHeightRatio = 1.5) {
|
|
5
|
+
if (typeof document === "undefined") {
|
|
6
|
+
// SSR / Node fallback
|
|
7
|
+
const charWidth = Math.round(fontSize * 0.6);
|
|
8
|
+
const lineHeight = Math.round(fontSize * lineHeightRatio);
|
|
9
|
+
return { charWidth, lineHeight };
|
|
10
|
+
}
|
|
11
|
+
const canvas = document.createElement("canvas");
|
|
12
|
+
const ctx = canvas.getContext("2d");
|
|
13
|
+
if (!ctx) {
|
|
14
|
+
const charWidth = Math.round(fontSize * 0.6);
|
|
15
|
+
const lineHeight = Math.round(fontSize * lineHeightRatio);
|
|
16
|
+
return { charWidth, lineHeight };
|
|
17
|
+
}
|
|
18
|
+
const font = `${fontSize}px ${fontFamily}`;
|
|
19
|
+
ctx.font = font;
|
|
20
|
+
const metrics = ctx.measureText("M");
|
|
21
|
+
const charWidth = Math.max(1, metrics.width);
|
|
22
|
+
const lineHeight = Math.round(fontSize * lineHeightRatio);
|
|
23
|
+
return { charWidth, lineHeight };
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Bitmap glyph atlas to accelerate monospace rendering on Canvas.
|
|
27
|
+
*/
|
|
28
|
+
export class GlyphAtlas {
|
|
29
|
+
canvas = null;
|
|
30
|
+
ctx = null;
|
|
31
|
+
glyphMap = new Map();
|
|
32
|
+
font = "";
|
|
33
|
+
charWidth = 0;
|
|
34
|
+
lineHeight = 0;
|
|
35
|
+
dpr = 1;
|
|
36
|
+
curX = 0;
|
|
37
|
+
curY = 0;
|
|
38
|
+
cellW = 0;
|
|
39
|
+
cellH = 0;
|
|
40
|
+
constructor(fontFamily, fontSize, dpr = 1, charWidth, lineHeight) {
|
|
41
|
+
this.dpr = dpr;
|
|
42
|
+
this.font = `${fontSize}px ${fontFamily}`;
|
|
43
|
+
const m = measureMonospaceFont(fontFamily, fontSize);
|
|
44
|
+
this.charWidth = charWidth && charWidth > 0 ? charWidth : m.charWidth;
|
|
45
|
+
this.lineHeight = lineHeight && lineHeight > 0 ? lineHeight : m.lineHeight;
|
|
46
|
+
this.cellW = Math.ceil(this.charWidth * this.dpr);
|
|
47
|
+
this.cellH = Math.ceil(this.lineHeight * this.dpr);
|
|
48
|
+
this.initAtlas();
|
|
49
|
+
}
|
|
50
|
+
initAtlas() {
|
|
51
|
+
if (typeof document === "undefined" && typeof OffscreenCanvas === "undefined") {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const atlasWidth = 1024 * this.dpr;
|
|
55
|
+
const atlasHeight = 512 * this.dpr;
|
|
56
|
+
if (typeof OffscreenCanvas !== "undefined") {
|
|
57
|
+
this.canvas = new OffscreenCanvas(atlasWidth, atlasHeight);
|
|
58
|
+
this.ctx = this.canvas.getContext("2d");
|
|
59
|
+
}
|
|
60
|
+
else if (typeof document !== "undefined") {
|
|
61
|
+
const c = document.createElement("canvas");
|
|
62
|
+
c.width = atlasWidth;
|
|
63
|
+
c.height = atlasHeight;
|
|
64
|
+
this.canvas = c;
|
|
65
|
+
this.ctx = c.getContext("2d");
|
|
66
|
+
}
|
|
67
|
+
if (this.ctx) {
|
|
68
|
+
this.ctx.font = `${Math.round(this.cellH * 0.7)}px monospace`;
|
|
69
|
+
this.ctx.textBaseline = "top";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Pre-warm the atlas with ASCII characters for a set of theme colors.
|
|
74
|
+
*/
|
|
75
|
+
prewarm(colors) {
|
|
76
|
+
if (!this.ctx || !this.canvas)
|
|
77
|
+
return;
|
|
78
|
+
for (const color of colors) {
|
|
79
|
+
if (!color)
|
|
80
|
+
continue;
|
|
81
|
+
for (let code = 32; code <= 126; code++) {
|
|
82
|
+
const char = String.fromCharCode(code);
|
|
83
|
+
this.cacheGlyph(char, color);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
cacheGlyph(char, color) {
|
|
88
|
+
if (!this.ctx || !this.canvas)
|
|
89
|
+
return null;
|
|
90
|
+
const key = `${char}:${color}`;
|
|
91
|
+
const existing = this.glyphMap.get(key);
|
|
92
|
+
if (existing)
|
|
93
|
+
return existing;
|
|
94
|
+
if (this.curX + this.cellW > this.canvas.width) {
|
|
95
|
+
this.curX = 0;
|
|
96
|
+
this.curY += this.cellH;
|
|
97
|
+
}
|
|
98
|
+
if (this.curY + this.cellH > this.canvas.height) {
|
|
99
|
+
// Atlas capacity reached
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const x = this.curX;
|
|
103
|
+
const y = this.curY;
|
|
104
|
+
this.ctx.fillStyle = color;
|
|
105
|
+
this.ctx.fillText(char, x, y);
|
|
106
|
+
const loc = {
|
|
107
|
+
x,
|
|
108
|
+
y,
|
|
109
|
+
width: this.cellW,
|
|
110
|
+
height: this.cellH,
|
|
111
|
+
};
|
|
112
|
+
this.glyphMap.set(key, loc);
|
|
113
|
+
this.curX += this.cellW;
|
|
114
|
+
return loc;
|
|
115
|
+
}
|
|
116
|
+
getGlyph(char, color) {
|
|
117
|
+
const key = `${char}:${color}`;
|
|
118
|
+
const cached = this.glyphMap.get(key);
|
|
119
|
+
if (cached)
|
|
120
|
+
return cached;
|
|
121
|
+
return this.cacheGlyph(char, color);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Draw text on destination context using atlas when possible, falling back to fillText.
|
|
125
|
+
*/
|
|
126
|
+
drawText(destCtx, text, color, x, y) {
|
|
127
|
+
if (!text)
|
|
128
|
+
return;
|
|
129
|
+
if (this.canvas && destCtx && typeof destCtx.drawImage === "function") {
|
|
130
|
+
let curX = x;
|
|
131
|
+
for (let i = 0; i < text.length; i++) {
|
|
132
|
+
const ch = text[i];
|
|
133
|
+
if (ch === " ") {
|
|
134
|
+
curX += this.charWidth;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const glyph = this.getGlyph(ch, color);
|
|
138
|
+
if (glyph) {
|
|
139
|
+
destCtx.drawImage(this.canvas, glyph.x, glyph.y, glyph.width, glyph.height, curX, y, this.charWidth, this.lineHeight);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
destCtx.fillStyle = color;
|
|
143
|
+
destCtx.font = this.font;
|
|
144
|
+
destCtx.textBaseline = "top";
|
|
145
|
+
destCtx.fillText(ch, curX, y);
|
|
146
|
+
}
|
|
147
|
+
curX += this.charWidth;
|
|
148
|
+
}
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// Fallback path when atlas is unavailable
|
|
152
|
+
destCtx.fillStyle = color;
|
|
153
|
+
destCtx.font = this.font;
|
|
154
|
+
destCtx.textBaseline = "top";
|
|
155
|
+
destCtx.fillText(text, x, y);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=GlyphAtlas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GlyphAtlas.js","sourceRoot":"","sources":["../src/GlyphAtlas.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kinetic Momentum Scroller with spring-damped physics.
|
|
3
|
+
* Provides high-refresh (120Hz/144Hz) trackpad momentum interpolation.
|
|
4
|
+
*/
|
|
5
|
+
export interface KineticScrollState {
|
|
6
|
+
scrollTop: number;
|
|
7
|
+
scrollLeft: number;
|
|
8
|
+
maxScrollTop: number;
|
|
9
|
+
maxScrollLeft: number;
|
|
10
|
+
}
|
|
11
|
+
export interface KineticScrollerOptions {
|
|
12
|
+
friction?: number;
|
|
13
|
+
minVelocity?: number;
|
|
14
|
+
bounceFriction?: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class KineticScroller {
|
|
17
|
+
private vx;
|
|
18
|
+
private vy;
|
|
19
|
+
private animId;
|
|
20
|
+
private readonly friction;
|
|
21
|
+
private readonly minVelocity;
|
|
22
|
+
private readonly bounceFriction;
|
|
23
|
+
private onUpdate;
|
|
24
|
+
private state;
|
|
25
|
+
constructor(options?: KineticScrollerOptions);
|
|
26
|
+
setState(state: Partial<KineticScrollState>): void;
|
|
27
|
+
setUpdateCallback(cb: (state: {
|
|
28
|
+
scrollTop: number;
|
|
29
|
+
scrollLeft: number;
|
|
30
|
+
}) => void): void;
|
|
31
|
+
/**
|
|
32
|
+
* Pushes a scroll impulse (e.g. from wheel event or touch drag release).
|
|
33
|
+
*/
|
|
34
|
+
pushImpulse(deltaX: number, deltaY: number): void;
|
|
35
|
+
stop(): void;
|
|
36
|
+
isScrolling(): boolean;
|
|
37
|
+
private startLoop;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=KineticScroller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KineticScroller.d.ts","sourceRoot":"","sources":["../src/KineticScroller.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,EAAE,CAAK;IACf,OAAO,CAAC,EAAE,CAAK;IACf,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAA6E;IAC7F,OAAO,CAAC,KAAK,CAKX;gBAEU,OAAO,GAAE,sBAA2B;IAMzC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI;IAIlD,iBAAiB,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,IAAI;IAI9F;;OAEG;IACI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAYjD,IAAI,IAAI,IAAI;IASZ,WAAW,IAAI,OAAO;IAQ7B,OAAO,CAAC,SAAS;CAiDlB"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kinetic Momentum Scroller with spring-damped physics.
|
|
3
|
+
* Provides high-refresh (120Hz/144Hz) trackpad momentum interpolation.
|
|
4
|
+
*/
|
|
5
|
+
export class KineticScroller {
|
|
6
|
+
vx = 0;
|
|
7
|
+
vy = 0;
|
|
8
|
+
animId = null;
|
|
9
|
+
friction;
|
|
10
|
+
minVelocity;
|
|
11
|
+
bounceFriction;
|
|
12
|
+
onUpdate = null;
|
|
13
|
+
state = {
|
|
14
|
+
scrollTop: 0,
|
|
15
|
+
scrollLeft: 0,
|
|
16
|
+
maxScrollTop: 0,
|
|
17
|
+
maxScrollLeft: 0,
|
|
18
|
+
};
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
this.friction = options.friction ?? 0.92;
|
|
21
|
+
this.minVelocity = options.minVelocity ?? 0.05;
|
|
22
|
+
this.bounceFriction = options.bounceFriction ?? 0.8;
|
|
23
|
+
}
|
|
24
|
+
setState(state) {
|
|
25
|
+
this.state = { ...this.state, ...state };
|
|
26
|
+
}
|
|
27
|
+
setUpdateCallback(cb) {
|
|
28
|
+
this.onUpdate = cb;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Pushes a scroll impulse (e.g. from wheel event or touch drag release).
|
|
32
|
+
*/
|
|
33
|
+
pushImpulse(deltaX, deltaY) {
|
|
34
|
+
this.vx += deltaX;
|
|
35
|
+
this.vy += deltaY;
|
|
36
|
+
if (this.animId === null &&
|
|
37
|
+
(Math.abs(this.vx) > this.minVelocity || Math.abs(this.vy) > this.minVelocity)) {
|
|
38
|
+
this.startLoop();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
stop() {
|
|
42
|
+
if (this.animId !== null && typeof cancelAnimationFrame !== "undefined") {
|
|
43
|
+
cancelAnimationFrame(this.animId);
|
|
44
|
+
this.animId = null;
|
|
45
|
+
}
|
|
46
|
+
this.vx = 0;
|
|
47
|
+
this.vy = 0;
|
|
48
|
+
}
|
|
49
|
+
isScrolling() {
|
|
50
|
+
return (this.animId !== null ||
|
|
51
|
+
Math.abs(this.vx) > this.minVelocity ||
|
|
52
|
+
Math.abs(this.vy) > this.minVelocity);
|
|
53
|
+
}
|
|
54
|
+
startLoop() {
|
|
55
|
+
const step = () => {
|
|
56
|
+
this.vx *= this.friction;
|
|
57
|
+
this.vy *= this.friction;
|
|
58
|
+
let nextTop = this.state.scrollTop + this.vy;
|
|
59
|
+
let nextLeft = this.state.scrollLeft + this.vx;
|
|
60
|
+
// Boundary clamping
|
|
61
|
+
if (nextTop < 0) {
|
|
62
|
+
nextTop = 0;
|
|
63
|
+
this.vy *= this.bounceFriction;
|
|
64
|
+
}
|
|
65
|
+
else if (nextTop > this.state.maxScrollTop) {
|
|
66
|
+
nextTop = this.state.maxScrollTop;
|
|
67
|
+
this.vy *= this.bounceFriction;
|
|
68
|
+
}
|
|
69
|
+
if (nextLeft < 0) {
|
|
70
|
+
nextLeft = 0;
|
|
71
|
+
this.vx *= this.bounceFriction;
|
|
72
|
+
}
|
|
73
|
+
else if (nextLeft > this.state.maxScrollLeft) {
|
|
74
|
+
nextLeft = this.state.maxScrollLeft;
|
|
75
|
+
this.vx *= this.bounceFriction;
|
|
76
|
+
}
|
|
77
|
+
this.state.scrollTop = nextTop;
|
|
78
|
+
this.state.scrollLeft = nextLeft;
|
|
79
|
+
if (this.onUpdate) {
|
|
80
|
+
this.onUpdate({ scrollTop: nextTop, scrollLeft: nextLeft });
|
|
81
|
+
}
|
|
82
|
+
if (Math.abs(this.vx) > this.minVelocity || Math.abs(this.vy) > this.minVelocity) {
|
|
83
|
+
if (typeof requestAnimationFrame !== "undefined") {
|
|
84
|
+
this.animId = requestAnimationFrame(step);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
this.animId = null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
this.stop();
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
if (typeof requestAnimationFrame !== "undefined") {
|
|
95
|
+
this.animId = requestAnimationFrame(step);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
step();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=KineticScroller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KineticScroller.js","sourceRoot":"","sources":["../src/KineticScroller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programming Font Ligature Engine.
|
|
3
|
+
* Detects multi-character ligature sequences and clusters them into unified glyph runs.
|
|
4
|
+
*/
|
|
5
|
+
export interface LigatureMatch {
|
|
6
|
+
start: number;
|
|
7
|
+
length: number;
|
|
8
|
+
text: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const DEFAULT_LIGATURE_SEQUENCES: readonly string[];
|
|
11
|
+
export declare class LigatureEngine {
|
|
12
|
+
private ligatures;
|
|
13
|
+
private maxLen;
|
|
14
|
+
constructor(sequences?: readonly string[]);
|
|
15
|
+
/**
|
|
16
|
+
* Scans a line or token string for ligature clusters.
|
|
17
|
+
*/
|
|
18
|
+
findLigatures(text: string): LigatureMatch[];
|
|
19
|
+
/**
|
|
20
|
+
* Splits a string into segments of plain text and ligature clusters.
|
|
21
|
+
*/
|
|
22
|
+
segmentText(text: string): Array<{
|
|
23
|
+
text: string;
|
|
24
|
+
isLigature: boolean;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=LigatureEngine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LigatureEngine.d.ts","sourceRoot":"","sources":["../src/LigatureEngine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAGD,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EA8BvD,CAAC;AAEF,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,MAAM,CAAS;gBAEX,SAAS,GAAE,SAAS,MAAM,EAA+B;IAKrE;;OAEG;IACI,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE;IA+BnD;;OAEG;IACI,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;CAgC/E"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programming Font Ligature Engine.
|
|
3
|
+
* Detects multi-character ligature sequences and clusters them into unified glyph runs.
|
|
4
|
+
*/
|
|
5
|
+
// Common programming ligature sequences ordered by length (longest first for greedy match)
|
|
6
|
+
export const DEFAULT_LIGATURE_SEQUENCES = [
|
|
7
|
+
"<!--",
|
|
8
|
+
"-->",
|
|
9
|
+
"===",
|
|
10
|
+
"!==",
|
|
11
|
+
"...",
|
|
12
|
+
"::=",
|
|
13
|
+
"<=>",
|
|
14
|
+
"->",
|
|
15
|
+
"<-",
|
|
16
|
+
"=>",
|
|
17
|
+
"<=",
|
|
18
|
+
">=",
|
|
19
|
+
"==",
|
|
20
|
+
"!=",
|
|
21
|
+
":=",
|
|
22
|
+
"::",
|
|
23
|
+
"/*",
|
|
24
|
+
"*/",
|
|
25
|
+
"//",
|
|
26
|
+
"**",
|
|
27
|
+
"??",
|
|
28
|
+
"||",
|
|
29
|
+
"&&",
|
|
30
|
+
"++",
|
|
31
|
+
"--",
|
|
32
|
+
"<<",
|
|
33
|
+
">>",
|
|
34
|
+
"|>",
|
|
35
|
+
"<|",
|
|
36
|
+
];
|
|
37
|
+
export class LigatureEngine {
|
|
38
|
+
ligatures;
|
|
39
|
+
maxLen;
|
|
40
|
+
constructor(sequences = DEFAULT_LIGATURE_SEQUENCES) {
|
|
41
|
+
this.ligatures = [...sequences].sort((a, b) => b.length - a.length);
|
|
42
|
+
this.maxLen = this.ligatures.reduce((max, s) => Math.max(max, s.length), 0);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Scans a line or token string for ligature clusters.
|
|
46
|
+
*/
|
|
47
|
+
findLigatures(text) {
|
|
48
|
+
const matches = [];
|
|
49
|
+
const len = text.length;
|
|
50
|
+
let i = 0;
|
|
51
|
+
while (i < len) {
|
|
52
|
+
let matched = false;
|
|
53
|
+
const remaining = len - i;
|
|
54
|
+
const checkLen = Math.min(remaining, this.maxLen);
|
|
55
|
+
for (const seq of this.ligatures) {
|
|
56
|
+
if (seq.length <= checkLen && text.startsWith(seq, i)) {
|
|
57
|
+
matches.push({
|
|
58
|
+
start: i,
|
|
59
|
+
length: seq.length,
|
|
60
|
+
text: seq,
|
|
61
|
+
});
|
|
62
|
+
i += seq.length;
|
|
63
|
+
matched = true;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (!matched) {
|
|
68
|
+
i++;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return matches;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Splits a string into segments of plain text and ligature clusters.
|
|
75
|
+
*/
|
|
76
|
+
segmentText(text) {
|
|
77
|
+
const matches = this.findLigatures(text);
|
|
78
|
+
if (matches.length === 0) {
|
|
79
|
+
return [{ text, isLigature: false }];
|
|
80
|
+
}
|
|
81
|
+
const segments = [];
|
|
82
|
+
let cur = 0;
|
|
83
|
+
for (const match of matches) {
|
|
84
|
+
if (match.start > cur) {
|
|
85
|
+
segments.push({
|
|
86
|
+
text: text.slice(cur, match.start),
|
|
87
|
+
isLigature: false,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
segments.push({
|
|
91
|
+
text: match.text,
|
|
92
|
+
isLigature: true,
|
|
93
|
+
});
|
|
94
|
+
cur = match.start + match.length;
|
|
95
|
+
}
|
|
96
|
+
if (cur < text.length) {
|
|
97
|
+
segments.push({
|
|
98
|
+
text: text.slice(cur),
|
|
99
|
+
isLigature: false,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return segments;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=LigatureEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LigatureEngine.js","sourceRoot":"","sources":["../src/LigatureEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface WebGLGlyphUV {
|
|
2
|
+
u0: number;
|
|
3
|
+
v0: number;
|
|
4
|
+
u1: number;
|
|
5
|
+
v1: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* GPU-friendly Texture Atlas for WebGL 2 / WebGPU instanced glyph and ligature rendering.
|
|
11
|
+
*/
|
|
12
|
+
export declare class WebGLGlyphAtlas {
|
|
13
|
+
private canvas;
|
|
14
|
+
private ctx;
|
|
15
|
+
private glyphMap;
|
|
16
|
+
charWidth: number;
|
|
17
|
+
lineHeight: number;
|
|
18
|
+
dpr: number;
|
|
19
|
+
readonly atlasWidth: number;
|
|
20
|
+
readonly atlasHeight: number;
|
|
21
|
+
private curX;
|
|
22
|
+
private curY;
|
|
23
|
+
private cellW;
|
|
24
|
+
private cellH;
|
|
25
|
+
private isDirty;
|
|
26
|
+
constructor(fontFamily: string, fontSize: number, dpr?: number, charWidth?: number, lineHeight?: number, atlasWidth?: number, atlasHeight?: number);
|
|
27
|
+
private initCanvas;
|
|
28
|
+
private prewarmAscii;
|
|
29
|
+
getOrRasterizeGlyph(char: string): WebGLGlyphUV | null;
|
|
30
|
+
getCanvasSource(): HTMLCanvasElement | OffscreenCanvas | null;
|
|
31
|
+
checkAndClearDirty(): boolean;
|
|
32
|
+
getGlyphUV(char: string): WebGLGlyphUV | null;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=WebGLGlyphAtlas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebGLGlyphAtlas.d.ts","sourceRoot":"","sources":["../src/WebGLGlyphAtlas.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAoD;IAClE,OAAO,CAAC,GAAG,CAA6E;IACxF,OAAO,CAAC,QAAQ,CAAmC;IAC5C,SAAS,EAAE,MAAM,CAAK;IACtB,UAAU,EAAE,MAAM,CAAK;IACvB,GAAG,EAAE,MAAM,CAAK;IACvB,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,WAAW,EAAE,MAAM,CAAC;IACpC,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,OAAO,CAAkB;gBAG/B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,GAAG,SAAI,EACP,SAAS,CAAC,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,MAAM,EACnB,UAAU,SAAO,EACjB,WAAW,SAAO;IAgBpB,OAAO,CAAC,UAAU;IAmBlB,OAAO,CAAC,YAAY;IAMb,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAuCtD,eAAe,IAAI,iBAAiB,GAAG,eAAe,GAAG,IAAI;IAI7D,kBAAkB,IAAI,OAAO;IAM7B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;CAGrD"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { measureMonospaceFont } from "./GlyphAtlas.js";
|
|
2
|
+
/**
|
|
3
|
+
* GPU-friendly Texture Atlas for WebGL 2 / WebGPU instanced glyph and ligature rendering.
|
|
4
|
+
*/
|
|
5
|
+
export class WebGLGlyphAtlas {
|
|
6
|
+
canvas = null;
|
|
7
|
+
ctx = null;
|
|
8
|
+
glyphMap = new Map();
|
|
9
|
+
charWidth = 0;
|
|
10
|
+
lineHeight = 0;
|
|
11
|
+
dpr = 1;
|
|
12
|
+
atlasWidth;
|
|
13
|
+
atlasHeight;
|
|
14
|
+
curX = 0;
|
|
15
|
+
curY = 0;
|
|
16
|
+
cellW = 0;
|
|
17
|
+
cellH = 0;
|
|
18
|
+
isDirty = false;
|
|
19
|
+
constructor(fontFamily, fontSize, dpr = 1, charWidth, lineHeight, atlasWidth = 1024, atlasHeight = 1024) {
|
|
20
|
+
this.dpr = dpr;
|
|
21
|
+
this.atlasWidth = atlasWidth * dpr;
|
|
22
|
+
this.atlasHeight = atlasHeight * dpr;
|
|
23
|
+
const m = measureMonospaceFont(fontFamily, fontSize);
|
|
24
|
+
this.charWidth = charWidth && charWidth > 0 ? charWidth : m.charWidth;
|
|
25
|
+
this.lineHeight = lineHeight && lineHeight > 0 ? lineHeight : m.lineHeight;
|
|
26
|
+
this.cellW = Math.ceil(this.charWidth * this.dpr);
|
|
27
|
+
this.cellH = Math.ceil(this.lineHeight * this.dpr);
|
|
28
|
+
this.initCanvas(fontFamily, fontSize);
|
|
29
|
+
this.prewarmAscii();
|
|
30
|
+
}
|
|
31
|
+
initCanvas(fontFamily, fontSize) {
|
|
32
|
+
if (typeof OffscreenCanvas !== "undefined") {
|
|
33
|
+
this.canvas = new OffscreenCanvas(this.atlasWidth, this.atlasHeight);
|
|
34
|
+
this.ctx = this.canvas.getContext("2d");
|
|
35
|
+
}
|
|
36
|
+
else if (typeof document !== "undefined") {
|
|
37
|
+
const c = document.createElement("canvas");
|
|
38
|
+
c.width = this.atlasWidth;
|
|
39
|
+
c.height = this.atlasHeight;
|
|
40
|
+
this.canvas = c;
|
|
41
|
+
this.ctx = c.getContext("2d");
|
|
42
|
+
}
|
|
43
|
+
if (this.ctx) {
|
|
44
|
+
this.ctx.font = `${Math.round(fontSize * this.dpr)}px ${fontFamily}, monospace`;
|
|
45
|
+
this.ctx.textBaseline = "top";
|
|
46
|
+
this.ctx.fillStyle = "#ffffff";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
prewarmAscii() {
|
|
50
|
+
for (let code = 32; code <= 126; code++) {
|
|
51
|
+
this.getOrRasterizeGlyph(String.fromCharCode(code));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
getOrRasterizeGlyph(char) {
|
|
55
|
+
if (this.glyphMap.has(char)) {
|
|
56
|
+
return this.glyphMap.get(char);
|
|
57
|
+
}
|
|
58
|
+
if (!this.ctx)
|
|
59
|
+
return null;
|
|
60
|
+
const widthCells = char.length > 1 ? char.length : 1;
|
|
61
|
+
const requiredWidth = this.cellW * widthCells;
|
|
62
|
+
if (this.curX + requiredWidth > this.atlasWidth) {
|
|
63
|
+
this.curX = 0;
|
|
64
|
+
this.curY += this.cellH;
|
|
65
|
+
}
|
|
66
|
+
if (this.curY + this.cellH > this.atlasHeight) {
|
|
67
|
+
// Atlas capacity reached
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const rx = this.curX;
|
|
71
|
+
const ry = this.curY;
|
|
72
|
+
this.ctx.fillStyle = "#ffffff";
|
|
73
|
+
this.ctx.fillText(char, rx, ry);
|
|
74
|
+
this.curX += requiredWidth;
|
|
75
|
+
this.isDirty = true;
|
|
76
|
+
const uv = {
|
|
77
|
+
u0: rx / this.atlasWidth,
|
|
78
|
+
v0: ry / this.atlasHeight,
|
|
79
|
+
u1: (rx + requiredWidth) / this.atlasWidth,
|
|
80
|
+
v1: (ry + this.cellH) / this.atlasHeight,
|
|
81
|
+
width: this.charWidth * widthCells,
|
|
82
|
+
height: this.lineHeight,
|
|
83
|
+
};
|
|
84
|
+
this.glyphMap.set(char, uv);
|
|
85
|
+
return uv;
|
|
86
|
+
}
|
|
87
|
+
getCanvasSource() {
|
|
88
|
+
return this.canvas;
|
|
89
|
+
}
|
|
90
|
+
checkAndClearDirty() {
|
|
91
|
+
const dirty = this.isDirty;
|
|
92
|
+
this.isDirty = false;
|
|
93
|
+
return dirty;
|
|
94
|
+
}
|
|
95
|
+
getGlyphUV(char) {
|
|
96
|
+
return this.glyphMap.get(char) ?? this.getOrRasterizeGlyph(char);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=WebGLGlyphAtlas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebGLGlyphAtlas.js","sourceRoot":"","sources":["../src/WebGLGlyphAtlas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAWvD;;GAEG;AACH,MAAM,OAAO,eAAe;IAClB,MAAM,GAA+C,IAAI,CAAC;IAC1D,GAAG,GAAwE,IAAI,CAAC;IAChF,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC5C,SAAS,GAAW,CAAC,CAAC;IACtB,UAAU,GAAW,CAAC,CAAC;IACvB,GAAG,GAAW,CAAC,CAAC;IACP,UAAU,CAAS;IACnB,WAAW,CAAS;IAC5B,IAAI,GAAW,CAAC,CAAC;IACjB,IAAI,GAAW,CAAC,CAAC;IACjB,KAAK,GAAW,CAAC,CAAC;IAClB,KAAK,GAAW,CAAC,CAAC;IAClB,OAAO,GAAY,KAAK,CAAC;IAEjC,YACE,UAAkB,EAClB,QAAgB,EAChB,GAAG,GAAG,CAAC,EACP,SAAkB,EAClB,UAAmB,EACnB,UAAU,GAAG,IAAI,EACjB,WAAW,GAAG,IAAI;QAElB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,UAAU,GAAG,GAAG,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,WAAW,GAAG,GAAG,CAAC;QAErC,MAAM,CAAC,GAAG,oBAAoB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACrD,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACtE,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;QAC3E,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAEnD,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAEO,UAAU,CAAC,UAAkB,EAAE,QAAgB;QACrD,IAAI,OAAO,eAAe,KAAK,WAAW,EAAE,CAAC;YAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;YACrE,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAsC,CAAC;QAC/E,CAAC;aAAM,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;YAC3C,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC3C,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC;YAC1B,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC;YAC5B,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YAChB,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,UAAU,aAAa,CAAC;YAChF,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC;QACjC,CAAC;IACH,CAAC;IAEO,YAAY;QAClB,KAAK,IAAI,IAAI,GAAG,EAAE,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC;YACxC,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAEM,mBAAmB,CAAC,IAAY;QACrC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QAClC,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QAE3B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;QAE9C,IAAI,IAAI,CAAC,IAAI,GAAG,aAAa,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAChD,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;YACd,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC;QAC1B,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAC9C,yBAAyB;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;QACrB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;QAErB,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,IAAI,aAAa,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,MAAM,EAAE,GAAiB;YACvB,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,UAAU;YACxB,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW;YACzB,EAAE,EAAE,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,IAAI,CAAC,UAAU;YAC1C,EAAE,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW;YACxC,KAAK,EAAE,IAAI,CAAC,SAAS,GAAG,UAAU;YAClC,MAAM,EAAE,IAAI,CAAC,UAAU;SACxB,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5B,OAAO,EAAE,CAAC;IACZ,CAAC;IAEM,eAAe;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAEM,kBAAkB;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,UAAU,CAAC,IAAY;QAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACnE,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { CanvasRenderOptions, CanvasViewport, LineDrawData, CaretRenderOptions, SelectionRenderOptions } from "./types.js";
|
|
2
|
+
import type { WebGLGlyphAtlas } from "./WebGLGlyphAtlas.js";
|
|
3
|
+
/**
|
|
4
|
+
* High-performance WebGL 2 Instanced Viewport Renderer with Ligature Clustering.
|
|
5
|
+
* Renders all glyphs and multi-character ligatures in a single GPU draw call at 144Hz-240Hz.
|
|
6
|
+
*/
|
|
7
|
+
export declare class WebGLViewportRenderer {
|
|
8
|
+
private gl;
|
|
9
|
+
private program;
|
|
10
|
+
private texture;
|
|
11
|
+
private quadVbo;
|
|
12
|
+
private instanceVbo;
|
|
13
|
+
private vao;
|
|
14
|
+
private atlas;
|
|
15
|
+
private ligatureEngine;
|
|
16
|
+
private maxInstances;
|
|
17
|
+
private instanceData;
|
|
18
|
+
private uResolutionLoc;
|
|
19
|
+
private uAtlasLoc;
|
|
20
|
+
constructor(canvas: HTMLCanvasElement, atlas: WebGLGlyphAtlas, _enableLigatures?: boolean);
|
|
21
|
+
private initGL;
|
|
22
|
+
private compileShader;
|
|
23
|
+
render(lines: LineDrawData[], viewport: CanvasViewport, options: CanvasRenderOptions, _caret?: CaretRenderOptions, _selection?: SelectionRenderOptions): void;
|
|
24
|
+
isSupported(): boolean;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=WebGLViewportRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebGLViewportRenderer.d.ts","sourceRoot":"","sources":["../src/WebGLViewportRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AA2D5D;;;GAGG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,EAAE,CAAuC;IACjD,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,GAAG,CAAuC;IAClD,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,cAAc,CAAiB;IAGvC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAA4C;IAChE,OAAO,CAAC,cAAc,CAAqC;IAC3D,OAAO,CAAC,SAAS,CAAqC;gBAE1C,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,eAAe,EAAE,gBAAgB,UAAO;IAMtF,OAAO,CAAC,MAAM;IAmEd,OAAO,CAAC,aAAa;IAad,MAAM,CACX,KAAK,EAAE,YAAY,EAAE,EACrB,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,mBAAmB,EAC5B,MAAM,CAAC,EAAE,kBAAkB,EAC3B,UAAU,CAAC,EAAE,sBAAsB,GAClC,IAAI;IAsKA,WAAW,IAAI,OAAO;CAG9B"}
|