@shotstack/shotstack-canvas 1.0.7 → 1.0.8
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/entry.node.cjs +49 -24
- package/dist/entry.node.cjs.map +1 -1
- package/dist/entry.node.d.cts +1 -0
- package/dist/entry.node.d.ts +1 -0
- package/dist/entry.node.js +49 -24
- package/dist/entry.node.js.map +1 -1
- package/dist/entry.web.d.ts +1 -0
- package/dist/entry.web.js +49 -24
- package/dist/entry.web.js.map +1 -1
- package/package.json +1 -1
package/dist/entry.node.cjs
CHANGED
|
@@ -186,14 +186,33 @@ var FontRegistry = class {
|
|
|
186
186
|
fonts = /* @__PURE__ */ new Map();
|
|
187
187
|
blobs = /* @__PURE__ */ new Map();
|
|
188
188
|
wasmBaseURL;
|
|
189
|
+
initPromise;
|
|
189
190
|
constructor(wasmBaseURL) {
|
|
190
191
|
this.wasmBaseURL = wasmBaseURL;
|
|
191
192
|
}
|
|
192
193
|
async init() {
|
|
193
|
-
if (
|
|
194
|
+
if (this.initPromise) {
|
|
195
|
+
await this.initPromise;
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (this.hb) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
this.initPromise = this._doInit();
|
|
202
|
+
await this.initPromise;
|
|
203
|
+
}
|
|
204
|
+
async _doInit() {
|
|
205
|
+
try {
|
|
206
|
+
this.hb = await initHB(this.wasmBaseURL);
|
|
207
|
+
} catch (error) {
|
|
208
|
+
this.initPromise = void 0;
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
194
211
|
}
|
|
195
|
-
getHB() {
|
|
196
|
-
if (!this.hb)
|
|
212
|
+
async getHB() {
|
|
213
|
+
if (!this.hb) {
|
|
214
|
+
await this.init();
|
|
215
|
+
}
|
|
197
216
|
return this.hb;
|
|
198
217
|
}
|
|
199
218
|
key(desc) {
|
|
@@ -212,23 +231,24 @@ var FontRegistry = class {
|
|
|
212
231
|
this.faces.set(k, face);
|
|
213
232
|
this.fonts.set(k, font);
|
|
214
233
|
}
|
|
215
|
-
getFont(desc) {
|
|
234
|
+
async getFont(desc) {
|
|
235
|
+
if (!this.hb) await this.init();
|
|
216
236
|
const k = this.key(desc);
|
|
217
237
|
const f = this.fonts.get(k);
|
|
218
238
|
if (!f) throw new Error(`Font not registered for ${k}`);
|
|
219
239
|
return f;
|
|
220
240
|
}
|
|
221
|
-
getFace(desc) {
|
|
241
|
+
async getFace(desc) {
|
|
242
|
+
if (!this.hb) await this.init();
|
|
222
243
|
const k = this.key(desc);
|
|
223
244
|
return this.faces.get(k);
|
|
224
245
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const face = this.getFace(desc);
|
|
246
|
+
async getUnitsPerEm(desc) {
|
|
247
|
+
const face = await this.getFace(desc);
|
|
228
248
|
return face?.upem || 1e3;
|
|
229
249
|
}
|
|
230
|
-
glyphPath(desc, glyphId) {
|
|
231
|
-
const font = this.getFont(desc);
|
|
250
|
+
async glyphPath(desc, glyphId) {
|
|
251
|
+
const font = await this.getFont(desc);
|
|
232
252
|
const path = font.glyphToPath(glyphId);
|
|
233
253
|
return path && path !== "" ? path : "M 0 0";
|
|
234
254
|
}
|
|
@@ -239,6 +259,8 @@ var FontRegistry = class {
|
|
|
239
259
|
this.fonts.clear();
|
|
240
260
|
this.faces.clear();
|
|
241
261
|
this.blobs.clear();
|
|
262
|
+
this.hb = void 0;
|
|
263
|
+
this.initPromise = void 0;
|
|
242
264
|
}
|
|
243
265
|
};
|
|
244
266
|
|
|
@@ -259,13 +281,13 @@ var LayoutEngine = class {
|
|
|
259
281
|
return t;
|
|
260
282
|
}
|
|
261
283
|
}
|
|
262
|
-
shapeFull(text, desc) {
|
|
263
|
-
const hb = this.fonts.getHB();
|
|
284
|
+
async shapeFull(text, desc) {
|
|
285
|
+
const hb = await this.fonts.getHB();
|
|
264
286
|
const buffer = hb.createBuffer();
|
|
265
287
|
buffer.addText(text);
|
|
266
288
|
buffer.guessSegmentProperties();
|
|
267
|
-
const font = this.fonts.getFont(desc);
|
|
268
|
-
const face = this.fonts.getFace(desc);
|
|
289
|
+
const font = await this.fonts.getFont(desc);
|
|
290
|
+
const face = await this.fonts.getFace(desc);
|
|
269
291
|
const upem = face?.upem || 1e3;
|
|
270
292
|
font.setScale(upem, upem);
|
|
271
293
|
hb.shape(font, buffer);
|
|
@@ -273,17 +295,17 @@ var LayoutEngine = class {
|
|
|
273
295
|
buffer.destroy();
|
|
274
296
|
return result;
|
|
275
297
|
}
|
|
276
|
-
layout(params) {
|
|
298
|
+
async layout(params) {
|
|
277
299
|
const { textTransform, desc, fontSize, letterSpacing, width } = params;
|
|
278
300
|
const input = this.transformText(params.text, textTransform);
|
|
279
301
|
if (!input || input.length === 0) {
|
|
280
302
|
return [];
|
|
281
303
|
}
|
|
282
|
-
const shaped = this.shapeFull(input, desc);
|
|
283
|
-
const face = this.fonts.getFace(desc);
|
|
304
|
+
const shaped = await this.shapeFull(input, desc);
|
|
305
|
+
const face = await this.fonts.getFace(desc);
|
|
284
306
|
const upem = face?.upem || 1e3;
|
|
285
307
|
const scale = fontSize / upem;
|
|
286
|
-
const glyphs = shaped.map((g
|
|
308
|
+
const glyphs = shaped.map((g) => {
|
|
287
309
|
const charIndex = g.cl;
|
|
288
310
|
let char;
|
|
289
311
|
if (charIndex >= 0 && charIndex < input.length) {
|
|
@@ -387,7 +409,7 @@ function decorationGeometry(kind, p) {
|
|
|
387
409
|
}
|
|
388
410
|
|
|
389
411
|
// src/core/drawops.ts
|
|
390
|
-
function buildDrawOps(p) {
|
|
412
|
+
async function buildDrawOps(p) {
|
|
391
413
|
const ops = [];
|
|
392
414
|
ops.push({
|
|
393
415
|
op: "BeginFrame",
|
|
@@ -398,7 +420,7 @@ function buildDrawOps(p) {
|
|
|
398
420
|
bg: p.background ? { color: p.background.color, opacity: p.background.opacity, radius: p.background.borderRadius } : void 0
|
|
399
421
|
});
|
|
400
422
|
if (p.lines.length === 0) return ops;
|
|
401
|
-
const upem = Math.max(1, p.getUnitsPerEm
|
|
423
|
+
const upem = Math.max(1, await p.getUnitsPerEm());
|
|
402
424
|
const scale = p.font.size / upem;
|
|
403
425
|
const blockHeight = p.lines[p.lines.length - 1].y;
|
|
404
426
|
let blockY;
|
|
@@ -434,7 +456,7 @@ function buildDrawOps(p) {
|
|
|
434
456
|
let xCursor = lineX;
|
|
435
457
|
const baselineY = blockY + line.y - p.font.size;
|
|
436
458
|
for (const glyph of line.glyphs) {
|
|
437
|
-
const path = p.glyphPathProvider(glyph.id);
|
|
459
|
+
const path = await p.glyphPathProvider(glyph.id);
|
|
438
460
|
if (!path || path === "M 0 0") {
|
|
439
461
|
xCursor += glyph.xAdvance;
|
|
440
462
|
continue;
|
|
@@ -1426,6 +1448,7 @@ async function createTextEngine(opts = {}) {
|
|
|
1426
1448
|
const fonts = new FontRegistry(wasmBaseURL);
|
|
1427
1449
|
const layout = new LayoutEngine(fonts);
|
|
1428
1450
|
const videoGenerator = new VideoGenerator();
|
|
1451
|
+
await fonts.init();
|
|
1429
1452
|
async function ensureFonts(asset) {
|
|
1430
1453
|
if (asset.customFonts) {
|
|
1431
1454
|
for (const cf of asset.customFonts) {
|
|
@@ -1467,7 +1490,7 @@ async function createTextEngine(opts = {}) {
|
|
|
1467
1490
|
async renderFrame(asset, tSeconds) {
|
|
1468
1491
|
const main = await ensureFonts(asset);
|
|
1469
1492
|
const desc = { family: main.family, weight: `${main.weight}`, style: main.style };
|
|
1470
|
-
const lines = layout.layout({
|
|
1493
|
+
const lines = await layout.layout({
|
|
1471
1494
|
text: asset.text,
|
|
1472
1495
|
width: asset.width ?? width,
|
|
1473
1496
|
letterSpacing: asset.style?.letterSpacing ?? 0,
|
|
@@ -1480,7 +1503,7 @@ async function createTextEngine(opts = {}) {
|
|
|
1480
1503
|
const canvasW = asset.width ?? width;
|
|
1481
1504
|
const canvasH = asset.height ?? height;
|
|
1482
1505
|
const canvasPR = asset.pixelRatio ?? pixelRatio;
|
|
1483
|
-
const ops0 = buildDrawOps({
|
|
1506
|
+
const ops0 = await buildDrawOps({
|
|
1484
1507
|
canvas: { width: canvasW, height: canvasH, pixelRatio: canvasPR },
|
|
1485
1508
|
textRect,
|
|
1486
1509
|
lines,
|
|
@@ -1502,7 +1525,6 @@ async function createTextEngine(opts = {}) {
|
|
|
1502
1525
|
align: asset.align ?? { horizontal: "left", vertical: "middle" },
|
|
1503
1526
|
background: asset.background,
|
|
1504
1527
|
glyphPathProvider: (gid) => fonts.glyphPath(desc, gid),
|
|
1505
|
-
/** NEW: provide UPEM so drawops can compute scale */
|
|
1506
1528
|
getUnitsPerEm: () => fonts.getUnitsPerEm(desc)
|
|
1507
1529
|
});
|
|
1508
1530
|
const ops = applyAnimation(ops0, lines, {
|
|
@@ -1538,6 +1560,9 @@ async function createTextEngine(opts = {}) {
|
|
|
1538
1560
|
return this.renderFrame(asset, time);
|
|
1539
1561
|
};
|
|
1540
1562
|
await videoGenerator.generateVideo(frameGenerator, finalOptions);
|
|
1563
|
+
},
|
|
1564
|
+
destroy() {
|
|
1565
|
+
fonts.destroy();
|
|
1541
1566
|
}
|
|
1542
1567
|
};
|
|
1543
1568
|
}
|