busybar-kit 2.0.0 → 2.2.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/dist/image/index.d.ts +5 -2
- package/dist/image/index.d.ts.map +1 -1
- package/dist/image/index.js +5 -2
- package/dist/image/index.js.map +1 -1
- package/dist/image/png.d.ts +9 -0
- package/dist/image/png.d.ts.map +1 -0
- package/dist/image/png.js +165 -0
- package/dist/image/png.js.map +1 -0
- package/dist/image/resize.d.ts +12 -0
- package/dist/image/resize.d.ts.map +1 -0
- package/dist/image/resize.js +83 -0
- package/dist/image/resize.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/input/index.d.ts +3 -0
- package/dist/input/index.d.ts.map +1 -0
- package/dist/input/index.js +3 -0
- package/dist/input/index.js.map +1 -0
- package/dist/input/input.d.ts +54 -0
- package/dist/input/input.d.ts.map +1 -0
- package/dist/input/input.js +222 -0
- package/dist/input/input.js.map +1 -0
- package/dist/input/protobuf.d.ts +28 -0
- package/dist/input/protobuf.d.ts.map +1 -0
- package/dist/input/protobuf.js +81 -0
- package/dist/input/protobuf.js.map +1 -0
- package/dist/preview/png.d.ts.map +1 -1
- package/dist/preview/png.js +20 -4
- package/dist/preview/png.js.map +1 -1
- package/dist/preview/raster.d.ts +8 -0
- package/dist/preview/raster.d.ts.map +1 -1
- package/dist/preview/raster.js +55 -7
- package/dist/preview/raster.js.map +1 -1
- package/dist/screen.d.ts +30 -0
- package/dist/screen.d.ts.map +1 -0
- package/dist/screen.js +49 -0
- package/dist/screen.js.map +1 -0
- package/package.json +4 -1
package/dist/image/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Bitmap } from '../preview/png.js';
|
|
2
2
|
import { type RgbaImage } from './dither.js';
|
|
3
3
|
export * from './dither.js';
|
|
4
|
+
export * from './png.js';
|
|
5
|
+
export * from './resize.js';
|
|
4
6
|
export type PanelImageOptions = {
|
|
5
7
|
/** Square side in pixels; the panel's own height by default. */
|
|
6
8
|
size?: number;
|
|
@@ -12,8 +14,9 @@ export type PanelImageOptions = {
|
|
|
12
14
|
* A picture, ready for the back panel: square, grey, dithered to the levels the
|
|
13
15
|
* device can show. `toPng()` on the result is what `AssetsUpload` wants.
|
|
14
16
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
+
* PNG arrives decoded by `decodePng` next door, which costs nothing because it
|
|
18
|
+
* is hand-rolled. JPEG stays the app's business: a decoder for it is a real
|
|
19
|
+
* dependency, and which one an app pays for is not this package's call.
|
|
17
20
|
*/
|
|
18
21
|
export declare function ditherToPanel(image: RgbaImage, options?: PanelImageOptions): Bitmap;
|
|
19
22
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/image/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,UAAU,CAAC;AAElB,cAAc,UAAU,CAAC;AAEzB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/image/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,UAAU,CAAC;AAElB,cAAc,UAAU,CAAC;AACzB,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AAEzB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAevF"}
|
package/dist/image/index.js
CHANGED
|
@@ -2,12 +2,15 @@ import { BACK } from '../device.js';
|
|
|
2
2
|
import { Bitmap } from '../preview/png.js';
|
|
3
3
|
import { autoContrast, ditherToShades, SHADES, toGreyTile, } from './dither.js';
|
|
4
4
|
export * from './dither.js';
|
|
5
|
+
export * from './png.js';
|
|
6
|
+
export * from './resize.js';
|
|
5
7
|
/**
|
|
6
8
|
* A picture, ready for the back panel: square, grey, dithered to the levels the
|
|
7
9
|
* device can show. `toPng()` on the result is what `AssetsUpload` wants.
|
|
8
10
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
+
* PNG arrives decoded by `decodePng` next door, which costs nothing because it
|
|
12
|
+
* is hand-rolled. JPEG stays the app's business: a decoder for it is a real
|
|
13
|
+
* dependency, and which one an app pays for is not this package's call.
|
|
11
14
|
*/
|
|
12
15
|
export function ditherToPanel(image, options = {}) {
|
|
13
16
|
const size = options.size ?? BACK.height;
|
package/dist/image/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/image/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EACL,YAAY,EACZ,cAAc,EACd,MAAM,EACN,UAAU,GAEX,MAAM,UAAU,CAAC;AAElB,cAAc,UAAU,CAAC;AAUzB
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/image/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EACL,YAAY,EACZ,cAAc,EACd,MAAM,EACN,UAAU,GAEX,MAAM,UAAU,CAAC;AAElB,cAAc,UAAU,CAAC;AACzB,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AAUzB;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,KAAgB,EAAE,UAA6B,EAAE;IAC7E,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC;IACzC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACxE,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAEtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;YACxC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RgbaImage } from './dither.js';
|
|
2
|
+
/**
|
|
3
|
+
* Enough of a PNG decoder for album art: 8- and 16-bit samples, every colour
|
|
4
|
+
* type, no interlacing. busybar-kit already hand-rolls the encoder, so this
|
|
5
|
+
* keeps the pair symmetrical instead of pulling in a decoder dependency for
|
|
6
|
+
* the minority of covers that are not JPEG.
|
|
7
|
+
*/
|
|
8
|
+
export declare function decodePng(bytes: Buffer): RgbaImage;
|
|
9
|
+
//# sourceMappingURL=png.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"png.d.ts","sourceRoot":"","sources":["../../src/image/png.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAM1C;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CA6ClD"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { inflateSync } from 'node:zlib';
|
|
2
|
+
const SIGNATURE = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
|
|
3
|
+
const CHANNELS = { 0: 1, 2: 3, 3: 1, 4: 2, 6: 4 };
|
|
4
|
+
/**
|
|
5
|
+
* Enough of a PNG decoder for album art: 8- and 16-bit samples, every colour
|
|
6
|
+
* type, no interlacing. busybar-kit already hand-rolls the encoder, so this
|
|
7
|
+
* keeps the pair symmetrical instead of pulling in a decoder dependency for
|
|
8
|
+
* the minority of covers that are not JPEG.
|
|
9
|
+
*/
|
|
10
|
+
export function decodePng(bytes) {
|
|
11
|
+
if (bytes.length < 8 || SIGNATURE.some((byte, index) => bytes[index] !== byte)) {
|
|
12
|
+
throw new Error('not a PNG');
|
|
13
|
+
}
|
|
14
|
+
let header = null;
|
|
15
|
+
let palette = null;
|
|
16
|
+
let transparency = null;
|
|
17
|
+
const parts = [];
|
|
18
|
+
for (let offset = 8; offset + 8 <= bytes.length;) {
|
|
19
|
+
const length = bytes.readUInt32BE(offset);
|
|
20
|
+
const type = bytes.toString('ascii', offset + 4, offset + 8);
|
|
21
|
+
const start = offset + 8;
|
|
22
|
+
const end = start + length;
|
|
23
|
+
if (end > bytes.length) {
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
if (type === 'IHDR') {
|
|
27
|
+
header = readHeader(bytes.subarray(start, end));
|
|
28
|
+
}
|
|
29
|
+
else if (type === 'PLTE') {
|
|
30
|
+
palette = bytes.subarray(start, end);
|
|
31
|
+
}
|
|
32
|
+
else if (type === 'tRNS') {
|
|
33
|
+
transparency = bytes.subarray(start, end);
|
|
34
|
+
}
|
|
35
|
+
else if (type === 'IDAT') {
|
|
36
|
+
parts.push(bytes.subarray(start, end));
|
|
37
|
+
}
|
|
38
|
+
else if (type === 'IEND') {
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
offset = end + 4;
|
|
42
|
+
}
|
|
43
|
+
if (!header) {
|
|
44
|
+
throw new Error('PNG has no header');
|
|
45
|
+
}
|
|
46
|
+
if (parts.length === 0) {
|
|
47
|
+
throw new Error('PNG has no pixel data');
|
|
48
|
+
}
|
|
49
|
+
const raw = inflateSync(Buffer.concat(parts));
|
|
50
|
+
const samples = unfilter(raw, header);
|
|
51
|
+
return expand(samples, header, palette, transparency);
|
|
52
|
+
}
|
|
53
|
+
function readHeader(chunk) {
|
|
54
|
+
const width = chunk.readUInt32BE(0);
|
|
55
|
+
const height = chunk.readUInt32BE(4);
|
|
56
|
+
const depth = chunk[8] ?? 0;
|
|
57
|
+
const colorType = chunk[9] ?? 0;
|
|
58
|
+
const interlace = chunk[12] ?? 0;
|
|
59
|
+
const channels = CHANNELS[colorType];
|
|
60
|
+
if (!channels) {
|
|
61
|
+
throw new Error(`unsupported PNG colour type ${colorType}`);
|
|
62
|
+
}
|
|
63
|
+
if (depth !== 8 && depth !== 16) {
|
|
64
|
+
throw new Error(`unsupported PNG bit depth ${depth}`);
|
|
65
|
+
}
|
|
66
|
+
if (interlace !== 0) {
|
|
67
|
+
throw new Error('interlaced PNG is not supported');
|
|
68
|
+
}
|
|
69
|
+
if (width <= 0 || height <= 0) {
|
|
70
|
+
throw new Error('PNG has no size');
|
|
71
|
+
}
|
|
72
|
+
const bytesPerSample = depth / 8;
|
|
73
|
+
const bpp = channels * bytesPerSample;
|
|
74
|
+
return { width, height, depth, colorType, channels, bpp, stride: width * bpp };
|
|
75
|
+
}
|
|
76
|
+
function unfilter(raw, header) {
|
|
77
|
+
const { stride, bpp, height } = header;
|
|
78
|
+
const out = Buffer.alloc(stride * height);
|
|
79
|
+
for (let y = 0; y < height; y += 1) {
|
|
80
|
+
const filterOffset = y * (stride + 1);
|
|
81
|
+
const filter = raw[filterOffset] ?? 0;
|
|
82
|
+
const line = filterOffset + 1;
|
|
83
|
+
const target = y * stride;
|
|
84
|
+
for (let x = 0; x < stride; x += 1) {
|
|
85
|
+
const value = raw[line + x] ?? 0;
|
|
86
|
+
const left = x >= bpp ? (out[target + x - bpp] ?? 0) : 0;
|
|
87
|
+
const up = y > 0 ? (out[target - stride + x] ?? 0) : 0;
|
|
88
|
+
const upLeft = y > 0 && x >= bpp ? (out[target - stride + x - bpp] ?? 0) : 0;
|
|
89
|
+
out[target + x] = (value + reconstruct(filter, left, up, upLeft)) & 0xff;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
function reconstruct(filter, left, up, upLeft) {
|
|
95
|
+
if (filter === 1) {
|
|
96
|
+
return left;
|
|
97
|
+
}
|
|
98
|
+
if (filter === 2) {
|
|
99
|
+
return up;
|
|
100
|
+
}
|
|
101
|
+
if (filter === 3) {
|
|
102
|
+
return (left + up) >> 1;
|
|
103
|
+
}
|
|
104
|
+
if (filter === 4) {
|
|
105
|
+
return paeth(left, up, upLeft);
|
|
106
|
+
}
|
|
107
|
+
return 0;
|
|
108
|
+
}
|
|
109
|
+
function paeth(a, b, c) {
|
|
110
|
+
const p = a + b - c;
|
|
111
|
+
const pa = Math.abs(p - a);
|
|
112
|
+
const pb = Math.abs(p - b);
|
|
113
|
+
const pc = Math.abs(p - c);
|
|
114
|
+
if (pa <= pb && pa <= pc) {
|
|
115
|
+
return a;
|
|
116
|
+
}
|
|
117
|
+
return pb <= pc ? b : c;
|
|
118
|
+
}
|
|
119
|
+
function expand(samples, header, palette, transparency) {
|
|
120
|
+
const { width, height, depth, colorType, channels } = header;
|
|
121
|
+
const step = depth / 8;
|
|
122
|
+
const data = new Uint8Array(width * height * 4);
|
|
123
|
+
for (let pixel = 0; pixel < width * height; pixel += 1) {
|
|
124
|
+
// 16-bit samples are read by their high byte: the panel has 16 grey levels,
|
|
125
|
+
// so the low byte cannot survive the trip anyway.
|
|
126
|
+
const base = pixel * channels * step;
|
|
127
|
+
const at = (index) => samples[base + index * step] ?? 0;
|
|
128
|
+
const out = pixel * 4;
|
|
129
|
+
let r;
|
|
130
|
+
let g;
|
|
131
|
+
let b;
|
|
132
|
+
let a = 255;
|
|
133
|
+
if (colorType === 0) {
|
|
134
|
+
r = g = b = at(0);
|
|
135
|
+
}
|
|
136
|
+
else if (colorType === 2) {
|
|
137
|
+
r = at(0);
|
|
138
|
+
g = at(1);
|
|
139
|
+
b = at(2);
|
|
140
|
+
}
|
|
141
|
+
else if (colorType === 3) {
|
|
142
|
+
const index = at(0);
|
|
143
|
+
r = palette?.[index * 3] ?? 0;
|
|
144
|
+
g = palette?.[index * 3 + 1] ?? 0;
|
|
145
|
+
b = palette?.[index * 3 + 2] ?? 0;
|
|
146
|
+
a = transparency?.[index] ?? 255;
|
|
147
|
+
}
|
|
148
|
+
else if (colorType === 4) {
|
|
149
|
+
r = g = b = at(0);
|
|
150
|
+
a = at(1);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
r = at(0);
|
|
154
|
+
g = at(1);
|
|
155
|
+
b = at(2);
|
|
156
|
+
a = at(3);
|
|
157
|
+
}
|
|
158
|
+
data[out] = r;
|
|
159
|
+
data[out + 1] = g;
|
|
160
|
+
data[out + 2] = b;
|
|
161
|
+
data[out + 3] = a;
|
|
162
|
+
}
|
|
163
|
+
return { width, height, data };
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=png.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"png.js","sourceRoot":"","sources":["../../src/image/png.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RgbaImage } from './dither.js';
|
|
2
|
+
/**
|
|
3
|
+
* Centre-crops to a square and box-filters down to `size`, in colour.
|
|
4
|
+
*
|
|
5
|
+
* The grey path next door does the same walk and throws the channels away at
|
|
6
|
+
* the end; a panel that can show colour wants them kept. Averaging happens in
|
|
7
|
+
* linear light for the same reason it does there — averaging gamma-encoded
|
|
8
|
+
* bytes is why a downscaled picture usually comes out muddier than the
|
|
9
|
+
* original. Alpha is averaged as-is, being linear already.
|
|
10
|
+
*/
|
|
11
|
+
export declare function toRgbaTile(image: RgbaImage, size: number): RgbaImage;
|
|
12
|
+
//# sourceMappingURL=resize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resize.d.ts","sourceRoot":"","sources":["../../src/image/resize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAK1C;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAyBpE"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const TO_LINEAR = buildLinearTable();
|
|
2
|
+
const TO_SRGB = buildSrgbTable();
|
|
3
|
+
/**
|
|
4
|
+
* Centre-crops to a square and box-filters down to `size`, in colour.
|
|
5
|
+
*
|
|
6
|
+
* The grey path next door does the same walk and throws the channels away at
|
|
7
|
+
* the end; a panel that can show colour wants them kept. Averaging happens in
|
|
8
|
+
* linear light for the same reason it does there — averaging gamma-encoded
|
|
9
|
+
* bytes is why a downscaled picture usually comes out muddier than the
|
|
10
|
+
* original. Alpha is averaged as-is, being linear already.
|
|
11
|
+
*/
|
|
12
|
+
export function toRgbaTile(image, size) {
|
|
13
|
+
const side = Math.min(image.width, image.height);
|
|
14
|
+
const offsetX = Math.floor((image.width - side) / 2);
|
|
15
|
+
const offsetY = Math.floor((image.height - side) / 2);
|
|
16
|
+
const data = new Uint8Array(size * size * 4);
|
|
17
|
+
for (let y = 0; y < size; y += 1) {
|
|
18
|
+
const startY = Math.floor((y * side) / size);
|
|
19
|
+
const endY = Math.max(startY + 1, Math.floor(((y + 1) * side) / size));
|
|
20
|
+
for (let x = 0; x < size; x += 1) {
|
|
21
|
+
const startX = Math.floor((x * side) / size);
|
|
22
|
+
const endX = Math.max(startX + 1, Math.floor(((x + 1) * side) / size));
|
|
23
|
+
const pixel = boxAverage(image, offsetX + startX, offsetY + startY, offsetX + endX, offsetY + endY);
|
|
24
|
+
data.set(pixel, (y * size + x) * 4);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return { width: size, height: size, data };
|
|
28
|
+
}
|
|
29
|
+
function boxAverage(image, startX, startY, endX, endY) {
|
|
30
|
+
let red = 0;
|
|
31
|
+
let green = 0;
|
|
32
|
+
let blue = 0;
|
|
33
|
+
let alpha = 0;
|
|
34
|
+
let count = 0;
|
|
35
|
+
for (let y = startY; y < endY; y += 1) {
|
|
36
|
+
if (y < 0 || y >= image.height) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
for (let x = startX; x < endX; x += 1) {
|
|
40
|
+
if (x < 0 || x >= image.width) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const offset = (y * image.width + x) * 4;
|
|
44
|
+
red += TO_LINEAR[image.data[offset] ?? 0] ?? 0;
|
|
45
|
+
green += TO_LINEAR[image.data[offset + 1] ?? 0] ?? 0;
|
|
46
|
+
blue += TO_LINEAR[image.data[offset + 2] ?? 0] ?? 0;
|
|
47
|
+
alpha += image.data[offset + 3] ?? 0;
|
|
48
|
+
count += 1;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (count === 0) {
|
|
52
|
+
return [0, 0, 0, 0];
|
|
53
|
+
}
|
|
54
|
+
return [
|
|
55
|
+
encode(red / count),
|
|
56
|
+
encode(green / count),
|
|
57
|
+
encode(blue / count),
|
|
58
|
+
Math.round(alpha / count),
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
function encode(linear) {
|
|
62
|
+
return TO_SRGB[Math.max(0, Math.min(4095, Math.round(linear * 4095)))] ?? 0;
|
|
63
|
+
}
|
|
64
|
+
function buildLinearTable() {
|
|
65
|
+
const table = new Float64Array(256);
|
|
66
|
+
for (let value = 0; value < 256; value += 1) {
|
|
67
|
+
const channel = value / 255;
|
|
68
|
+
table[value] =
|
|
69
|
+
channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;
|
|
70
|
+
}
|
|
71
|
+
return table;
|
|
72
|
+
}
|
|
73
|
+
/** The inverse, at 12 bits — enough that rounding never costs a visible level. */
|
|
74
|
+
function buildSrgbTable() {
|
|
75
|
+
const table = new Uint8Array(4096);
|
|
76
|
+
for (let step = 0; step < 4096; step += 1) {
|
|
77
|
+
const linear = step / 4095;
|
|
78
|
+
const encoded = linear <= 0.0031308 ? linear * 12.92 : 1.055 * linear ** (1 / 2.4) - 0.055;
|
|
79
|
+
table[step] = Math.round(Math.max(0, Math.min(1, encoded)) * 255);
|
|
80
|
+
}
|
|
81
|
+
return table;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=resize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resize.js","sourceRoot":"","sources":["../../src/image/resize.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,9 @@ export * from './elements.js';
|
|
|
8
8
|
export * from './errors.js';
|
|
9
9
|
export * from './format.js';
|
|
10
10
|
export * from './image/index.js';
|
|
11
|
+
export * from './input/index.js';
|
|
11
12
|
export * from './preview/index.js';
|
|
12
13
|
export * from './profile.js';
|
|
14
|
+
export * from './screen.js';
|
|
13
15
|
export * from './ticker/index.js';
|
|
14
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,9 @@ export * from './elements.js';
|
|
|
8
8
|
export * from './errors.js';
|
|
9
9
|
export * from './format.js';
|
|
10
10
|
export * from './image/index.js';
|
|
11
|
+
export * from './input/index.js';
|
|
11
12
|
export * from './preview/index.js';
|
|
12
13
|
export * from './profile.js';
|
|
14
|
+
export * from './screen.js';
|
|
13
15
|
export * from './ticker/index.js';
|
|
14
16
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/input/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/input/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Bar's physical controls, over its status socket.
|
|
3
|
+
*
|
|
4
|
+
* `ws://<bar>/api/status/ws` streams `BSB_State.State` frames; input events are
|
|
5
|
+
* one of the fifteen things a `StateUpdate` can carry. busy-lib's own reader for
|
|
6
|
+
* this runs in a browser Worker, so this opens the socket itself — Node has had
|
|
7
|
+
* a WebSocket since 22, and the walk to the events is short enough to hand-roll.
|
|
8
|
+
*
|
|
9
|
+
* Every app that wants the Bar's buttons needs exactly this, so it lives here
|
|
10
|
+
* rather than once per app.
|
|
11
|
+
*/
|
|
12
|
+
export declare const WS_PATH = "/api/status/ws";
|
|
13
|
+
declare const BUTTONS: readonly ["ok", "back", "start"];
|
|
14
|
+
declare const ACTIONS: readonly ["press", "release"];
|
|
15
|
+
declare const SWITCH_POSITIONS: readonly ["busy", "custom", "off", "apps", "settings"];
|
|
16
|
+
export type BarButton = (typeof BUTTONS)[number];
|
|
17
|
+
export type ButtonAction = (typeof ACTIONS)[number];
|
|
18
|
+
export type SwitchPosition = (typeof SWITCH_POSITIONS)[number];
|
|
19
|
+
export type InputEvent = {
|
|
20
|
+
kind: 'button';
|
|
21
|
+
button: BarButton;
|
|
22
|
+
action: ButtonAction;
|
|
23
|
+
} | {
|
|
24
|
+
kind: 'encoder';
|
|
25
|
+
delta: number;
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'switch';
|
|
28
|
+
position: SwitchPosition;
|
|
29
|
+
};
|
|
30
|
+
export type BarInputOptions = {
|
|
31
|
+
addr: string;
|
|
32
|
+
/** HTTP Access password (Wi-Fi) or cloud token; both travel the same way. */
|
|
33
|
+
credential?: string;
|
|
34
|
+
isCloud?: boolean;
|
|
35
|
+
onEvent: (event: InputEvent) => void;
|
|
36
|
+
onWarning?: (message: string) => void;
|
|
37
|
+
};
|
|
38
|
+
export declare class BarInput {
|
|
39
|
+
private readonly options;
|
|
40
|
+
private socket;
|
|
41
|
+
private timer;
|
|
42
|
+
private running;
|
|
43
|
+
constructor(options: BarInputOptions);
|
|
44
|
+
start(): void;
|
|
45
|
+
stop(): void;
|
|
46
|
+
private connect;
|
|
47
|
+
private handle;
|
|
48
|
+
private retry;
|
|
49
|
+
private url;
|
|
50
|
+
}
|
|
51
|
+
/** Every input event in one `BSB_State.State` frame. */
|
|
52
|
+
export declare function decodeInputEvents(frame: Uint8Array): InputEvent[];
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/input/input.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,mBAAmB,CAAC;AAaxC,QAAA,MAAM,OAAO,kCAAmC,CAAC;AACjD,QAAA,MAAM,OAAO,+BAAgC,CAAC;AAC9C,QAAA,MAAM,gBAAgB,wDAAyD,CAAC;AAEhF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AACjD,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AACpD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,CAAC;AAEjD,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,CAAC;AAIF,qBAAa,QAAQ;IAKP,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,OAAO,CAAS;gBAEK,OAAO,EAAE,eAAe;IAErD,KAAK,IAAI,IAAI;IAKb,IAAI,IAAI,IAAI;IAUZ,OAAO,CAAC,OAAO;YA+CD,MAAM;IAWpB,OAAO,CAAC,KAAK;IAWb,OAAO,CAAC,GAAG;CAeZ;AAED,wDAAwD;AACxD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,EAAE,CAyBjE"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { eachField } from './protobuf.js';
|
|
2
|
+
/**
|
|
3
|
+
* The Bar's physical controls, over its status socket.
|
|
4
|
+
*
|
|
5
|
+
* `ws://<bar>/api/status/ws` streams `BSB_State.State` frames; input events are
|
|
6
|
+
* one of the fifteen things a `StateUpdate` can carry. busy-lib's own reader for
|
|
7
|
+
* this runs in a browser Worker, so this opens the socket itself — Node has had
|
|
8
|
+
* a WebSocket since 22, and the walk to the events is short enough to hand-roll.
|
|
9
|
+
*
|
|
10
|
+
* Every app that wants the Bar's buttons needs exactly this, so it lives here
|
|
11
|
+
* rather than once per app.
|
|
12
|
+
*/
|
|
13
|
+
export const WS_PATH = '/api/status/ws';
|
|
14
|
+
/** Field numbers, from the schema busy-lib ships. */
|
|
15
|
+
const STATE_UPDATES = 2;
|
|
16
|
+
const UPDATE_INPUT = 11;
|
|
17
|
+
const INPUT_BUTTON = 1;
|
|
18
|
+
const INPUT_SWITCH = 2;
|
|
19
|
+
const INPUT_ENCODER = 3;
|
|
20
|
+
const BUTTON_WHICH = 1;
|
|
21
|
+
const BUTTON_ACTION = 2;
|
|
22
|
+
const ENCODER_DELTA = 1;
|
|
23
|
+
const SWITCH_POSITION = 1;
|
|
24
|
+
const BUTTONS = ['ok', 'back', 'start'];
|
|
25
|
+
const ACTIONS = ['press', 'release'];
|
|
26
|
+
const SWITCH_POSITIONS = ['busy', 'custom', 'off', 'apps', 'settings'];
|
|
27
|
+
const RECONNECT_MS = 2000;
|
|
28
|
+
export class BarInput {
|
|
29
|
+
options;
|
|
30
|
+
socket = null;
|
|
31
|
+
timer = null;
|
|
32
|
+
running = false;
|
|
33
|
+
constructor(options) {
|
|
34
|
+
this.options = options;
|
|
35
|
+
}
|
|
36
|
+
start() {
|
|
37
|
+
this.running = true;
|
|
38
|
+
this.connect();
|
|
39
|
+
}
|
|
40
|
+
stop() {
|
|
41
|
+
this.running = false;
|
|
42
|
+
if (this.timer) {
|
|
43
|
+
clearTimeout(this.timer);
|
|
44
|
+
this.timer = null;
|
|
45
|
+
}
|
|
46
|
+
this.socket?.close();
|
|
47
|
+
this.socket = null;
|
|
48
|
+
}
|
|
49
|
+
connect() {
|
|
50
|
+
if (!this.running) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
let socket;
|
|
54
|
+
try {
|
|
55
|
+
socket = new WebSocket(this.url());
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
this.retry(`input socket: ${message(error)}`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.socket = socket;
|
|
62
|
+
socket.binaryType = 'arraybuffer';
|
|
63
|
+
socket.onopen = () => {
|
|
64
|
+
// The device stays silent until streaming is switched on; the credential
|
|
65
|
+
// goes in the URL as well, but a cloud socket wants it as a message too.
|
|
66
|
+
socket.send(JSON.stringify({ enable: true }));
|
|
67
|
+
if (this.options.credential) {
|
|
68
|
+
socket.send(JSON.stringify({ token: this.options.credential }));
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
socket.onmessage = (event) => {
|
|
72
|
+
void this.handle(event.data).catch((error) => {
|
|
73
|
+
this.options.onWarning?.(`input frame: ${message(error)}`);
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
socket.onerror = () => {
|
|
77
|
+
// `onclose` always follows, and carries the reason worth reporting.
|
|
78
|
+
};
|
|
79
|
+
socket.onclose = (event) => {
|
|
80
|
+
if (this.socket === socket) {
|
|
81
|
+
this.socket = null;
|
|
82
|
+
this.retry(event.reason
|
|
83
|
+
? `input socket closed: ${event.reason}`
|
|
84
|
+
: 'input socket closed, reconnecting');
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async handle(data) {
|
|
89
|
+
const bytes = await toBytes(data);
|
|
90
|
+
if (!bytes) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
for (const event of decodeInputEvents(bytes)) {
|
|
94
|
+
this.options.onEvent(event);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
retry(warning) {
|
|
98
|
+
if (!this.running || this.timer) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this.options.onWarning?.(warning);
|
|
102
|
+
this.timer = setTimeout(() => {
|
|
103
|
+
this.timer = null;
|
|
104
|
+
this.connect();
|
|
105
|
+
}, RECONNECT_MS);
|
|
106
|
+
}
|
|
107
|
+
url() {
|
|
108
|
+
const base = /^[a-z]+:\/\//i.test(this.options.addr)
|
|
109
|
+
? this.options.addr
|
|
110
|
+
: `http://${this.options.addr}`;
|
|
111
|
+
const url = new URL(base);
|
|
112
|
+
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
113
|
+
if (url.pathname === '/' || !url.pathname) {
|
|
114
|
+
url.pathname = WS_PATH;
|
|
115
|
+
}
|
|
116
|
+
if (this.options.credential) {
|
|
117
|
+
url.searchParams.set('x-api-token', this.options.credential);
|
|
118
|
+
}
|
|
119
|
+
return url.toString();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** Every input event in one `BSB_State.State` frame. */
|
|
123
|
+
export function decodeInputEvents(frame) {
|
|
124
|
+
const events = [];
|
|
125
|
+
eachField(frame, (field, wire, reader) => {
|
|
126
|
+
if (field !== STATE_UPDATES || wire !== 2) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const update = reader.bytes_();
|
|
130
|
+
eachField(update, (updateField, updateWire, updateReader) => {
|
|
131
|
+
if (updateField !== UPDATE_INPUT || updateWire !== 2) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const event = decodeInputEvent(updateReader.bytes_());
|
|
135
|
+
if (event) {
|
|
136
|
+
events.push(event);
|
|
137
|
+
}
|
|
138
|
+
return true;
|
|
139
|
+
});
|
|
140
|
+
return true;
|
|
141
|
+
});
|
|
142
|
+
return events;
|
|
143
|
+
}
|
|
144
|
+
function decodeInputEvent(bytes) {
|
|
145
|
+
let event = null;
|
|
146
|
+
eachField(bytes, (field, wire, reader) => {
|
|
147
|
+
if (wire !== 2) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (field === INPUT_BUTTON) {
|
|
151
|
+
event = decodeButton(reader.bytes_());
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
if (field === INPUT_ENCODER) {
|
|
155
|
+
event = decodeEncoder(reader.bytes_());
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
if (field === INPUT_SWITCH) {
|
|
159
|
+
event = decodeSwitch(reader.bytes_());
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
return event;
|
|
164
|
+
}
|
|
165
|
+
function decodeButton(bytes) {
|
|
166
|
+
// Proto3 leaves a zero-valued field off the wire entirely, so the defaults
|
|
167
|
+
// here are the enums' zeroes: OK, and PRESS.
|
|
168
|
+
let button = 'ok';
|
|
169
|
+
let action = 'press';
|
|
170
|
+
eachField(bytes, (field, wire, reader) => {
|
|
171
|
+
if (wire !== 0) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (field === BUTTON_WHICH) {
|
|
175
|
+
button = BUTTONS[reader.varint()] ?? button;
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
if (field === BUTTON_ACTION) {
|
|
179
|
+
action = ACTIONS[reader.varint()] ?? action;
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
return { kind: 'button', button, action };
|
|
184
|
+
}
|
|
185
|
+
function decodeEncoder(bytes) {
|
|
186
|
+
let delta = 0;
|
|
187
|
+
eachField(bytes, (field, wire, reader) => {
|
|
188
|
+
if (field === ENCODER_DELTA && wire === 0) {
|
|
189
|
+
// sint32: signed, so zigzagged rather than two's complement.
|
|
190
|
+
delta = reader.zigzag();
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
return delta === 0 ? null : { kind: 'encoder', delta };
|
|
195
|
+
}
|
|
196
|
+
function decodeSwitch(bytes) {
|
|
197
|
+
let position = 'busy';
|
|
198
|
+
eachField(bytes, (field, wire, reader) => {
|
|
199
|
+
if (field === SWITCH_POSITION && wire === 0) {
|
|
200
|
+
position = SWITCH_POSITIONS[reader.varint()] ?? position;
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
return { kind: 'switch', position };
|
|
205
|
+
}
|
|
206
|
+
async function toBytes(data) {
|
|
207
|
+
if (data instanceof ArrayBuffer) {
|
|
208
|
+
return new Uint8Array(data);
|
|
209
|
+
}
|
|
210
|
+
if (ArrayBuffer.isView(data)) {
|
|
211
|
+
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
212
|
+
}
|
|
213
|
+
if (typeof Blob !== 'undefined' && data instanceof Blob) {
|
|
214
|
+
return new Uint8Array(await data.arrayBuffer());
|
|
215
|
+
}
|
|
216
|
+
// Text frames are the device's own JSON acknowledgements, not state.
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
function message(error) {
|
|
220
|
+
return error instanceof Error ? error.message : String(error);
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","sourceRoot":"","sources":["../../src/input/input.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Just enough protobuf to read one message off the Bar's status socket.
|
|
3
|
+
*
|
|
4
|
+
* The device streams `BSB_State.State` frames, and busy-lib decodes them with a
|
|
5
|
+
* bundled protobufjs — inside a browser Worker, which is why none of it runs
|
|
6
|
+
* here. All anyone wants out of a frame is the input events, so it walks the
|
|
7
|
+
* three fields on the way to them and skips everything else.
|
|
8
|
+
*/
|
|
9
|
+
export declare class Reader {
|
|
10
|
+
private readonly bytes;
|
|
11
|
+
private offset;
|
|
12
|
+
constructor(bytes: Uint8Array);
|
|
13
|
+
get done(): boolean;
|
|
14
|
+
/** Field number and wire type of the next field. */
|
|
15
|
+
tag(): {
|
|
16
|
+
field: number;
|
|
17
|
+
wire: number;
|
|
18
|
+
};
|
|
19
|
+
varint(): number;
|
|
20
|
+
/** Signed varint, as protobuf's `sint32` writes it. */
|
|
21
|
+
zigzag(): number;
|
|
22
|
+
bytes_(): Uint8Array;
|
|
23
|
+
/** Steps over a field this app does not care about. */
|
|
24
|
+
skip(wire: number): void;
|
|
25
|
+
}
|
|
26
|
+
/** Runs `visit` over every field of a message. */
|
|
27
|
+
export declare function eachField(bytes: Uint8Array, visit: (field: number, wire: number, reader: Reader) => boolean | void): void;
|
|
28
|
+
//# sourceMappingURL=protobuf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protobuf.d.ts","sourceRoot":"","sources":["../../src/input/protobuf.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,qBAAa,MAAM;IAGL,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFlC,OAAO,CAAC,MAAM,CAAK;gBAEU,KAAK,EAAE,UAAU;IAE9C,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,oDAAoD;IACpD,GAAG,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAMtC,MAAM,IAAI,MAAM;IAkBhB,uDAAuD;IACvD,MAAM,IAAI,MAAM;IAMhB,MAAM,IAAI,UAAU;IAQpB,uDAAuD;IACvD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAezB;AAED,kDAAkD;AAClD,wBAAgB,SAAS,CACvB,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,GACrE,IAAI,CAQN"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Just enough protobuf to read one message off the Bar's status socket.
|
|
3
|
+
*
|
|
4
|
+
* The device streams `BSB_State.State` frames, and busy-lib decodes them with a
|
|
5
|
+
* bundled protobufjs — inside a browser Worker, which is why none of it runs
|
|
6
|
+
* here. All anyone wants out of a frame is the input events, so it walks the
|
|
7
|
+
* three fields on the way to them and skips everything else.
|
|
8
|
+
*/
|
|
9
|
+
export class Reader {
|
|
10
|
+
bytes;
|
|
11
|
+
offset = 0;
|
|
12
|
+
constructor(bytes) {
|
|
13
|
+
this.bytes = bytes;
|
|
14
|
+
}
|
|
15
|
+
get done() {
|
|
16
|
+
return this.offset >= this.bytes.length;
|
|
17
|
+
}
|
|
18
|
+
/** Field number and wire type of the next field. */
|
|
19
|
+
tag() {
|
|
20
|
+
const key = this.varint();
|
|
21
|
+
return { field: key >>> 3, wire: key & 7 };
|
|
22
|
+
}
|
|
23
|
+
varint() {
|
|
24
|
+
let result = 0;
|
|
25
|
+
let shift = 0;
|
|
26
|
+
while (this.offset < this.bytes.length) {
|
|
27
|
+
const byte = this.bytes[this.offset] ?? 0;
|
|
28
|
+
this.offset += 1;
|
|
29
|
+
// Numbers stay safe integers here: these are enums, small deltas and
|
|
30
|
+
// lengths, never the 64-bit timestamp, which is skipped as fixed64.
|
|
31
|
+
result += shift < 28 ? (byte & 0x7f) << shift : (byte & 0x7f) * 2 ** shift;
|
|
32
|
+
if ((byte & 0x80) === 0) {
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
shift += 7;
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
/** Signed varint, as protobuf's `sint32` writes it. */
|
|
40
|
+
zigzag() {
|
|
41
|
+
const value = this.varint();
|
|
42
|
+
return (value >>> 1) ^ -(value & 1);
|
|
43
|
+
}
|
|
44
|
+
bytes_() {
|
|
45
|
+
const length = this.varint();
|
|
46
|
+
const start = this.offset;
|
|
47
|
+
this.offset = Math.min(this.bytes.length, start + length);
|
|
48
|
+
return this.bytes.subarray(start, this.offset);
|
|
49
|
+
}
|
|
50
|
+
/** Steps over a field this app does not care about. */
|
|
51
|
+
skip(wire) {
|
|
52
|
+
if (wire === 0) {
|
|
53
|
+
this.varint();
|
|
54
|
+
}
|
|
55
|
+
else if (wire === 1) {
|
|
56
|
+
this.offset += 8;
|
|
57
|
+
}
|
|
58
|
+
else if (wire === 2) {
|
|
59
|
+
this.bytes_();
|
|
60
|
+
}
|
|
61
|
+
else if (wire === 5) {
|
|
62
|
+
this.offset += 4;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// Groups (3, 4) are not in this schema; treating one as the end of the
|
|
66
|
+
// message beats looping forever on a byte we cannot measure.
|
|
67
|
+
this.offset = this.bytes.length;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Runs `visit` over every field of a message. */
|
|
72
|
+
export function eachField(bytes, visit) {
|
|
73
|
+
const reader = new Reader(bytes);
|
|
74
|
+
while (!reader.done) {
|
|
75
|
+
const { field, wire } = reader.tag();
|
|
76
|
+
if (visit(field, wire, reader) !== true) {
|
|
77
|
+
reader.skip(wire);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=protobuf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protobuf.js","sourceRoot":"","sources":["../../src/input/protobuf.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"png.d.ts","sourceRoot":"","sources":["../../src/preview/png.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,IAAI,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAElE,qBAAa,MAAM;IAIf,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM;IAJzB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;gBAGf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACvB,UAAU,GAAE,IAAmC;IAMjD,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI;
|
|
1
|
+
{"version":3,"file":"png.d.ts","sourceRoot":"","sources":["../../src/preview/png.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,IAAI,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAElE,qBAAa,MAAM;IAIf,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM;IAJzB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;gBAGf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACvB,UAAU,GAAE,IAAmC;IAMjD,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI;IAmCrC,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI;IAQzE,+EAA+E;IAC/E,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM;IAOxE;;;;OAIG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAiB5D,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAiB7B,KAAK,IAAI,MAAM;CAGhB;AAID,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAa9C"}
|
package/dist/preview/png.js
CHANGED
|
@@ -22,12 +22,25 @@ export class Bitmap {
|
|
|
22
22
|
this.data[offset + 3] = 255;
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
// Source-over, including the alpha channel. Onto an opaque pixel this is
|
|
26
|
+
// the plain blend it always was, since the result is opaque either way.
|
|
27
|
+
// Onto a transparent one it is not: forcing the result opaque there turns
|
|
28
|
+
// a soft edge into a hard dark fringe, which is what a mask's edge is.
|
|
29
|
+
const source = color.a / 255;
|
|
30
|
+
const destination = (this.data[offset + 3] ?? 0) / 255;
|
|
31
|
+
const out = source + destination * (1 - source);
|
|
32
|
+
if (out <= 0) {
|
|
33
|
+
this.data[offset] = 0;
|
|
34
|
+
this.data[offset + 1] = 0;
|
|
35
|
+
this.data[offset + 2] = 0;
|
|
36
|
+
this.data[offset + 3] = 0;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const blend = (channel, value) => Math.round((value * source + channel * destination * (1 - source)) / out);
|
|
27
40
|
this.data[offset] = blend(this.data[offset] ?? 0, color.r);
|
|
28
41
|
this.data[offset + 1] = blend(this.data[offset + 1] ?? 0, color.g);
|
|
29
42
|
this.data[offset + 2] = blend(this.data[offset + 2] ?? 0, color.b);
|
|
30
|
-
this.data[offset + 3] = 255;
|
|
43
|
+
this.data[offset + 3] = Math.round(out * 255);
|
|
31
44
|
}
|
|
32
45
|
fillRect(x, y, width, height, color) {
|
|
33
46
|
for (let row = 0; row < height; row += 1) {
|
|
@@ -55,7 +68,10 @@ export class Bitmap {
|
|
|
55
68
|
r: source.data[offset] ?? 0,
|
|
56
69
|
g: source.data[offset + 1] ?? 0,
|
|
57
70
|
b: source.data[offset + 2] ?? 0,
|
|
58
|
-
|
|
71
|
+
// Carried through rather than forced opaque: a masked source — a
|
|
72
|
+
// circle cut out of a square, say — has to leave what is behind it
|
|
73
|
+
// showing, and `set` already blends.
|
|
74
|
+
a: source.data[offset + 3] ?? 255,
|
|
59
75
|
});
|
|
60
76
|
}
|
|
61
77
|
}
|
package/dist/preview/png.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"png.js","sourceRoot":"","sources":["../../src/preview/png.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAIhF,MAAM,OAAO,MAAM;IAIN;IACA;IAJF,IAAI,CAAa;IAE1B,YACW,KAAa,EACb,MAAc,EACvB,aAAmB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE;QAFtC,UAAK,GAAL,KAAK,CAAQ;QACb,WAAM,GAAN,MAAM,CAAQ;QAGvB,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IACjD,CAAC;IAED,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,KAAW;QACnC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3E,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,KAAK,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;YAC5B,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;YAChC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;YAChC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;YAC5B,OAAO;QACT,CAAC;QACD,MAAM,
|
|
1
|
+
{"version":3,"file":"png.js","sourceRoot":"","sources":["../../src/preview/png.ts"],"names":[],"mappings":"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"}
|
package/dist/preview/raster.d.ts
CHANGED
|
@@ -3,4 +3,12 @@ import { Bitmap } from './png.js';
|
|
|
3
3
|
export type { AnyElement };
|
|
4
4
|
export declare function renderFront(elements: AnyElement[]): Bitmap;
|
|
5
5
|
export declare function renderBack(elements: AnyElement[]): Bitmap;
|
|
6
|
+
/**
|
|
7
|
+
* Draws onto a panel that already has something on it.
|
|
8
|
+
*
|
|
9
|
+
* The device layers elements in the order they arrive, and an app that puts a
|
|
10
|
+
* picture under an outline needs the preview to agree. `renderFront` cannot,
|
|
11
|
+
* having made the bitmap itself; this can.
|
|
12
|
+
*/
|
|
13
|
+
export declare function renderOnto(bitmap: Bitmap, elements: AnyElement[], display: 'front' | 'back'): Bitmap;
|
|
6
14
|
//# sourceMappingURL=raster.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raster.d.ts","sourceRoot":"","sources":["../../src/preview/raster.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,OAAO,EAAE,MAAM,EAAyB,MAAM,OAAO,CAAC;AAEtD,YAAY,EAAE,UAAU,EAAE,CAAC;AAI3B,wBAAgB,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,CAE1D;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,CAEzD"}
|
|
1
|
+
{"version":3,"file":"raster.d.ts","sourceRoot":"","sources":["../../src/preview/raster.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,OAAO,EAAE,MAAM,EAAyB,MAAM,OAAO,CAAC;AAEtD,YAAY,EAAE,UAAU,EAAE,CAAC;AAI3B,wBAAgB,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,CAE1D;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,CAEzD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,UAAU,EAAE,EACtB,OAAO,EAAE,OAAO,GAAG,MAAM,GACxB,MAAM,CAER"}
|
package/dist/preview/raster.js
CHANGED
|
@@ -9,8 +9,20 @@ export function renderFront(elements) {
|
|
|
9
9
|
export function renderBack(elements) {
|
|
10
10
|
return render(elements, 'back', BACK.width, BACK.height, true);
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Draws onto a panel that already has something on it.
|
|
14
|
+
*
|
|
15
|
+
* The device layers elements in the order they arrive, and an app that puts a
|
|
16
|
+
* picture under an outline needs the preview to agree. `renderFront` cannot,
|
|
17
|
+
* having made the bitmap itself; this can.
|
|
18
|
+
*/
|
|
19
|
+
export function renderOnto(bitmap, elements, display) {
|
|
20
|
+
return paintAll(bitmap, elements, display, display === 'back');
|
|
21
|
+
}
|
|
12
22
|
function render(elements, display, width, height, greyscale) {
|
|
13
|
-
|
|
23
|
+
return paintAll(new Bitmap(width, height, shade(OFF_PIXEL, greyscale)), elements, display, greyscale);
|
|
24
|
+
}
|
|
25
|
+
function paintAll(bitmap, elements, display, greyscale) {
|
|
14
26
|
for (const element of elements) {
|
|
15
27
|
if (element.display !== display) {
|
|
16
28
|
continue;
|
|
@@ -38,21 +50,57 @@ function drawRectangle(bitmap, element, greyscale) {
|
|
|
38
50
|
const width = element.width ?? 0;
|
|
39
51
|
const height = element.height ?? 0;
|
|
40
52
|
const { x, y } = anchor(element.align, element.x, element.y, width, height);
|
|
53
|
+
// A radius of half the shorter side is a circle, which is how the device is
|
|
54
|
+
// asked for one. Clamped, because a larger radius has nowhere left to go.
|
|
55
|
+
const radius = Math.max(0, Math.min(element.radius ?? 0, Math.floor(Math.min(width, height) / 2)));
|
|
41
56
|
if (element.fill !== 'none') {
|
|
42
57
|
const fill = shade(parseColor(element.fill_colors?.[0] ?? '#00000000'), greyscale);
|
|
43
|
-
bitmap
|
|
58
|
+
paint(bitmap, x, y, width, height, radius, 0, fill);
|
|
44
59
|
}
|
|
45
60
|
const borderWidth = element.border_width ?? 0;
|
|
46
61
|
if (borderWidth <= 0) {
|
|
47
62
|
return;
|
|
48
63
|
}
|
|
49
64
|
const border = shade(parseColor(element.border_color ?? '#00000000'), greyscale);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
paint(bitmap, x, y, width, height, radius, borderWidth, border);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A rounded rectangle, filled or as an outline `thickness` pixels wide.
|
|
69
|
+
*
|
|
70
|
+
* Corners are measured from the centre of the corner's arc, so a radius of
|
|
71
|
+
* half the side collapses the straight edges entirely and what is left is a
|
|
72
|
+
* circle. `thickness` of zero fills; anything else keeps the ring between the
|
|
73
|
+
* outer shape and the same shape inset by that much.
|
|
74
|
+
*/
|
|
75
|
+
function paint(bitmap, x, y, width, height, radius, thickness, color) {
|
|
76
|
+
for (let row = 0; row < height; row += 1) {
|
|
77
|
+
for (let column = 0; column < width; column += 1) {
|
|
78
|
+
if (!within(column, row, width, height, radius)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (thickness > 0 &&
|
|
82
|
+
within(column - thickness, row - thickness, width - thickness * 2, height - thickness * 2, Math.max(0, radius - thickness))) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
bitmap.set(x + column, y + row, color);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Whether a pixel is inside a rounded rectangle of this size. */
|
|
90
|
+
function within(column, row, width, height, radius) {
|
|
91
|
+
if (column < 0 || row < 0 || column >= width || row >= height) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
if (radius <= 0) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
// Only the four corner squares are curved; everything else is a rectangle.
|
|
98
|
+
const dx = column < radius ? radius - column : column >= width - radius ? column - (width - radius) + 1 : 0;
|
|
99
|
+
const dy = row < radius ? radius - row : row >= height - radius ? row - (height - radius) + 1 : 0;
|
|
100
|
+
if (dx === 0 || dy === 0) {
|
|
101
|
+
return true;
|
|
55
102
|
}
|
|
103
|
+
return Math.hypot(dx, dy) <= radius + 0.5;
|
|
56
104
|
}
|
|
57
105
|
function drawText(bitmap, element, greyscale) {
|
|
58
106
|
const text = element.text ?? '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raster.js","sourceRoot":"","sources":["../../src/preview/raster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC1E,OAAO,EAAE,MAAM,EAAE,UAAU,EAAa,MAAM,OAAO,CAAC;AAItD,MAAM,SAAS,GAAS,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC;AAExD,MAAM,UAAU,WAAW,CAAC,QAAsB;IAChD,OAAO,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAsB;IAC/C,OAAO,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,MAAM,CACb,QAAsB,EACtB,OAAyB,EACzB,KAAa,EACb,MAAc,EACd,SAAkB;IAElB,
|
|
1
|
+
{"version":3,"file":"raster.js","sourceRoot":"","sources":["../../src/preview/raster.ts"],"names":[],"mappings":"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"}
|
package/dist/screen.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Bitmap } from './preview/png.js';
|
|
2
|
+
/**
|
|
3
|
+
* A photograph of a panel, as the device actually sends it.
|
|
4
|
+
*
|
|
5
|
+
* `GET /screen?display=0|1` is documented as `image/bmp`, and it is not: the
|
|
6
|
+
* body is base64 text, and what it decodes to is raw pixels with no header of
|
|
7
|
+
* any kind. Handing that to an `<img>` gets you a broken image icon, which is
|
|
8
|
+
* how this came to be written down.
|
|
9
|
+
*
|
|
10
|
+
* The two panels are not the same picture, either:
|
|
11
|
+
*
|
|
12
|
+
* - **front**, 72×16, three bytes a pixel — RGB, no alpha and no padding.
|
|
13
|
+
* - **back**, 160×80, half a byte a pixel — four bits of grey, high nibble
|
|
14
|
+
* first, which is the sixteen levels the panel actually has.
|
|
15
|
+
*/
|
|
16
|
+
export type Display = 0 | 1;
|
|
17
|
+
export declare const SCREEN: {
|
|
18
|
+
readonly 0: {
|
|
19
|
+
readonly width: 72;
|
|
20
|
+
readonly height: 16;
|
|
21
|
+
readonly bytes: number;
|
|
22
|
+
};
|
|
23
|
+
readonly 1: {
|
|
24
|
+
readonly width: 160;
|
|
25
|
+
readonly height: 80;
|
|
26
|
+
readonly bytes: number;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export declare function decodeScreenFrame(payload: string | Buffer, display: Display): Bitmap;
|
|
30
|
+
//# sourceMappingURL=screen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../src/screen.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;AAE5B,eAAO,MAAM,MAAM;;;;;;;;;;;CAGmE,CAAC;AAMvF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAWpF"}
|
package/dist/screen.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { BACK, FRONT } from './device.js';
|
|
2
|
+
import { Bitmap } from './preview/png.js';
|
|
3
|
+
export const SCREEN = {
|
|
4
|
+
0: { width: FRONT.width, height: FRONT.height, bytes: FRONT.width * FRONT.height * 3 },
|
|
5
|
+
1: { width: BACK.width, height: BACK.height, bytes: (BACK.width * BACK.height) / 2 },
|
|
6
|
+
};
|
|
7
|
+
/** Grey levels the back panel has, and the step between them at eight bits. */
|
|
8
|
+
const BACK_LEVELS = 16;
|
|
9
|
+
const BACK_STEP = 255 / (BACK_LEVELS - 1);
|
|
10
|
+
export function decodeScreenFrame(payload, display) {
|
|
11
|
+
const bytes = typeof payload === 'string' ? Buffer.from(payload, 'base64') : payload;
|
|
12
|
+
const panel = SCREEN[display];
|
|
13
|
+
if (bytes.length < panel.bytes) {
|
|
14
|
+
throw new Error(`screen ${display} came back ${bytes.length} bytes short of the ${panel.bytes} a ${panel.width}×${panel.height} frame needs`);
|
|
15
|
+
}
|
|
16
|
+
return display === 0 ? front(bytes) : back(bytes);
|
|
17
|
+
}
|
|
18
|
+
function front(bytes) {
|
|
19
|
+
const { width, height } = SCREEN[0];
|
|
20
|
+
const bitmap = new Bitmap(width, height);
|
|
21
|
+
for (let pixel = 0; pixel < width * height; pixel += 1) {
|
|
22
|
+
const offset = pixel * 3;
|
|
23
|
+
bitmap.set(pixel % width, Math.floor(pixel / width), {
|
|
24
|
+
r: bytes[offset] ?? 0,
|
|
25
|
+
g: bytes[offset + 1] ?? 0,
|
|
26
|
+
b: bytes[offset + 2] ?? 0,
|
|
27
|
+
a: 255,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return bitmap;
|
|
31
|
+
}
|
|
32
|
+
function back(bytes) {
|
|
33
|
+
const { width, height } = SCREEN[1];
|
|
34
|
+
const bitmap = new Bitmap(width, height);
|
|
35
|
+
for (let pixel = 0; pixel < width * height; pixel += 1) {
|
|
36
|
+
const byte = bytes[pixel >> 1] ?? 0;
|
|
37
|
+
// Two pixels to a byte, the left-hand one in the high nibble.
|
|
38
|
+
const level = pixel % 2 === 0 ? (byte >> 4) & 0xf : byte & 0xf;
|
|
39
|
+
const value = Math.round(level * BACK_STEP);
|
|
40
|
+
bitmap.set(pixel % width, Math.floor(pixel / width), {
|
|
41
|
+
r: value,
|
|
42
|
+
g: value,
|
|
43
|
+
b: value,
|
|
44
|
+
a: 255,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return bitmap;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen.js","sourceRoot":"","sources":["../src/screen.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "busybar-kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Shared building blocks for BUSY Bar apps: device geometry, colours, formatters, ticker text, error taxonomy and an offline PNG preview renderer",
|
|
5
5
|
"author": "viirtualp1",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,8 +27,10 @@
|
|
|
27
27
|
"./errors": "./dist/errors.js",
|
|
28
28
|
"./format": "./dist/format.js",
|
|
29
29
|
"./image": "./dist/image/index.js",
|
|
30
|
+
"./input": "./dist/input/index.js",
|
|
30
31
|
"./preview": "./dist/preview/index.js",
|
|
31
32
|
"./profile": "./dist/profile.js",
|
|
33
|
+
"./screen": "./dist/screen.js",
|
|
32
34
|
"./ticker": "./dist/ticker/index.js",
|
|
33
35
|
"./tsconfig.json": "./configs/tsconfig.base.json",
|
|
34
36
|
"./eslint": "./configs/eslint.config.js",
|
|
@@ -59,6 +61,7 @@
|
|
|
59
61
|
"scripts": {
|
|
60
62
|
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
61
63
|
"build": "npm run clean && tsc -p tsconfig.build.json && node scripts/fix-esm-extensions.mjs",
|
|
64
|
+
"prepack": "npm run build",
|
|
62
65
|
"typecheck": "tsc -p tsconfig.json",
|
|
63
66
|
"lint": "eslint .",
|
|
64
67
|
"lint:fix": "eslint . --fix",
|