@tldraw/tlschema 4.3.0-canary.fda2775019a1 → 4.3.0-next.085293d79c32
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-cjs/index.d.ts +33 -25
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/misc/b64Vecs.js +166 -80
- package/dist-cjs/misc/b64Vecs.js.map +2 -2
- package/dist-cjs/shapes/TLDrawShape.js +33 -12
- package/dist-cjs/shapes/TLDrawShape.js.map +2 -2
- package/dist-cjs/shapes/TLHighlightShape.js +30 -9
- package/dist-cjs/shapes/TLHighlightShape.js.map +2 -2
- package/dist-esm/index.d.mts +33 -25
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/misc/b64Vecs.mjs +166 -80
- package/dist-esm/misc/b64Vecs.mjs.map +2 -2
- package/dist-esm/shapes/TLDrawShape.mjs +33 -12
- package/dist-esm/shapes/TLDrawShape.mjs.map +2 -2
- package/dist-esm/shapes/TLHighlightShape.mjs +30 -9
- package/dist-esm/shapes/TLHighlightShape.mjs.map +2 -2
- package/package.json +5 -5
- package/src/migrations.test.ts +246 -60
- package/src/misc/b64Vecs.test.ts +480 -0
- package/src/misc/b64Vecs.ts +245 -123
- package/src/shapes/TLDrawShape.ts +46 -19
- package/src/shapes/TLHighlightShape.ts +36 -13
package/dist-cjs/index.d.ts
CHANGED
|
@@ -308,47 +308,51 @@ export declare const assetValidator: T.Validator<TLAsset>;
|
|
|
308
308
|
* @public
|
|
309
309
|
*/
|
|
310
310
|
export declare class b64Vecs {
|
|
311
|
+
/* Excluded from this release type: _legacyEncodePoint */
|
|
312
|
+
/* Excluded from this release type: _legacyEncodePoints */
|
|
313
|
+
/* Excluded from this release type: _legacyDecodePoints */
|
|
311
314
|
/**
|
|
312
|
-
* Encode
|
|
313
|
-
*
|
|
315
|
+
* Encode an array of VecModels using delta encoding for improved precision.
|
|
316
|
+
* The first point is stored as Float32 (high precision for absolute position),
|
|
317
|
+
* subsequent points are stored as Float16 deltas from the previous point.
|
|
318
|
+
* This provides full precision for the starting position and excellent precision
|
|
319
|
+
* for deltas between consecutive points (which are typically small values).
|
|
314
320
|
*
|
|
315
|
-
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
* @returns An 8-character base64 string representing the point
|
|
319
|
-
*/
|
|
320
|
-
static encodePoint(x: number, y: number, z: number): string;
|
|
321
|
-
/**
|
|
322
|
-
* Convert an array of VecModels to a base64 string for compact storage.
|
|
323
|
-
* Uses Float16 encoding for each coordinate (x, y, z). If a point's z value is
|
|
324
|
-
* undefined, it defaults to 0.5.
|
|
321
|
+
* Format:
|
|
322
|
+
* - First point: 3 Float32 values = 12 bytes = 16 base64 chars
|
|
323
|
+
* - Delta points: 3 Float16 values each = 6 bytes = 8 base64 chars each
|
|
325
324
|
*
|
|
326
325
|
* @param points - An array of VecModel objects to encode
|
|
327
|
-
* @returns A base64-encoded string containing
|
|
326
|
+
* @returns A base64-encoded string containing delta-encoded points
|
|
327
|
+
* @public
|
|
328
328
|
*/
|
|
329
329
|
static encodePoints(points: VecModel[]): string;
|
|
330
330
|
/**
|
|
331
|
-
*
|
|
332
|
-
*
|
|
331
|
+
* Decode a delta-encoded base64 string back to an array of absolute VecModels.
|
|
332
|
+
* The first point is stored as Float32 (high precision), subsequent points are
|
|
333
|
+
* Float16 deltas that are accumulated to reconstruct absolute positions.
|
|
333
334
|
*
|
|
334
|
-
* @param base64 - The base64-encoded string containing point data
|
|
335
|
-
* @returns An array of VecModel objects
|
|
335
|
+
* @param base64 - The base64-encoded string containing delta-encoded point data
|
|
336
|
+
* @returns An array of VecModel objects with absolute coordinates
|
|
337
|
+
* @public
|
|
336
338
|
*/
|
|
337
339
|
static decodePoints(base64: string): VecModel[];
|
|
338
|
-
/* Excluded from this release type: decodePointAt */
|
|
339
340
|
/**
|
|
340
|
-
* Get the first point from a
|
|
341
|
+
* Get the first point from a delta-encoded base64 string.
|
|
342
|
+
* The first point is stored as Float32 for full precision.
|
|
341
343
|
*
|
|
342
|
-
* @param b64Points - The
|
|
344
|
+
* @param b64Points - The delta-encoded base64 string
|
|
343
345
|
* @returns The first point as a VecModel, or null if the string is too short
|
|
344
346
|
* @public
|
|
345
347
|
*/
|
|
346
348
|
static decodeFirstPoint(b64Points: string): null | VecModel;
|
|
347
349
|
/**
|
|
348
|
-
* Get the last point from a
|
|
350
|
+
* Get the last point from a delta-encoded base64 string.
|
|
351
|
+
* Requires decoding all points to accumulate deltas.
|
|
349
352
|
*
|
|
350
|
-
* @param b64Points - The
|
|
353
|
+
* @param b64Points - The delta-encoded base64 string
|
|
351
354
|
* @returns The last point as a VecModel, or null if the string is too short
|
|
355
|
+
* @public
|
|
352
356
|
*/
|
|
353
357
|
static decodeLastPoint(b64Points: string): null | VecModel;
|
|
354
358
|
}
|
|
@@ -481,8 +485,9 @@ export declare const CameraRecordType: RecordType<TLCamera, never>;
|
|
|
481
485
|
export declare const canvasUiColorTypeValidator: T.Validator<"accent" | "black" | "laser" | "muted-1" | "selection-fill" | "selection-stroke" | "white">;
|
|
482
486
|
|
|
483
487
|
/**
|
|
484
|
-
* Compress legacy draw shape segments by converting VecModel[] points to base64 format.
|
|
488
|
+
* Compress legacy draw shape segments by converting VecModel[] points to delta-encoded base64 format.
|
|
485
489
|
* This function is useful for converting old draw shape data to the new compressed format.
|
|
490
|
+
* Uses delta encoding for improved Float16 precision.
|
|
486
491
|
*
|
|
487
492
|
* @public
|
|
488
493
|
*/
|
|
@@ -4215,8 +4220,11 @@ export declare interface TLDrawShapeProps {
|
|
|
4215
4220
|
export declare interface TLDrawShapeSegment {
|
|
4216
4221
|
/** Type of drawing segment - 'free' for freehand curves, 'straight' for line segments */
|
|
4217
4222
|
type: 'free' | 'straight';
|
|
4218
|
-
/**
|
|
4219
|
-
|
|
4223
|
+
/**
|
|
4224
|
+
* Delta-encoded base64 path data.
|
|
4225
|
+
* First point stored as Float32 (12 bytes) for precision, subsequent points as Float16 deltas (6 bytes each).
|
|
4226
|
+
*/
|
|
4227
|
+
path: string;
|
|
4220
4228
|
}
|
|
4221
4229
|
|
|
4222
4230
|
/**
|
package/dist-cjs/index.js
CHANGED
|
@@ -181,7 +181,7 @@ var import_translations = require("./translations/translations");
|
|
|
181
181
|
var import_b64Vecs = require("./misc/b64Vecs");
|
|
182
182
|
(0, import_utils.registerTldrawLibraryVersion)(
|
|
183
183
|
"@tldraw/tlschema",
|
|
184
|
-
"4.3.0-
|
|
184
|
+
"4.3.0-next.085293d79c32",
|
|
185
185
|
"cjs"
|
|
186
186
|
);
|
|
187
187
|
//# sourceMappingURL=index.js.map
|
package/dist-cjs/misc/b64Vecs.js
CHANGED
|
@@ -18,10 +18,16 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var b64Vecs_exports = {};
|
|
20
20
|
__export(b64Vecs_exports, {
|
|
21
|
-
b64Vecs: () => b64Vecs
|
|
21
|
+
b64Vecs: () => b64Vecs,
|
|
22
|
+
fallbackBase64ToUint8Array: () => fallbackBase64ToUint8Array,
|
|
23
|
+
fallbackUint8ArrayToBase64: () => fallbackUint8ArrayToBase64,
|
|
24
|
+
float16BitsToNumber: () => float16BitsToNumber,
|
|
25
|
+
numberToFloat16Bits: () => numberToFloat16Bits
|
|
22
26
|
});
|
|
23
27
|
module.exports = __toCommonJS(b64Vecs_exports);
|
|
24
|
-
|
|
28
|
+
var import_utils = require("@tldraw/utils");
|
|
29
|
+
const _POINT_B64_LENGTH = 8;
|
|
30
|
+
const FIRST_POINT_B64_LENGTH = 16;
|
|
25
31
|
const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
26
32
|
const B64_LOOKUP = new Uint8Array(128);
|
|
27
33
|
for (let i = 0; i < 64; i++) {
|
|
@@ -36,23 +42,25 @@ const MANTISSA = new Float64Array(1024);
|
|
|
36
42
|
for (let i = 0; i < 1024; i++) {
|
|
37
43
|
MANTISSA[i] = 1 + i / 1024;
|
|
38
44
|
}
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
function nativeGetFloat16(dataView, offset) {
|
|
46
|
+
return dataView.getFloat16(offset, true);
|
|
47
|
+
}
|
|
48
|
+
function fallbackGetFloat16(dataView, offset) {
|
|
49
|
+
return float16BitsToNumber(dataView.getUint16(offset, true));
|
|
50
|
+
}
|
|
51
|
+
const getFloat16 = typeof DataView.prototype.getFloat16 === "function" ? nativeGetFloat16 : fallbackGetFloat16;
|
|
52
|
+
function nativeSetFloat16(dataView, offset, value) {
|
|
53
|
+
;
|
|
54
|
+
dataView.setFloat16(offset, value, true);
|
|
55
|
+
}
|
|
56
|
+
function fallbackSetFloat16(dataView, offset, value) {
|
|
57
|
+
dataView.setUint16(offset, numberToFloat16Bits(value), true);
|
|
58
|
+
}
|
|
59
|
+
const setFloat16 = typeof DataView.prototype.setFloat16 === "function" ? nativeSetFloat16 : fallbackSetFloat16;
|
|
60
|
+
function nativeBase64ToUint8Array(base64) {
|
|
61
|
+
return Uint8Array.fromBase64(base64);
|
|
54
62
|
}
|
|
55
|
-
function
|
|
63
|
+
function fallbackBase64ToUint8Array(base64) {
|
|
56
64
|
const numBytes = Math.floor(base64.length * 3 / 4);
|
|
57
65
|
const bytes = new Uint8Array(numBytes);
|
|
58
66
|
let byteIndex = 0;
|
|
@@ -66,8 +74,25 @@ function base64ToUint16Array(base64) {
|
|
|
66
74
|
bytes[byteIndex++] = bitmap >> 8 & 255;
|
|
67
75
|
bytes[byteIndex++] = bitmap & 255;
|
|
68
76
|
}
|
|
69
|
-
return
|
|
77
|
+
return bytes;
|
|
70
78
|
}
|
|
79
|
+
function nativeUint8ArrayToBase64(uint8Array) {
|
|
80
|
+
return uint8Array.toBase64();
|
|
81
|
+
}
|
|
82
|
+
function fallbackUint8ArrayToBase64(uint8Array) {
|
|
83
|
+
(0, import_utils.assert)(uint8Array.length % 3 === 0, "Uint8Array length must be a multiple of 3");
|
|
84
|
+
let result = "";
|
|
85
|
+
for (let i = 0; i < uint8Array.length; i += 3) {
|
|
86
|
+
const byte1 = uint8Array[i];
|
|
87
|
+
const byte2 = uint8Array[i + 1];
|
|
88
|
+
const byte3 = uint8Array[i + 2];
|
|
89
|
+
const bitmap = byte1 << 16 | byte2 << 8 | byte3;
|
|
90
|
+
result += BASE64_CHARS[bitmap >> 18 & 63] + BASE64_CHARS[bitmap >> 12 & 63] + BASE64_CHARS[bitmap >> 6 & 63] + BASE64_CHARS[bitmap & 63];
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
const uint8ArrayToBase64 = typeof Uint8Array.prototype.toBase64 === "function" ? nativeUint8ArrayToBase64 : fallbackUint8ArrayToBase64;
|
|
95
|
+
const base64ToUint8Array = typeof Uint8Array.fromBase64 === "function" ? nativeBase64ToUint8Array : fallbackBase64ToUint8Array;
|
|
71
96
|
function float16BitsToNumber(bits) {
|
|
72
97
|
const sign = bits >> 15;
|
|
73
98
|
const exp = bits >> 10 & 31;
|
|
@@ -111,114 +136,175 @@ function numberToFloat16Bits(value) {
|
|
|
111
136
|
}
|
|
112
137
|
class b64Vecs {
|
|
113
138
|
/**
|
|
114
|
-
* Encode a single point (x, y, z) to 8 base64 characters.
|
|
139
|
+
* Encode a single point (x, y, z) to 8 base64 characters using legacy Float16 encoding.
|
|
115
140
|
* Each coordinate is encoded as a Float16 value, resulting in 6 bytes total.
|
|
116
141
|
*
|
|
117
142
|
* @param x - The x coordinate
|
|
118
143
|
* @param y - The y coordinate
|
|
119
144
|
* @param z - The z coordinate
|
|
120
145
|
* @returns An 8-character base64 string representing the point
|
|
146
|
+
* @internal
|
|
121
147
|
*/
|
|
122
|
-
static
|
|
123
|
-
const
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const b3 = yBits >> 8 & 255;
|
|
130
|
-
const b4 = zBits & 255;
|
|
131
|
-
const b5 = zBits >> 8 & 255;
|
|
132
|
-
const bitmap1 = b0 << 16 | b1 << 8 | b2;
|
|
133
|
-
const bitmap2 = b3 << 16 | b4 << 8 | b5;
|
|
134
|
-
return BASE64_CHARS[bitmap1 >> 18 & 63] + BASE64_CHARS[bitmap1 >> 12 & 63] + BASE64_CHARS[bitmap1 >> 6 & 63] + BASE64_CHARS[bitmap1 & 63] + BASE64_CHARS[bitmap2 >> 18 & 63] + BASE64_CHARS[bitmap2 >> 12 & 63] + BASE64_CHARS[bitmap2 >> 6 & 63] + BASE64_CHARS[bitmap2 & 63];
|
|
148
|
+
static _legacyEncodePoint(x, y, z) {
|
|
149
|
+
const buffer = new Uint8Array(6);
|
|
150
|
+
const dataView = new DataView(buffer.buffer);
|
|
151
|
+
setFloat16(dataView, 0, x);
|
|
152
|
+
setFloat16(dataView, 2, y);
|
|
153
|
+
setFloat16(dataView, 4, z);
|
|
154
|
+
return uint8ArrayToBase64(buffer);
|
|
135
155
|
}
|
|
136
156
|
/**
|
|
137
|
-
* Convert an array of VecModels to a base64 string
|
|
157
|
+
* Convert an array of VecModels to a base64 string using legacy Float16 encoding.
|
|
138
158
|
* Uses Float16 encoding for each coordinate (x, y, z). If a point's z value is
|
|
139
159
|
* undefined, it defaults to 0.5.
|
|
140
160
|
*
|
|
141
161
|
* @param points - An array of VecModel objects to encode
|
|
142
162
|
* @returns A base64-encoded string containing all points
|
|
163
|
+
* @internal Used only for migrations from legacy format
|
|
143
164
|
*/
|
|
144
|
-
static
|
|
145
|
-
|
|
165
|
+
static _legacyEncodePoints(points) {
|
|
166
|
+
if (points.length === 0) return "";
|
|
167
|
+
const buffer = new Uint8Array(points.length * 6);
|
|
168
|
+
const dataView = new DataView(buffer.buffer);
|
|
146
169
|
for (let i = 0; i < points.length; i++) {
|
|
147
170
|
const p = points[i];
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
171
|
+
const offset = i * 6;
|
|
172
|
+
setFloat16(dataView, offset, p.x);
|
|
173
|
+
setFloat16(dataView, offset + 2, p.y);
|
|
174
|
+
setFloat16(dataView, offset + 4, p.z ?? 0.5);
|
|
151
175
|
}
|
|
152
|
-
return
|
|
176
|
+
return uint8ArrayToBase64(buffer);
|
|
153
177
|
}
|
|
154
178
|
/**
|
|
155
|
-
* Convert a base64 string back to an array of VecModels.
|
|
179
|
+
* Convert a legacy base64 string back to an array of VecModels.
|
|
156
180
|
* Decodes Float16-encoded coordinates (x, y, z) from the base64 string.
|
|
157
181
|
*
|
|
158
182
|
* @param base64 - The base64-encoded string containing point data
|
|
159
183
|
* @returns An array of VecModel objects decoded from the string
|
|
184
|
+
* @internal Used only for migrations from legacy format
|
|
160
185
|
*/
|
|
161
|
-
static
|
|
162
|
-
const
|
|
186
|
+
static _legacyDecodePoints(base64) {
|
|
187
|
+
const bytes = base64ToUint8Array(base64);
|
|
188
|
+
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
163
189
|
const result = [];
|
|
164
|
-
for (let
|
|
190
|
+
for (let offset = 0; offset < bytes.length; offset += 6) {
|
|
165
191
|
result.push({
|
|
166
|
-
x:
|
|
167
|
-
y:
|
|
168
|
-
z:
|
|
192
|
+
x: getFloat16(dataView, offset),
|
|
193
|
+
y: getFloat16(dataView, offset + 2),
|
|
194
|
+
z: getFloat16(dataView, offset + 4)
|
|
169
195
|
});
|
|
170
196
|
}
|
|
171
197
|
return result;
|
|
172
198
|
}
|
|
173
199
|
/**
|
|
174
|
-
*
|
|
175
|
-
*
|
|
200
|
+
* Encode an array of VecModels using delta encoding for improved precision.
|
|
201
|
+
* The first point is stored as Float32 (high precision for absolute position),
|
|
202
|
+
* subsequent points are stored as Float16 deltas from the previous point.
|
|
203
|
+
* This provides full precision for the starting position and excellent precision
|
|
204
|
+
* for deltas between consecutive points (which are typically small values).
|
|
176
205
|
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
206
|
+
* Format:
|
|
207
|
+
* - First point: 3 Float32 values = 12 bytes = 16 base64 chars
|
|
208
|
+
* - Delta points: 3 Float16 values each = 6 bytes = 8 base64 chars each
|
|
209
|
+
*
|
|
210
|
+
* @param points - An array of VecModel objects to encode
|
|
211
|
+
* @returns A base64-encoded string containing delta-encoded points
|
|
212
|
+
* @public
|
|
181
213
|
*/
|
|
182
|
-
static
|
|
183
|
-
|
|
184
|
-
const
|
|
185
|
-
const
|
|
186
|
-
const
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
214
|
+
static encodePoints(points) {
|
|
215
|
+
if (points.length === 0) return "";
|
|
216
|
+
const firstPointBytes = 12;
|
|
217
|
+
const deltaBytes = (points.length - 1) * 6;
|
|
218
|
+
const totalBytes = firstPointBytes + deltaBytes;
|
|
219
|
+
const buffer = new Uint8Array(totalBytes);
|
|
220
|
+
const dataView = new DataView(buffer.buffer);
|
|
221
|
+
const first = points[0];
|
|
222
|
+
dataView.setFloat32(0, first.x, true);
|
|
223
|
+
dataView.setFloat32(4, first.y, true);
|
|
224
|
+
dataView.setFloat32(8, first.z ?? 0.5, true);
|
|
225
|
+
let prevX = first.x;
|
|
226
|
+
let prevY = first.y;
|
|
227
|
+
let prevZ = first.z ?? 0.5;
|
|
228
|
+
for (let i = 1; i < points.length; i++) {
|
|
229
|
+
const p = points[i];
|
|
230
|
+
const z = p.z ?? 0.5;
|
|
231
|
+
const offset = firstPointBytes + (i - 1) * 6;
|
|
232
|
+
setFloat16(dataView, offset, p.x - prevX);
|
|
233
|
+
setFloat16(dataView, offset + 2, p.y - prevY);
|
|
234
|
+
setFloat16(dataView, offset + 4, z - prevZ);
|
|
235
|
+
prevX = p.x;
|
|
236
|
+
prevY = p.y;
|
|
237
|
+
prevZ = z;
|
|
238
|
+
}
|
|
239
|
+
return uint8ArrayToBase64(buffer);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Decode a delta-encoded base64 string back to an array of absolute VecModels.
|
|
243
|
+
* The first point is stored as Float32 (high precision), subsequent points are
|
|
244
|
+
* Float16 deltas that are accumulated to reconstruct absolute positions.
|
|
245
|
+
*
|
|
246
|
+
* @param base64 - The base64-encoded string containing delta-encoded point data
|
|
247
|
+
* @returns An array of VecModel objects with absolute coordinates
|
|
248
|
+
* @public
|
|
249
|
+
*/
|
|
250
|
+
static decodePoints(base64) {
|
|
251
|
+
if (base64.length === 0) return [];
|
|
252
|
+
const bytes = base64ToUint8Array(base64);
|
|
253
|
+
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
254
|
+
const result = [];
|
|
255
|
+
let x = dataView.getFloat32(0, true);
|
|
256
|
+
let y = dataView.getFloat32(4, true);
|
|
257
|
+
let z = dataView.getFloat32(8, true);
|
|
258
|
+
result.push({ x, y, z });
|
|
259
|
+
const firstPointBytes = 12;
|
|
260
|
+
for (let offset = firstPointBytes; offset < bytes.length; offset += 6) {
|
|
261
|
+
x += getFloat16(dataView, offset);
|
|
262
|
+
y += getFloat16(dataView, offset + 2);
|
|
263
|
+
z += getFloat16(dataView, offset + 4);
|
|
264
|
+
result.push({ x, y, z });
|
|
265
|
+
}
|
|
266
|
+
return result;
|
|
201
267
|
}
|
|
202
268
|
/**
|
|
203
|
-
* Get the first point from a
|
|
269
|
+
* Get the first point from a delta-encoded base64 string.
|
|
270
|
+
* The first point is stored as Float32 for full precision.
|
|
204
271
|
*
|
|
205
|
-
* @param b64Points - The
|
|
272
|
+
* @param b64Points - The delta-encoded base64 string
|
|
206
273
|
* @returns The first point as a VecModel, or null if the string is too short
|
|
207
274
|
* @public
|
|
208
275
|
*/
|
|
209
276
|
static decodeFirstPoint(b64Points) {
|
|
210
|
-
if (b64Points.length <
|
|
211
|
-
|
|
277
|
+
if (b64Points.length < FIRST_POINT_B64_LENGTH) return null;
|
|
278
|
+
const bytes = base64ToUint8Array(b64Points.slice(0, FIRST_POINT_B64_LENGTH));
|
|
279
|
+
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
280
|
+
return {
|
|
281
|
+
x: dataView.getFloat32(0, true),
|
|
282
|
+
y: dataView.getFloat32(4, true),
|
|
283
|
+
z: dataView.getFloat32(8, true)
|
|
284
|
+
};
|
|
212
285
|
}
|
|
213
286
|
/**
|
|
214
|
-
* Get the last point from a
|
|
287
|
+
* Get the last point from a delta-encoded base64 string.
|
|
288
|
+
* Requires decoding all points to accumulate deltas.
|
|
215
289
|
*
|
|
216
|
-
* @param b64Points - The
|
|
290
|
+
* @param b64Points - The delta-encoded base64 string
|
|
217
291
|
* @returns The last point as a VecModel, or null if the string is too short
|
|
292
|
+
* @public
|
|
218
293
|
*/
|
|
219
294
|
static decodeLastPoint(b64Points) {
|
|
220
|
-
if (b64Points.length <
|
|
221
|
-
|
|
295
|
+
if (b64Points.length < FIRST_POINT_B64_LENGTH) return null;
|
|
296
|
+
const bytes = base64ToUint8Array(b64Points);
|
|
297
|
+
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
298
|
+
let x = dataView.getFloat32(0, true);
|
|
299
|
+
let y = dataView.getFloat32(4, true);
|
|
300
|
+
let z = dataView.getFloat32(8, true);
|
|
301
|
+
const firstPointBytes = 12;
|
|
302
|
+
for (let offset = firstPointBytes; offset < bytes.length; offset += 6) {
|
|
303
|
+
x += getFloat16(dataView, offset);
|
|
304
|
+
y += getFloat16(dataView, offset + 2);
|
|
305
|
+
z += getFloat16(dataView, offset + 4);
|
|
306
|
+
}
|
|
307
|
+
return { x, y, z };
|
|
222
308
|
}
|
|
223
309
|
}
|
|
224
310
|
//# sourceMappingURL=b64Vecs.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/misc/b64Vecs.ts"],
|
|
4
|
-
"sourcesContent": ["import { VecModel } from './geometry-types'\n\n// Each point = 3 Float16s = 6 bytes = 8 base64 chars\nconst POINT_B64_LENGTH = 8\n\n// O(1) lookup table for base64 decoding (maps char code -> 6-bit value)\nconst BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nconst B64_LOOKUP = new Uint8Array(128)\nfor (let i = 0; i < 64; i++) {\n\tB64_LOOKUP[BASE64_CHARS.charCodeAt(i)] = i\n}\n\n// Precomputed powers of 2 for Float16 exponents (exp - 15, so indices 0-30 map to 2^-15 to 2^15)\nconst POW2 = new Float64Array(31)\nfor (let i = 0; i < 31; i++) {\n\tPOW2[i] = Math.pow(2, i - 15)\n}\nconst POW2_SUBNORMAL = Math.pow(2, -14) / 1024 // For subnormal numbers\n\n// Precomputed mantissa values: 1 + frac/1024 for all 1024 possible frac values\n// Avoids division in hot path\nconst MANTISSA = new Float64Array(1024)\nfor (let i = 0; i < 1024; i++) {\n\tMANTISSA[i] = 1 + i / 1024\n}\n\n/**\n * Convert a Uint16Array (containing Float16 bits) to base64.\n * Processes bytes in groups of 3 to produce 4 base64 characters.\n *\n * @internal\n */\nfunction uint16ArrayToBase64(uint16Array: Uint16Array): string {\n\tconst uint8Array = new Uint8Array(\n\t\tuint16Array.buffer,\n\t\tuint16Array.byteOffset,\n\t\tuint16Array.byteLength\n\t)\n\tlet result = ''\n\n\t// Process bytes in groups of 3 -> 4 base64 chars\n\tfor (let i = 0; i < uint8Array.length; i += 3) {\n\t\tconst byte1 = uint8Array[i]\n\t\tconst byte2 = uint8Array[i + 1] // Always exists for our use case (multiple of 6 bytes)\n\t\tconst byte3 = uint8Array[i + 2]\n\n\t\tconst bitmap = (byte1 << 16) | (byte2 << 8) | byte3\n\t\tresult +=\n\t\t\tBASE64_CHARS[(bitmap >> 18) & 63] +\n\t\t\tBASE64_CHARS[(bitmap >> 12) & 63] +\n\t\t\tBASE64_CHARS[(bitmap >> 6) & 63] +\n\t\t\tBASE64_CHARS[bitmap & 63]\n\t}\n\n\treturn result\n}\n\n/**\n * Convert a base64 string to Uint16Array containing Float16 bits.\n * The base64 string must have a length that is a multiple of 4.\n *\n * @param base64 - The base64-encoded string to decode\n * @returns A Uint16Array containing the decoded Float16 bit values\n * @public\n */\nfunction base64ToUint16Array(base64: string): Uint16Array {\n\t// Calculate exact number of bytes (4 base64 chars = 3 bytes)\n\tconst numBytes = Math.floor((base64.length * 3) / 4)\n\tconst bytes = new Uint8Array(numBytes)\n\tlet byteIndex = 0\n\n\t// Process in groups of 4 base64 characters\n\tfor (let i = 0; i < base64.length; i += 4) {\n\t\tconst c0 = B64_LOOKUP[base64.charCodeAt(i)]\n\t\tconst c1 = B64_LOOKUP[base64.charCodeAt(i + 1)]\n\t\tconst c2 = B64_LOOKUP[base64.charCodeAt(i + 2)]\n\t\tconst c3 = B64_LOOKUP[base64.charCodeAt(i + 3)]\n\n\t\tconst bitmap = (c0 << 18) | (c1 << 12) | (c2 << 6) | c3\n\n\t\tbytes[byteIndex++] = (bitmap >> 16) & 255\n\t\tbytes[byteIndex++] = (bitmap >> 8) & 255\n\t\tbytes[byteIndex++] = bitmap & 255\n\t}\n\n\treturn new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 2)\n}\n\n/**\n * Convert Float16 bits to a number using optimized lookup tables.\n * Handles normal numbers, subnormal numbers, zero, infinity, and NaN.\n *\n * @param bits - The 16-bit Float16 value to decode\n * @returns The decoded number value\n */\nfunction float16BitsToNumber(bits: number): number {\n\tconst sign = bits >> 15\n\tconst exp = (bits >> 10) & 0x1f\n\tconst frac = bits & 0x3ff\n\n\tif (exp === 0) {\n\t\t// Subnormal or zero - rare case\n\t\treturn sign ? -frac * POW2_SUBNORMAL : frac * POW2_SUBNORMAL\n\t}\n\tif (exp === 31) {\n\t\t// Infinity or NaN - very rare\n\t\treturn frac ? NaN : sign ? -Infinity : Infinity\n\t}\n\t// Normal case - two table lookups, one multiply, no division\n\tconst magnitude = POW2[exp] * MANTISSA[frac]\n\treturn sign ? -magnitude : magnitude\n}\n\n/**\n * Convert a number to Float16 bits.\n * Handles normal numbers, subnormal numbers, zero, infinity, and NaN.\n *\n * @param value - The number to encode as Float16\n * @returns The 16-bit Float16 representation of the number\n * @internal\n */\nfunction numberToFloat16Bits(value: number): number {\n\tif (value === 0) return Object.is(value, -0) ? 0x8000 : 0\n\tif (!Number.isFinite(value)) {\n\t\tif (Number.isNaN(value)) return 0x7e00\n\t\treturn value > 0 ? 0x7c00 : 0xfc00\n\t}\n\n\tconst sign = value < 0 ? 1 : 0\n\tvalue = Math.abs(value)\n\n\t// Find exponent and mantissa\n\tconst exp = Math.floor(Math.log2(value))\n\tlet expBiased = exp + 15\n\n\tif (expBiased >= 31) {\n\t\t// Overflow to infinity\n\t\treturn (sign << 15) | 0x7c00\n\t}\n\tif (expBiased <= 0) {\n\t\t// Subnormal or underflow\n\t\tconst frac = Math.round(value * Math.pow(2, 14) * 1024)\n\t\treturn (sign << 15) | (frac & 0x3ff)\n\t}\n\n\t// Normal number\n\tconst mantissa = value / Math.pow(2, exp) - 1\n\tlet frac = Math.round(mantissa * 1024)\n\n\t// Handle rounding overflow: if frac rounds to 1024, increment exponent\n\tif (frac >= 1024) {\n\t\tfrac = 0\n\t\texpBiased++\n\t\tif (expBiased >= 31) {\n\t\t\t// Overflow to infinity\n\t\t\treturn (sign << 15) | 0x7c00\n\t\t}\n\t}\n\n\treturn (sign << 15) | (expBiased << 10) | frac\n}\n\n/**\n * Utilities for encoding and decoding points using base64 and Float16 encoding.\n * Provides functions for converting between VecModel arrays and compact base64 strings,\n * as well as individual point encoding/decoding operations.\n *\n * @public\n */\nexport class b64Vecs {\n\t/**\n\t * Encode a single point (x, y, z) to 8 base64 characters.\n\t * Each coordinate is encoded as a Float16 value, resulting in 6 bytes total.\n\t *\n\t * @param x - The x coordinate\n\t * @param y - The y coordinate\n\t * @param z - The z coordinate\n\t * @returns An 8-character base64 string representing the point\n\t */\n\tstatic encodePoint(x: number, y: number, z: number): string {\n\t\tconst xBits = numberToFloat16Bits(x)\n\t\tconst yBits = numberToFloat16Bits(y)\n\t\tconst zBits = numberToFloat16Bits(z)\n\n\t\t// Convert Float16 bits to 6 bytes (little-endian)\n\t\tconst b0 = xBits & 0xff\n\t\tconst b1 = (xBits >> 8) & 0xff\n\t\tconst b2 = yBits & 0xff\n\t\tconst b3 = (yBits >> 8) & 0xff\n\t\tconst b4 = zBits & 0xff\n\t\tconst b5 = (zBits >> 8) & 0xff\n\n\t\t// Convert 6 bytes to 8 base64 chars\n\t\tconst bitmap1 = (b0 << 16) | (b1 << 8) | b2\n\t\tconst bitmap2 = (b3 << 16) | (b4 << 8) | b5\n\n\t\treturn (\n\t\t\tBASE64_CHARS[(bitmap1 >> 18) & 0x3f] +\n\t\t\tBASE64_CHARS[(bitmap1 >> 12) & 0x3f] +\n\t\t\tBASE64_CHARS[(bitmap1 >> 6) & 0x3f] +\n\t\t\tBASE64_CHARS[bitmap1 & 0x3f] +\n\t\t\tBASE64_CHARS[(bitmap2 >> 18) & 0x3f] +\n\t\t\tBASE64_CHARS[(bitmap2 >> 12) & 0x3f] +\n\t\t\tBASE64_CHARS[(bitmap2 >> 6) & 0x3f] +\n\t\t\tBASE64_CHARS[bitmap2 & 0x3f]\n\t\t)\n\t}\n\n\t/**\n\t * Convert an array of VecModels to a base64 string for compact storage.\n\t * Uses Float16 encoding for each coordinate (x, y, z). If a point's z value is\n\t * undefined, it defaults to 0.5.\n\t *\n\t * @param points - An array of VecModel objects to encode\n\t * @returns A base64-encoded string containing all points\n\t */\n\tstatic encodePoints(points: VecModel[]): string {\n\t\tconst uint16s = new Uint16Array(points.length * 3)\n\t\tfor (let i = 0; i < points.length; i++) {\n\t\t\tconst p = points[i]\n\t\t\tuint16s[i * 3] = numberToFloat16Bits(p.x)\n\t\t\tuint16s[i * 3 + 1] = numberToFloat16Bits(p.y)\n\t\t\tuint16s[i * 3 + 2] = numberToFloat16Bits(p.z ?? 0.5)\n\t\t}\n\t\treturn uint16ArrayToBase64(uint16s)\n\t}\n\n\t/**\n\t * Convert a base64 string back to an array of VecModels.\n\t * Decodes Float16-encoded coordinates (x, y, z) from the base64 string.\n\t *\n\t * @param base64 - The base64-encoded string containing point data\n\t * @returns An array of VecModel objects decoded from the string\n\t */\n\tstatic decodePoints(base64: string): VecModel[] {\n\t\tconst uint16s = base64ToUint16Array(base64)\n\t\tconst result: VecModel[] = []\n\t\tfor (let i = 0; i < uint16s.length; i += 3) {\n\t\t\tresult.push({\n\t\t\t\tx: float16BitsToNumber(uint16s[i]),\n\t\t\t\ty: float16BitsToNumber(uint16s[i + 1]),\n\t\t\t\tz: float16BitsToNumber(uint16s[i + 2]),\n\t\t\t})\n\t\t}\n\t\treturn result\n\t}\n\n\t/**\n\t * Decode a single point (8 base64 chars) starting at the given offset.\n\t * Each point is encoded as 3 Float16 values (x, y, z) in 8 base64 characters.\n\t *\n\t * @param b64Points - The base64-encoded string containing point data\n\t * @param charOffset - The character offset where the point starts (must be a multiple of 8)\n\t * @returns A VecModel object with x, y, and z coordinates\n\t * @internal\n\t */\n\tstatic decodePointAt(b64Points: string, charOffset: number): VecModel {\n\t\t// Decode 8 base64 chars -> 6 bytes -> 3 Float16s using O(1) lookup\n\t\tconst c0 = B64_LOOKUP[b64Points.charCodeAt(charOffset)]\n\t\tconst c1 = B64_LOOKUP[b64Points.charCodeAt(charOffset + 1)]\n\t\tconst c2 = B64_LOOKUP[b64Points.charCodeAt(charOffset + 2)]\n\t\tconst c3 = B64_LOOKUP[b64Points.charCodeAt(charOffset + 3)]\n\t\tconst c4 = B64_LOOKUP[b64Points.charCodeAt(charOffset + 4)]\n\t\tconst c5 = B64_LOOKUP[b64Points.charCodeAt(charOffset + 5)]\n\t\tconst c6 = B64_LOOKUP[b64Points.charCodeAt(charOffset + 6)]\n\t\tconst c7 = B64_LOOKUP[b64Points.charCodeAt(charOffset + 7)]\n\n\t\t// 4 base64 chars -> 24 bits -> 3 bytes\n\t\tconst bitmap1 = (c0 << 18) | (c1 << 12) | (c2 << 6) | c3\n\t\tconst bitmap2 = (c4 << 18) | (c5 << 12) | (c6 << 6) | c7\n\n\t\t// Extract Float16 bits directly (little-endian byte order)\n\t\t// bitmap1 = [byte0:8][byte1:8][byte2:8], bitmap2 = [byte3:8][byte4:8][byte5:8]\n\t\t// xBits = byte0 | (byte1 << 8), yBits = byte2 | (byte3 << 8), zBits = byte4 | (byte5 << 8)\n\t\tconst xBits = ((bitmap1 >> 16) & 0xff) | (bitmap1 & 0xff00)\n\t\tconst yBits = (bitmap1 & 0xff) | ((bitmap2 >> 8) & 0xff00)\n\t\tconst zBits = ((bitmap2 >> 8) & 0xff) | ((bitmap2 << 8) & 0xff00)\n\n\t\treturn {\n\t\t\tx: float16BitsToNumber(xBits),\n\t\t\ty: float16BitsToNumber(yBits),\n\t\t\tz: float16BitsToNumber(zBits),\n\t\t}\n\t}\n\n\t/**\n\t * Get the first point from a base64-encoded string of points.\n\t *\n\t * @param b64Points - The base64-encoded string containing point data\n\t * @returns The first point as a VecModel, or null if the string is too short\n\t * @public\n\t */\n\tstatic decodeFirstPoint(b64Points: string): VecModel | null {\n\t\tif (b64Points.length < POINT_B64_LENGTH) return null\n\t\treturn b64Vecs.decodePointAt(b64Points, 0)\n\t}\n\n\t/**\n\t * Get the last point from a base64-encoded string of points.\n\t *\n\t * @param b64Points - The base64-encoded string containing point data\n\t * @returns The last point as a VecModel, or null if the string is too short\n\t */\n\tstatic decodeLastPoint(b64Points: string): VecModel | null {\n\t\tif (b64Points.length < POINT_B64_LENGTH) return null\n\t\treturn b64Vecs.decodePointAt(b64Points, b64Points.length - POINT_B64_LENGTH)\n\t}\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import { assert } from '@tldraw/utils'\nimport { VecModel } from './geometry-types'\n\n// Each point = 3 Float16s = 6 bytes = 8 base64 chars (legacy format)\nconst _POINT_B64_LENGTH = 8\n\n// First point in delta encoding = 3 Float32s = 12 bytes = 16 base64 chars\nconst FIRST_POINT_B64_LENGTH = 16\n\n// O(1) lookup table for base64 decoding (maps char code -> 6-bit value)\nconst BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nconst B64_LOOKUP = new Uint8Array(128)\nfor (let i = 0; i < 64; i++) {\n\tB64_LOOKUP[BASE64_CHARS.charCodeAt(i)] = i\n}\n\n// Precomputed powers of 2 for Float16 exponents (exp - 15, so indices 0-30 map to 2^-15 to 2^15)\nconst POW2 = new Float64Array(31)\nfor (let i = 0; i < 31; i++) {\n\tPOW2[i] = Math.pow(2, i - 15)\n}\nconst POW2_SUBNORMAL = Math.pow(2, -14) / 1024 // For subnormal numbers\n\n// Precomputed mantissa values: 1 + frac/1024 for all 1024 possible frac values\n// Avoids division in hot path\nconst MANTISSA = new Float64Array(1024)\nfor (let i = 0; i < 1024; i++) {\n\tMANTISSA[i] = 1 + i / 1024\n}\n\ndeclare global {\n\tinterface Uint8Array {\n\t\ttoBase64?(): string\n\t}\n\tinterface Uint8ArrayConstructor {\n\t\tfromBase64?(base64: string): Uint8Array\n\t}\n}\n\nfunction nativeGetFloat16(dataView: DataView, offset: number): number {\n\treturn (dataView as any).getFloat16(offset, true)\n}\nfunction fallbackGetFloat16(dataView: DataView, offset: number): number {\n\treturn float16BitsToNumber(dataView.getUint16(offset, true))\n}\n\nconst getFloat16 =\n\ttypeof (DataView.prototype as any).getFloat16 === 'function'\n\t\t? nativeGetFloat16\n\t\t: fallbackGetFloat16\n\nfunction nativeSetFloat16(dataView: DataView, offset: number, value: number): void {\n\t;(dataView as any).setFloat16(offset, value, true)\n}\nfunction fallbackSetFloat16(dataView: DataView, offset: number, value: number): void {\n\tdataView.setUint16(offset, numberToFloat16Bits(value), true)\n}\n\nconst setFloat16 =\n\ttypeof (DataView.prototype as any).setFloat16 === 'function'\n\t\t? nativeSetFloat16\n\t\t: fallbackSetFloat16\n\nfunction nativeBase64ToUint8Array(base64: string): Uint8Array {\n\treturn Uint8Array.fromBase64!(base64)\n}\n\n/** @internal */\nexport function fallbackBase64ToUint8Array(base64: string): Uint8Array {\n\tconst numBytes = Math.floor((base64.length * 3) / 4)\n\tconst bytes = new Uint8Array(numBytes)\n\tlet byteIndex = 0\n\n\tfor (let i = 0; i < base64.length; i += 4) {\n\t\tconst c0 = B64_LOOKUP[base64.charCodeAt(i)]\n\t\tconst c1 = B64_LOOKUP[base64.charCodeAt(i + 1)]\n\t\tconst c2 = B64_LOOKUP[base64.charCodeAt(i + 2)]\n\t\tconst c3 = B64_LOOKUP[base64.charCodeAt(i + 3)]\n\n\t\tconst bitmap = (c0 << 18) | (c1 << 12) | (c2 << 6) | c3\n\n\t\tbytes[byteIndex++] = (bitmap >> 16) & 255\n\t\tbytes[byteIndex++] = (bitmap >> 8) & 255\n\t\tbytes[byteIndex++] = bitmap & 255\n\t}\n\n\treturn bytes\n}\n\nfunction nativeUint8ArrayToBase64(uint8Array: Uint8Array): string {\n\treturn uint8Array.toBase64!()\n}\n\n/** @internal */\nexport function fallbackUint8ArrayToBase64(uint8Array: Uint8Array): string {\n\tassert(uint8Array.length % 3 === 0, 'Uint8Array length must be a multiple of 3')\n\tlet result = ''\n\n\t// Process bytes in groups of 3 -> 4 base64 chars\n\tfor (let i = 0; i < uint8Array.length; i += 3) {\n\t\tconst byte1 = uint8Array[i]\n\t\tconst byte2 = uint8Array[i + 1]\n\t\tconst byte3 = uint8Array[i + 2]\n\n\t\tconst bitmap = (byte1 << 16) | (byte2 << 8) | byte3\n\t\tresult +=\n\t\t\tBASE64_CHARS[(bitmap >> 18) & 63] +\n\t\t\tBASE64_CHARS[(bitmap >> 12) & 63] +\n\t\t\tBASE64_CHARS[(bitmap >> 6) & 63] +\n\t\t\tBASE64_CHARS[bitmap & 63]\n\t}\n\n\treturn result\n}\n\n/**\n * Convert a Uint8Array to base64.\n * Processes bytes in groups of 3 to produce 4 base64 characters.\n *\n * @internal\n */\nconst uint8ArrayToBase64 =\n\ttypeof Uint8Array.prototype.toBase64 === 'function'\n\t\t? nativeUint8ArrayToBase64\n\t\t: fallbackUint8ArrayToBase64\n\n/**\n * Convert a base64 string to Uint8Array.\n *\n * @internal\n */\nconst base64ToUint8Array =\n\ttypeof Uint8Array.fromBase64 === 'function'\n\t\t? nativeBase64ToUint8Array\n\t\t: fallbackBase64ToUint8Array\n\n/**\n * Convert Float16 bits to a number using optimized lookup tables.\n * Handles normal numbers, subnormal numbers, zero, infinity, and NaN.\n *\n * @param bits - The 16-bit Float16 value to decode\n * @returns The decoded number value\n * @internal\n */\nexport function float16BitsToNumber(bits: number): number {\n\tconst sign = bits >> 15\n\tconst exp = (bits >> 10) & 0x1f\n\tconst frac = bits & 0x3ff\n\n\tif (exp === 0) {\n\t\t// Subnormal or zero - rare case\n\t\treturn sign ? -frac * POW2_SUBNORMAL : frac * POW2_SUBNORMAL\n\t}\n\tif (exp === 31) {\n\t\t// Infinity or NaN - very rare\n\t\treturn frac ? NaN : sign ? -Infinity : Infinity\n\t}\n\t// Normal case - two table lookups, one multiply, no division\n\tconst magnitude = POW2[exp] * MANTISSA[frac]\n\treturn sign ? -magnitude : magnitude\n}\n\n/**\n * Convert a number to Float16 bits.\n * Handles normal numbers, subnormal numbers, zero, infinity, and NaN.\n *\n * @param value - The number to encode as Float16\n * @returns The 16-bit Float16 representation of the number\n * @internal\n */\nexport function numberToFloat16Bits(value: number): number {\n\tif (value === 0) return Object.is(value, -0) ? 0x8000 : 0\n\tif (!Number.isFinite(value)) {\n\t\tif (Number.isNaN(value)) return 0x7e00\n\t\treturn value > 0 ? 0x7c00 : 0xfc00\n\t}\n\n\tconst sign = value < 0 ? 1 : 0\n\tvalue = Math.abs(value)\n\n\t// Find exponent and mantissa\n\tconst exp = Math.floor(Math.log2(value))\n\tlet expBiased = exp + 15\n\n\tif (expBiased >= 31) {\n\t\t// Overflow to infinity\n\t\treturn (sign << 15) | 0x7c00\n\t}\n\tif (expBiased <= 0) {\n\t\t// Subnormal or underflow\n\t\tconst frac = Math.round(value * Math.pow(2, 14) * 1024)\n\t\treturn (sign << 15) | (frac & 0x3ff)\n\t}\n\n\t// Normal number\n\tconst mantissa = value / Math.pow(2, exp) - 1\n\tlet frac = Math.round(mantissa * 1024)\n\n\t// Handle rounding overflow: if frac rounds to 1024, increment exponent\n\tif (frac >= 1024) {\n\t\tfrac = 0\n\t\texpBiased++\n\t\tif (expBiased >= 31) {\n\t\t\t// Overflow to infinity\n\t\t\treturn (sign << 15) | 0x7c00\n\t\t}\n\t}\n\n\treturn (sign << 15) | (expBiased << 10) | frac\n}\n\n/**\n * Utilities for encoding and decoding points using base64 and Float16 encoding.\n * Provides functions for converting between VecModel arrays and compact base64 strings,\n * as well as individual point encoding/decoding operations.\n *\n * @public\n */\nexport class b64Vecs {\n\t/**\n\t * Encode a single point (x, y, z) to 8 base64 characters using legacy Float16 encoding.\n\t * Each coordinate is encoded as a Float16 value, resulting in 6 bytes total.\n\t *\n\t * @param x - The x coordinate\n\t * @param y - The y coordinate\n\t * @param z - The z coordinate\n\t * @returns An 8-character base64 string representing the point\n\t * @internal\n\t */\n\tstatic _legacyEncodePoint(x: number, y: number, z: number): string {\n\t\tconst buffer = new Uint8Array(6)\n\t\tconst dataView = new DataView(buffer.buffer)\n\n\t\tsetFloat16(dataView, 0, x)\n\t\tsetFloat16(dataView, 2, y)\n\t\tsetFloat16(dataView, 4, z)\n\n\t\treturn uint8ArrayToBase64(buffer)\n\t}\n\n\t/**\n\t * Convert an array of VecModels to a base64 string using legacy Float16 encoding.\n\t * Uses Float16 encoding for each coordinate (x, y, z). If a point's z value is\n\t * undefined, it defaults to 0.5.\n\t *\n\t * @param points - An array of VecModel objects to encode\n\t * @returns A base64-encoded string containing all points\n\t * @internal Used only for migrations from legacy format\n\t */\n\tstatic _legacyEncodePoints(points: VecModel[]): string {\n\t\tif (points.length === 0) return ''\n\n\t\t// 3 Float16s per point = 6 bytes per point\n\t\tconst buffer = new Uint8Array(points.length * 6)\n\t\tconst dataView = new DataView(buffer.buffer)\n\n\t\tfor (let i = 0; i < points.length; i++) {\n\t\t\tconst p = points[i]\n\t\t\tconst offset = i * 6\n\t\t\tsetFloat16(dataView, offset, p.x)\n\t\t\tsetFloat16(dataView, offset + 2, p.y)\n\t\t\tsetFloat16(dataView, offset + 4, p.z ?? 0.5)\n\t\t}\n\n\t\treturn uint8ArrayToBase64(buffer)\n\t}\n\n\t/**\n\t * Convert a legacy base64 string back to an array of VecModels.\n\t * Decodes Float16-encoded coordinates (x, y, z) from the base64 string.\n\t *\n\t * @param base64 - The base64-encoded string containing point data\n\t * @returns An array of VecModel objects decoded from the string\n\t * @internal Used only for migrations from legacy format\n\t */\n\tstatic _legacyDecodePoints(base64: string): VecModel[] {\n\t\tconst bytes = base64ToUint8Array(base64)\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\t\tconst result: VecModel[] = []\n\t\tfor (let offset = 0; offset < bytes.length; offset += 6) {\n\t\t\tresult.push({\n\t\t\t\tx: getFloat16(dataView, offset),\n\t\t\t\ty: getFloat16(dataView, offset + 2),\n\t\t\t\tz: getFloat16(dataView, offset + 4),\n\t\t\t})\n\t\t}\n\t\treturn result\n\t}\n\n\t/**\n\t * Encode an array of VecModels using delta encoding for improved precision.\n\t * The first point is stored as Float32 (high precision for absolute position),\n\t * subsequent points are stored as Float16 deltas from the previous point.\n\t * This provides full precision for the starting position and excellent precision\n\t * for deltas between consecutive points (which are typically small values).\n\t *\n\t * Format:\n\t * - First point: 3 Float32 values = 12 bytes = 16 base64 chars\n\t * - Delta points: 3 Float16 values each = 6 bytes = 8 base64 chars each\n\t *\n\t * @param points - An array of VecModel objects to encode\n\t * @returns A base64-encoded string containing delta-encoded points\n\t * @public\n\t */\n\tstatic encodePoints(points: VecModel[]): string {\n\t\tif (points.length === 0) return ''\n\n\t\t// First point: 3 Float32s = 12 bytes\n\t\t// Remaining points: 3 Float16s each = 6 bytes each\n\t\tconst firstPointBytes = 12\n\t\tconst deltaBytes = (points.length - 1) * 6\n\t\tconst totalBytes = firstPointBytes + deltaBytes\n\n\t\tconst buffer = new Uint8Array(totalBytes)\n\t\tconst dataView = new DataView(buffer.buffer)\n\n\t\t// First point is stored as Float32 for full precision\n\t\tconst first = points[0]\n\t\tdataView.setFloat32(0, first.x, true) // little-endian\n\t\tdataView.setFloat32(4, first.y, true)\n\t\tdataView.setFloat32(8, first.z ?? 0.5, true)\n\n\t\t// Subsequent points are Float16 deltas from the previous point\n\t\tlet prevX = first.x\n\t\tlet prevY = first.y\n\t\tlet prevZ = first.z ?? 0.5\n\n\t\tfor (let i = 1; i < points.length; i++) {\n\t\t\tconst p = points[i]\n\t\t\tconst z = p.z ?? 0.5\n\n\t\t\tconst offset = firstPointBytes + (i - 1) * 6\n\t\t\tsetFloat16(dataView, offset, p.x - prevX)\n\t\t\tsetFloat16(dataView, offset + 2, p.y - prevY)\n\t\t\tsetFloat16(dataView, offset + 4, z - prevZ)\n\n\t\t\tprevX = p.x\n\t\t\tprevY = p.y\n\t\t\tprevZ = z\n\t\t}\n\n\t\treturn uint8ArrayToBase64(buffer)\n\t}\n\n\t/**\n\t * Decode a delta-encoded base64 string back to an array of absolute VecModels.\n\t * The first point is stored as Float32 (high precision), subsequent points are\n\t * Float16 deltas that are accumulated to reconstruct absolute positions.\n\t *\n\t * @param base64 - The base64-encoded string containing delta-encoded point data\n\t * @returns An array of VecModel objects with absolute coordinates\n\t * @public\n\t */\n\tstatic decodePoints(base64: string): VecModel[] {\n\t\tif (base64.length === 0) return []\n\n\t\tconst bytes = base64ToUint8Array(base64)\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\t\tconst result: VecModel[] = []\n\n\t\t// First point is Float32 (12 bytes)\n\t\tlet x = dataView.getFloat32(0, true)\n\t\tlet y = dataView.getFloat32(4, true)\n\t\tlet z = dataView.getFloat32(8, true)\n\t\tresult.push({ x, y, z })\n\n\t\t// Subsequent points are Float16 deltas - accumulate to get absolute positions\n\t\tconst firstPointBytes = 12\n\t\tfor (let offset = firstPointBytes; offset < bytes.length; offset += 6) {\n\t\t\tx += getFloat16(dataView, offset)\n\t\t\ty += getFloat16(dataView, offset + 2)\n\t\t\tz += getFloat16(dataView, offset + 4)\n\t\t\tresult.push({ x, y, z })\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Get the first point from a delta-encoded base64 string.\n\t * The first point is stored as Float32 for full precision.\n\t *\n\t * @param b64Points - The delta-encoded base64 string\n\t * @returns The first point as a VecModel, or null if the string is too short\n\t * @public\n\t */\n\tstatic decodeFirstPoint(b64Points: string): VecModel | null {\n\t\t// First point needs 16 base64 chars (12 bytes as Float32)\n\t\tif (b64Points.length < FIRST_POINT_B64_LENGTH) return null\n\n\t\tconst bytes = base64ToUint8Array(b64Points.slice(0, FIRST_POINT_B64_LENGTH))\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\n\t\treturn {\n\t\t\tx: dataView.getFloat32(0, true),\n\t\t\ty: dataView.getFloat32(4, true),\n\t\t\tz: dataView.getFloat32(8, true),\n\t\t}\n\t}\n\n\t/**\n\t * Get the last point from a delta-encoded base64 string.\n\t * Requires decoding all points to accumulate deltas.\n\t *\n\t * @param b64Points - The delta-encoded base64 string\n\t * @returns The last point as a VecModel, or null if the string is too short\n\t * @public\n\t */\n\tstatic decodeLastPoint(b64Points: string): VecModel | null {\n\t\tif (b64Points.length < FIRST_POINT_B64_LENGTH) return null\n\n\t\tconst bytes = base64ToUint8Array(b64Points)\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\n\t\t// Start with first point (Float32)\n\t\tlet x = dataView.getFloat32(0, true)\n\t\tlet y = dataView.getFloat32(4, true)\n\t\tlet z = dataView.getFloat32(8, true)\n\n\t\t// Accumulate all Float16 deltas to get the last point\n\t\tconst firstPointBytes = 12\n\t\tfor (let offset = firstPointBytes; offset < bytes.length; offset += 6) {\n\t\t\tx += getFloat16(dataView, offset)\n\t\t\ty += getFloat16(dataView, offset + 2)\n\t\t\tz += getFloat16(dataView, offset + 4)\n\t\t}\n\n\t\treturn { x, y, z }\n\t}\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAuB;AAIvB,MAAM,oBAAoB;AAG1B,MAAM,yBAAyB;AAG/B,MAAM,eAAe;AACrB,MAAM,aAAa,IAAI,WAAW,GAAG;AACrC,SAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC5B,aAAW,aAAa,WAAW,CAAC,CAAC,IAAI;AAC1C;AAGA,MAAM,OAAO,IAAI,aAAa,EAAE;AAChC,SAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC5B,OAAK,CAAC,IAAI,KAAK,IAAI,GAAG,IAAI,EAAE;AAC7B;AACA,MAAM,iBAAiB,KAAK,IAAI,GAAG,GAAG,IAAI;AAI1C,MAAM,WAAW,IAAI,aAAa,IAAI;AACtC,SAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC9B,WAAS,CAAC,IAAI,IAAI,IAAI;AACvB;AAWA,SAAS,iBAAiB,UAAoB,QAAwB;AACrE,SAAQ,SAAiB,WAAW,QAAQ,IAAI;AACjD;AACA,SAAS,mBAAmB,UAAoB,QAAwB;AACvE,SAAO,oBAAoB,SAAS,UAAU,QAAQ,IAAI,CAAC;AAC5D;AAEA,MAAM,aACL,OAAQ,SAAS,UAAkB,eAAe,aAC/C,mBACA;AAEJ,SAAS,iBAAiB,UAAoB,QAAgB,OAAqB;AAClF;AAAC,EAAC,SAAiB,WAAW,QAAQ,OAAO,IAAI;AAClD;AACA,SAAS,mBAAmB,UAAoB,QAAgB,OAAqB;AACpF,WAAS,UAAU,QAAQ,oBAAoB,KAAK,GAAG,IAAI;AAC5D;AAEA,MAAM,aACL,OAAQ,SAAS,UAAkB,eAAe,aAC/C,mBACA;AAEJ,SAAS,yBAAyB,QAA4B;AAC7D,SAAO,WAAW,WAAY,MAAM;AACrC;AAGO,SAAS,2BAA2B,QAA4B;AACtE,QAAM,WAAW,KAAK,MAAO,OAAO,SAAS,IAAK,CAAC;AACnD,QAAM,QAAQ,IAAI,WAAW,QAAQ;AACrC,MAAI,YAAY;AAEhB,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;AAC1C,UAAM,KAAK,WAAW,OAAO,WAAW,CAAC,CAAC;AAC1C,UAAM,KAAK,WAAW,OAAO,WAAW,IAAI,CAAC,CAAC;AAC9C,UAAM,KAAK,WAAW,OAAO,WAAW,IAAI,CAAC,CAAC;AAC9C,UAAM,KAAK,WAAW,OAAO,WAAW,IAAI,CAAC,CAAC;AAE9C,UAAM,SAAU,MAAM,KAAO,MAAM,KAAO,MAAM,IAAK;AAErD,UAAM,WAAW,IAAK,UAAU,KAAM;AACtC,UAAM,WAAW,IAAK,UAAU,IAAK;AACrC,UAAM,WAAW,IAAI,SAAS;AAAA,EAC/B;AAEA,SAAO;AACR;AAEA,SAAS,yBAAyB,YAAgC;AACjE,SAAO,WAAW,SAAU;AAC7B;AAGO,SAAS,2BAA2B,YAAgC;AAC1E,2BAAO,WAAW,SAAS,MAAM,GAAG,2CAA2C;AAC/E,MAAI,SAAS;AAGb,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK,GAAG;AAC9C,UAAM,QAAQ,WAAW,CAAC;AAC1B,UAAM,QAAQ,WAAW,IAAI,CAAC;AAC9B,UAAM,QAAQ,WAAW,IAAI,CAAC;AAE9B,UAAM,SAAU,SAAS,KAAO,SAAS,IAAK;AAC9C,cACC,aAAc,UAAU,KAAM,EAAE,IAChC,aAAc,UAAU,KAAM,EAAE,IAChC,aAAc,UAAU,IAAK,EAAE,IAC/B,aAAa,SAAS,EAAE;AAAA,EAC1B;AAEA,SAAO;AACR;AAQA,MAAM,qBACL,OAAO,WAAW,UAAU,aAAa,aACtC,2BACA;AAOJ,MAAM,qBACL,OAAO,WAAW,eAAe,aAC9B,2BACA;AAUG,SAAS,oBAAoB,MAAsB;AACzD,QAAM,OAAO,QAAQ;AACrB,QAAM,MAAO,QAAQ,KAAM;AAC3B,QAAM,OAAO,OAAO;AAEpB,MAAI,QAAQ,GAAG;AAEd,WAAO,OAAO,CAAC,OAAO,iBAAiB,OAAO;AAAA,EAC/C;AACA,MAAI,QAAQ,IAAI;AAEf,WAAO,OAAO,MAAM,OAAO,YAAY;AAAA,EACxC;AAEA,QAAM,YAAY,KAAK,GAAG,IAAI,SAAS,IAAI;AAC3C,SAAO,OAAO,CAAC,YAAY;AAC5B;AAUO,SAAS,oBAAoB,OAAuB;AAC1D,MAAI,UAAU,EAAG,QAAO,OAAO,GAAG,OAAO,EAAE,IAAI,QAAS;AACxD,MAAI,CAAC,OAAO,SAAS,KAAK,GAAG;AAC5B,QAAI,OAAO,MAAM,KAAK,EAAG,QAAO;AAChC,WAAO,QAAQ,IAAI,QAAS;AAAA,EAC7B;AAEA,QAAM,OAAO,QAAQ,IAAI,IAAI;AAC7B,UAAQ,KAAK,IAAI,KAAK;AAGtB,QAAM,MAAM,KAAK,MAAM,KAAK,KAAK,KAAK,CAAC;AACvC,MAAI,YAAY,MAAM;AAEtB,MAAI,aAAa,IAAI;AAEpB,WAAQ,QAAQ,KAAM;AAAA,EACvB;AACA,MAAI,aAAa,GAAG;AAEnB,UAAMA,QAAO,KAAK,MAAM,QAAQ,KAAK,IAAI,GAAG,EAAE,IAAI,IAAI;AACtD,WAAQ,QAAQ,KAAOA,QAAO;AAAA,EAC/B;AAGA,QAAM,WAAW,QAAQ,KAAK,IAAI,GAAG,GAAG,IAAI;AAC5C,MAAI,OAAO,KAAK,MAAM,WAAW,IAAI;AAGrC,MAAI,QAAQ,MAAM;AACjB,WAAO;AACP;AACA,QAAI,aAAa,IAAI;AAEpB,aAAQ,QAAQ,KAAM;AAAA,IACvB;AAAA,EACD;AAEA,SAAQ,QAAQ,KAAO,aAAa,KAAM;AAC3C;AASO,MAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWpB,OAAO,mBAAmB,GAAW,GAAW,GAAmB;AAClE,UAAM,SAAS,IAAI,WAAW,CAAC;AAC/B,UAAM,WAAW,IAAI,SAAS,OAAO,MAAM;AAE3C,eAAW,UAAU,GAAG,CAAC;AACzB,eAAW,UAAU,GAAG,CAAC;AACzB,eAAW,UAAU,GAAG,CAAC;AAEzB,WAAO,mBAAmB,MAAM;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,oBAAoB,QAA4B;AACtD,QAAI,OAAO,WAAW,EAAG,QAAO;AAGhC,UAAM,SAAS,IAAI,WAAW,OAAO,SAAS,CAAC;AAC/C,UAAM,WAAW,IAAI,SAAS,OAAO,MAAM;AAE3C,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACvC,YAAM,IAAI,OAAO,CAAC;AAClB,YAAM,SAAS,IAAI;AACnB,iBAAW,UAAU,QAAQ,EAAE,CAAC;AAChC,iBAAW,UAAU,SAAS,GAAG,EAAE,CAAC;AACpC,iBAAW,UAAU,SAAS,GAAG,EAAE,KAAK,GAAG;AAAA,IAC5C;AAEA,WAAO,mBAAmB,MAAM;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,oBAAoB,QAA4B;AACtD,UAAM,QAAQ,mBAAmB,MAAM;AACvC,UAAM,WAAW,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAC9E,UAAM,SAAqB,CAAC;AAC5B,aAAS,SAAS,GAAG,SAAS,MAAM,QAAQ,UAAU,GAAG;AACxD,aAAO,KAAK;AAAA,QACX,GAAG,WAAW,UAAU,MAAM;AAAA,QAC9B,GAAG,WAAW,UAAU,SAAS,CAAC;AAAA,QAClC,GAAG,WAAW,UAAU,SAAS,CAAC;AAAA,MACnC,CAAC;AAAA,IACF;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,OAAO,aAAa,QAA4B;AAC/C,QAAI,OAAO,WAAW,EAAG,QAAO;AAIhC,UAAM,kBAAkB;AACxB,UAAM,cAAc,OAAO,SAAS,KAAK;AACzC,UAAM,aAAa,kBAAkB;AAErC,UAAM,SAAS,IAAI,WAAW,UAAU;AACxC,UAAM,WAAW,IAAI,SAAS,OAAO,MAAM;AAG3C,UAAM,QAAQ,OAAO,CAAC;AACtB,aAAS,WAAW,GAAG,MAAM,GAAG,IAAI;AACpC,aAAS,WAAW,GAAG,MAAM,GAAG,IAAI;AACpC,aAAS,WAAW,GAAG,MAAM,KAAK,KAAK,IAAI;AAG3C,QAAI,QAAQ,MAAM;AAClB,QAAI,QAAQ,MAAM;AAClB,QAAI,QAAQ,MAAM,KAAK;AAEvB,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACvC,YAAM,IAAI,OAAO,CAAC;AAClB,YAAM,IAAI,EAAE,KAAK;AAEjB,YAAM,SAAS,mBAAmB,IAAI,KAAK;AAC3C,iBAAW,UAAU,QAAQ,EAAE,IAAI,KAAK;AACxC,iBAAW,UAAU,SAAS,GAAG,EAAE,IAAI,KAAK;AAC5C,iBAAW,UAAU,SAAS,GAAG,IAAI,KAAK;AAE1C,cAAQ,EAAE;AACV,cAAQ,EAAE;AACV,cAAQ;AAAA,IACT;AAEA,WAAO,mBAAmB,MAAM;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,aAAa,QAA4B;AAC/C,QAAI,OAAO,WAAW,EAAG,QAAO,CAAC;AAEjC,UAAM,QAAQ,mBAAmB,MAAM;AACvC,UAAM,WAAW,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAC9E,UAAM,SAAqB,CAAC;AAG5B,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,WAAO,KAAK,EAAE,GAAG,GAAG,EAAE,CAAC;AAGvB,UAAM,kBAAkB;AACxB,aAAS,SAAS,iBAAiB,SAAS,MAAM,QAAQ,UAAU,GAAG;AACtE,WAAK,WAAW,UAAU,MAAM;AAChC,WAAK,WAAW,UAAU,SAAS,CAAC;AACpC,WAAK,WAAW,UAAU,SAAS,CAAC;AACpC,aAAO,KAAK,EAAE,GAAG,GAAG,EAAE,CAAC;AAAA,IACxB;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,iBAAiB,WAAoC;AAE3D,QAAI,UAAU,SAAS,uBAAwB,QAAO;AAEtD,UAAM,QAAQ,mBAAmB,UAAU,MAAM,GAAG,sBAAsB,CAAC;AAC3E,UAAM,WAAW,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAE9E,WAAO;AAAA,MACN,GAAG,SAAS,WAAW,GAAG,IAAI;AAAA,MAC9B,GAAG,SAAS,WAAW,GAAG,IAAI;AAAA,MAC9B,GAAG,SAAS,WAAW,GAAG,IAAI;AAAA,IAC/B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,gBAAgB,WAAoC;AAC1D,QAAI,UAAU,SAAS,uBAAwB,QAAO;AAEtD,UAAM,QAAQ,mBAAmB,SAAS;AAC1C,UAAM,WAAW,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAG9E,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AAGnC,UAAM,kBAAkB;AACxB,aAAS,SAAS,iBAAiB,SAAS,MAAM,QAAQ,UAAU,GAAG;AACtE,WAAK,WAAW,UAAU,MAAM;AAChC,WAAK,WAAW,UAAU,SAAS,CAAC;AACpC,WAAK,WAAW,UAAU,SAAS,CAAC;AAAA,IACrC;AAEA,WAAO,EAAE,GAAG,GAAG,EAAE;AAAA,EAClB;AACD;",
|
|
6
6
|
"names": ["frac"]
|
|
7
7
|
}
|
|
@@ -34,7 +34,7 @@ var import_TLFillStyle = require("../styles/TLFillStyle");
|
|
|
34
34
|
var import_TLSizeStyle = require("../styles/TLSizeStyle");
|
|
35
35
|
const DrawShapeSegment = import_validate.T.object({
|
|
36
36
|
type: import_validate.T.literalEnum("free", "straight"),
|
|
37
|
-
|
|
37
|
+
path: import_validate.T.string
|
|
38
38
|
});
|
|
39
39
|
const drawShapeProps = {
|
|
40
40
|
color: import_TLColorStyle.DefaultColorStyle,
|
|
@@ -52,7 +52,8 @@ const drawShapeProps = {
|
|
|
52
52
|
const Versions = (0, import_TLShape.createShapePropsMigrationIds)("draw", {
|
|
53
53
|
AddInPen: 1,
|
|
54
54
|
AddScale: 2,
|
|
55
|
-
Base64: 3
|
|
55
|
+
Base64: 3,
|
|
56
|
+
LegacyPointsConversion: 4
|
|
56
57
|
});
|
|
57
58
|
const drawShapeMigrations = (0, import_TLShape.createShapePropsMigrationSequence)({
|
|
58
59
|
sequence: [
|
|
@@ -85,31 +86,51 @@ const drawShapeMigrations = (0, import_TLShape.createShapePropsMigrationSequence
|
|
|
85
86
|
id: Versions.Base64,
|
|
86
87
|
up: (props) => {
|
|
87
88
|
props.segments = props.segments.map((segment) => {
|
|
89
|
+
if (segment.path !== void 0) return segment;
|
|
90
|
+
const { points, ...rest } = segment;
|
|
91
|
+
const vecModels = Array.isArray(points) ? points : import_b64Vecs.b64Vecs._legacyDecodePoints(points);
|
|
88
92
|
return {
|
|
89
|
-
...
|
|
90
|
-
|
|
91
|
-
points: typeof segment.points === "string" ? segment.points : import_b64Vecs.b64Vecs.encodePoints(segment.points)
|
|
93
|
+
...rest,
|
|
94
|
+
path: import_b64Vecs.b64Vecs.encodePoints(vecModels)
|
|
92
95
|
};
|
|
93
96
|
});
|
|
94
97
|
props.scaleX = props.scaleX ?? 1;
|
|
95
98
|
props.scaleY = props.scaleY ?? 1;
|
|
96
99
|
},
|
|
97
100
|
down: (props) => {
|
|
98
|
-
props.segments = props.segments.map((segment) =>
|
|
99
|
-
...segment
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
props.segments = props.segments.map((segment) => {
|
|
102
|
+
const { path, ...rest } = segment;
|
|
103
|
+
return {
|
|
104
|
+
...rest,
|
|
105
|
+
points: import_b64Vecs.b64Vecs.decodePoints(path)
|
|
106
|
+
};
|
|
107
|
+
});
|
|
103
108
|
delete props.scaleX;
|
|
104
109
|
delete props.scaleY;
|
|
105
110
|
}
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: Versions.LegacyPointsConversion,
|
|
114
|
+
up: (props) => {
|
|
115
|
+
props.segments = props.segments.map((segment) => {
|
|
116
|
+
if (segment.path !== void 0) return segment;
|
|
117
|
+
const { points, ...rest } = segment;
|
|
118
|
+
const vecModels = Array.isArray(points) ? points : import_b64Vecs.b64Vecs._legacyDecodePoints(points);
|
|
119
|
+
return {
|
|
120
|
+
...rest,
|
|
121
|
+
path: import_b64Vecs.b64Vecs.encodePoints(vecModels)
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
},
|
|
125
|
+
down: (_props) => {
|
|
126
|
+
}
|
|
106
127
|
}
|
|
107
128
|
]
|
|
108
129
|
});
|
|
109
130
|
function compressLegacySegments(segments) {
|
|
110
131
|
return segments.map((segment) => ({
|
|
111
|
-
|
|
112
|
-
|
|
132
|
+
type: segment.type,
|
|
133
|
+
path: import_b64Vecs.b64Vecs.encodePoints(segment.points)
|
|
113
134
|
}));
|
|
114
135
|
}
|
|
115
136
|
//# sourceMappingURL=TLDrawShape.js.map
|