@shotstack/shotstack-canvas 2.1.2 → 2.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.
@@ -1851,8 +1851,8 @@ async function buildDrawOps(p) {
1851
1851
  const canvasCenterY = p.canvas.height / 2;
1852
1852
  const bgX = canvasCenterX - contentWidth / 2;
1853
1853
  const bgY = canvasCenterY - contentHeight / 2;
1854
- const maxRadius = Math.min(contentWidth - borderWidth2, contentHeight - borderWidth2) / 2;
1855
- const outerRadius = Math.min(borderRadius, maxRadius);
1854
+ const maxRadius = Math.max(0, Math.min(contentWidth - borderWidth2, contentHeight - borderWidth2) / 2);
1855
+ const outerRadius = Math.max(0, Math.min(borderRadius, maxRadius));
1856
1856
  const innerRadius = Math.max(0, outerRadius - halfBorder);
1857
1857
  if (p.background?.color) {
1858
1858
  ops.push({
@@ -3478,9 +3478,14 @@ async function createNodePainter(opts) {
3478
3478
  i++;
3479
3479
  }
3480
3480
  renderToBoth((context) => {
3481
+ const bgSortedOps = [...captionWordOps].sort((a, b) => {
3482
+ const dy = Math.round(a.y) - Math.round(b.y);
3483
+ if (dy !== 0) return dy;
3484
+ return a.x + a.transform.translateX - (b.x + b.transform.translateX);
3485
+ });
3481
3486
  let bgIdx = 0;
3482
- while (bgIdx < captionWordOps.length) {
3483
- const wordOp = captionWordOps[bgIdx];
3487
+ while (bgIdx < bgSortedOps.length) {
3488
+ const wordOp = bgSortedOps[bgIdx];
3484
3489
  if (!wordOp.background) {
3485
3490
  bgIdx++;
3486
3491
  continue;
@@ -3492,13 +3497,12 @@ async function createNodePainter(opts) {
3492
3497
  }
3493
3498
  const mergeGroup = [wordOp];
3494
3499
  let nextIdx = bgIdx + 1;
3495
- while (nextIdx < captionWordOps.length) {
3496
- const nextWord = captionWordOps[nextIdx];
3500
+ while (nextIdx < bgSortedOps.length) {
3501
+ const nextWord = bgSortedOps[nextIdx];
3497
3502
  if (!nextWord.background) break;
3498
3503
  const nextDisplay = getVisibleText(nextWord.text, nextWord.visibleCharacters, nextWord.isRTL);
3499
3504
  if (nextDisplay.length === 0) break;
3500
3505
  if (Math.round(nextWord.y) !== Math.round(wordOp.y)) break;
3501
- if (nextWord.background.color !== wordOp.background.color) break;
3502
3506
  mergeGroup.push(nextWord);
3503
3507
  nextIdx++;
3504
3508
  }
@@ -3526,11 +3530,13 @@ async function createNodePainter(opts) {
3526
3530
  const bgY = -bgAscent - firstBg.padding;
3527
3531
  const bgW = mergedWidth + firstBg.padding * 2;
3528
3532
  const bgH = bgTextHeight + firstBg.padding * 2;
3529
- const bgC = parseHex6(firstBg.color, firstBg.opacity);
3530
- context.fillStyle = `rgba(${bgC.r},${bgC.g},${bgC.b},${bgC.a})`;
3531
- context.beginPath();
3532
- roundRectPath(context, bgX, bgY, bgW, bgH, firstBg.borderRadius);
3533
- context.fill();
3533
+ if (bgW > 0 && bgH > 0) {
3534
+ const bgC = parseHex6(firstBg.color, firstBg.opacity);
3535
+ context.fillStyle = `rgba(${bgC.r},${bgC.g},${bgC.b},${bgC.a})`;
3536
+ context.beginPath();
3537
+ roundRectPath(context, bgX, bgY, bgW, bgH, firstBg.borderRadius);
3538
+ context.fill();
3539
+ }
3534
3540
  context.restore();
3535
3541
  bgIdx = nextIdx;
3536
3542
  }
@@ -3827,8 +3833,8 @@ function computePathBounds2(d) {
3827
3833
  };
3828
3834
  }
3829
3835
  function roundRectPath(ctx, x, y, w, h, r) {
3830
- const maxRadius = Math.min(w, h) / 2;
3831
- const radius = Math.min(r, maxRadius);
3836
+ const maxRadius = Math.max(0, Math.min(w, h) / 2);
3837
+ const radius = Math.max(0, Math.min(r, maxRadius));
3832
3838
  ctx.moveTo(x + radius, y);
3833
3839
  ctx.arcTo(x + w, y, x + w, y + h, radius);
3834
3840
  ctx.arcTo(x + w, y + h, x, y + h, radius);
@@ -1448,8 +1448,8 @@ async function buildDrawOps(p) {
1448
1448
  const canvasCenterY = p.canvas.height / 2;
1449
1449
  const bgX = canvasCenterX - contentWidth / 2;
1450
1450
  const bgY = canvasCenterY - contentHeight / 2;
1451
- const maxRadius = Math.min(contentWidth - borderWidth2, contentHeight - borderWidth2) / 2;
1452
- const outerRadius = Math.min(borderRadius, maxRadius);
1451
+ const maxRadius = Math.max(0, Math.min(contentWidth - borderWidth2, contentHeight - borderWidth2) / 2);
1452
+ const outerRadius = Math.max(0, Math.min(borderRadius, maxRadius));
1453
1453
  const innerRadius = Math.max(0, outerRadius - halfBorder);
1454
1454
  if (p.background?.color) {
1455
1455
  ops.push({
@@ -3075,9 +3075,14 @@ async function createNodePainter(opts) {
3075
3075
  i++;
3076
3076
  }
3077
3077
  renderToBoth((context) => {
3078
+ const bgSortedOps = [...captionWordOps].sort((a, b) => {
3079
+ const dy = Math.round(a.y) - Math.round(b.y);
3080
+ if (dy !== 0) return dy;
3081
+ return a.x + a.transform.translateX - (b.x + b.transform.translateX);
3082
+ });
3078
3083
  let bgIdx = 0;
3079
- while (bgIdx < captionWordOps.length) {
3080
- const wordOp = captionWordOps[bgIdx];
3084
+ while (bgIdx < bgSortedOps.length) {
3085
+ const wordOp = bgSortedOps[bgIdx];
3081
3086
  if (!wordOp.background) {
3082
3087
  bgIdx++;
3083
3088
  continue;
@@ -3089,13 +3094,12 @@ async function createNodePainter(opts) {
3089
3094
  }
3090
3095
  const mergeGroup = [wordOp];
3091
3096
  let nextIdx = bgIdx + 1;
3092
- while (nextIdx < captionWordOps.length) {
3093
- const nextWord = captionWordOps[nextIdx];
3097
+ while (nextIdx < bgSortedOps.length) {
3098
+ const nextWord = bgSortedOps[nextIdx];
3094
3099
  if (!nextWord.background) break;
3095
3100
  const nextDisplay = getVisibleText(nextWord.text, nextWord.visibleCharacters, nextWord.isRTL);
3096
3101
  if (nextDisplay.length === 0) break;
3097
3102
  if (Math.round(nextWord.y) !== Math.round(wordOp.y)) break;
3098
- if (nextWord.background.color !== wordOp.background.color) break;
3099
3103
  mergeGroup.push(nextWord);
3100
3104
  nextIdx++;
3101
3105
  }
@@ -3123,11 +3127,13 @@ async function createNodePainter(opts) {
3123
3127
  const bgY = -bgAscent - firstBg.padding;
3124
3128
  const bgW = mergedWidth + firstBg.padding * 2;
3125
3129
  const bgH = bgTextHeight + firstBg.padding * 2;
3126
- const bgC = parseHex6(firstBg.color, firstBg.opacity);
3127
- context.fillStyle = `rgba(${bgC.r},${bgC.g},${bgC.b},${bgC.a})`;
3128
- context.beginPath();
3129
- roundRectPath(context, bgX, bgY, bgW, bgH, firstBg.borderRadius);
3130
- context.fill();
3130
+ if (bgW > 0 && bgH > 0) {
3131
+ const bgC = parseHex6(firstBg.color, firstBg.opacity);
3132
+ context.fillStyle = `rgba(${bgC.r},${bgC.g},${bgC.b},${bgC.a})`;
3133
+ context.beginPath();
3134
+ roundRectPath(context, bgX, bgY, bgW, bgH, firstBg.borderRadius);
3135
+ context.fill();
3136
+ }
3131
3137
  context.restore();
3132
3138
  bgIdx = nextIdx;
3133
3139
  }
@@ -3424,8 +3430,8 @@ function computePathBounds2(d) {
3424
3430
  };
3425
3431
  }
3426
3432
  function roundRectPath(ctx, x, y, w, h, r) {
3427
- const maxRadius = Math.min(w, h) / 2;
3428
- const radius = Math.min(r, maxRadius);
3433
+ const maxRadius = Math.max(0, Math.min(w, h) / 2);
3434
+ const radius = Math.max(0, Math.min(r, maxRadius));
3429
3435
  ctx.moveTo(x + radius, y);
3430
3436
  ctx.arcTo(x + w, y, x + w, y + h, radius);
3431
3437
  ctx.arcTo(x + w, y + h, x, y + h, radius);
package/dist/entry.web.js CHANGED
@@ -33483,8 +33483,8 @@ async function buildDrawOps(p) {
33483
33483
  const canvasCenterY = p.canvas.height / 2;
33484
33484
  const bgX = canvasCenterX - contentWidth / 2;
33485
33485
  const bgY = canvasCenterY - contentHeight / 2;
33486
- const maxRadius = Math.min(contentWidth - borderWidth2, contentHeight - borderWidth2) / 2;
33487
- const outerRadius = Math.min(borderRadius, maxRadius);
33486
+ const maxRadius = Math.max(0, Math.min(contentWidth - borderWidth2, contentHeight - borderWidth2) / 2);
33487
+ const outerRadius = Math.max(0, Math.min(borderRadius, maxRadius));
33488
33488
  const innerRadius = Math.max(0, outerRadius - halfBorder);
33489
33489
  if (p.background?.color) {
33490
33490
  ops.push({
@@ -34937,8 +34937,8 @@ function createWebPainter(canvas) {
34937
34937
  const y2 = op.y;
34938
34938
  const w = op.width;
34939
34939
  const h = op.height;
34940
- const maxRadius = Math.min(w, h) / 2;
34941
- const r = Math.min(op.borderRadius, maxRadius);
34940
+ const maxRadius = Math.max(0, Math.min(w, h) / 2);
34941
+ const r = Math.max(0, Math.min(op.borderRadius, maxRadius));
34942
34942
  p.moveTo(x2 + r, y2);
34943
34943
  p.arcTo(x2 + w, y2, x2 + w, y2 + h, r);
34944
34944
  p.arcTo(x2 + w, y2 + h, x2, y2 + h, r);
@@ -35043,9 +35043,14 @@ function createWebPainter(canvas) {
35043
35043
  captionWordOps.push(nextOp);
35044
35044
  i++;
35045
35045
  }
35046
+ const bgSortedOps = [...captionWordOps].sort((a, b) => {
35047
+ const dy = Math.round(a.y) - Math.round(b.y);
35048
+ if (dy !== 0) return dy;
35049
+ return a.x + a.transform.translateX - (b.x + b.transform.translateX);
35050
+ });
35046
35051
  let bgIdx = 0;
35047
- while (bgIdx < captionWordOps.length) {
35048
- const wordOp = captionWordOps[bgIdx];
35052
+ while (bgIdx < bgSortedOps.length) {
35053
+ const wordOp = bgSortedOps[bgIdx];
35049
35054
  if (!wordOp.background) {
35050
35055
  bgIdx++;
35051
35056
  continue;
@@ -35057,13 +35062,12 @@ function createWebPainter(canvas) {
35057
35062
  }
35058
35063
  const mergeGroup = [wordOp];
35059
35064
  let nextIdx = bgIdx + 1;
35060
- while (nextIdx < captionWordOps.length) {
35061
- const nextWord = captionWordOps[nextIdx];
35065
+ while (nextIdx < bgSortedOps.length) {
35066
+ const nextWord = bgSortedOps[nextIdx];
35062
35067
  if (!nextWord.background) break;
35063
35068
  const nextDisplay = getVisibleText(nextWord.text, nextWord.visibleCharacters, nextWord.isRTL);
35064
35069
  if (nextDisplay.length === 0) break;
35065
35070
  if (Math.round(nextWord.y) !== Math.round(wordOp.y)) break;
35066
- if (nextWord.background.color !== wordOp.background.color) break;
35067
35071
  mergeGroup.push(nextWord);
35068
35072
  nextIdx++;
35069
35073
  }
@@ -35091,9 +35095,11 @@ function createWebPainter(canvas) {
35091
35095
  const bgY = -bgAscent - firstBg.padding;
35092
35096
  const bgW = mergedWidth + firstBg.padding * 2;
35093
35097
  const bgH = bgTextHeight + firstBg.padding * 2;
35094
- const bgC = parseHex6(firstBg.color, firstBg.opacity);
35095
- ctx.fillStyle = `rgba(${bgC.r},${bgC.g},${bgC.b},${bgC.a})`;
35096
- drawRoundedRect(ctx, bgX, bgY, bgW, bgH, firstBg.borderRadius);
35098
+ if (bgW > 0 && bgH > 0) {
35099
+ const bgC = parseHex6(firstBg.color, firstBg.opacity);
35100
+ ctx.fillStyle = `rgba(${bgC.r},${bgC.g},${bgC.b},${bgC.a})`;
35101
+ drawRoundedRect(ctx, bgX, bgY, bgW, bgH, firstBg.borderRadius);
35102
+ }
35097
35103
  ctx.restore();
35098
35104
  bgIdx = nextIdx;
35099
35105
  }
@@ -35195,8 +35201,8 @@ function createWebPainter(canvas) {
35195
35201
  };
35196
35202
  }
35197
35203
  function drawRoundedRect(ctx, x2, y2, w, h, r) {
35198
- const maxRadius = Math.min(w, h) / 2;
35199
- const radius = Math.min(r, maxRadius);
35204
+ const maxRadius = Math.max(0, Math.min(w, h) / 2);
35205
+ const radius = Math.max(0, Math.min(r, maxRadius));
35200
35206
  const p = new Path2D();
35201
35207
  p.moveTo(x2 + radius, y2);
35202
35208
  p.arcTo(x2 + w, y2, x2 + w, y2 + h, radius);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shotstack/shotstack-canvas",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
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",