@micahdb/tscon 0.0.0-stage → 0.1.0
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 +21 -0
- package/README.md +44 -2
- package/dist/canvas.d.ts +147 -0
- package/dist/canvas.js +369 -0
- package/dist/colour.d.ts +56 -0
- package/dist/colour.js +77 -0
- package/dist/cp437.d.ts +48 -0
- package/dist/cp437.js +124 -0
- package/dist/glyphs.d.ts +222 -0
- package/dist/glyphs.js +449 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +9 -0
- package/dist/math.d.ts +214 -0
- package/dist/math.js +499 -0
- package/dist/moderndos.d.ts +1 -0
- package/dist/moderndos.js +322 -0
- package/dist/program.d.ts +72 -0
- package/dist/program.js +127 -0
- package/dist/rect.d.ts +26 -0
- package/dist/rect.js +1 -0
- package/dist/renderer.d.ts +59 -0
- package/dist/renderer.js +172 -0
- package/dist/shaders.d.ts +5 -0
- package/dist/shaders.js +470 -0
- package/dist/terminal.d.ts +92 -0
- package/dist/terminal.js +275 -0
- package/dist/texture.d.ts +66 -0
- package/dist/texture.js +119 -0
- package/package.json +44 -5
package/dist/colour.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Indices into the 16-entry terminal {@link PALETTE}.
|
|
3
|
+
*
|
|
4
|
+
* The palette is split into eight "dark" colours (0..7) and eight "bright"
|
|
5
|
+
* colours (8..15). Glyph text encodes a foreground and background colour as
|
|
6
|
+
* 4-bit values, the high bit of which selects the bright half of the palette.
|
|
7
|
+
*
|
|
8
|
+
* Use these members with the `Colour` escape sequences understood by
|
|
9
|
+
* {@link textGlyphs} (`\fX`, `\FX`, `\bX`, `\BX`) and as the `fg`/`bg`
|
|
10
|
+
* indices when building glyphs programmatically.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { Colour } from "@micahdb/tscon";
|
|
15
|
+
*
|
|
16
|
+
* // bright-blue foreground on black background
|
|
17
|
+
* const text = "\\F4\\b0Link";
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export var Colour;
|
|
21
|
+
(function (Colour) {
|
|
22
|
+
// palette indices
|
|
23
|
+
Colour[Colour["BLACK"] = 0] = "BLACK";
|
|
24
|
+
Colour[Colour["RED"] = 1] = "RED";
|
|
25
|
+
Colour[Colour["GREEN"] = 2] = "GREEN";
|
|
26
|
+
Colour[Colour["ORANGE"] = 3] = "ORANGE";
|
|
27
|
+
Colour[Colour["BLUE"] = 4] = "BLUE";
|
|
28
|
+
Colour[Colour["MAGENTA"] = 5] = "MAGENTA";
|
|
29
|
+
Colour[Colour["CYAN"] = 6] = "CYAN";
|
|
30
|
+
Colour[Colour["GREY"] = 7] = "GREY";
|
|
31
|
+
Colour[Colour["BRIGHT_BLACK"] = 8] = "BRIGHT_BLACK";
|
|
32
|
+
Colour[Colour["BRIGHT_RED"] = 9] = "BRIGHT_RED";
|
|
33
|
+
Colour[Colour["BRIGHT_GREEN"] = 10] = "BRIGHT_GREEN";
|
|
34
|
+
Colour[Colour["YELLOW"] = 11] = "YELLOW";
|
|
35
|
+
Colour[Colour["BRIGHT_BLUE"] = 12] = "BRIGHT_BLUE";
|
|
36
|
+
Colour[Colour["BRIGHT_MAGENTA"] = 13] = "BRIGHT_MAGENTA";
|
|
37
|
+
Colour[Colour["BRIGHT_CYAN"] = 14] = "BRIGHT_CYAN";
|
|
38
|
+
Colour[Colour["WHITE"] = 15] = "WHITE";
|
|
39
|
+
})(Colour || (Colour = {}));
|
|
40
|
+
/**
|
|
41
|
+
* The 16-colour terminal palette as flat 8-bit-per-channel RGB bytes.
|
|
42
|
+
*
|
|
43
|
+
* The array contains 48 entries: 16 colours of three bytes each, ordered to
|
|
44
|
+
* match the {@link Colour} enum. Each triplet is an `[R, G, B]` value in the
|
|
45
|
+
* range `0x00`-`0xff`.
|
|
46
|
+
*
|
|
47
|
+
* The first eight entries are the dark colours ({@link Colour.BLACK} ..
|
|
48
|
+
* {@link Colour.GREY}) and the last eight are the bright colours
|
|
49
|
+
* ({@link Colour.BRIGHT_BLACK} .. {@link Colour.WHITE}).
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* import { Colour, PALETTE } from "@micahdb/tscon";
|
|
54
|
+
*
|
|
55
|
+
* const [r, g, b] = PALETTE.slice(Colour.BLUE * 3, Colour.BLUE * 3 + 3);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export const PALETTE = [
|
|
59
|
+
// dark colours
|
|
60
|
+
0x08, 0x08, 0x08, // Colour.BLACK
|
|
61
|
+
0xed, 0x33, 0x3b, // Colour.RED
|
|
62
|
+
0x57, 0xe3, 0x89, // Colour.GREEN
|
|
63
|
+
0xff, 0x78, 0x00, // Colour.ORANGE
|
|
64
|
+
0x62, 0xa0, 0xea, // Colour.BLUE
|
|
65
|
+
0x91, 0x41, 0xac, // Colour.MAGENTA
|
|
66
|
+
0x5b, 0xc8, 0xaf, // Colour.CYAN
|
|
67
|
+
0xc0, 0xc0, 0xc0, // Colour.GREY
|
|
68
|
+
// bright colours
|
|
69
|
+
0x80, 0x80, 0x80, // Colour.BRIGHT_BLACK
|
|
70
|
+
0xf6, 0x61, 0x51, // Colour.BRIGHT_RED
|
|
71
|
+
0x8f, 0xf0, 0xa4, // Colour.BRIGHT_GREEN
|
|
72
|
+
0xff, 0xa3, 0x48, // Colour.YELLOW
|
|
73
|
+
0x99, 0xc1, 0xf1, // Colour.BRIGHT_BLUE
|
|
74
|
+
0xdc, 0x8a, 0xdd, // Colour.BRIGHT_MAGENTA
|
|
75
|
+
0x93, 0xdd, 0xc2, // Colour.BRIGHT_CYAN
|
|
76
|
+
0xf4, 0xf4, 0xf4 // Colour.WHITE
|
|
77
|
+
];
|
package/dist/cp437.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The 256 characters of IBM Code Page 437, as a string indexed by code.
|
|
3
|
+
*
|
|
4
|
+
* Index 0 is a blank (the CP437 NUL is unused) and index 255 is also treated
|
|
5
|
+
* as blank; all other indices 1..254 map to the corresponding CP437 glyph.
|
|
6
|
+
* This is the character set tscon's bitmap font covers and that
|
|
7
|
+
* {@link textGlyphs} encodes glyphs in.
|
|
8
|
+
*
|
|
9
|
+
* NOTE: chars at 0 and 255 are ignored.
|
|
10
|
+
*/
|
|
11
|
+
export declare const CP437_CHARS = " \u263A\u263B\u2665\u2666\u2663\u2660\u2022\u25D8\u25CB\u25D9\u2642\u2640\u266A\u266B\u263C\u25BA\u25C4\u2195\u203C\u00B6\u00A7\u25AC\u21A8\u2191\u2193\u2192\u2190\u221F\u2194\u25B2\u25BC !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\u00C7\u00FC\u00E9\u00E2\u00E4\u00E0\u00E5\u00E7\u00EA\u00EB\u00E8\u00EF\u00EE\u00EC\u00C4\u00C5\u00C9\u00E6\u00C6\u00F4\u00F6\u00F2\u00FB\u00F9\u00FF\u00D6\u00DC\u00A2\u00A3\u00A5\u20A7\u0192\u00E1\u00ED\u00F3\u00FA\u00F1\u00D1\u00AA\u00BA\u00BF\u2310\u00AC\u00BD\u00BC\u00A1\u00AB\u00BB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\u00DF\u0393\u03C0\u03A3\u03C3\u00B5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\u00B1\u2265\u2264\u2320\u2321\u00F7\u2248\u00B0\u2219\u00B7\u221A\u207F\u00B2\u25A0 ";
|
|
12
|
+
/**
|
|
13
|
+
* Map a Unicode code point to its CP437 index, or `0` if not representable.
|
|
14
|
+
*
|
|
15
|
+
* Characters in {@link CP437_CHARS} are mapped to their index (1..254); any
|
|
16
|
+
* code point above the maximum one present in CP437 (or otherwise absent)
|
|
17
|
+
* returns `0` (blank). This is used internally by {@link textGlyphs} when
|
|
18
|
+
* encoding characters into glyphs.
|
|
19
|
+
*
|
|
20
|
+
* @param code_point The Unicode code point to look up.
|
|
21
|
+
* @returns The CP437 index (1..254), or `0` if not representable.
|
|
22
|
+
*/
|
|
23
|
+
export declare function charCodeInCp437(code_point: number): number;
|
|
24
|
+
/**
|
|
25
|
+
* Render the CP437 character set onto a 2D canvas for use as a font texture.
|
|
26
|
+
*
|
|
27
|
+
* Loads the given `font` CSS string via the Font Loading API, measures an
|
|
28
|
+
* `"A"` glyph to determine per-cell dimensions, then paints all 255 CP437
|
|
29
|
+
* glyphs into a 32-column x 8-row grid on the supplied `canvas` (white on
|
|
30
|
+
* black). Box-drawing characters are replaced with `"@"` placeholders so
|
|
31
|
+
* they are not double-drawn; tscon's built-in bitmap font is used for those.
|
|
32
|
+
*
|
|
33
|
+
* The resulting canvas is intended to be captured (e.g. via `toDataURL` or a
|
|
34
|
+
* WebGL texture upload) to produce an application-provided font texture that
|
|
35
|
+
* can be assigned to {@link Canvas.user_font}.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { renderCp437 } from "@micahdb/tscon";
|
|
40
|
+
*
|
|
41
|
+
* const canvas = document.getElementById("2d") as HTMLCanvasElement;
|
|
42
|
+
* await renderCp437(canvas, "160px 'JetBrains Mono'");
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @param canvas The 2D canvas to render onto. Its `width`/`height` are set.
|
|
46
|
+
* @param font A CSS font string used to render the glyphs.
|
|
47
|
+
*/
|
|
48
|
+
export declare function renderCp437(canvas: HTMLCanvasElement, font: string): Promise<void>;
|
package/dist/cp437.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/*
|
|
2
|
+
╔═══════════ Code Page 437 ══════════╗
|
|
3
|
+
║ ║
|
|
4
|
+
║ ☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ ║
|
|
5
|
+
║ !"#$%&'()*+,-./0123456789:;<=>? ║
|
|
6
|
+
║ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ ║
|
|
7
|
+
║ `abcdefghijklmnopqrstuvwxyz{|}~⌂ ║
|
|
8
|
+
║ ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒ ║
|
|
9
|
+
║ áíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐ ║
|
|
10
|
+
║ └┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀ ║
|
|
11
|
+
║ αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ ║
|
|
12
|
+
║ ║
|
|
13
|
+
╚════════════════════════════════════╝
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* The 256 characters of IBM Code Page 437, as a string indexed by code.
|
|
17
|
+
*
|
|
18
|
+
* Index 0 is a blank (the CP437 NUL is unused) and index 255 is also treated
|
|
19
|
+
* as blank; all other indices 1..254 map to the corresponding CP437 glyph.
|
|
20
|
+
* This is the character set tscon's bitmap font covers and that
|
|
21
|
+
* {@link textGlyphs} encodes glyphs in.
|
|
22
|
+
*
|
|
23
|
+
* NOTE: chars at 0 and 255 are ignored.
|
|
24
|
+
*/
|
|
25
|
+
export const CP437_CHARS = `\
|
|
26
|
+
☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼\
|
|
27
|
+
!"#$%&'()*+,-./0123456789:;<=>?\
|
|
28
|
+
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\
|
|
29
|
+
\`abcdefghijklmnopqrstuvwxyz{|}~⌂\
|
|
30
|
+
ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒ\
|
|
31
|
+
áíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐\
|
|
32
|
+
└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀\
|
|
33
|
+
αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ `;
|
|
34
|
+
let max_code_point = 0;
|
|
35
|
+
for (let i = 1; i < 255; i++) {
|
|
36
|
+
const code_point = CP437_CHARS.codePointAt(i);
|
|
37
|
+
if (code_point > max_code_point) {
|
|
38
|
+
max_code_point = code_point;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const CP437_MAX_CODE_POINT = max_code_point;
|
|
42
|
+
// map from any character code point <= CP437_MAX_CODE_POINT to index in CP437
|
|
43
|
+
const CP437_MAP = new Uint8Array(CP437_MAX_CODE_POINT + 1);
|
|
44
|
+
// populate CP437_MAP
|
|
45
|
+
for (let i = 1; i < 255; i++) {
|
|
46
|
+
const code_point = CP437_CHARS.codePointAt(i);
|
|
47
|
+
CP437_MAP[code_point] = i;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Map a Unicode code point to its CP437 index, or `0` if not representable.
|
|
51
|
+
*
|
|
52
|
+
* Characters in {@link CP437_CHARS} are mapped to their index (1..254); any
|
|
53
|
+
* code point above the maximum one present in CP437 (or otherwise absent)
|
|
54
|
+
* returns `0` (blank). This is used internally by {@link textGlyphs} when
|
|
55
|
+
* encoding characters into glyphs.
|
|
56
|
+
*
|
|
57
|
+
* @param code_point The Unicode code point to look up.
|
|
58
|
+
* @returns The CP437 index (1..254), or `0` if not representable.
|
|
59
|
+
*/
|
|
60
|
+
export function charCodeInCp437(code_point) {
|
|
61
|
+
if (code_point > CP437_MAX_CODE_POINT) {
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
return CP437_MAP[code_point];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Render the CP437 character set onto a 2D canvas for use as a font texture.
|
|
68
|
+
*
|
|
69
|
+
* Loads the given `font` CSS string via the Font Loading API, measures an
|
|
70
|
+
* `"A"` glyph to determine per-cell dimensions, then paints all 255 CP437
|
|
71
|
+
* glyphs into a 32-column x 8-row grid on the supplied `canvas` (white on
|
|
72
|
+
* black). Box-drawing characters are replaced with `"@"` placeholders so
|
|
73
|
+
* they are not double-drawn; tscon's built-in bitmap font is used for those.
|
|
74
|
+
*
|
|
75
|
+
* The resulting canvas is intended to be captured (e.g. via `toDataURL` or a
|
|
76
|
+
* WebGL texture upload) to produce an application-provided font texture that
|
|
77
|
+
* can be assigned to {@link Canvas.user_font}.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* import { renderCp437 } from "@micahdb/tscon";
|
|
82
|
+
*
|
|
83
|
+
* const canvas = document.getElementById("2d") as HTMLCanvasElement;
|
|
84
|
+
* await renderCp437(canvas, "160px 'JetBrains Mono'");
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @param canvas The 2D canvas to render onto. Its `width`/`height` are set.
|
|
88
|
+
* @param font A CSS font string used to render the glyphs.
|
|
89
|
+
*/
|
|
90
|
+
export async function renderCp437(canvas, font) {
|
|
91
|
+
await document.fonts.load(font);
|
|
92
|
+
const ctx = canvas.getContext("2d");
|
|
93
|
+
ctx.font = font;
|
|
94
|
+
const metrics = ctx.measureText("A");
|
|
95
|
+
const padding = 1; // px
|
|
96
|
+
const glyph_width = metrics.width + 2 * padding;
|
|
97
|
+
const glyph_height = 2 * metrics.width + 2 * padding;
|
|
98
|
+
const ascent = Math.ceil(metrics.fontBoundingBoxAscent);
|
|
99
|
+
const cols = 32;
|
|
100
|
+
const rows = 8;
|
|
101
|
+
canvas.width = glyph_width * cols;
|
|
102
|
+
canvas.height = glyph_height * rows;
|
|
103
|
+
// fill canvas with black first
|
|
104
|
+
ctx.fillStyle = "black";
|
|
105
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
106
|
+
// reset these
|
|
107
|
+
ctx.font = font;
|
|
108
|
+
ctx.fillStyle = "white";
|
|
109
|
+
// don't want to draw box drawing characters;
|
|
110
|
+
// the moderndos font will be used for these
|
|
111
|
+
const box_drawing = "░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀";
|
|
112
|
+
const chars = CP437_CHARS.replace(box_drawing, "@".repeat(box_drawing.length));
|
|
113
|
+
// render all glyphs
|
|
114
|
+
for (let i = 1; i < 255; i++) {
|
|
115
|
+
const x = (i % cols) * glyph_width;
|
|
116
|
+
const y = Math.floor(i / cols) * glyph_height;
|
|
117
|
+
ctx.save();
|
|
118
|
+
ctx.beginPath();
|
|
119
|
+
ctx.rect(x + padding, y + padding, glyph_width - 2 * padding, glyph_height - 2 * padding);
|
|
120
|
+
ctx.clip();
|
|
121
|
+
ctx.fillText(chars.slice(i, i + 1), x + padding, y + ascent + padding);
|
|
122
|
+
ctx.restore();
|
|
123
|
+
}
|
|
124
|
+
}
|
package/dist/glyphs.d.ts
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Number of columns a tab advances the cursor by.
|
|
3
|
+
*
|
|
4
|
+
* Tabs in text processed by {@link textToLines} and {@link textGlyphs}
|
|
5
|
+
* advance the column position to the next multiple of this width.
|
|
6
|
+
*/
|
|
7
|
+
export declare const TAB_WIDTH = 8;
|
|
8
|
+
/**
|
|
9
|
+
* Layout `text` into lines no wider than `cols` columns.
|
|
10
|
+
*
|
|
11
|
+
* This is the line-breaking pass used by {@link textGlyphs}. It interprets
|
|
12
|
+
* the tscon text escape sequences so they are not counted against the
|
|
13
|
+
* column budget, and returns the raw visible content of each line as a
|
|
14
|
+
* string (still containing the escape codes for later processing).
|
|
15
|
+
*
|
|
16
|
+
* The following escape sequences are recognised and treated as taking up
|
|
17
|
+
* zero columns:
|
|
18
|
+
*
|
|
19
|
+
* - `\\` -- a literal backslash (collapses to one displayed char)
|
|
20
|
+
* - `\aX` and `\aX{options}` -- an anchor in group `X` (0-9), with an
|
|
21
|
+
* optional `{...}` options string
|
|
22
|
+
* - `\fX` / `\FX` -- set foreground to colour `X` (dark / bright)
|
|
23
|
+
* - `\bX` / `\BX` -- set background to colour `X` (dark / bright)
|
|
24
|
+
*
|
|
25
|
+
* Newlines always break the line. A backslash immediately followed by a
|
|
26
|
+
* newline is a line continuation: the two characters are removed and the
|
|
27
|
+
* following content joins the current line. Tabs advance to the next
|
|
28
|
+
* multiple of {@link TAB_WIDTH}.
|
|
29
|
+
*
|
|
30
|
+
* When `wrap` is `true`, lines longer than `cols` are wrapped at the most
|
|
31
|
+
* recent space (or broken mid-word if a single word fills a whole line).
|
|
32
|
+
* When `wrap` is `false`, lines longer than `cols` are truncated at the
|
|
33
|
+
* end of the line and the rest of that logical line is discarded.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* import { textToLines } from "@micahdb/tscon";
|
|
38
|
+
*
|
|
39
|
+
* textToLines("hello world", 80, true); // ["hello world"]
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @param text The text to lay out, possibly with escape sequences.
|
|
43
|
+
* @param cols Maximum number of visible columns per line. If `<= 0`, an
|
|
44
|
+
* empty array is returned.
|
|
45
|
+
* @param wrap Whether to word-wrap long lines (`true`) or truncate them
|
|
46
|
+
* (`false`).
|
|
47
|
+
* @returns The laid-out visible lines, with escape sequences preserved.
|
|
48
|
+
*/
|
|
49
|
+
export declare function textToLines(text: string, cols: number, wrap: boolean): string[];
|
|
50
|
+
/**
|
|
51
|
+
* A named position inside a {@link Glyphs} block, produced by an `\aX`
|
|
52
|
+
* anchor escape sequence in the source text.
|
|
53
|
+
*
|
|
54
|
+
* Anchors are grouped by the single digit `X` (0-9) following the `\a`
|
|
55
|
+
* escape, and the position recorded is the row/column of the glyph the
|
|
56
|
+
* anchor precedes. The optional `{...}` payload becomes {@link options}.
|
|
57
|
+
*
|
|
58
|
+
* They are how the text format marks interactive or navigable points
|
|
59
|
+
* (links, section headings, image placements, etc.) that the application
|
|
60
|
+
* can later find and render -- for example link text + URL or a section hash.
|
|
61
|
+
*/
|
|
62
|
+
export type Anchor = {
|
|
63
|
+
/**
|
|
64
|
+
* The text inside the anchor's optional `{...}` payload, or `null` if
|
|
65
|
+
* the anchor had no payload (or an empty payload, which is treated as
|
|
66
|
+
* `null`). Conventions like `"text|url"` are defined by the caller.
|
|
67
|
+
*/
|
|
68
|
+
options: string | null;
|
|
69
|
+
/** Row (y) of the anchor within the glyph grid. */
|
|
70
|
+
row: number;
|
|
71
|
+
/** Column (x) of the anchor within the glyph grid. */
|
|
72
|
+
col: number;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* A grid of pre-rendered terminal glyphs produced by {@link textGlyphs}.
|
|
76
|
+
*
|
|
77
|
+
* Each cell is a single 16-bit value packing a CP437 character code in the
|
|
78
|
+
* low byte and a 4-bit foreground / 4-bit background colour pair in the
|
|
79
|
+
* high byte: `[ fg (4) | bg (4) | char_code (8) ]`. Colours are indices into
|
|
80
|
+
* {@link PALETTE} (see {@link Colour}). Cells that are blank (a space on
|
|
81
|
+
* the default black-on-black colour) are left as zero.
|
|
82
|
+
*
|
|
83
|
+
* `data` is laid out row-major with `rows * cols` entries, so the glyph at
|
|
84
|
+
* `(row, col)` is at index `row * cols + col`.
|
|
85
|
+
*
|
|
86
|
+
* {@link anchors} records the positions of every `\aX` anchor found while
|
|
87
|
+
* rendering, keyed by group number 0-9.
|
|
88
|
+
*
|
|
89
|
+
* Pass a `Glyphs` to {@link Terminal.blit} to copy it onto the console's
|
|
90
|
+
* framebuffer.
|
|
91
|
+
*/
|
|
92
|
+
export type Glyphs = {
|
|
93
|
+
/** Packed glyph data, length `rows * cols`, row-major. */
|
|
94
|
+
data: Uint16Array;
|
|
95
|
+
/** Number of rows in the grid. */
|
|
96
|
+
rows: number;
|
|
97
|
+
/** Number of columns in the grid. */
|
|
98
|
+
cols: number;
|
|
99
|
+
/**
|
|
100
|
+
* Anchors keyed by group number (0-9). Each value is the list of
|
|
101
|
+
* anchors in that group, in the order they appear in the text.
|
|
102
|
+
*/
|
|
103
|
+
anchors: Record<number, Anchor[]>;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Render `text` into a grid of terminal glyphs `cols` wide.
|
|
107
|
+
*
|
|
108
|
+
* This is the primary text-rendering entry point. It runs {@link textToLines}
|
|
109
|
+
* to lay the text out, then encodes each visible character as a packed
|
|
110
|
+
* 16-bit glyph (CP437 code + colour pair) into the resulting {@link Glyphs}.
|
|
111
|
+
*
|
|
112
|
+
* The escape sequences understood by the text format are interpreted here:
|
|
113
|
+
*
|
|
114
|
+
* - `\\` -- emits a single literal backslash
|
|
115
|
+
* - `\aX` / `\aX{options}` -- records an anchor in group `X` (0-9) at the
|
|
116
|
+
* current position, with optional `options` string (see {@link Anchor})
|
|
117
|
+
* - `\fX` / `\FX` -- set foreground colour to `X` (dark / bright)
|
|
118
|
+
* - `\bX` / `\BX` -- set background colour to `X` (dark / bright)
|
|
119
|
+
*
|
|
120
|
+
* Colours `X` are clamped to 0-7; the `F`/`B` (capital) variants add 8 to
|
|
121
|
+
* select the bright half of the palette. The initial foreground is
|
|
122
|
+
* {@link Colour.WHITE} and the initial background is {@link Colour.BLACK}.
|
|
123
|
+
*
|
|
124
|
+
* Tabs advance the column to the next multiple of {@link TAB_WIDTH} but
|
|
125
|
+
* do not emit anything. Characters outside the CP437 range map to 0
|
|
126
|
+
* (blank), and trailing space on the default colour is left as zero so it
|
|
127
|
+
* does not overwrite whatever is already on the console.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* import { textGlyphs } from "@micahdb/tscon";
|
|
132
|
+
*
|
|
133
|
+
* // bright-blue on black "Link", 4 cols wide
|
|
134
|
+
* const g = textGlyphs("\\F4\\b0Link", 4, false);
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @param text The text to render, with escape sequences.
|
|
138
|
+
* @param cols Width of the grid in cells. If `<= 0`, an empty grid is
|
|
139
|
+
* returned.
|
|
140
|
+
* @param wrap Whether to word-wrap long lines (`true`) or truncate them
|
|
141
|
+
* (`false`).
|
|
142
|
+
* @returns The rendered glyph grid, with anchors populated.
|
|
143
|
+
*/
|
|
144
|
+
export declare function textGlyphs(text: string, cols: number, wrap: boolean): Glyphs;
|
|
145
|
+
/**
|
|
146
|
+
* How each cell of a {@link TexGlyphs} grid samples its source texture.
|
|
147
|
+
*
|
|
148
|
+
* The value is packed into each texture-glyph and read by the renderer's
|
|
149
|
+
* vertex shader to decide, per cell, how to turn the source texture into a
|
|
150
|
+
* drawn glyph.
|
|
151
|
+
*
|
|
152
|
+
* - `SAMPLE` -- render the source texture directly. Each cell is given UV
|
|
153
|
+
* coordinates into the texture, so the full rendered region
|
|
154
|
+
* simply shows the source texture as-is.
|
|
155
|
+
* - `GLYPHS` -- sample the texture and convert it to a glyph: the
|
|
156
|
+
* character is chosen by the sample's brightness and the
|
|
157
|
+
* colour by dithering (Bayer matrix + nearest palette hue).
|
|
158
|
+
* The background stays black. Preferred when you want the
|
|
159
|
+
* texture rendered as coloured characters without it being
|
|
160
|
+
* too bright or jarring.
|
|
161
|
+
* - `BG_GLYPHS` -- like `GLYPHS`, but also sets the background colour, so
|
|
162
|
+
* the full glyph (foreground + background) carries more of
|
|
163
|
+
* the sample's colour. This is noticeably brighter and more
|
|
164
|
+
* visually accurate; use it when no text is drawn on top of
|
|
165
|
+
* the rendered texture.
|
|
166
|
+
* - `MIX` -- alternate `SAMPLE`/`GLYPHS` in a checkerboard pattern.
|
|
167
|
+
* - `ROWS` -- alternate `SAMPLE`/`GLYPHS` by row.
|
|
168
|
+
* - `COLS` -- alternate `SAMPLE`/`GLYPHS` by column.
|
|
169
|
+
*/
|
|
170
|
+
export declare enum TexGlyphMode {
|
|
171
|
+
SAMPLE = 0,
|
|
172
|
+
GLYPHS = 1,
|
|
173
|
+
BG_GLYPHS = 2,
|
|
174
|
+
MIX = 3,
|
|
175
|
+
ROWS = 4,
|
|
176
|
+
COLS = 5
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* A grid of texture-sampling descriptors produced by {@link textureGlyphs}
|
|
180
|
+
* and consumed by {@link Renderer.draw}.
|
|
181
|
+
*
|
|
182
|
+
* Each cell is a 32-bit value packing the cell's row, its {@link TexGlyphMode},
|
|
183
|
+
* and its column: `[ row (8) | mode (8) | col (16) ]`.
|
|
184
|
+
*
|
|
185
|
+
* `data` is laid out row-major with `rows * cols` entries.
|
|
186
|
+
*/
|
|
187
|
+
export type TexGlyphs = {
|
|
188
|
+
/** Packed texture-glyph data, length `rows * cols`, row-major. */
|
|
189
|
+
data: Uint32Array;
|
|
190
|
+
/** Number of rows in the grid. */
|
|
191
|
+
rows: number;
|
|
192
|
+
/** Number of columns in the grid. */
|
|
193
|
+
cols: number;
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* Build a {@link TexGlyphs} grid of `rows` by `cols` cells that samples a
|
|
197
|
+
* texture in the given {@link TexGlyphMode}.
|
|
198
|
+
*
|
|
199
|
+
* The grid is sized to match a region of the terminal (typically the whole
|
|
200
|
+
* canvas, `canvas.rows` x `canvas.cols`, or a smaller sub-region) and is
|
|
201
|
+
* passed to {@link Renderer.draw} along with the texture to display.
|
|
202
|
+
*
|
|
203
|
+
* For the `MIX`, `ROWS`, and `COLS` modes the requested `mode` is used as a
|
|
204
|
+
* base and individual cells are switched between `SAMPLE` and `GLYPHS`
|
|
205
|
+
* according to the pattern (see {@link TexGlyphMode} for what each mode does
|
|
206
|
+
* to the sampled texture). The packed per-cell value encodes the cell's own
|
|
207
|
+
* row/column and the (possibly per-cell) effective mode.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* import { TexGlyphMode, textureGlyphs } from "@micahdb/tscon";
|
|
212
|
+
*
|
|
213
|
+
* // whole-canvas glyphs that sample the texture as coloured characters
|
|
214
|
+
* const tg = textureGlyphs(canvas.rows, canvas.cols, TexGlyphMode.GLYPHS);
|
|
215
|
+
* ```
|
|
216
|
+
*
|
|
217
|
+
* @param rows Height of the grid in cells.
|
|
218
|
+
* @param cols Width of the grid in cells.
|
|
219
|
+
* @param mode Sampling mode to apply to the cells.
|
|
220
|
+
* @returns The packed texture-glyph grid.
|
|
221
|
+
*/
|
|
222
|
+
export declare function textureGlyphs(rows: number, cols: number, mode: TexGlyphMode): TexGlyphs;
|