@shotstack/shotstack-canvas 1.1.1 → 1.1.3

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.
@@ -191,13 +191,17 @@ async function initHB(wasmBaseURL) {
191
191
  }
192
192
 
193
193
  // src/core/font-registry.ts
194
- var FontRegistry = class {
194
+ var FontRegistry = class _FontRegistry {
195
195
  hb;
196
196
  faces = /* @__PURE__ */ new Map();
197
197
  fonts = /* @__PURE__ */ new Map();
198
198
  blobs = /* @__PURE__ */ new Map();
199
199
  wasmBaseURL;
200
200
  initPromise;
201
+ static fallbackLoader;
202
+ static setFallbackLoader(loader) {
203
+ _FontRegistry.fallbackLoader = loader;
204
+ }
201
205
  constructor(wasmBaseURL) {
202
206
  this.wasmBaseURL = wasmBaseURL;
203
207
  }
@@ -206,9 +210,7 @@ var FontRegistry = class {
206
210
  await this.initPromise;
207
211
  return;
208
212
  }
209
- if (this.hb) {
210
- return;
211
- }
213
+ if (this.hb) return;
212
214
  this.initPromise = this._doInit();
213
215
  try {
214
216
  await this.initPromise;
@@ -260,11 +262,35 @@ var FontRegistry = class {
260
262
  );
261
263
  }
262
264
  }
265
+ async tryFallbackInstall(desc) {
266
+ const loader = _FontRegistry.fallbackLoader;
267
+ if (!loader) return false;
268
+ try {
269
+ const bytes = await loader({
270
+ family: desc.family,
271
+ weight: desc.weight ?? "400",
272
+ style: desc.style ?? "normal"
273
+ });
274
+ if (!bytes) return false;
275
+ await this.registerFromBytes(bytes, {
276
+ family: desc.family,
277
+ weight: desc.weight ?? "400",
278
+ style: desc.style ?? "normal"
279
+ });
280
+ return true;
281
+ } catch {
282
+ return false;
283
+ }
284
+ }
263
285
  async getFont(desc) {
264
286
  try {
265
287
  if (!this.hb) await this.init();
266
288
  const k = this.key(desc);
267
- const f = this.fonts.get(k);
289
+ let f = this.fonts.get(k);
290
+ if (!f) {
291
+ const installed = await this.tryFallbackInstall(desc);
292
+ f = installed ? this.fonts.get(k) : void 0;
293
+ }
268
294
  if (!f) throw new Error(`Font not registered for ${k}`);
269
295
  return f;
270
296
  } catch (err) {
@@ -280,7 +306,12 @@ var FontRegistry = class {
280
306
  try {
281
307
  if (!this.hb) await this.init();
282
308
  const k = this.key(desc);
283
- return this.faces.get(k);
309
+ let face = this.faces.get(k);
310
+ if (!face) {
311
+ const installed = await this.tryFallbackInstall(desc);
312
+ face = installed ? this.faces.get(k) : void 0;
313
+ }
314
+ return face;
284
315
  } catch (err) {
285
316
  throw new Error(
286
317
  `Failed to get face for "${desc.family}": ${err instanceof Error ? err.message : String(err)}`
@@ -536,7 +567,7 @@ async function buildDrawOps(p) {
536
567
  height: p.canvas.height,
537
568
  pixelRatio: p.canvas.pixelRatio,
538
569
  clear: true,
539
- bg: p.background ? { color: p.background.color, opacity: p.background.opacity, radius: p.background.borderRadius } : void 0
570
+ bg: p.background && p.background.color ? { color: p.background.color, opacity: p.background.opacity, radius: p.background.borderRadius } : void 0
540
571
  });
541
572
  if (p.lines.length === 0) return ops;
542
573
  const upem = Math.max(1, await p.getUnitsPerEm());
@@ -1166,6 +1197,7 @@ async function createNodePainter(opts) {
1166
1197
  const globalBox = computeGlobalTextBounds(ops);
1167
1198
  for (const op of ops) {
1168
1199
  if (op.op === "BeginFrame") {
1200
+ if (op.clear) ctx.clearRect(0, 0, op.width, op.height);
1169
1201
  const dpr = op.pixelRatio ?? opts.pixelRatio;
1170
1202
  const wantW = Math.floor(op.width * dpr);
1171
1203
  const wantH = Math.floor(op.height * dpr);
@@ -1174,8 +1206,10 @@ async function createNodePainter(opts) {
1174
1206
  canvas.height = wantH;
1175
1207
  }
1176
1208
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
1177
- if (op.clear) ctx.clearRect(0, 0, op.width, op.height);
1178
- if (op.bg) {
1209
+ ctx.save();
1210
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
1211
+ ctx.restore();
1212
+ if (op.bg && op.bg.color) {
1179
1213
  const { color, opacity, radius } = op.bg;
1180
1214
  if (color) {
1181
1215
  const c = parseHex6(color, opacity);