@vectojs/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,376 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } var _class; var _class2;// src/text/ArabicShaper.ts
2
+ var ArabicShaper = (_class = class _ArabicShaper {
3
+ static __initStatic() {this.MAPPINGS = {
4
+ 1569: { isolated: 65152, initial: 65152, medial: 65152, final: 65152, joining: "U" },
5
+ // Hamza
6
+ 1570: { isolated: 65153, initial: 65153, medial: 65154, final: 65154, joining: "R" },
7
+ // Alef Madda
8
+ 1571: { isolated: 65155, initial: 65155, medial: 65156, final: 65156, joining: "R" },
9
+ // Alef Hamza Above
10
+ 1572: { isolated: 65157, initial: 65157, medial: 65158, final: 65158, joining: "R" },
11
+ // Waw Hamza
12
+ 1573: { isolated: 65159, initial: 65159, medial: 65160, final: 65160, joining: "R" },
13
+ // Alef Hamza Below
14
+ 1574: { isolated: 65161, initial: 65163, medial: 65164, final: 65162, joining: "D" },
15
+ // Yeh Hamza
16
+ 1575: { isolated: 65165, initial: 65165, medial: 65166, final: 65166, joining: "R" },
17
+ // Alef
18
+ 1576: { isolated: 65167, initial: 65169, medial: 65170, final: 65168, joining: "D" },
19
+ // Ba
20
+ 1577: { isolated: 65171, initial: 65171, medial: 65172, final: 65172, joining: "R" },
21
+ // Teh Marbuta
22
+ 1578: { isolated: 65173, initial: 65175, medial: 65176, final: 65174, joining: "D" },
23
+ // Teh
24
+ 1579: { isolated: 65177, initial: 65179, medial: 65180, final: 65178, joining: "D" },
25
+ // Theh
26
+ 1580: { isolated: 65181, initial: 65183, medial: 65184, final: 65182, joining: "D" },
27
+ // Jeem
28
+ 1581: { isolated: 65185, initial: 65187, medial: 65188, final: 65186, joining: "D" },
29
+ // Hah
30
+ 1582: { isolated: 65189, initial: 65191, medial: 65192, final: 65190, joining: "D" },
31
+ // Khav
32
+ 1583: { isolated: 65193, initial: 65193, medial: 65194, final: 65194, joining: "R" },
33
+ // Dal
34
+ 1584: { isolated: 65195, initial: 65195, medial: 65196, final: 65196, joining: "R" },
35
+ // Thal
36
+ 1585: { isolated: 65197, initial: 65197, medial: 65198, final: 65198, joining: "R" },
37
+ // Ra
38
+ 1586: { isolated: 65199, initial: 65199, medial: 65200, final: 65200, joining: "R" },
39
+ // Zay
40
+ 1587: { isolated: 65201, initial: 65203, medial: 65204, final: 65202, joining: "D" },
41
+ // Seen
42
+ 1588: { isolated: 65205, initial: 65207, medial: 65208, final: 65206, joining: "D" },
43
+ // Sheen
44
+ 1589: { isolated: 65209, initial: 65211, medial: 65212, final: 65210, joining: "D" },
45
+ // Sad
46
+ 1590: { isolated: 65213, initial: 65215, medial: 65216, final: 65214, joining: "D" },
47
+ // Dad
48
+ 1591: { isolated: 65217, initial: 65219, medial: 65220, final: 65218, joining: "D" },
49
+ // Tah
50
+ 1592: { isolated: 65221, initial: 65223, medial: 65224, final: 65222, joining: "D" },
51
+ // Zah
52
+ 1593: { isolated: 65225, initial: 65227, medial: 65228, final: 65226, joining: "D" },
53
+ // Ain
54
+ 1594: { isolated: 65229, initial: 65231, medial: 65232, final: 65230, joining: "D" },
55
+ // Ghain
56
+ 1601: { isolated: 65233, initial: 65235, medial: 65236, final: 65234, joining: "D" },
57
+ // Feh
58
+ 1602: { isolated: 65237, initial: 65239, medial: 65240, final: 65238, joining: "D" },
59
+ // Qaf
60
+ 1603: { isolated: 65241, initial: 65243, medial: 65244, final: 65242, joining: "D" },
61
+ // Kaf
62
+ 1604: { isolated: 65245, initial: 65247, medial: 65248, final: 65246, joining: "D" },
63
+ // Lam
64
+ 1605: { isolated: 65249, initial: 65251, medial: 65252, final: 65250, joining: "D" },
65
+ // Meem
66
+ 1606: { isolated: 65253, initial: 65255, medial: 65256, final: 65254, joining: "D" },
67
+ // Noon
68
+ 1607: { isolated: 65257, initial: 65259, medial: 65260, final: 65258, joining: "D" },
69
+ // Heh
70
+ 1608: { isolated: 65261, initial: 65261, medial: 65262, final: 65262, joining: "R" },
71
+ // Waw
72
+ 1609: { isolated: 65263, initial: 65263, medial: 65264, final: 65264, joining: "R" },
73
+ // Alef Maksura
74
+ 1610: { isolated: 65265, initial: 65267, medial: 65268, final: 65266, joining: "D" },
75
+ // Yeh
76
+ // Persian / Urdu Extensions
77
+ 1662: { isolated: 64342, initial: 64344, medial: 64345, final: 64343, joining: "D" },
78
+ // Peh
79
+ 1670: { isolated: 64378, initial: 64380, medial: 64381, final: 64379, joining: "D" },
80
+ // Tcheh
81
+ 1705: { isolated: 64398, initial: 64400, medial: 64401, final: 64399, joining: "D" },
82
+ // Keheh
83
+ 1729: { isolated: 64422, initial: 64424, medial: 64425, final: 64423, joining: "D" },
84
+ // Heh Goal
85
+ 1740: { isolated: 64509, initial: 64511, medial: 64512, final: 64510, joining: "D" }
86
+ // Farsi Yeh
87
+ }}
88
+ static isHarakat(code) {
89
+ return code >= 1611 && code <= 1631 || code === 1648;
90
+ }
91
+ static getJoiningType(code) {
92
+ const f = _ArabicShaper.MAPPINGS[code];
93
+ return f ? f.joining : "U";
94
+ }
95
+ static shapeArabic(text) {
96
+ const len = text.length;
97
+ const shapedChars = [];
98
+ const sourceIndices = [];
99
+ let i = 0;
100
+ while (i < len) {
101
+ const code = text.charCodeAt(i);
102
+ if (code === 1604 && i + 1 < len) {
103
+ const nextCode2 = text.charCodeAt(i + 1);
104
+ let ligature = 0;
105
+ if (nextCode2 === 1570)
106
+ ligature = 65269;
107
+ else if (nextCode2 === 1571)
108
+ ligature = 65271;
109
+ else if (nextCode2 === 1573)
110
+ ligature = 65273;
111
+ else if (nextCode2 === 1575) ligature = 65275;
112
+ if (ligature !== 0) {
113
+ shapedChars.push(String.fromCharCode(ligature));
114
+ sourceIndices.push(i);
115
+ i += 2;
116
+ continue;
117
+ }
118
+ }
119
+ if (_ArabicShaper.isHarakat(code)) {
120
+ shapedChars.push(text[i]);
121
+ sourceIndices.push(i);
122
+ i++;
123
+ continue;
124
+ }
125
+ const forms = _ArabicShaper.MAPPINGS[code];
126
+ if (!forms) {
127
+ shapedChars.push(text[i]);
128
+ sourceIndices.push(i);
129
+ i++;
130
+ continue;
131
+ }
132
+ let prevCode = 0;
133
+ let j = i - 1;
134
+ while (j >= 0) {
135
+ const c = text.charCodeAt(j);
136
+ if (!_ArabicShaper.isHarakat(c)) {
137
+ prevCode = c;
138
+ break;
139
+ }
140
+ j--;
141
+ }
142
+ let nextCode = 0;
143
+ let k = i + 1;
144
+ while (k < len) {
145
+ const c = text.charCodeAt(k);
146
+ if (!_ArabicShaper.isHarakat(c)) {
147
+ nextCode = c;
148
+ break;
149
+ }
150
+ k++;
151
+ }
152
+ const connectPrev = prevCode !== 0 && _ArabicShaper.getJoiningType(prevCode) === "D" && (forms.joining === "D" || forms.joining === "R");
153
+ const connectNext = nextCode !== 0 && forms.joining === "D" && (_ArabicShaper.getJoiningType(nextCode) === "D" || _ArabicShaper.getJoiningType(nextCode) === "R");
154
+ let glyph = forms.isolated;
155
+ if (connectPrev && connectNext) glyph = forms.medial;
156
+ else if (connectPrev) glyph = forms.final;
157
+ else if (connectNext) glyph = forms.initial;
158
+ shapedChars.push(String.fromCharCode(glyph));
159
+ sourceIndices.push(i);
160
+ i++;
161
+ }
162
+ return {
163
+ shapedText: shapedChars.join(""),
164
+ indexMap: new Int32Array(sourceIndices)
165
+ };
166
+ }
167
+ }, _class.__initStatic(), _class);
168
+
169
+ // src/text/BidiResolver.ts
170
+ var BidiResolver = class _BidiResolver {
171
+ static getDirectionClass(code) {
172
+ if (code >= 1424 && code <= 1535 || code >= 64285 && code <= 64335) return "R";
173
+ if (code >= 1536 && code <= 1791 || code >= 1872 && code <= 1919 || code >= 2208 && code <= 2303 || code >= 64336 && code <= 65023 || code >= 65136 && code <= 65279) {
174
+ if (code === 1548 || code === 1563 || code === 1567) return "ON";
175
+ return "AL";
176
+ }
177
+ if (code >= 48 && code <= 57) return "EN";
178
+ if (code >= 1632 && code <= 1641) return "AN";
179
+ if (code === 32 || code === 9 || code === 160) return "WS";
180
+ if (code >= 8192 && code <= 8303) return "ON";
181
+ if (code >= 33 && code <= 47 || code >= 58 && code <= 64 || code >= 91 && code <= 96 || code >= 123 && code <= 126)
182
+ return "ON";
183
+ return "L";
184
+ }
185
+ static getBaseLevel(text) {
186
+ const len = text.length;
187
+ for (let i = 0; i < len; i++) {
188
+ const cls = _BidiResolver.getDirectionClass(text.charCodeAt(i));
189
+ if (cls === "L") return 0;
190
+ if (cls === "R" || cls === "AL") return 1;
191
+ }
192
+ return 0;
193
+ }
194
+ static resolveLevels(text) {
195
+ const len = text.length;
196
+ const classes = [];
197
+ for (let i = 0; i < len; i++) {
198
+ classes.push(_BidiResolver.getDirectionClass(text.charCodeAt(i)));
199
+ }
200
+ let baseLevel = 0;
201
+ for (let i = 0; i < len; i++) {
202
+ const c = classes[i];
203
+ if (c === "L") {
204
+ baseLevel = 0;
205
+ break;
206
+ } else if (c === "R" || c === "AL") {
207
+ baseLevel = 1;
208
+ break;
209
+ }
210
+ }
211
+ const levels = new Uint8Array(len);
212
+ levels.fill(baseLevel);
213
+ const stack = [baseLevel];
214
+ let overflowCounter = 0;
215
+ for (let i = 0; i < len; i++) {
216
+ const charCode = text.charCodeAt(i);
217
+ const isPushLRE = charCode === 8234;
218
+ const isPushRLE = charCode === 8235;
219
+ const isPopPDF = charCode === 8236;
220
+ if (isPushLRE || isPushRLE) {
221
+ const currentLevel = stack[stack.length - 1];
222
+ const nextLevel = Math.min(
223
+ 125,
224
+ isPushRLE ? currentLevel + 1 | 1 : currentLevel + 2 & ~1
225
+ );
226
+ if (stack.length >= 125) {
227
+ overflowCounter++;
228
+ } else {
229
+ stack.push(nextLevel);
230
+ }
231
+ } else if (isPopPDF) {
232
+ if (overflowCounter > 0) {
233
+ overflowCounter--;
234
+ } else if (stack.length > 1) {
235
+ stack.pop();
236
+ }
237
+ } else {
238
+ const currentLevel = stack[stack.length - 1];
239
+ const cls = classes[i];
240
+ let val = currentLevel;
241
+ if (cls === "L") {
242
+ val = currentLevel % 2 === 1 ? currentLevel + 1 : currentLevel;
243
+ } else if (cls === "R" || cls === "AL") {
244
+ val = currentLevel % 2 === 0 ? currentLevel + 1 : currentLevel;
245
+ } else if (cls === "EN" || cls === "AN") {
246
+ val = currentLevel % 2 === 1 ? currentLevel + 1 : currentLevel;
247
+ }
248
+ levels[i] = Math.min(125, val);
249
+ }
250
+ }
251
+ return levels;
252
+ }
253
+ static reorderVisual(nodes, baseLevel) {
254
+ const len = nodes.length;
255
+ if (len === 0) return;
256
+ let i = len - 1;
257
+ while (i >= 0) {
258
+ const node = nodes[i];
259
+ const code = node.char.charCodeAt(0);
260
+ const isWS = code === 32 || code === 9 || code === 160 || code === 8234 || code === 8235 || code === 8236;
261
+ if (isWS) {
262
+ node.level = baseLevel;
263
+ } else {
264
+ break;
265
+ }
266
+ i--;
267
+ }
268
+ let maxLevel = baseLevel;
269
+ for (let j = 0; j < len; j++) {
270
+ if (nodes[j].level > maxLevel) maxLevel = nodes[j].level;
271
+ }
272
+ for (let level = maxLevel; level >= 1; level--) {
273
+ let start = 0;
274
+ while (start < len) {
275
+ if (nodes[start].level >= level) {
276
+ let end = start;
277
+ while (end < len && nodes[end].level >= level) {
278
+ end++;
279
+ }
280
+ let left = start;
281
+ let right = end - 1;
282
+ while (left < right) {
283
+ const temp = nodes[left];
284
+ nodes[left] = nodes[right];
285
+ nodes[right] = temp;
286
+ left++;
287
+ right--;
288
+ }
289
+ start = end;
290
+ } else {
291
+ start++;
292
+ }
293
+ }
294
+ }
295
+ }
296
+ };
297
+
298
+ // src/layout/LayoutWorkerSource.ts
299
+ var WORKER_SOURCE_STRING = '"use strict";(()=>{var b=new Map;self.onmessage=x=>{let{id:S,seqId:k,text:A,fontId:i,fontData:c,maxWidth:d,maxHeight:H,fontSize:o,lineHeight:F,letterSpacing:C}=x.data;c&&b.set(i,c);let n=b.get(i);if(!n)return;let f=[],u=[],y=[],l=[],e=0,r=0,h=n.metrics?.ascender??.8,D=n.metrics?.descender??-.2,m=F??o*(h-D),p=Array.from(A);for(let s=0;s<p.length;s++){let a=p[s].codePointAt(0),g=(n.glyphs?.find(w=>w.unicode===a)?.advance??1)*o;e+g>d&&a===32&&(e=0,r++),f.push(a),u.push(e);let M=r*m+h*o;y.push(M),l.push(-256),e+=g+(C??0)}let t={id:S,seqId:k,width:Math.min(e,d),height:(r+1)*m,codePoints:new Uint32Array(f),xCoords:new Float32Array(u),yCoords:new Float32Array(y),packedStyles:new Uint32Array(l)};self.postMessage(t,[t.codePoints.buffer,t.xCoords.buffer,t.yCoords.buffer,t.packedStyles.buffer])};})();\n';
300
+
301
+ // src/layout/LayoutWorkerManager.ts
302
+ var LayoutWorkerManager = (_class2 = class _LayoutWorkerManager {
303
+
304
+
305
+ __init() {this.registeredFonts = /* @__PURE__ */ new Set()}
306
+ __init2() {this.pendingCallbacks = /* @__PURE__ */ new Map()}
307
+ __init3() {this.seqIdCounter = /* @__PURE__ */ new Map()}
308
+ __init4() {this.debounceTimers = /* @__PURE__ */ new Map()}
309
+ constructor() {;_class2.prototype.__init.call(this);_class2.prototype.__init2.call(this);_class2.prototype.__init3.call(this);_class2.prototype.__init4.call(this);
310
+ const workerBlob = new Blob([WORKER_SOURCE_STRING], { type: "application/javascript" });
311
+ const workerURL = URL.createObjectURL(workerBlob);
312
+ this.worker = new Worker(workerURL);
313
+ setTimeout(() => URL.revokeObjectURL(workerURL), 2e3);
314
+ this.worker.onmessage = (e) => {
315
+ const response = e.data;
316
+ const callback = this.pendingCallbacks.get(`${response.id}-${response.seqId}`);
317
+ if (callback) {
318
+ callback(response);
319
+ this.pendingCallbacks.delete(`${response.id}-${response.seqId}`);
320
+ }
321
+ };
322
+ }
323
+ static getInstance() {
324
+ if (!_LayoutWorkerManager.instance) {
325
+ _LayoutWorkerManager.instance = new _LayoutWorkerManager();
326
+ }
327
+ return _LayoutWorkerManager.instance;
328
+ }
329
+ queueLayout(entityId, text, options) {
330
+ const existingTimer = this.debounceTimers.get(entityId);
331
+ if (existingTimer) {
332
+ clearTimeout(existingTimer);
333
+ }
334
+ const runLayout = () => {
335
+ const nextSeqId = (_nullishCoalesce(this.seqIdCounter.get(entityId), () => ( 0))) + 1;
336
+ this.seqIdCounter.set(entityId, nextSeqId);
337
+ const request = {
338
+ id: entityId,
339
+ seqId: nextSeqId,
340
+ text,
341
+ fontId: options.fontId,
342
+ maxWidth: options.maxWidth,
343
+ maxHeight: options.maxHeight,
344
+ fontSize: options.fontSize,
345
+ lineHeight: options.lineHeight,
346
+ letterSpacing: options.letterSpacing
347
+ };
348
+ if (!this.registeredFonts.has(options.fontId) && options.fontData) {
349
+ request.fontData = options.fontData;
350
+ this.registeredFonts.add(options.fontId);
351
+ }
352
+ this.pendingCallbacks.set(`${entityId}-${nextSeqId}`, options.callback);
353
+ this.worker.postMessage(request);
354
+ };
355
+ if (!this.seqIdCounter.has(entityId)) {
356
+ runLayout();
357
+ } else {
358
+ const timer = setTimeout(runLayout, 50);
359
+ this.debounceTimers.set(entityId, timer);
360
+ }
361
+ }
362
+ cancelLayout(entityId) {
363
+ const existingTimer = this.debounceTimers.get(entityId);
364
+ if (existingTimer) {
365
+ clearTimeout(existingTimer);
366
+ this.debounceTimers.delete(entityId);
367
+ }
368
+ this.seqIdCounter.delete(entityId);
369
+ }
370
+ }, _class2);
371
+
372
+
373
+
374
+
375
+
376
+ exports.ArabicShaper = ArabicShaper; exports.BidiResolver = BidiResolver; exports.LayoutWorkerManager = LayoutWorkerManager;