@shotstack/shotstack-canvas 1.3.0 → 1.3.1

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.
@@ -184,18 +184,31 @@ async function loadWasmNode() {
184
184
  const { readFile: readFile2 } = await import("fs/promises");
185
185
  const { fileURLToPath } = await import("url");
186
186
  const path = await import("path");
187
+ const { createRequire } = await import("module");
187
188
  const currentDir = path.dirname(fileURLToPath(import_meta.url));
189
+ let harfbuzzWasmPath;
190
+ try {
191
+ const require2 = createRequire(import_meta.url);
192
+ const harfbuzzPkgPath = require2.resolve("harfbuzzjs/package.json");
193
+ const harfbuzzDir = path.dirname(harfbuzzPkgPath);
194
+ harfbuzzWasmPath = path.join(harfbuzzDir, "hb.wasm");
195
+ } catch {
196
+ }
188
197
  const candidates = [
198
+ ...harfbuzzWasmPath ? [harfbuzzWasmPath] : [],
189
199
  path.join(currentDir, "../../dist/hb.wasm"),
190
200
  path.join(currentDir, "../dist/hb.wasm"),
191
201
  path.join(currentDir, "../../assets/wasm/hb.wasm"),
192
202
  path.join(currentDir, "../assets/wasm/hb.wasm"),
193
203
  path.join(currentDir, "./hb.wasm"),
194
- path.join(currentDir, "../hb.wasm")
204
+ path.join(currentDir, "../hb.wasm"),
205
+ path.join(currentDir, "../../node_modules/harfbuzzjs/hb.wasm"),
206
+ path.join(currentDir, "../../../node_modules/harfbuzzjs/hb.wasm")
195
207
  ];
196
208
  for (const candidate of candidates) {
197
209
  try {
198
210
  const buffer = await readFile2(candidate);
211
+ console.log(`\u2705 Found WASM at: ${candidate}`);
199
212
  return bufferToArrayBuffer(buffer);
200
213
  } catch {
201
214
  continue;
@@ -1377,11 +1390,27 @@ async function createNodePainter(opts) {
1377
1390
  const c = parseHex6(color, opacity);
1378
1391
  ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
1379
1392
  if (radius && radius > 0) {
1393
+ needsAlphaExtraction = true;
1394
+ ctx.save();
1395
+ ctx.fillStyle = "rgb(255, 255, 255)";
1396
+ ctx.fillRect(0, 0, op.width, op.height);
1397
+ ctx.restore();
1398
+ offscreenCtx.save();
1399
+ offscreenCtx.fillStyle = "rgb(0, 0, 0)";
1400
+ offscreenCtx.fillRect(0, 0, op.width, op.height);
1401
+ offscreenCtx.restore();
1380
1402
  ctx.save();
1403
+ ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
1381
1404
  ctx.beginPath();
1382
1405
  roundRectPath(ctx, 0, 0, op.width, op.height, radius);
1383
1406
  ctx.fill();
1384
1407
  ctx.restore();
1408
+ offscreenCtx.save();
1409
+ offscreenCtx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
1410
+ offscreenCtx.beginPath();
1411
+ roundRectPath(offscreenCtx, 0, 0, op.width, op.height, radius);
1412
+ offscreenCtx.fill();
1413
+ offscreenCtx.restore();
1385
1414
  } else {
1386
1415
  ctx.fillRect(0, 0, op.width, op.height);
1387
1416
  }
@@ -2107,9 +2136,10 @@ async function createTextEngine(opts = {}) {
2107
2136
  try {
2108
2137
  const hasBackground = !!asset.background?.color;
2109
2138
  const hasAnimation = !!asset.animation?.preset;
2110
- const needsAlpha = !hasBackground && hasAnimation;
2139
+ const hasBorderRadius = (asset.background?.borderRadius ?? 0) > 0;
2140
+ const needsAlpha = !hasBackground && hasAnimation || hasBorderRadius;
2111
2141
  console.log(
2112
- `\u{1F3A8} Video settings: Animation=${hasAnimation}, Background=${hasBackground}, Alpha=${needsAlpha}`
2142
+ `\u{1F3A8} Video settings: Animation=${hasAnimation}, Background=${hasBackground}, BorderRadius=${hasBorderRadius}, Alpha=${needsAlpha}`
2113
2143
  );
2114
2144
  const finalOptions = {
2115
2145
  width: asset.width ?? width,
@@ -145,18 +145,31 @@ async function loadWasmNode() {
145
145
  const { readFile: readFile2 } = await import("fs/promises");
146
146
  const { fileURLToPath } = await import("url");
147
147
  const path = await import("path");
148
+ const { createRequire } = await import("module");
148
149
  const currentDir = path.dirname(fileURLToPath(import.meta.url));
150
+ let harfbuzzWasmPath;
151
+ try {
152
+ const require2 = createRequire(import.meta.url);
153
+ const harfbuzzPkgPath = require2.resolve("harfbuzzjs/package.json");
154
+ const harfbuzzDir = path.dirname(harfbuzzPkgPath);
155
+ harfbuzzWasmPath = path.join(harfbuzzDir, "hb.wasm");
156
+ } catch {
157
+ }
149
158
  const candidates = [
159
+ ...harfbuzzWasmPath ? [harfbuzzWasmPath] : [],
150
160
  path.join(currentDir, "../../dist/hb.wasm"),
151
161
  path.join(currentDir, "../dist/hb.wasm"),
152
162
  path.join(currentDir, "../../assets/wasm/hb.wasm"),
153
163
  path.join(currentDir, "../assets/wasm/hb.wasm"),
154
164
  path.join(currentDir, "./hb.wasm"),
155
- path.join(currentDir, "../hb.wasm")
165
+ path.join(currentDir, "../hb.wasm"),
166
+ path.join(currentDir, "../../node_modules/harfbuzzjs/hb.wasm"),
167
+ path.join(currentDir, "../../../node_modules/harfbuzzjs/hb.wasm")
156
168
  ];
157
169
  for (const candidate of candidates) {
158
170
  try {
159
171
  const buffer = await readFile2(candidate);
172
+ console.log(`\u2705 Found WASM at: ${candidate}`);
160
173
  return bufferToArrayBuffer(buffer);
161
174
  } catch {
162
175
  continue;
@@ -1338,11 +1351,27 @@ async function createNodePainter(opts) {
1338
1351
  const c = parseHex6(color, opacity);
1339
1352
  ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
1340
1353
  if (radius && radius > 0) {
1354
+ needsAlphaExtraction = true;
1355
+ ctx.save();
1356
+ ctx.fillStyle = "rgb(255, 255, 255)";
1357
+ ctx.fillRect(0, 0, op.width, op.height);
1358
+ ctx.restore();
1359
+ offscreenCtx.save();
1360
+ offscreenCtx.fillStyle = "rgb(0, 0, 0)";
1361
+ offscreenCtx.fillRect(0, 0, op.width, op.height);
1362
+ offscreenCtx.restore();
1341
1363
  ctx.save();
1364
+ ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
1342
1365
  ctx.beginPath();
1343
1366
  roundRectPath(ctx, 0, 0, op.width, op.height, radius);
1344
1367
  ctx.fill();
1345
1368
  ctx.restore();
1369
+ offscreenCtx.save();
1370
+ offscreenCtx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
1371
+ offscreenCtx.beginPath();
1372
+ roundRectPath(offscreenCtx, 0, 0, op.width, op.height, radius);
1373
+ offscreenCtx.fill();
1374
+ offscreenCtx.restore();
1346
1375
  } else {
1347
1376
  ctx.fillRect(0, 0, op.width, op.height);
1348
1377
  }
@@ -2068,9 +2097,10 @@ async function createTextEngine(opts = {}) {
2068
2097
  try {
2069
2098
  const hasBackground = !!asset.background?.color;
2070
2099
  const hasAnimation = !!asset.animation?.preset;
2071
- const needsAlpha = !hasBackground && hasAnimation;
2100
+ const hasBorderRadius = (asset.background?.borderRadius ?? 0) > 0;
2101
+ const needsAlpha = !hasBackground && hasAnimation || hasBorderRadius;
2072
2102
  console.log(
2073
- `\u{1F3A8} Video settings: Animation=${hasAnimation}, Background=${hasBackground}, Alpha=${needsAlpha}`
2103
+ `\u{1F3A8} Video settings: Animation=${hasAnimation}, Background=${hasBackground}, BorderRadius=${hasBorderRadius}, Alpha=${needsAlpha}`
2074
2104
  );
2075
2105
  const finalOptions = {
2076
2106
  width: asset.width ?? width,
package/dist/entry.web.js CHANGED
@@ -149,18 +149,31 @@ async function loadWasmNode() {
149
149
  const { readFile } = await import("fs/promises");
150
150
  const { fileURLToPath } = await import("url");
151
151
  const path = await import("path");
152
+ const { createRequire } = await import("module");
152
153
  const currentDir = path.dirname(fileURLToPath(import.meta.url));
154
+ let harfbuzzWasmPath;
155
+ try {
156
+ const require2 = createRequire(import.meta.url);
157
+ const harfbuzzPkgPath = require2.resolve("harfbuzzjs/package.json");
158
+ const harfbuzzDir = path.dirname(harfbuzzPkgPath);
159
+ harfbuzzWasmPath = path.join(harfbuzzDir, "hb.wasm");
160
+ } catch {
161
+ }
153
162
  const candidates = [
163
+ ...harfbuzzWasmPath ? [harfbuzzWasmPath] : [],
154
164
  path.join(currentDir, "../../dist/hb.wasm"),
155
165
  path.join(currentDir, "../dist/hb.wasm"),
156
166
  path.join(currentDir, "../../assets/wasm/hb.wasm"),
157
167
  path.join(currentDir, "../assets/wasm/hb.wasm"),
158
168
  path.join(currentDir, "./hb.wasm"),
159
- path.join(currentDir, "../hb.wasm")
169
+ path.join(currentDir, "../hb.wasm"),
170
+ path.join(currentDir, "../../node_modules/harfbuzzjs/hb.wasm"),
171
+ path.join(currentDir, "../../../node_modules/harfbuzzjs/hb.wasm")
160
172
  ];
161
173
  for (const candidate of candidates) {
162
174
  try {
163
175
  const buffer = await readFile(candidate);
176
+ console.log(`\u2705 Found WASM at: ${candidate}`);
164
177
  return bufferToArrayBuffer(buffer);
165
178
  } catch {
166
179
  continue;
@@ -1332,11 +1345,12 @@ function createWebPainter(canvas) {
1332
1345
  const { color, opacity, radius } = op.bg;
1333
1346
  if (color) {
1334
1347
  const c = parseHex6(color, opacity);
1335
- ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
1336
1348
  if (radius && radius > 0) {
1349
+ ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
1337
1350
  drawRoundedRect(ctx, 0, 0, w, h, radius);
1338
1351
  ctx.fill();
1339
1352
  } else {
1353
+ ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
1340
1354
  ctx.fillRect(0, 0, w, h);
1341
1355
  }
1342
1356
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shotstack/shotstack-canvas",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Text layout & animation engine (HarfBuzz) for Node & Web - fully self-contained.",
5
5
  "type": "module",
6
6
  "main": "./dist/entry.node.cjs",