@shotstack/shotstack-canvas 1.4.6 → 1.5.0
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/chunk-HYGMWVDX.js +19 -0
- package/dist/entry.node.cjs +154 -30
- package/dist/entry.node.d.cts +31 -0
- package/dist/entry.node.d.ts +31 -0
- package/dist/entry.node.js +154 -30
- package/dist/entry.web.d.ts +31 -0
- package/dist/entry.web.js +161 -33
- package/dist/hb-KXF2MJ2J.js +550 -0
- package/dist/hbjs-ZTRARROF.js +499 -0
- package/package.json +62 -62
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
5
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
6
|
+
}) : x)(function(x) {
|
|
7
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
8
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
9
|
+
});
|
|
10
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
11
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
12
|
+
};
|
|
13
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
__require,
|
|
17
|
+
__commonJS,
|
|
18
|
+
__publicField
|
|
19
|
+
};
|
package/dist/entry.node.cjs
CHANGED
|
@@ -132,11 +132,26 @@ var animationSchema = import_joi.default.object({
|
|
|
132
132
|
otherwise: import_joi.default.forbidden()
|
|
133
133
|
})
|
|
134
134
|
}).unknown(false);
|
|
135
|
+
var borderSchema = import_joi.default.object({
|
|
136
|
+
width: import_joi.default.number().min(0).default(0),
|
|
137
|
+
color: import_joi.default.string().pattern(HEX6).default("#000000"),
|
|
138
|
+
opacity: import_joi.default.number().min(0).max(1).default(1)
|
|
139
|
+
}).unknown(false);
|
|
135
140
|
var backgroundSchema = import_joi.default.object({
|
|
136
141
|
color: import_joi.default.string().pattern(HEX6).optional(),
|
|
137
142
|
opacity: import_joi.default.number().min(0).max(1).default(1),
|
|
138
|
-
borderRadius: import_joi.default.number().min(0).default(0)
|
|
143
|
+
borderRadius: import_joi.default.number().min(0).default(0),
|
|
144
|
+
border: borderSchema.optional()
|
|
139
145
|
}).unknown(false);
|
|
146
|
+
var paddingSchema = import_joi.default.alternatives().try(
|
|
147
|
+
import_joi.default.number().min(0).default(0),
|
|
148
|
+
import_joi.default.object({
|
|
149
|
+
top: import_joi.default.number().min(0).default(0),
|
|
150
|
+
right: import_joi.default.number().min(0).default(0),
|
|
151
|
+
bottom: import_joi.default.number().min(0).default(0),
|
|
152
|
+
left: import_joi.default.number().min(0).default(0)
|
|
153
|
+
}).unknown(false)
|
|
154
|
+
);
|
|
140
155
|
var customFontSchema = import_joi.default.object({
|
|
141
156
|
src: import_joi.default.string().uri().required(),
|
|
142
157
|
family: import_joi.default.string().required(),
|
|
@@ -154,6 +169,7 @@ var RichTextAssetSchema = import_joi.default.object({
|
|
|
154
169
|
stroke: strokeSchema.optional(),
|
|
155
170
|
shadow: shadowSchema.optional(),
|
|
156
171
|
background: backgroundSchema.optional(),
|
|
172
|
+
padding: paddingSchema.optional(),
|
|
157
173
|
align: alignmentSchema.optional(),
|
|
158
174
|
animation: animationSchema.optional(),
|
|
159
175
|
customFonts: import_joi.default.array().items(customFontSchema).optional(),
|
|
@@ -293,6 +309,23 @@ function setupWasmInterceptors(wasmBinary) {
|
|
|
293
309
|
}
|
|
294
310
|
return originalFetch.apply(this, [input, init]);
|
|
295
311
|
};
|
|
312
|
+
const originalInstantiate = WebAssembly.instantiate;
|
|
313
|
+
WebAssembly.instantiate = async function(bufferSourceOrModule, importObject) {
|
|
314
|
+
console.log(
|
|
315
|
+
`\u{1F504} WebAssembly.instantiate called, type: ${bufferSourceOrModule instanceof WebAssembly.Module ? "Module" : "BufferSource"}`
|
|
316
|
+
);
|
|
317
|
+
if (bufferSourceOrModule instanceof WebAssembly.Module) {
|
|
318
|
+
return originalInstantiate.call(WebAssembly, bufferSourceOrModule, importObject);
|
|
319
|
+
}
|
|
320
|
+
console.log(`\u{1F504} Intercepted WebAssembly.instantiate, using pre-loaded WASM binary`);
|
|
321
|
+
const module2 = await WebAssembly.compile(wasmBinary);
|
|
322
|
+
const instance = await originalInstantiate.call(
|
|
323
|
+
WebAssembly,
|
|
324
|
+
module2,
|
|
325
|
+
importObject
|
|
326
|
+
);
|
|
327
|
+
return { module: module2, instance };
|
|
328
|
+
};
|
|
296
329
|
const originalInstantiateStreaming = WebAssembly.instantiateStreaming;
|
|
297
330
|
if (originalInstantiateStreaming) {
|
|
298
331
|
WebAssembly.instantiateStreaming = async function(source, importObject) {
|
|
@@ -330,21 +363,25 @@ async function initHB(wasmBaseURL) {
|
|
|
330
363
|
console.log(`\u2705 WASM binary loaded successfully (${wasmBinary.byteLength} bytes)`);
|
|
331
364
|
if (!isNode()) {
|
|
332
365
|
setupWasmInterceptors(wasmBinary);
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
}
|
|
366
|
+
window.Module = {
|
|
367
|
+
wasmBinary,
|
|
368
|
+
locateFile: (path) => {
|
|
369
|
+
console.log(`\u{1F50D} locateFile called for: ${path}`);
|
|
370
|
+
return path;
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
console.log(`\u{1F30D} Set global Module.wasmBinary (${wasmBinary.byteLength} bytes)`);
|
|
374
|
+
}
|
|
375
|
+
console.log("\u{1F504} Importing harfbuzzjs/hb.js (factory)");
|
|
376
|
+
const hbModule = await import("harfbuzzjs/hb.js");
|
|
377
|
+
const hbFactory = hbModule.default || hbModule;
|
|
378
|
+
console.log("\u{1F504} Calling hb factory with wasmBinary");
|
|
379
|
+
const hbInstance = await hbFactory({ wasmBinary });
|
|
380
|
+
console.log("\u{1F504} Importing harfbuzzjs/hbjs.js (wrapper)");
|
|
381
|
+
const hbjsModule = await import("harfbuzzjs/hbjs.js");
|
|
382
|
+
const hbjsWrapper = hbjsModule.default || hbjsModule;
|
|
383
|
+
console.log("\u{1F504} Wrapping hb instance");
|
|
384
|
+
const hb = hbjsWrapper(hbInstance);
|
|
348
385
|
if (!hb || typeof hb.createBuffer !== "function" || typeof hb.createFont !== "function") {
|
|
349
386
|
throw new Error("Failed to initialize HarfBuzz: unexpected export shape from 'harfbuzzjs'.");
|
|
350
387
|
}
|
|
@@ -807,15 +844,27 @@ function decorationGeometry(kind, p) {
|
|
|
807
844
|
}
|
|
808
845
|
|
|
809
846
|
// src/core/drawops.ts
|
|
847
|
+
function normalizePadding(padding) {
|
|
848
|
+
if (padding === void 0 || padding === null) {
|
|
849
|
+
return { top: 0, right: 0, bottom: 0, left: 0 };
|
|
850
|
+
}
|
|
851
|
+
if (typeof padding === "number") {
|
|
852
|
+
return { top: padding, right: padding, bottom: padding, left: padding };
|
|
853
|
+
}
|
|
854
|
+
return padding;
|
|
855
|
+
}
|
|
810
856
|
async function buildDrawOps(p) {
|
|
811
857
|
const ops = [];
|
|
858
|
+
const padding = normalizePadding(p.padding);
|
|
859
|
+
const borderWidth = p.background?.border?.width ?? 0;
|
|
812
860
|
ops.push({
|
|
813
861
|
op: "BeginFrame",
|
|
814
862
|
width: p.canvas.width,
|
|
815
863
|
height: p.canvas.height,
|
|
816
864
|
pixelRatio: p.canvas.pixelRatio,
|
|
817
865
|
clear: true,
|
|
818
|
-
bg:
|
|
866
|
+
bg: void 0
|
|
867
|
+
// Background will be drawn as a separate layer with proper padding/border
|
|
819
868
|
});
|
|
820
869
|
if (p.lines.length === 0) return ops;
|
|
821
870
|
const upem = Math.max(1, await p.getUnitsPerEm());
|
|
@@ -825,33 +874,34 @@ async function buildDrawOps(p) {
|
|
|
825
874
|
let blockY;
|
|
826
875
|
switch (p.align.vertical) {
|
|
827
876
|
case "top":
|
|
828
|
-
blockY = p.font.size;
|
|
877
|
+
blockY = p.font.size + padding.top;
|
|
829
878
|
break;
|
|
830
879
|
case "bottom":
|
|
831
|
-
blockY = p.textRect.height - (numLines - 1) * lineHeightPx;
|
|
880
|
+
blockY = p.textRect.height - (numLines - 1) * lineHeightPx + padding.top;
|
|
832
881
|
break;
|
|
833
882
|
case "middle":
|
|
834
883
|
default:
|
|
835
884
|
const capHeightRatio = 0.35;
|
|
836
885
|
const visualOffset = p.font.size * capHeightRatio;
|
|
837
|
-
blockY = (p.textRect.height - (numLines - 1) * lineHeightPx) / 2 + visualOffset;
|
|
886
|
+
blockY = (p.textRect.height - (numLines - 1) * lineHeightPx) / 2 + visualOffset + padding.top;
|
|
838
887
|
break;
|
|
839
888
|
}
|
|
840
889
|
const fill = p.style.gradient ? gradientSpecFrom(p.style.gradient, 1) : { kind: "solid", color: p.font.color, opacity: p.font.opacity };
|
|
841
890
|
const decoColor = p.style.gradient ? p.style.gradient.stops[p.style.gradient.stops.length - 1]?.color ?? p.font.color : p.font.color;
|
|
891
|
+
const textOps = [];
|
|
842
892
|
let gMinX = Infinity, gMinY = Infinity, gMaxX = -Infinity, gMaxY = -Infinity;
|
|
843
893
|
for (const line of p.lines) {
|
|
844
894
|
let lineX;
|
|
845
895
|
switch (p.align.horizontal) {
|
|
846
896
|
case "left":
|
|
847
|
-
lineX =
|
|
897
|
+
lineX = padding.left;
|
|
848
898
|
break;
|
|
849
899
|
case "right":
|
|
850
|
-
lineX = p.textRect.width - line.width;
|
|
900
|
+
lineX = p.textRect.width - line.width + padding.left;
|
|
851
901
|
break;
|
|
852
902
|
case "center":
|
|
853
903
|
default:
|
|
854
|
-
lineX = (p.textRect.width - line.width) / 2;
|
|
904
|
+
lineX = (p.textRect.width - line.width) / 2 + padding.left;
|
|
855
905
|
break;
|
|
856
906
|
}
|
|
857
907
|
let xCursor = lineX;
|
|
@@ -875,7 +925,7 @@ async function buildDrawOps(p) {
|
|
|
875
925
|
if (x2 > gMaxX) gMaxX = x2;
|
|
876
926
|
if (y2 > gMaxY) gMaxY = y2;
|
|
877
927
|
if (p.shadow && p.shadow.blur > 0) {
|
|
878
|
-
|
|
928
|
+
textOps.push({
|
|
879
929
|
isShadow: true,
|
|
880
930
|
op: "FillPath",
|
|
881
931
|
path,
|
|
@@ -886,7 +936,7 @@ async function buildDrawOps(p) {
|
|
|
886
936
|
});
|
|
887
937
|
}
|
|
888
938
|
if (p.stroke && p.stroke.width > 0) {
|
|
889
|
-
|
|
939
|
+
textOps.push({
|
|
890
940
|
op: "StrokePath",
|
|
891
941
|
path,
|
|
892
942
|
x: glyphX,
|
|
@@ -897,7 +947,7 @@ async function buildDrawOps(p) {
|
|
|
897
947
|
opacity: p.stroke.opacity
|
|
898
948
|
});
|
|
899
949
|
}
|
|
900
|
-
|
|
950
|
+
textOps.push({
|
|
901
951
|
op: "FillPath",
|
|
902
952
|
path,
|
|
903
953
|
x: glyphX,
|
|
@@ -914,7 +964,7 @@ async function buildDrawOps(p) {
|
|
|
914
964
|
lineWidth: line.width,
|
|
915
965
|
xStart: lineX
|
|
916
966
|
});
|
|
917
|
-
|
|
967
|
+
textOps.push({
|
|
918
968
|
op: "DecorationLine",
|
|
919
969
|
from: { x: deco.x1, y: deco.y },
|
|
920
970
|
to: { x: deco.x2, y: deco.y },
|
|
@@ -926,12 +976,46 @@ async function buildDrawOps(p) {
|
|
|
926
976
|
}
|
|
927
977
|
if (gMinX !== Infinity) {
|
|
928
978
|
const gbox = { x: gMinX, y: gMinY, w: Math.max(1, gMaxX - gMinX), h: Math.max(1, gMaxY - gMinY) };
|
|
929
|
-
for (const op of
|
|
979
|
+
for (const op of textOps) {
|
|
930
980
|
if (op.op === "FillPath" && !op.isShadow) {
|
|
931
981
|
op.gradientBBox = gbox;
|
|
932
982
|
}
|
|
933
983
|
}
|
|
934
984
|
}
|
|
985
|
+
if (p.background && (p.background.color || p.background.border)) {
|
|
986
|
+
const bgX = 0;
|
|
987
|
+
const bgY = 0;
|
|
988
|
+
const bgWidth = p.canvas.width;
|
|
989
|
+
const bgHeight = p.canvas.height;
|
|
990
|
+
if (p.background.color) {
|
|
991
|
+
ops.push({
|
|
992
|
+
op: "Rectangle",
|
|
993
|
+
x: bgX,
|
|
994
|
+
y: bgY,
|
|
995
|
+
width: bgWidth,
|
|
996
|
+
height: bgHeight,
|
|
997
|
+
fill: { kind: "solid", color: p.background.color, opacity: p.background.opacity },
|
|
998
|
+
borderRadius: p.background.borderRadius
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
if (p.background.border && p.background.border.width > 0) {
|
|
1002
|
+
const halfBorder = p.background.border.width / 2;
|
|
1003
|
+
ops.push({
|
|
1004
|
+
op: "RectangleStroke",
|
|
1005
|
+
x: bgX + halfBorder,
|
|
1006
|
+
y: bgY + halfBorder,
|
|
1007
|
+
width: bgWidth - p.background.border.width,
|
|
1008
|
+
height: bgHeight - p.background.border.width,
|
|
1009
|
+
stroke: {
|
|
1010
|
+
width: p.background.border.width,
|
|
1011
|
+
color: p.background.border.color,
|
|
1012
|
+
opacity: p.background.border.opacity
|
|
1013
|
+
},
|
|
1014
|
+
borderRadius: Math.max(0, p.background.borderRadius - halfBorder)
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
ops.push(...textOps);
|
|
935
1019
|
return ops;
|
|
936
1020
|
}
|
|
937
1021
|
function tokenizePath(d) {
|
|
@@ -1741,6 +1825,44 @@ async function createNodePainter(opts) {
|
|
|
1741
1825
|
});
|
|
1742
1826
|
continue;
|
|
1743
1827
|
}
|
|
1828
|
+
if (op.op === "Rectangle") {
|
|
1829
|
+
renderToBoth((context) => {
|
|
1830
|
+
context.save();
|
|
1831
|
+
const fill = makeGradientFromBBox(context, op.fill, {
|
|
1832
|
+
x: op.x,
|
|
1833
|
+
y: op.y,
|
|
1834
|
+
w: op.width,
|
|
1835
|
+
h: op.height
|
|
1836
|
+
});
|
|
1837
|
+
context.fillStyle = fill;
|
|
1838
|
+
if (op.borderRadius && op.borderRadius > 0) {
|
|
1839
|
+
context.beginPath();
|
|
1840
|
+
roundRectPath(context, op.x, op.y, op.width, op.height, op.borderRadius);
|
|
1841
|
+
context.fill();
|
|
1842
|
+
} else {
|
|
1843
|
+
context.fillRect(op.x, op.y, op.width, op.height);
|
|
1844
|
+
}
|
|
1845
|
+
context.restore();
|
|
1846
|
+
});
|
|
1847
|
+
continue;
|
|
1848
|
+
}
|
|
1849
|
+
if (op.op === "RectangleStroke") {
|
|
1850
|
+
renderToBoth((context) => {
|
|
1851
|
+
context.save();
|
|
1852
|
+
const c = parseHex6(op.stroke.color, op.stroke.opacity);
|
|
1853
|
+
context.strokeStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
|
|
1854
|
+
context.lineWidth = op.stroke.width;
|
|
1855
|
+
if (op.borderRadius && op.borderRadius > 0) {
|
|
1856
|
+
context.beginPath();
|
|
1857
|
+
roundRectPath(context, op.x, op.y, op.width, op.height, op.borderRadius);
|
|
1858
|
+
context.stroke();
|
|
1859
|
+
} else {
|
|
1860
|
+
context.strokeRect(op.x, op.y, op.width, op.height);
|
|
1861
|
+
}
|
|
1862
|
+
context.restore();
|
|
1863
|
+
});
|
|
1864
|
+
continue;
|
|
1865
|
+
}
|
|
1744
1866
|
}
|
|
1745
1867
|
if (needsAlphaExtraction) {
|
|
1746
1868
|
const whiteData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
@@ -2304,14 +2426,15 @@ async function createTextEngine(opts = {}) {
|
|
|
2304
2426
|
`Failed to layout text: ${err instanceof Error ? err.message : String(err)}`
|
|
2305
2427
|
);
|
|
2306
2428
|
}
|
|
2429
|
+
const padding = asset.padding ? typeof asset.padding === "number" ? { top: asset.padding, right: asset.padding, bottom: asset.padding, left: asset.padding } : asset.padding : { top: 0, right: 0, bottom: 0, left: 0 };
|
|
2307
2430
|
const textRect = {
|
|
2308
2431
|
x: 0,
|
|
2309
2432
|
y: 0,
|
|
2310
2433
|
width: asset.width ?? width,
|
|
2311
2434
|
height: asset.height ?? height
|
|
2312
2435
|
};
|
|
2313
|
-
const canvasW = asset.width ?? width;
|
|
2314
|
-
const canvasH = asset.height ?? height;
|
|
2436
|
+
const canvasW = (asset.width ?? width) + padding.left + padding.right;
|
|
2437
|
+
const canvasH = (asset.height ?? height) + padding.top + padding.bottom;
|
|
2315
2438
|
const canvasPR = asset.pixelRatio ?? pixelRatio;
|
|
2316
2439
|
let ops0;
|
|
2317
2440
|
try {
|
|
@@ -2338,6 +2461,7 @@ async function createTextEngine(opts = {}) {
|
|
|
2338
2461
|
vertical: asset.align?.vertical ?? "middle"
|
|
2339
2462
|
},
|
|
2340
2463
|
background: asset.background,
|
|
2464
|
+
padding: asset.padding,
|
|
2341
2465
|
glyphPathProvider: (gid, fontDesc) => fonts.glyphPath(fontDesc || desc, gid),
|
|
2342
2466
|
getUnitsPerEm: (fontDesc) => fonts.getUnitsPerEm(fontDesc || desc)
|
|
2343
2467
|
});
|
package/dist/entry.node.d.cts
CHANGED
|
@@ -64,6 +64,17 @@ type RichTextValidated = Required<{
|
|
|
64
64
|
color?: string;
|
|
65
65
|
opacity: number;
|
|
66
66
|
borderRadius: number;
|
|
67
|
+
border?: {
|
|
68
|
+
width: number;
|
|
69
|
+
color: string;
|
|
70
|
+
opacity: number;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
padding?: number | {
|
|
74
|
+
top: number;
|
|
75
|
+
right: number;
|
|
76
|
+
bottom: number;
|
|
77
|
+
left: number;
|
|
67
78
|
};
|
|
68
79
|
align?: {
|
|
69
80
|
horizontal: "left" | "center" | "right";
|
|
@@ -177,6 +188,26 @@ type DrawOp = {
|
|
|
177
188
|
width: number;
|
|
178
189
|
color: string;
|
|
179
190
|
opacity: number;
|
|
191
|
+
} | {
|
|
192
|
+
op: "Rectangle";
|
|
193
|
+
x: number;
|
|
194
|
+
y: number;
|
|
195
|
+
width: number;
|
|
196
|
+
height: number;
|
|
197
|
+
fill: GradientSpec;
|
|
198
|
+
borderRadius?: number;
|
|
199
|
+
} | {
|
|
200
|
+
op: "RectangleStroke";
|
|
201
|
+
x: number;
|
|
202
|
+
y: number;
|
|
203
|
+
width: number;
|
|
204
|
+
height: number;
|
|
205
|
+
stroke: {
|
|
206
|
+
width: number;
|
|
207
|
+
color: string;
|
|
208
|
+
opacity: number;
|
|
209
|
+
};
|
|
210
|
+
borderRadius?: number;
|
|
180
211
|
};
|
|
181
212
|
type EngineInit = {
|
|
182
213
|
width: number;
|
package/dist/entry.node.d.ts
CHANGED
|
@@ -64,6 +64,17 @@ type RichTextValidated = Required<{
|
|
|
64
64
|
color?: string;
|
|
65
65
|
opacity: number;
|
|
66
66
|
borderRadius: number;
|
|
67
|
+
border?: {
|
|
68
|
+
width: number;
|
|
69
|
+
color: string;
|
|
70
|
+
opacity: number;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
padding?: number | {
|
|
74
|
+
top: number;
|
|
75
|
+
right: number;
|
|
76
|
+
bottom: number;
|
|
77
|
+
left: number;
|
|
67
78
|
};
|
|
68
79
|
align?: {
|
|
69
80
|
horizontal: "left" | "center" | "right";
|
|
@@ -177,6 +188,26 @@ type DrawOp = {
|
|
|
177
188
|
width: number;
|
|
178
189
|
color: string;
|
|
179
190
|
opacity: number;
|
|
191
|
+
} | {
|
|
192
|
+
op: "Rectangle";
|
|
193
|
+
x: number;
|
|
194
|
+
y: number;
|
|
195
|
+
width: number;
|
|
196
|
+
height: number;
|
|
197
|
+
fill: GradientSpec;
|
|
198
|
+
borderRadius?: number;
|
|
199
|
+
} | {
|
|
200
|
+
op: "RectangleStroke";
|
|
201
|
+
x: number;
|
|
202
|
+
y: number;
|
|
203
|
+
width: number;
|
|
204
|
+
height: number;
|
|
205
|
+
stroke: {
|
|
206
|
+
width: number;
|
|
207
|
+
color: string;
|
|
208
|
+
opacity: number;
|
|
209
|
+
};
|
|
210
|
+
borderRadius?: number;
|
|
180
211
|
};
|
|
181
212
|
type EngineInit = {
|
|
182
213
|
width: number;
|