@shotstack/shotstack-canvas 1.5.5 → 1.5.6

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.
@@ -136,15 +136,11 @@ var borderSchema = import_joi.default.object({
136
136
  width: import_joi.default.number().min(0).default(0),
137
137
  color: import_joi.default.string().pattern(HEX6).default("#000000"),
138
138
  opacity: import_joi.default.number().min(0).max(1).default(1),
139
- borderRadius: import_joi.default.number().min(0).optional()
139
+ radius: import_joi.default.number().min(0).default(0)
140
140
  }).unknown(false);
141
141
  var backgroundSchema = import_joi.default.object({
142
142
  color: import_joi.default.string().pattern(HEX6).optional(),
143
- opacity: import_joi.default.number().min(0).max(1).default(1),
144
- backgroundRadius: import_joi.default.number().min(0).default(0),
145
- borderRadius: import_joi.default.number().min(0).optional(),
146
- // Deprecated: use backgroundRadius
147
- border: borderSchema.optional()
143
+ opacity: import_joi.default.number().min(0).max(1).default(1)
148
144
  }).unknown(false);
149
145
  var paddingSchema = import_joi.default.alternatives().try(
150
146
  import_joi.default.number().min(0).default(0),
@@ -172,6 +168,7 @@ var RichTextAssetSchema = import_joi.default.object({
172
168
  stroke: strokeSchema.optional(),
173
169
  shadow: shadowSchema.optional(),
174
170
  background: backgroundSchema.optional(),
171
+ border: borderSchema.optional(),
175
172
  padding: paddingSchema.optional(),
176
173
  align: alignmentSchema.optional(),
177
174
  animation: animationSchema.optional(),
@@ -983,40 +980,41 @@ async function buildDrawOps(p) {
983
980
  }
984
981
  }
985
982
  }
986
- if (p.background && (p.background.color || p.background.border)) {
983
+ if (p.background || p.border) {
987
984
  const bgX = 0;
988
985
  const bgY = 0;
989
986
  const bgWidth = p.canvas.width;
990
987
  const bgHeight = p.canvas.height;
991
- const backgroundRadius = p.background.backgroundRadius ?? p.background.borderRadius ?? 0;
992
- const halfBorder = p.background.border?.width ? p.background.border.width / 2 : 0;
993
- if (p.background.color) {
994
- const bgInset = halfBorder;
995
- const bgFillRadius = Math.max(0, backgroundRadius - bgInset);
988
+ const borderWidth2 = p.border?.width ?? 0;
989
+ const borderRadius = p.border?.radius ?? 0;
990
+ const halfBorder = borderWidth2 / 2;
991
+ const maxRadius = Math.min(bgWidth - borderWidth2, bgHeight - borderWidth2) / 2;
992
+ const outerRadius = Math.min(borderRadius, maxRadius);
993
+ const innerRadius = Math.max(0, outerRadius - halfBorder);
994
+ if (p.background?.color) {
996
995
  ops.push({
997
996
  op: "Rectangle",
998
- x: bgX + bgInset,
999
- y: bgY + bgInset,
1000
- width: bgWidth - bgInset * 2,
1001
- height: bgHeight - bgInset * 2,
997
+ x: bgX + borderWidth2,
998
+ y: bgY + borderWidth2,
999
+ width: bgWidth - borderWidth2 * 2,
1000
+ height: bgHeight - borderWidth2 * 2,
1002
1001
  fill: { kind: "solid", color: p.background.color, opacity: p.background.opacity },
1003
- borderRadius: bgFillRadius
1002
+ borderRadius: innerRadius
1004
1003
  });
1005
1004
  }
1006
- if (p.background.border && p.background.border.width > 0) {
1007
- const borderRadius = p.background.border.borderRadius !== void 0 ? p.background.border.borderRadius : backgroundRadius;
1005
+ if (p.border && p.border.width > 0) {
1008
1006
  ops.push({
1009
1007
  op: "RectangleStroke",
1010
- x: bgX,
1011
- y: bgY,
1012
- width: bgWidth,
1013
- height: bgHeight,
1008
+ x: bgX + halfBorder,
1009
+ y: bgY + halfBorder,
1010
+ width: bgWidth - borderWidth2,
1011
+ height: bgHeight - borderWidth2,
1014
1012
  stroke: {
1015
- width: p.background.border.width,
1016
- color: p.background.border.color,
1017
- opacity: p.background.border.opacity
1013
+ width: p.border.width,
1014
+ color: p.border.color,
1015
+ opacity: p.border.opacity
1018
1016
  },
1019
- borderRadius
1017
+ borderRadius: outerRadius
1020
1018
  });
1021
1019
  }
1022
1020
  }
@@ -2468,6 +2466,7 @@ async function createTextEngine(opts = {}) {
2468
2466
  vertical: asset.align?.vertical ?? "middle"
2469
2467
  },
2470
2468
  background: asset.background,
2469
+ border: asset.border,
2471
2470
  padding: asset.padding,
2472
2471
  glyphPathProvider: (gid, fontDesc) => fonts.glyphPath(fontDesc || desc, gid),
2473
2472
  getUnitsPerEm: (fontDesc) => fonts.getUnitsPerEm(fontDesc || desc)
@@ -2520,7 +2519,7 @@ async function createTextEngine(opts = {}) {
2520
2519
  try {
2521
2520
  const hasBackground = !!asset.background?.color;
2522
2521
  const hasAnimation = !!asset.animation?.preset;
2523
- const hasBorderRadius = (asset.background?.borderRadius ?? 0) > 0;
2522
+ const hasBorderRadius = (asset.border?.radius ?? 0) > 0;
2524
2523
  const needsAlpha = !hasBackground && hasAnimation || hasBorderRadius;
2525
2524
  console.log(
2526
2525
  `\u{1F3A8} Video settings: Animation=${hasAnimation}, Background=${hasBackground}, BorderRadius=${hasBorderRadius}, Alpha=${needsAlpha}`
@@ -63,14 +63,12 @@ type RichTextValidated = Required<{
63
63
  background?: {
64
64
  color?: string;
65
65
  opacity: number;
66
- backgroundRadius: number;
67
- borderRadius?: number;
68
- border?: {
69
- width: number;
70
- color: string;
71
- opacity: number;
72
- borderRadius?: number;
73
- };
66
+ };
67
+ border?: {
68
+ width: number;
69
+ color: string;
70
+ opacity: number;
71
+ radius: number;
74
72
  };
75
73
  padding?: number | {
76
74
  top: number;
@@ -63,14 +63,12 @@ type RichTextValidated = Required<{
63
63
  background?: {
64
64
  color?: string;
65
65
  opacity: number;
66
- backgroundRadius: number;
67
- borderRadius?: number;
68
- border?: {
69
- width: number;
70
- color: string;
71
- opacity: number;
72
- borderRadius?: number;
73
- };
66
+ };
67
+ border?: {
68
+ width: number;
69
+ color: string;
70
+ opacity: number;
71
+ radius: number;
74
72
  };
75
73
  padding?: number | {
76
74
  top: number;
@@ -98,15 +98,11 @@ var borderSchema = Joi.object({
98
98
  width: Joi.number().min(0).default(0),
99
99
  color: Joi.string().pattern(HEX6).default("#000000"),
100
100
  opacity: Joi.number().min(0).max(1).default(1),
101
- borderRadius: Joi.number().min(0).optional()
101
+ radius: Joi.number().min(0).default(0)
102
102
  }).unknown(false);
103
103
  var backgroundSchema = Joi.object({
104
104
  color: Joi.string().pattern(HEX6).optional(),
105
- opacity: Joi.number().min(0).max(1).default(1),
106
- backgroundRadius: Joi.number().min(0).default(0),
107
- borderRadius: Joi.number().min(0).optional(),
108
- // Deprecated: use backgroundRadius
109
- border: borderSchema.optional()
105
+ opacity: Joi.number().min(0).max(1).default(1)
110
106
  }).unknown(false);
111
107
  var paddingSchema = Joi.alternatives().try(
112
108
  Joi.number().min(0).default(0),
@@ -134,6 +130,7 @@ var RichTextAssetSchema = Joi.object({
134
130
  stroke: strokeSchema.optional(),
135
131
  shadow: shadowSchema.optional(),
136
132
  background: backgroundSchema.optional(),
133
+ border: borderSchema.optional(),
137
134
  padding: paddingSchema.optional(),
138
135
  align: alignmentSchema.optional(),
139
136
  animation: animationSchema.optional(),
@@ -944,40 +941,41 @@ async function buildDrawOps(p) {
944
941
  }
945
942
  }
946
943
  }
947
- if (p.background && (p.background.color || p.background.border)) {
944
+ if (p.background || p.border) {
948
945
  const bgX = 0;
949
946
  const bgY = 0;
950
947
  const bgWidth = p.canvas.width;
951
948
  const bgHeight = p.canvas.height;
952
- const backgroundRadius = p.background.backgroundRadius ?? p.background.borderRadius ?? 0;
953
- const halfBorder = p.background.border?.width ? p.background.border.width / 2 : 0;
954
- if (p.background.color) {
955
- const bgInset = halfBorder;
956
- const bgFillRadius = Math.max(0, backgroundRadius - bgInset);
949
+ const borderWidth2 = p.border?.width ?? 0;
950
+ const borderRadius = p.border?.radius ?? 0;
951
+ const halfBorder = borderWidth2 / 2;
952
+ const maxRadius = Math.min(bgWidth - borderWidth2, bgHeight - borderWidth2) / 2;
953
+ const outerRadius = Math.min(borderRadius, maxRadius);
954
+ const innerRadius = Math.max(0, outerRadius - halfBorder);
955
+ if (p.background?.color) {
957
956
  ops.push({
958
957
  op: "Rectangle",
959
- x: bgX + bgInset,
960
- y: bgY + bgInset,
961
- width: bgWidth - bgInset * 2,
962
- height: bgHeight - bgInset * 2,
958
+ x: bgX + borderWidth2,
959
+ y: bgY + borderWidth2,
960
+ width: bgWidth - borderWidth2 * 2,
961
+ height: bgHeight - borderWidth2 * 2,
963
962
  fill: { kind: "solid", color: p.background.color, opacity: p.background.opacity },
964
- borderRadius: bgFillRadius
963
+ borderRadius: innerRadius
965
964
  });
966
965
  }
967
- if (p.background.border && p.background.border.width > 0) {
968
- const borderRadius = p.background.border.borderRadius !== void 0 ? p.background.border.borderRadius : backgroundRadius;
966
+ if (p.border && p.border.width > 0) {
969
967
  ops.push({
970
968
  op: "RectangleStroke",
971
- x: bgX,
972
- y: bgY,
973
- width: bgWidth,
974
- height: bgHeight,
969
+ x: bgX + halfBorder,
970
+ y: bgY + halfBorder,
971
+ width: bgWidth - borderWidth2,
972
+ height: bgHeight - borderWidth2,
975
973
  stroke: {
976
- width: p.background.border.width,
977
- color: p.background.border.color,
978
- opacity: p.background.border.opacity
974
+ width: p.border.width,
975
+ color: p.border.color,
976
+ opacity: p.border.opacity
979
977
  },
980
- borderRadius
978
+ borderRadius: outerRadius
981
979
  });
982
980
  }
983
981
  }
@@ -2429,6 +2427,7 @@ async function createTextEngine(opts = {}) {
2429
2427
  vertical: asset.align?.vertical ?? "middle"
2430
2428
  },
2431
2429
  background: asset.background,
2430
+ border: asset.border,
2432
2431
  padding: asset.padding,
2433
2432
  glyphPathProvider: (gid, fontDesc) => fonts.glyphPath(fontDesc || desc, gid),
2434
2433
  getUnitsPerEm: (fontDesc) => fonts.getUnitsPerEm(fontDesc || desc)
@@ -2481,7 +2480,7 @@ async function createTextEngine(opts = {}) {
2481
2480
  try {
2482
2481
  const hasBackground = !!asset.background?.color;
2483
2482
  const hasAnimation = !!asset.animation?.preset;
2484
- const hasBorderRadius = (asset.background?.borderRadius ?? 0) > 0;
2483
+ const hasBorderRadius = (asset.border?.radius ?? 0) > 0;
2485
2484
  const needsAlpha = !hasBackground && hasAnimation || hasBorderRadius;
2486
2485
  console.log(
2487
2486
  `\u{1F3A8} Video settings: Animation=${hasAnimation}, Background=${hasBackground}, BorderRadius=${hasBorderRadius}, Alpha=${needsAlpha}`
@@ -63,14 +63,12 @@ type RichTextValidated = Required<{
63
63
  background?: {
64
64
  color?: string;
65
65
  opacity: number;
66
- backgroundRadius: number;
67
- borderRadius?: number;
68
- border?: {
69
- width: number;
70
- color: string;
71
- opacity: number;
72
- borderRadius?: number;
73
- };
66
+ };
67
+ border?: {
68
+ width: number;
69
+ color: string;
70
+ opacity: number;
71
+ radius: number;
74
72
  };
75
73
  padding?: number | {
76
74
  top: number;
package/dist/entry.web.js CHANGED
@@ -102,15 +102,11 @@ var borderSchema = Joi.object({
102
102
  width: Joi.number().min(0).default(0),
103
103
  color: Joi.string().pattern(HEX6).default("#000000"),
104
104
  opacity: Joi.number().min(0).max(1).default(1),
105
- borderRadius: Joi.number().min(0).optional()
105
+ radius: Joi.number().min(0).default(0)
106
106
  }).unknown(false);
107
107
  var backgroundSchema = Joi.object({
108
108
  color: Joi.string().pattern(HEX6).optional(),
109
- opacity: Joi.number().min(0).max(1).default(1),
110
- backgroundRadius: Joi.number().min(0).default(0),
111
- borderRadius: Joi.number().min(0).optional(),
112
- // Deprecated: use backgroundRadius
113
- border: borderSchema.optional()
109
+ opacity: Joi.number().min(0).max(1).default(1)
114
110
  }).unknown(false);
115
111
  var paddingSchema = Joi.alternatives().try(
116
112
  Joi.number().min(0).default(0),
@@ -138,6 +134,7 @@ var RichTextAssetSchema = Joi.object({
138
134
  stroke: strokeSchema.optional(),
139
135
  shadow: shadowSchema.optional(),
140
136
  background: backgroundSchema.optional(),
137
+ border: borderSchema.optional(),
141
138
  padding: paddingSchema.optional(),
142
139
  align: alignmentSchema.optional(),
143
140
  animation: animationSchema.optional(),
@@ -949,40 +946,41 @@ async function buildDrawOps(p) {
949
946
  }
950
947
  }
951
948
  }
952
- if (p.background && (p.background.color || p.background.border)) {
949
+ if (p.background || p.border) {
953
950
  const bgX = 0;
954
951
  const bgY = 0;
955
952
  const bgWidth = p.canvas.width;
956
953
  const bgHeight = p.canvas.height;
957
- const backgroundRadius = p.background.backgroundRadius ?? p.background.borderRadius ?? 0;
958
- const halfBorder = p.background.border?.width ? p.background.border.width / 2 : 0;
959
- if (p.background.color) {
960
- const bgInset = halfBorder;
961
- const bgFillRadius = Math.max(0, backgroundRadius - bgInset);
954
+ const borderWidth2 = p.border?.width ?? 0;
955
+ const borderRadius = p.border?.radius ?? 0;
956
+ const halfBorder = borderWidth2 / 2;
957
+ const maxRadius = Math.min(bgWidth - borderWidth2, bgHeight - borderWidth2) / 2;
958
+ const outerRadius = Math.min(borderRadius, maxRadius);
959
+ const innerRadius = Math.max(0, outerRadius - halfBorder);
960
+ if (p.background?.color) {
962
961
  ops.push({
963
962
  op: "Rectangle",
964
- x: bgX + bgInset,
965
- y: bgY + bgInset,
966
- width: bgWidth - bgInset * 2,
967
- height: bgHeight - bgInset * 2,
963
+ x: bgX + borderWidth2,
964
+ y: bgY + borderWidth2,
965
+ width: bgWidth - borderWidth2 * 2,
966
+ height: bgHeight - borderWidth2 * 2,
968
967
  fill: { kind: "solid", color: p.background.color, opacity: p.background.opacity },
969
- borderRadius: bgFillRadius
968
+ borderRadius: innerRadius
970
969
  });
971
970
  }
972
- if (p.background.border && p.background.border.width > 0) {
973
- const borderRadius = p.background.border.borderRadius !== void 0 ? p.background.border.borderRadius : backgroundRadius;
971
+ if (p.border && p.border.width > 0) {
974
972
  ops.push({
975
973
  op: "RectangleStroke",
976
- x: bgX,
977
- y: bgY,
978
- width: bgWidth,
979
- height: bgHeight,
974
+ x: bgX + halfBorder,
975
+ y: bgY + halfBorder,
976
+ width: bgWidth - borderWidth2,
977
+ height: bgHeight - borderWidth2,
980
978
  stroke: {
981
- width: p.background.border.width,
982
- color: p.background.border.color,
983
- opacity: p.background.border.opacity
979
+ width: p.border.width,
980
+ color: p.border.color,
981
+ opacity: p.border.opacity
984
982
  },
985
- borderRadius
983
+ borderRadius: outerRadius
986
984
  });
987
985
  }
988
986
  }
@@ -2153,6 +2151,7 @@ async function createTextEngine(opts = {}) {
2153
2151
  vertical: asset.align?.vertical ?? "middle"
2154
2152
  },
2155
2153
  background: asset.background,
2154
+ border: asset.border,
2156
2155
  padding: asset.padding,
2157
2156
  glyphPathProvider: (gid, fontDesc) => fonts.glyphPath(fontDesc || desc, gid),
2158
2157
  getUnitsPerEm: (fontDesc) => fonts.getUnitsPerEm(fontDesc || desc)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shotstack/shotstack-canvas",
3
- "version": "1.5.5",
3
+ "version": "1.5.6",
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",