@shotstack/shotstack-canvas 1.8.3 → 1.8.4
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/entry.node.cjs +499 -726
- package/dist/entry.node.d.cts +78 -186
- package/dist/entry.node.d.ts +78 -186
- package/dist/entry.node.js +493 -699
- package/dist/entry.web.d.ts +79 -186
- package/dist/entry.web.js +527 -711
- package/package.json +3 -1
package/dist/entry.node.cjs
CHANGED
|
@@ -33,38 +33,20 @@ __export(entry_node_exports, {
|
|
|
33
33
|
CanvasRichTextAssetSchema: () => CanvasRichTextAssetSchema,
|
|
34
34
|
CanvasSvgAssetSchema: () => CanvasSvgAssetSchema,
|
|
35
35
|
arcToCubicBeziers: () => arcToCubicBeziers,
|
|
36
|
-
centerPath: () => centerPath,
|
|
37
36
|
commandsToPathString: () => commandsToPathString,
|
|
38
|
-
|
|
37
|
+
computeSimplePathBounds: () => computeSimplePathBounds,
|
|
39
38
|
createNodePainter: () => createNodePainter,
|
|
40
39
|
createTextEngine: () => createTextEngine,
|
|
41
|
-
|
|
42
|
-
generateCirclePath: () => generateCirclePath,
|
|
43
|
-
generateCrossPath: () => generateCrossPath,
|
|
44
|
-
generateEllipsePath: () => generateEllipsePath,
|
|
45
|
-
generateHeartPath: () => generateHeartPath,
|
|
46
|
-
generateLinePath: () => generateLinePath,
|
|
47
|
-
generatePolygonPath: () => generatePolygonPath,
|
|
48
|
-
generatePolygonPoints: () => generatePolygonPoints,
|
|
49
|
-
generateRectanglePath: () => generateRectanglePath,
|
|
50
|
-
generateRingPath: () => generateRingPath,
|
|
51
|
-
generateShapePath: () => generateShapePath,
|
|
52
|
-
generateStarPath: () => generateStarPath,
|
|
53
|
-
generateStarPoints: () => generateStarPoints,
|
|
54
|
-
generateTrianglePath: () => generateTrianglePath,
|
|
55
|
-
importSvg: () => importSvg,
|
|
40
|
+
generateShapePathData: () => generateShapePathData,
|
|
56
41
|
isGlyphFill: () => isGlyphFill2,
|
|
57
42
|
isShadowFill: () => isShadowFill2,
|
|
58
43
|
normalizePath: () => normalizePath,
|
|
59
44
|
normalizePathString: () => normalizePathString,
|
|
60
|
-
normalizePathToSize: () => normalizePathToSize,
|
|
61
|
-
parseSvgMarkup: () => parseSvgMarkup,
|
|
62
45
|
parseSvgPath: () => parseSvgPath,
|
|
63
|
-
pointsToPath: () => pointsToPath,
|
|
64
46
|
quadraticToCubic: () => quadraticToCubic,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
47
|
+
renderSvgAssetToPng: () => renderSvgAssetToPng,
|
|
48
|
+
renderSvgToPng: () => renderSvgToPng,
|
|
49
|
+
shapeToSvgString: () => shapeToSvgString,
|
|
68
50
|
svgAssetSchema: () => import_zod2.svgAssetSchema,
|
|
69
51
|
svgGradientStopSchema: () => import_zod2.svgGradientStopSchema,
|
|
70
52
|
svgLinearGradientFillSchema: () => import_zod2.svgLinearGradientFillSchema,
|
|
@@ -73,10 +55,7 @@ __export(entry_node_exports, {
|
|
|
73
55
|
svgShapeSchema: () => import_zod2.svgShapeSchema,
|
|
74
56
|
svgSolidFillSchema: () => import_zod2.svgSolidFillSchema,
|
|
75
57
|
svgStrokeSchema: () => import_zod2.svgStrokeSchema,
|
|
76
|
-
|
|
77
|
-
svgToSingleAsset: () => svgToSingleAsset,
|
|
78
|
-
svgTransformSchema: () => import_zod2.svgTransformSchema,
|
|
79
|
-
translatePath: () => translatePath
|
|
58
|
+
svgTransformSchema: () => import_zod2.svgTransformSchema
|
|
80
59
|
});
|
|
81
60
|
module.exports = __toCommonJS(entry_node_exports);
|
|
82
61
|
|
|
@@ -2755,335 +2734,6 @@ var isGlyphFill2 = (op) => {
|
|
|
2755
2734
|
return op.op === "FillPath" && op.isShadow !== true;
|
|
2756
2735
|
};
|
|
2757
2736
|
|
|
2758
|
-
// src/core/shape-generators.ts
|
|
2759
|
-
var KAPPA = 0.5522847498307936;
|
|
2760
|
-
var DEG_TO_RAD = Math.PI / 180;
|
|
2761
|
-
function generateShapePath(params) {
|
|
2762
|
-
switch (params.shape) {
|
|
2763
|
-
case "rectangle":
|
|
2764
|
-
return generateRectanglePath(params);
|
|
2765
|
-
case "circle":
|
|
2766
|
-
return generateCirclePath(params);
|
|
2767
|
-
case "ellipse":
|
|
2768
|
-
return generateEllipsePath(params);
|
|
2769
|
-
case "line":
|
|
2770
|
-
return generateLinePath(params);
|
|
2771
|
-
case "triangle":
|
|
2772
|
-
return generateTrianglePath(params);
|
|
2773
|
-
case "polygon":
|
|
2774
|
-
return generatePolygonPath(params);
|
|
2775
|
-
case "star":
|
|
2776
|
-
return generateStarPath(params);
|
|
2777
|
-
case "arrow":
|
|
2778
|
-
return generateArrowPath(params);
|
|
2779
|
-
case "heart":
|
|
2780
|
-
return generateHeartPath(params);
|
|
2781
|
-
case "cross":
|
|
2782
|
-
return generateCrossPath(params);
|
|
2783
|
-
case "ring":
|
|
2784
|
-
return generateRingPath(params);
|
|
2785
|
-
}
|
|
2786
|
-
}
|
|
2787
|
-
function generateRectanglePath(params) {
|
|
2788
|
-
const { width, height, cornerRadius = 0 } = params;
|
|
2789
|
-
if (cornerRadius === 0) {
|
|
2790
|
-
return `M 0 0 L ${width} 0 L ${width} ${height} L 0 ${height} Z`;
|
|
2791
|
-
}
|
|
2792
|
-
const r = Math.min(cornerRadius, width / 2, height / 2);
|
|
2793
|
-
return [
|
|
2794
|
-
`M ${r} 0`,
|
|
2795
|
-
`L ${width - r} 0`,
|
|
2796
|
-
`Q ${width} 0 ${width} ${r}`,
|
|
2797
|
-
`L ${width} ${height - r}`,
|
|
2798
|
-
`Q ${width} ${height} ${width - r} ${height}`,
|
|
2799
|
-
`L ${r} ${height}`,
|
|
2800
|
-
`Q 0 ${height} 0 ${height - r}`,
|
|
2801
|
-
`L 0 ${r}`,
|
|
2802
|
-
`Q 0 0 ${r} 0`,
|
|
2803
|
-
"Z"
|
|
2804
|
-
].join(" ");
|
|
2805
|
-
}
|
|
2806
|
-
function generateCirclePath(params) {
|
|
2807
|
-
const { radius } = params;
|
|
2808
|
-
return generateEllipsePath({ radiusX: radius, radiusY: radius });
|
|
2809
|
-
}
|
|
2810
|
-
function generateEllipsePath(params) {
|
|
2811
|
-
const { radiusX, radiusY } = params;
|
|
2812
|
-
const kx = radiusX * KAPPA;
|
|
2813
|
-
const ky = radiusY * KAPPA;
|
|
2814
|
-
return [
|
|
2815
|
-
`M ${radiusX} 0`,
|
|
2816
|
-
`C ${radiusX} ${ky} ${kx} ${radiusY} 0 ${radiusY}`,
|
|
2817
|
-
`C ${-kx} ${radiusY} ${-radiusX} ${ky} ${-radiusX} 0`,
|
|
2818
|
-
`C ${-radiusX} ${-ky} ${-kx} ${-radiusY} 0 ${-radiusY}`,
|
|
2819
|
-
`C ${kx} ${-radiusY} ${radiusX} ${-ky} ${radiusX} 0`,
|
|
2820
|
-
"Z"
|
|
2821
|
-
].join(" ");
|
|
2822
|
-
}
|
|
2823
|
-
function generateLinePath(params) {
|
|
2824
|
-
const { length, thickness } = params;
|
|
2825
|
-
const halfThickness = thickness / 2;
|
|
2826
|
-
return [
|
|
2827
|
-
`M 0 ${-halfThickness}`,
|
|
2828
|
-
`L ${length} ${-halfThickness}`,
|
|
2829
|
-
`L ${length} ${halfThickness}`,
|
|
2830
|
-
`L 0 ${halfThickness}`,
|
|
2831
|
-
"Z"
|
|
2832
|
-
].join(" ");
|
|
2833
|
-
}
|
|
2834
|
-
function generateTrianglePath(params) {
|
|
2835
|
-
const { width, height } = params;
|
|
2836
|
-
const halfWidth = width / 2;
|
|
2837
|
-
return `M 0 ${height} L ${halfWidth} 0 L ${width} ${height} Z`;
|
|
2838
|
-
}
|
|
2839
|
-
function generatePolygonPath(params) {
|
|
2840
|
-
const { sides, radius } = params;
|
|
2841
|
-
const points = generatePolygonPoints(sides, radius);
|
|
2842
|
-
return pointsToPath(points, true);
|
|
2843
|
-
}
|
|
2844
|
-
function generatePolygonPoints(sides, radius) {
|
|
2845
|
-
const points = [];
|
|
2846
|
-
const angleStep = 2 * Math.PI / sides;
|
|
2847
|
-
const startAngle = -Math.PI / 2;
|
|
2848
|
-
for (let i = 0; i < sides; i++) {
|
|
2849
|
-
const angle = startAngle + i * angleStep;
|
|
2850
|
-
points.push({
|
|
2851
|
-
x: radius * Math.cos(angle),
|
|
2852
|
-
y: radius * Math.sin(angle)
|
|
2853
|
-
});
|
|
2854
|
-
}
|
|
2855
|
-
return points;
|
|
2856
|
-
}
|
|
2857
|
-
function generateStarPath(params) {
|
|
2858
|
-
const { points, outerRadius, innerRadius } = params;
|
|
2859
|
-
const starPoints = generateStarPoints(points, outerRadius, innerRadius);
|
|
2860
|
-
return pointsToPath(starPoints, true);
|
|
2861
|
-
}
|
|
2862
|
-
function generateStarPoints(pointCount, outerRadius, innerRadius) {
|
|
2863
|
-
const points = [];
|
|
2864
|
-
const totalPoints = pointCount * 2;
|
|
2865
|
-
const angleStep = Math.PI / pointCount;
|
|
2866
|
-
const startAngle = -Math.PI / 2;
|
|
2867
|
-
for (let i = 0; i < totalPoints; i++) {
|
|
2868
|
-
const radius = i % 2 === 0 ? outerRadius : innerRadius;
|
|
2869
|
-
const angle = startAngle + i * angleStep;
|
|
2870
|
-
points.push({
|
|
2871
|
-
x: radius * Math.cos(angle),
|
|
2872
|
-
y: radius * Math.sin(angle)
|
|
2873
|
-
});
|
|
2874
|
-
}
|
|
2875
|
-
return points;
|
|
2876
|
-
}
|
|
2877
|
-
function generateArrowPath(params) {
|
|
2878
|
-
const { length, headWidth, headLength, shaftWidth } = params;
|
|
2879
|
-
const halfShaft = shaftWidth / 2;
|
|
2880
|
-
const halfHead = headWidth / 2;
|
|
2881
|
-
const shaftLength = length - headLength;
|
|
2882
|
-
return [
|
|
2883
|
-
`M 0 ${-halfShaft}`,
|
|
2884
|
-
`L ${shaftLength} ${-halfShaft}`,
|
|
2885
|
-
`L ${shaftLength} ${-halfHead}`,
|
|
2886
|
-
`L ${length} 0`,
|
|
2887
|
-
`L ${shaftLength} ${halfHead}`,
|
|
2888
|
-
`L ${shaftLength} ${halfShaft}`,
|
|
2889
|
-
`L 0 ${halfShaft}`,
|
|
2890
|
-
"Z"
|
|
2891
|
-
].join(" ");
|
|
2892
|
-
}
|
|
2893
|
-
function generateHeartPath(params) {
|
|
2894
|
-
const { size } = params;
|
|
2895
|
-
const s = size / 2;
|
|
2896
|
-
return [
|
|
2897
|
-
`M 0 ${s * 0.3}`,
|
|
2898
|
-
`C 0 ${-s * 0.3} ${-s} ${-s * 0.3} ${-s} ${s * 0.3}`,
|
|
2899
|
-
`C ${-s} ${s * 0.7} 0 ${s} 0 ${s * 1.2}`,
|
|
2900
|
-
`C 0 ${s} ${s} ${s * 0.7} ${s} ${s * 0.3}`,
|
|
2901
|
-
`C ${s} ${-s * 0.3} 0 ${-s * 0.3} 0 ${s * 0.3}`,
|
|
2902
|
-
"Z"
|
|
2903
|
-
].join(" ");
|
|
2904
|
-
}
|
|
2905
|
-
function generateCrossPath(params) {
|
|
2906
|
-
const { width, height, thickness } = params;
|
|
2907
|
-
const halfThickness = thickness / 2;
|
|
2908
|
-
const halfWidth = width / 2;
|
|
2909
|
-
const halfHeight = height / 2;
|
|
2910
|
-
return [
|
|
2911
|
-
`M ${-halfThickness} ${-halfHeight}`,
|
|
2912
|
-
`L ${halfThickness} ${-halfHeight}`,
|
|
2913
|
-
`L ${halfThickness} ${-halfThickness}`,
|
|
2914
|
-
`L ${halfWidth} ${-halfThickness}`,
|
|
2915
|
-
`L ${halfWidth} ${halfThickness}`,
|
|
2916
|
-
`L ${halfThickness} ${halfThickness}`,
|
|
2917
|
-
`L ${halfThickness} ${halfHeight}`,
|
|
2918
|
-
`L ${-halfThickness} ${halfHeight}`,
|
|
2919
|
-
`L ${-halfThickness} ${halfThickness}`,
|
|
2920
|
-
`L ${-halfWidth} ${halfThickness}`,
|
|
2921
|
-
`L ${-halfWidth} ${-halfThickness}`,
|
|
2922
|
-
`L ${-halfThickness} ${-halfThickness}`,
|
|
2923
|
-
"Z"
|
|
2924
|
-
].join(" ");
|
|
2925
|
-
}
|
|
2926
|
-
function generateRingPath(params) {
|
|
2927
|
-
const { outerRadius, innerRadius } = params;
|
|
2928
|
-
const outerPath = generateCirclePath({ radius: outerRadius });
|
|
2929
|
-
const innerPath = generateCirclePath({ radius: innerRadius });
|
|
2930
|
-
return `${outerPath} ${reverseWindingOrder(innerPath)}`;
|
|
2931
|
-
}
|
|
2932
|
-
function pointsToPath(points, closed = true) {
|
|
2933
|
-
if (points.length === 0) return "";
|
|
2934
|
-
const commands = [`M ${points[0].x} ${points[0].y}`];
|
|
2935
|
-
for (let i = 1; i < points.length; i++) {
|
|
2936
|
-
commands.push(`L ${points[i].x} ${points[i].y}`);
|
|
2937
|
-
}
|
|
2938
|
-
if (closed) {
|
|
2939
|
-
commands.push("Z");
|
|
2940
|
-
}
|
|
2941
|
-
return commands.join(" ");
|
|
2942
|
-
}
|
|
2943
|
-
function reverseWindingOrder(path) {
|
|
2944
|
-
const commands = parsePathCommands(path);
|
|
2945
|
-
const reversed = [];
|
|
2946
|
-
const points = [];
|
|
2947
|
-
let currentX = 0;
|
|
2948
|
-
let currentY = 0;
|
|
2949
|
-
for (const cmd of commands) {
|
|
2950
|
-
if (cmd.type === "M" || cmd.type === "L") {
|
|
2951
|
-
points.push({ x: cmd.x, y: cmd.y });
|
|
2952
|
-
currentX = cmd.x;
|
|
2953
|
-
currentY = cmd.y;
|
|
2954
|
-
} else if (cmd.type === "C") {
|
|
2955
|
-
points.push({ x: cmd.x, y: cmd.y });
|
|
2956
|
-
currentX = cmd.x;
|
|
2957
|
-
currentY = cmd.y;
|
|
2958
|
-
}
|
|
2959
|
-
}
|
|
2960
|
-
if (points.length === 0) return path;
|
|
2961
|
-
points.reverse();
|
|
2962
|
-
reversed.push(`M ${points[0].x} ${points[0].y}`);
|
|
2963
|
-
for (let i = 1; i < points.length; i++) {
|
|
2964
|
-
reversed.push(`L ${points[i].x} ${points[i].y}`);
|
|
2965
|
-
}
|
|
2966
|
-
reversed.push("Z");
|
|
2967
|
-
return reversed.join(" ");
|
|
2968
|
-
}
|
|
2969
|
-
function parsePathCommands(path) {
|
|
2970
|
-
const commands = [];
|
|
2971
|
-
const regex = /([MLCQZ])\s*([^MLCQZ]*)/gi;
|
|
2972
|
-
let match;
|
|
2973
|
-
while ((match = regex.exec(path)) !== null) {
|
|
2974
|
-
const type = match[1].toUpperCase();
|
|
2975
|
-
const args = match[2].trim().split(/[\s,]+/).filter((s) => s.length > 0).map(parseFloat);
|
|
2976
|
-
if (type === "M" || type === "L") {
|
|
2977
|
-
commands.push({ type, x: args[0], y: args[1] });
|
|
2978
|
-
} else if (type === "C") {
|
|
2979
|
-
commands.push({
|
|
2980
|
-
type,
|
|
2981
|
-
x1: args[0],
|
|
2982
|
-
y1: args[1],
|
|
2983
|
-
x2: args[2],
|
|
2984
|
-
y2: args[3],
|
|
2985
|
-
x: args[4],
|
|
2986
|
-
y: args[5]
|
|
2987
|
-
});
|
|
2988
|
-
} else if (type === "Q") {
|
|
2989
|
-
commands.push({
|
|
2990
|
-
type,
|
|
2991
|
-
x1: args[0],
|
|
2992
|
-
y1: args[1],
|
|
2993
|
-
x: args[2],
|
|
2994
|
-
y: args[3]
|
|
2995
|
-
});
|
|
2996
|
-
} else if (type === "Z") {
|
|
2997
|
-
commands.push({ type });
|
|
2998
|
-
}
|
|
2999
|
-
}
|
|
3000
|
-
return commands;
|
|
3001
|
-
}
|
|
3002
|
-
function computePathBounds3(path) {
|
|
3003
|
-
const commands = parsePathCommands(path);
|
|
3004
|
-
let minX = Infinity;
|
|
3005
|
-
let minY = Infinity;
|
|
3006
|
-
let maxX = -Infinity;
|
|
3007
|
-
let maxY = -Infinity;
|
|
3008
|
-
const updateBounds = (x, y) => {
|
|
3009
|
-
minX = Math.min(minX, x);
|
|
3010
|
-
minY = Math.min(minY, y);
|
|
3011
|
-
maxX = Math.max(maxX, x);
|
|
3012
|
-
maxY = Math.max(maxY, y);
|
|
3013
|
-
};
|
|
3014
|
-
for (const cmd of commands) {
|
|
3015
|
-
if (cmd.x !== void 0 && cmd.y !== void 0) {
|
|
3016
|
-
updateBounds(cmd.x, cmd.y);
|
|
3017
|
-
}
|
|
3018
|
-
if (cmd.x1 !== void 0 && cmd.y1 !== void 0) {
|
|
3019
|
-
updateBounds(cmd.x1, cmd.y1);
|
|
3020
|
-
}
|
|
3021
|
-
if (cmd.x2 !== void 0 && cmd.y2 !== void 0) {
|
|
3022
|
-
updateBounds(cmd.x2, cmd.y2);
|
|
3023
|
-
}
|
|
3024
|
-
}
|
|
3025
|
-
if (minX === Infinity) {
|
|
3026
|
-
return { x: 0, y: 0, w: 0, h: 0 };
|
|
3027
|
-
}
|
|
3028
|
-
return {
|
|
3029
|
-
x: minX,
|
|
3030
|
-
y: minY,
|
|
3031
|
-
w: maxX - minX,
|
|
3032
|
-
h: maxY - minY
|
|
3033
|
-
};
|
|
3034
|
-
}
|
|
3035
|
-
function translatePath(path, dx, dy) {
|
|
3036
|
-
return path.replace(
|
|
3037
|
-
/(-?\d*\.?\d+(?:e[-+]?\d+)?)\s+(-?\d*\.?\d+(?:e[-+]?\d+)?)/gi,
|
|
3038
|
-
(match, x, y) => {
|
|
3039
|
-
const newX = parseFloat(x) + dx;
|
|
3040
|
-
const newY = parseFloat(y) + dy;
|
|
3041
|
-
return `${newX} ${newY}`;
|
|
3042
|
-
}
|
|
3043
|
-
);
|
|
3044
|
-
}
|
|
3045
|
-
function scalePath(path, sx, sy = sx) {
|
|
3046
|
-
return path.replace(
|
|
3047
|
-
/(-?\d*\.?\d+(?:e[-+]?\d+)?)\s+(-?\d*\.?\d+(?:e[-+]?\d+)?)/gi,
|
|
3048
|
-
(match, x, y) => {
|
|
3049
|
-
const newX = parseFloat(x) * sx;
|
|
3050
|
-
const newY = parseFloat(y) * sy;
|
|
3051
|
-
return `${newX} ${newY}`;
|
|
3052
|
-
}
|
|
3053
|
-
);
|
|
3054
|
-
}
|
|
3055
|
-
function rotatePath(path, angleDegrees) {
|
|
3056
|
-
const angleRadians = angleDegrees * DEG_TO_RAD;
|
|
3057
|
-
const cos = Math.cos(angleRadians);
|
|
3058
|
-
const sin = Math.sin(angleRadians);
|
|
3059
|
-
return path.replace(
|
|
3060
|
-
/(-?\d*\.?\d+(?:e[-+]?\d+)?)\s+(-?\d*\.?\d+(?:e[-+]?\d+)?)/gi,
|
|
3061
|
-
(match, x, y) => {
|
|
3062
|
-
const px = parseFloat(x);
|
|
3063
|
-
const py = parseFloat(y);
|
|
3064
|
-
const newX = px * cos - py * sin;
|
|
3065
|
-
const newY = px * sin + py * cos;
|
|
3066
|
-
return `${newX} ${newY}`;
|
|
3067
|
-
}
|
|
3068
|
-
);
|
|
3069
|
-
}
|
|
3070
|
-
function centerPath(path) {
|
|
3071
|
-
const bounds = computePathBounds3(path);
|
|
3072
|
-
const cx = bounds.x + bounds.w / 2;
|
|
3073
|
-
const cy = bounds.y + bounds.h / 2;
|
|
3074
|
-
return translatePath(path, -cx, -cy);
|
|
3075
|
-
}
|
|
3076
|
-
function normalizePathToSize(path, targetWidth, targetHeight) {
|
|
3077
|
-
const bounds = computePathBounds3(path);
|
|
3078
|
-
if (bounds.w === 0 || bounds.h === 0) return path;
|
|
3079
|
-
const scaleX = targetWidth / bounds.w;
|
|
3080
|
-
const scaleY = targetHeight / bounds.h;
|
|
3081
|
-
const scale = Math.min(scaleX, scaleY);
|
|
3082
|
-
let normalized = translatePath(path, -bounds.x, -bounds.y);
|
|
3083
|
-
normalized = scalePath(normalized, scale);
|
|
3084
|
-
return normalized;
|
|
3085
|
-
}
|
|
3086
|
-
|
|
3087
2737
|
// src/core/svg-path-utils.ts
|
|
3088
2738
|
var TAU = Math.PI * 2;
|
|
3089
2739
|
var PATH_COMMAND_REGEX = /([MmLlHhVvCcSsQqTtAaZz])([^MmLlHhVvCcSsQqTtAaZz]*)/g;
|
|
@@ -3480,109 +3130,183 @@ function quadraticToCubic(x0, y0, qx, qy, x, y) {
|
|
|
3480
3130
|
};
|
|
3481
3131
|
}
|
|
3482
3132
|
|
|
3483
|
-
// src/core/
|
|
3484
|
-
var
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
const
|
|
3494
|
-
|
|
3495
|
-
|
|
3133
|
+
// src/core/resvg-renderer.ts
|
|
3134
|
+
var resvgModule = null;
|
|
3135
|
+
async function getResvg() {
|
|
3136
|
+
if (!resvgModule) {
|
|
3137
|
+
resvgModule = await import("@resvg/resvg-js");
|
|
3138
|
+
}
|
|
3139
|
+
return resvgModule;
|
|
3140
|
+
}
|
|
3141
|
+
async function renderSvgToPng(svgString, options = {}) {
|
|
3142
|
+
const { Resvg } = await getResvg();
|
|
3143
|
+
const resvgOptions = {};
|
|
3144
|
+
if (options.background) {
|
|
3145
|
+
resvgOptions.background = options.background;
|
|
3146
|
+
}
|
|
3147
|
+
if (options.fitTo) {
|
|
3148
|
+
resvgOptions.fitTo = options.fitTo;
|
|
3149
|
+
} else if (options.width) {
|
|
3150
|
+
resvgOptions.fitTo = { mode: "width", value: options.width };
|
|
3151
|
+
} else if (options.height) {
|
|
3152
|
+
resvgOptions.fitTo = { mode: "height", value: options.height };
|
|
3153
|
+
}
|
|
3154
|
+
const resvg = new Resvg(svgString, resvgOptions);
|
|
3155
|
+
const rendered = resvg.render();
|
|
3156
|
+
const png = rendered.asPng();
|
|
3157
|
+
return {
|
|
3158
|
+
png,
|
|
3159
|
+
width: rendered.width,
|
|
3160
|
+
height: rendered.height
|
|
3161
|
+
};
|
|
3496
3162
|
}
|
|
3497
|
-
function
|
|
3498
|
-
if (!
|
|
3499
|
-
|
|
3163
|
+
function shapeToSvgString(asset, defaultWidth, defaultHeight) {
|
|
3164
|
+
if (!asset.shape) {
|
|
3165
|
+
throw new Error("Shape is required for shape mode");
|
|
3166
|
+
}
|
|
3167
|
+
const width = asset.width ?? defaultWidth;
|
|
3168
|
+
const height = asset.height ?? defaultHeight;
|
|
3169
|
+
const pathData = generateShapePathData(asset.shape);
|
|
3170
|
+
const bounds = computeSimplePathBounds(pathData);
|
|
3171
|
+
const centerX = width / 2;
|
|
3172
|
+
const centerY = height / 2;
|
|
3173
|
+
const pathCenterX = bounds.x + bounds.w / 2;
|
|
3174
|
+
const pathCenterY = bounds.y + bounds.h / 2;
|
|
3175
|
+
let offsetX = centerX - pathCenterX;
|
|
3176
|
+
let offsetY = centerY - pathCenterY;
|
|
3177
|
+
if (asset.transform) {
|
|
3178
|
+
offsetX += asset.transform.x ?? 0;
|
|
3179
|
+
offsetY += asset.transform.y ?? 0;
|
|
3180
|
+
}
|
|
3181
|
+
const elements = [];
|
|
3182
|
+
if (asset.shadow) {
|
|
3183
|
+
const shadowOffsetX = asset.shadow.offsetX ?? 4;
|
|
3184
|
+
const shadowOffsetY = asset.shadow.offsetY ?? 4;
|
|
3185
|
+
const shadowColor = asset.shadow.color ?? "#000000";
|
|
3186
|
+
const shadowOpacity = asset.shadow.opacity ?? 0.5;
|
|
3187
|
+
elements.push(
|
|
3188
|
+
`<path d="${pathData}" transform="translate(${offsetX + shadowOffsetX}, ${offsetY + shadowOffsetY})" fill="${shadowColor}" fill-opacity="${shadowOpacity}"/>`
|
|
3189
|
+
);
|
|
3500
3190
|
}
|
|
3501
|
-
|
|
3502
|
-
if (
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
return `#${r}${r}${g}${g}${b}${b}`.toUpperCase();
|
|
3191
|
+
const pathAttrs = [`d="${pathData}"`, `transform="translate(${offsetX}, ${offsetY})"`];
|
|
3192
|
+
if (asset.fill) {
|
|
3193
|
+
const fillId = `fill-${Date.now()}`;
|
|
3194
|
+
const fillDef = generateFillDefinition(asset.fill, fillId, bounds);
|
|
3195
|
+
if (fillDef.defs) {
|
|
3196
|
+
elements.unshift(fillDef.defs);
|
|
3508
3197
|
}
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
const b = parseInt(rgbMatch[3], 10);
|
|
3516
|
-
return rgbToHex(r, g, b);
|
|
3198
|
+
pathAttrs.push(`fill="${fillDef.fill}"`);
|
|
3199
|
+
if (asset.fill.opacity !== void 0 && asset.fill.opacity !== 1) {
|
|
3200
|
+
pathAttrs.push(`fill-opacity="${asset.fill.opacity}"`);
|
|
3201
|
+
}
|
|
3202
|
+
} else {
|
|
3203
|
+
pathAttrs.push(`fill="none"`);
|
|
3517
3204
|
}
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3205
|
+
if (asset.stroke && asset.stroke.width && asset.stroke.width > 0) {
|
|
3206
|
+
pathAttrs.push(`stroke="${asset.stroke.color ?? "#000000"}"`);
|
|
3207
|
+
pathAttrs.push(`stroke-width="${asset.stroke.width}"`);
|
|
3208
|
+
if (asset.stroke.opacity !== void 0 && asset.stroke.opacity !== 1) {
|
|
3209
|
+
pathAttrs.push(`stroke-opacity="${asset.stroke.opacity}"`);
|
|
3210
|
+
}
|
|
3211
|
+
if (asset.stroke.dashArray && asset.stroke.dashArray.length > 0) {
|
|
3212
|
+
pathAttrs.push(`stroke-dasharray="${asset.stroke.dashArray.join(" ")}"`);
|
|
3213
|
+
}
|
|
3214
|
+
if (asset.stroke.lineCap) {
|
|
3215
|
+
pathAttrs.push(`stroke-linecap="${asset.stroke.lineCap}"`);
|
|
3216
|
+
}
|
|
3217
|
+
if (asset.stroke.lineJoin) {
|
|
3218
|
+
pathAttrs.push(`stroke-linejoin="${asset.stroke.lineJoin}"`);
|
|
3219
|
+
}
|
|
3524
3220
|
}
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
white: "#FFFFFF",
|
|
3528
|
-
red: "#FF0000",
|
|
3529
|
-
green: "#008000",
|
|
3530
|
-
blue: "#0000FF",
|
|
3531
|
-
yellow: "#FFFF00",
|
|
3532
|
-
cyan: "#00FFFF",
|
|
3533
|
-
magenta: "#FF00FF",
|
|
3534
|
-
gray: "#808080",
|
|
3535
|
-
grey: "#808080",
|
|
3536
|
-
orange: "#FFA500",
|
|
3537
|
-
purple: "#800080",
|
|
3538
|
-
pink: "#FFC0CB",
|
|
3539
|
-
brown: "#A52A2A",
|
|
3540
|
-
navy: "#000080",
|
|
3541
|
-
teal: "#008080",
|
|
3542
|
-
olive: "#808000",
|
|
3543
|
-
maroon: "#800000",
|
|
3544
|
-
aqua: "#00FFFF",
|
|
3545
|
-
lime: "#00FF00",
|
|
3546
|
-
silver: "#C0C0C0",
|
|
3547
|
-
fuchsia: "#FF00FF"
|
|
3548
|
-
};
|
|
3549
|
-
const lowerColor = color.toLowerCase();
|
|
3550
|
-
if (namedColors[lowerColor]) {
|
|
3551
|
-
return namedColors[lowerColor];
|
|
3221
|
+
if (asset.opacity !== void 0 && asset.opacity !== 1) {
|
|
3222
|
+
pathAttrs.push(`opacity="${asset.opacity}"`);
|
|
3552
3223
|
}
|
|
3553
|
-
|
|
3554
|
-
}
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
const hex = Math.max(0, Math.min(255, n)).toString(16);
|
|
3558
|
-
return hex.length === 1 ? "0" + hex : hex;
|
|
3559
|
-
};
|
|
3560
|
-
return `#${toHex(r)}${toHex(g)}${toHex(b)}`.toUpperCase();
|
|
3224
|
+
elements.push(`<path ${pathAttrs.join(" ")}/>`);
|
|
3225
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">${elements.join(
|
|
3226
|
+
""
|
|
3227
|
+
)}</svg>`;
|
|
3561
3228
|
}
|
|
3562
|
-
function
|
|
3563
|
-
if (
|
|
3564
|
-
|
|
3565
|
-
|
|
3229
|
+
function generateFillDefinition(fill, id, bounds) {
|
|
3230
|
+
if (fill.type === "solid") {
|
|
3231
|
+
return { fill: fill.color };
|
|
3232
|
+
}
|
|
3233
|
+
if (fill.type === "linear") {
|
|
3234
|
+
const angle = fill.angle ?? 0;
|
|
3235
|
+
const rad = angle * Math.PI / 180;
|
|
3236
|
+
const x1 = 50 - Math.cos(rad) * 50;
|
|
3237
|
+
const y1 = 50 - Math.sin(rad) * 50;
|
|
3238
|
+
const x2 = 50 + Math.cos(rad) * 50;
|
|
3239
|
+
const y2 = 50 + Math.sin(rad) * 50;
|
|
3240
|
+
const stops = fill.stops.map((s) => `<stop offset="${s.offset * 100}%" stop-color="${s.color}"/>`).join("");
|
|
3241
|
+
const defs = `<defs><linearGradient id="${id}" x1="${x1}%" y1="${y1}%" x2="${x2}%" y2="${y2}%">${stops}</linearGradient></defs>`;
|
|
3242
|
+
return { fill: `url(#${id})`, defs };
|
|
3243
|
+
}
|
|
3244
|
+
if (fill.type === "radial") {
|
|
3245
|
+
const stops = fill.stops.map((s) => `<stop offset="${s.offset * 100}%" stop-color="${s.color}"/>`).join("");
|
|
3246
|
+
const defs = `<defs><radialGradient id="${id}" cx="50%" cy="50%" r="50%">${stops}</radialGradient></defs>`;
|
|
3247
|
+
return { fill: `url(#${id})`, defs };
|
|
3248
|
+
}
|
|
3249
|
+
return { fill: "#000000" };
|
|
3566
3250
|
}
|
|
3567
|
-
function
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3251
|
+
function generateShapePathData(shape) {
|
|
3252
|
+
const shapeType = shape.type;
|
|
3253
|
+
switch (shapeType) {
|
|
3254
|
+
case "rectangle": {
|
|
3255
|
+
const s = shape;
|
|
3256
|
+
return generateRectanglePath(s.width, s.height, s.cornerRadius ?? 0);
|
|
3257
|
+
}
|
|
3258
|
+
case "circle": {
|
|
3259
|
+
const s = shape;
|
|
3260
|
+
return generateCirclePath(s.radius);
|
|
3261
|
+
}
|
|
3262
|
+
case "ellipse": {
|
|
3263
|
+
const s = shape;
|
|
3264
|
+
return generateEllipsePath(s.radiusX, s.radiusY);
|
|
3265
|
+
}
|
|
3266
|
+
case "line": {
|
|
3267
|
+
const s = shape;
|
|
3268
|
+
return generateLinePath(s.length, s.thickness ?? 2);
|
|
3269
|
+
}
|
|
3270
|
+
case "polygon": {
|
|
3271
|
+
const s = shape;
|
|
3272
|
+
return generatePolygonPath(s.sides, s.radius);
|
|
3273
|
+
}
|
|
3274
|
+
case "star": {
|
|
3275
|
+
const s = shape;
|
|
3276
|
+
return generateStarPath(s.points, s.outerRadius, s.innerRadius);
|
|
3277
|
+
}
|
|
3278
|
+
case "arrow": {
|
|
3279
|
+
const s = shape;
|
|
3280
|
+
return generateArrowPath(s.length, s.headWidth ?? 30, s.headLength ?? 25, s.shaftWidth ?? 10);
|
|
3281
|
+
}
|
|
3282
|
+
case "heart": {
|
|
3283
|
+
const s = shape;
|
|
3284
|
+
return generateHeartPath(s.size);
|
|
3285
|
+
}
|
|
3286
|
+
case "cross": {
|
|
3287
|
+
const s = shape;
|
|
3288
|
+
return generateCrossPath(s.width, s.height, s.thickness);
|
|
3289
|
+
}
|
|
3290
|
+
case "ring": {
|
|
3291
|
+
const s = shape;
|
|
3292
|
+
return generateRingPath(s.outerRadius, s.innerRadius);
|
|
3293
|
+
}
|
|
3294
|
+
case "path": {
|
|
3295
|
+
const s = shape;
|
|
3296
|
+
return s.d;
|
|
3297
|
+
}
|
|
3298
|
+
default:
|
|
3299
|
+
throw new Error(`Unknown shape type: ${shapeType}`);
|
|
3572
3300
|
}
|
|
3573
|
-
return void 0;
|
|
3574
3301
|
}
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
const
|
|
3578
|
-
const
|
|
3579
|
-
const
|
|
3580
|
-
|
|
3581
|
-
const ry = parseNumber(extractAttribute(attrs, "ry")) || rx;
|
|
3582
|
-
if (rx === 0 && ry === 0) {
|
|
3302
|
+
var KAPPA = 0.5522847498307936;
|
|
3303
|
+
function generateRectanglePath(width, height, cornerRadius) {
|
|
3304
|
+
const x = -width / 2;
|
|
3305
|
+
const y = -height / 2;
|
|
3306
|
+
const r = Math.min(cornerRadius, width / 2, height / 2);
|
|
3307
|
+
if (r === 0) {
|
|
3583
3308
|
return `M ${x} ${y} L ${x + width} ${y} L ${x + width} ${y + height} L ${x} ${y + height} Z`;
|
|
3584
3309
|
}
|
|
3585
|
-
const r = Math.min(rx, ry, width / 2, height / 2);
|
|
3586
3310
|
return [
|
|
3587
3311
|
`M ${x + r} ${y}`,
|
|
3588
3312
|
`L ${x + width - r} ${y}`,
|
|
@@ -3596,288 +3320,358 @@ function rectToPath(attrs) {
|
|
|
3596
3320
|
"Z"
|
|
3597
3321
|
].join(" ");
|
|
3598
3322
|
}
|
|
3599
|
-
function
|
|
3600
|
-
const
|
|
3601
|
-
const cy = parseNumber(extractAttribute(attrs, "cy")) || 0;
|
|
3602
|
-
const r = parseNumber(extractAttribute(attrs, "r")) || 0;
|
|
3603
|
-
if (r === 0) return "";
|
|
3604
|
-
const KAPPA2 = 0.5522847498307936;
|
|
3605
|
-
const k = r * KAPPA2;
|
|
3323
|
+
function generateCirclePath(radius) {
|
|
3324
|
+
const k = radius * KAPPA;
|
|
3606
3325
|
return [
|
|
3607
|
-
`M ${
|
|
3608
|
-
`C ${
|
|
3609
|
-
`C ${
|
|
3610
|
-
`C ${
|
|
3611
|
-
`C ${
|
|
3326
|
+
`M ${radius} 0`,
|
|
3327
|
+
`C ${radius} ${k} ${k} ${radius} 0 ${radius}`,
|
|
3328
|
+
`C ${-k} ${radius} ${-radius} ${k} ${-radius} 0`,
|
|
3329
|
+
`C ${-radius} ${-k} ${-k} ${-radius} 0 ${-radius}`,
|
|
3330
|
+
`C ${k} ${-radius} ${radius} ${-k} ${radius} 0`,
|
|
3612
3331
|
"Z"
|
|
3613
3332
|
].join(" ");
|
|
3614
3333
|
}
|
|
3615
|
-
function
|
|
3616
|
-
const
|
|
3617
|
-
const
|
|
3618
|
-
const rx = parseNumber(extractAttribute(attrs, "rx")) || 0;
|
|
3619
|
-
const ry = parseNumber(extractAttribute(attrs, "ry")) || 0;
|
|
3620
|
-
if (rx === 0 || ry === 0) return "";
|
|
3621
|
-
const KAPPA2 = 0.5522847498307936;
|
|
3622
|
-
const kx = rx * KAPPA2;
|
|
3623
|
-
const ky = ry * KAPPA2;
|
|
3334
|
+
function generateEllipsePath(radiusX, radiusY) {
|
|
3335
|
+
const kx = radiusX * KAPPA;
|
|
3336
|
+
const ky = radiusY * KAPPA;
|
|
3624
3337
|
return [
|
|
3625
|
-
`M ${
|
|
3626
|
-
`C ${
|
|
3627
|
-
`C ${
|
|
3628
|
-
`C ${
|
|
3629
|
-
`C ${
|
|
3338
|
+
`M ${radiusX} 0`,
|
|
3339
|
+
`C ${radiusX} ${ky} ${kx} ${radiusY} 0 ${radiusY}`,
|
|
3340
|
+
`C ${-kx} ${radiusY} ${-radiusX} ${ky} ${-radiusX} 0`,
|
|
3341
|
+
`C ${-radiusX} ${-ky} ${-kx} ${-radiusY} 0 ${-radiusY}`,
|
|
3342
|
+
`C ${kx} ${-radiusY} ${radiusX} ${-ky} ${radiusX} 0`,
|
|
3630
3343
|
"Z"
|
|
3631
3344
|
].join(" ");
|
|
3632
3345
|
}
|
|
3633
|
-
function
|
|
3634
|
-
const
|
|
3635
|
-
const
|
|
3636
|
-
|
|
3637
|
-
const y2 = parseNumber(extractAttribute(attrs, "y2")) || 0;
|
|
3638
|
-
return `M ${x1} ${y1} L ${x2} ${y2}`;
|
|
3346
|
+
function generateLinePath(length, thickness) {
|
|
3347
|
+
const halfLen = length / 2;
|
|
3348
|
+
const halfThick = thickness / 2;
|
|
3349
|
+
return `M ${-halfLen} ${-halfThick} L ${halfLen} ${-halfThick} L ${halfLen} ${halfThick} L ${-halfLen} ${halfThick} Z`;
|
|
3639
3350
|
}
|
|
3640
|
-
function
|
|
3641
|
-
const
|
|
3642
|
-
|
|
3643
|
-
const
|
|
3644
|
-
|
|
3351
|
+
function generatePolygonPath(sides, radius) {
|
|
3352
|
+
const angleStep = 2 * Math.PI / sides;
|
|
3353
|
+
const startAngle = -Math.PI / 2;
|
|
3354
|
+
const points = [];
|
|
3355
|
+
for (let i = 0; i < sides; i++) {
|
|
3356
|
+
const angle = startAngle + i * angleStep;
|
|
3357
|
+
const x = Math.cos(angle) * radius;
|
|
3358
|
+
const y = Math.sin(angle) * radius;
|
|
3359
|
+
points.push(i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`);
|
|
3360
|
+
}
|
|
3361
|
+
points.push("Z");
|
|
3362
|
+
return points.join(" ");
|
|
3363
|
+
}
|
|
3364
|
+
function generateStarPath(points, outerRadius, innerRadius) {
|
|
3365
|
+
const angleStep = Math.PI / points;
|
|
3366
|
+
const startAngle = -Math.PI / 2;
|
|
3645
3367
|
const pathParts = [];
|
|
3646
|
-
for (let i = 0; i <
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
}
|
|
3653
|
-
}
|
|
3368
|
+
for (let i = 0; i < points * 2; i++) {
|
|
3369
|
+
const angle = startAngle + i * angleStep;
|
|
3370
|
+
const radius = i % 2 === 0 ? outerRadius : innerRadius;
|
|
3371
|
+
const x = Math.cos(angle) * radius;
|
|
3372
|
+
const y = Math.sin(angle) * radius;
|
|
3373
|
+
pathParts.push(i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`);
|
|
3654
3374
|
}
|
|
3375
|
+
pathParts.push("Z");
|
|
3655
3376
|
return pathParts.join(" ");
|
|
3656
3377
|
}
|
|
3657
|
-
function
|
|
3658
|
-
const
|
|
3659
|
-
|
|
3660
|
-
|
|
3378
|
+
function generateArrowPath(length, headWidth, headLength, shaftWidth) {
|
|
3379
|
+
const halfShaft = shaftWidth / 2;
|
|
3380
|
+
const halfHead = headWidth / 2;
|
|
3381
|
+
const shaftLength = length - headLength;
|
|
3382
|
+
const startX = -length / 2;
|
|
3383
|
+
return [
|
|
3384
|
+
`M ${startX} ${-halfShaft}`,
|
|
3385
|
+
`L ${startX + shaftLength} ${-halfShaft}`,
|
|
3386
|
+
`L ${startX + shaftLength} ${-halfHead}`,
|
|
3387
|
+
`L ${startX + length} 0`,
|
|
3388
|
+
`L ${startX + shaftLength} ${halfHead}`,
|
|
3389
|
+
`L ${startX + shaftLength} ${halfShaft}`,
|
|
3390
|
+
`L ${startX} ${halfShaft}`,
|
|
3391
|
+
"Z"
|
|
3392
|
+
].join(" ");
|
|
3661
3393
|
}
|
|
3662
|
-
function
|
|
3663
|
-
const
|
|
3664
|
-
const
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
const fillMatch = style.match(/fill\s*:\s*([^;]+)/i);
|
|
3678
|
-
if (fillMatch) styleFill = fillMatch[1].trim();
|
|
3679
|
-
const strokeMatch = style.match(/stroke\s*:\s*([^;]+)/i);
|
|
3680
|
-
if (strokeMatch) styleStroke = strokeMatch[1].trim();
|
|
3681
|
-
const strokeWidthMatch = style.match(/stroke-width\s*:\s*([^;]+)/i);
|
|
3682
|
-
if (strokeWidthMatch) styleStrokeWidth = parseNumber(strokeWidthMatch[1].trim());
|
|
3683
|
-
const opacityMatch = style.match(/opacity\s*:\s*([^;]+)/i);
|
|
3684
|
-
if (opacityMatch) styleOpacity = parseNumber(opacityMatch[1].trim());
|
|
3685
|
-
}
|
|
3686
|
-
return {
|
|
3687
|
-
d,
|
|
3688
|
-
fill: styleFill,
|
|
3689
|
-
fillOpacity,
|
|
3690
|
-
stroke: styleStroke,
|
|
3691
|
-
strokeWidth: styleStrokeWidth,
|
|
3692
|
-
strokeOpacity,
|
|
3693
|
-
opacity: styleOpacity,
|
|
3694
|
-
transform
|
|
3695
|
-
};
|
|
3394
|
+
function generateHeartPath(size) {
|
|
3395
|
+
const scale = size / 32;
|
|
3396
|
+
const points = [
|
|
3397
|
+
"M 0 6",
|
|
3398
|
+
"C -0.5 -3 -12 -3 -12 6",
|
|
3399
|
+
"C -12 12 0 18 0 24",
|
|
3400
|
+
"C 0 18 12 12 12 6",
|
|
3401
|
+
"C 12 -3 0.5 -3 0 6",
|
|
3402
|
+
"Z"
|
|
3403
|
+
];
|
|
3404
|
+
return points.map((cmd) => {
|
|
3405
|
+
return cmd.replace(/-?\d+(\.\d+)?/g, (match) => {
|
|
3406
|
+
return String(parseFloat(match) * scale);
|
|
3407
|
+
});
|
|
3408
|
+
}).join(" ");
|
|
3696
3409
|
}
|
|
3697
|
-
function
|
|
3698
|
-
const
|
|
3699
|
-
|
|
3700
|
-
const
|
|
3701
|
-
|
|
3702
|
-
|
|
3410
|
+
function generateCrossPath(width, height, thickness) {
|
|
3411
|
+
const hw = width / 2;
|
|
3412
|
+
const hh = height / 2;
|
|
3413
|
+
const ht = thickness / 2;
|
|
3414
|
+
return [
|
|
3415
|
+
`M ${-ht} ${-hh}`,
|
|
3416
|
+
`L ${ht} ${-hh}`,
|
|
3417
|
+
`L ${ht} ${-ht}`,
|
|
3418
|
+
`L ${hw} ${-ht}`,
|
|
3419
|
+
`L ${hw} ${ht}`,
|
|
3420
|
+
`L ${ht} ${ht}`,
|
|
3421
|
+
`L ${ht} ${hh}`,
|
|
3422
|
+
`L ${-ht} ${hh}`,
|
|
3423
|
+
`L ${-ht} ${ht}`,
|
|
3424
|
+
`L ${-hw} ${ht}`,
|
|
3425
|
+
`L ${-hw} ${-ht}`,
|
|
3426
|
+
`L ${-ht} ${-ht}`,
|
|
3427
|
+
"Z"
|
|
3428
|
+
].join(" ");
|
|
3703
3429
|
}
|
|
3704
|
-
function
|
|
3705
|
-
const
|
|
3706
|
-
const
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3430
|
+
function generateRingPath(outerRadius, innerRadius) {
|
|
3431
|
+
const outerPath = generateCirclePath(outerRadius);
|
|
3432
|
+
const innerPath = generateCirclePathReversed(innerRadius);
|
|
3433
|
+
return `${outerPath} ${innerPath}`;
|
|
3434
|
+
}
|
|
3435
|
+
function generateCirclePathReversed(radius) {
|
|
3436
|
+
const k = radius * KAPPA;
|
|
3437
|
+
return [
|
|
3438
|
+
`M ${radius} 0`,
|
|
3439
|
+
`C ${radius} ${-k} ${k} ${-radius} 0 ${-radius}`,
|
|
3440
|
+
`C ${-k} ${-radius} ${-radius} ${-k} ${-radius} 0`,
|
|
3441
|
+
`C ${-radius} ${k} ${-k} ${radius} 0 ${radius}`,
|
|
3442
|
+
`C ${k} ${radius} ${radius} ${k} ${radius} 0`,
|
|
3443
|
+
"Z"
|
|
3444
|
+
].join(" ");
|
|
3445
|
+
}
|
|
3446
|
+
function computeSimplePathBounds(d) {
|
|
3447
|
+
const numberRegex = /-?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/g;
|
|
3448
|
+
const numbers = [];
|
|
3718
3449
|
let match;
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
paths.push(pathAttrs);
|
|
3450
|
+
while ((match = numberRegex.exec(d)) !== null) {
|
|
3451
|
+
const num = parseFloat(match[0]);
|
|
3452
|
+
if (!isNaN(num) && isFinite(num)) {
|
|
3453
|
+
numbers.push(num);
|
|
3724
3454
|
}
|
|
3725
3455
|
}
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
const path = extractShapeAsPath(match[1], rectToPath);
|
|
3729
|
-
if (path) paths.push(path);
|
|
3730
|
-
}
|
|
3731
|
-
CIRCLE_TAG_REGEX.lastIndex = 0;
|
|
3732
|
-
while ((match = CIRCLE_TAG_REGEX.exec(svgString)) !== null) {
|
|
3733
|
-
const path = extractShapeAsPath(match[1], circleToPath);
|
|
3734
|
-
if (path) paths.push(path);
|
|
3735
|
-
}
|
|
3736
|
-
ELLIPSE_TAG_REGEX.lastIndex = 0;
|
|
3737
|
-
while ((match = ELLIPSE_TAG_REGEX.exec(svgString)) !== null) {
|
|
3738
|
-
const path = extractShapeAsPath(match[1], ellipseToPath);
|
|
3739
|
-
if (path) paths.push(path);
|
|
3740
|
-
}
|
|
3741
|
-
LINE_TAG_REGEX.lastIndex = 0;
|
|
3742
|
-
while ((match = LINE_TAG_REGEX.exec(svgString)) !== null) {
|
|
3743
|
-
const path = extractShapeAsPath(match[1], lineToPath);
|
|
3744
|
-
if (path) paths.push(path);
|
|
3456
|
+
if (numbers.length < 2) {
|
|
3457
|
+
return { x: 0, y: 0, w: 0, h: 0 };
|
|
3745
3458
|
}
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3459
|
+
let minX = Infinity;
|
|
3460
|
+
let minY = Infinity;
|
|
3461
|
+
let maxX = -Infinity;
|
|
3462
|
+
let maxY = -Infinity;
|
|
3463
|
+
let currentX = 0;
|
|
3464
|
+
let currentY = 0;
|
|
3465
|
+
let i = 0;
|
|
3466
|
+
const commands = d.match(/[MmLlHhVvCcSsQqTtAaZz]/g) || [];
|
|
3467
|
+
const commandPositions = [];
|
|
3468
|
+
let searchPos = 0;
|
|
3469
|
+
for (const cmd of commands) {
|
|
3470
|
+
const pos = d.indexOf(cmd, searchPos);
|
|
3471
|
+
commandPositions.push(pos);
|
|
3472
|
+
searchPos = pos + 1;
|
|
3473
|
+
}
|
|
3474
|
+
let cmdIndex = 0;
|
|
3475
|
+
let numIndex = 0;
|
|
3476
|
+
while (cmdIndex < commands.length) {
|
|
3477
|
+
const cmd = commands[cmdIndex];
|
|
3478
|
+
switch (cmd) {
|
|
3479
|
+
case "M":
|
|
3480
|
+
case "L":
|
|
3481
|
+
case "T":
|
|
3482
|
+
if (numIndex + 1 < numbers.length) {
|
|
3483
|
+
currentX = numbers[numIndex++];
|
|
3484
|
+
currentY = numbers[numIndex++];
|
|
3485
|
+
minX = Math.min(minX, currentX);
|
|
3486
|
+
maxX = Math.max(maxX, currentX);
|
|
3487
|
+
minY = Math.min(minY, currentY);
|
|
3488
|
+
maxY = Math.max(maxY, currentY);
|
|
3489
|
+
}
|
|
3490
|
+
break;
|
|
3491
|
+
case "m":
|
|
3492
|
+
case "l":
|
|
3493
|
+
case "t":
|
|
3494
|
+
if (numIndex + 1 < numbers.length) {
|
|
3495
|
+
currentX += numbers[numIndex++];
|
|
3496
|
+
currentY += numbers[numIndex++];
|
|
3497
|
+
minX = Math.min(minX, currentX);
|
|
3498
|
+
maxX = Math.max(maxX, currentX);
|
|
3499
|
+
minY = Math.min(minY, currentY);
|
|
3500
|
+
maxY = Math.max(maxY, currentY);
|
|
3501
|
+
}
|
|
3502
|
+
break;
|
|
3503
|
+
case "H":
|
|
3504
|
+
if (numIndex < numbers.length) {
|
|
3505
|
+
currentX = numbers[numIndex++];
|
|
3506
|
+
minX = Math.min(minX, currentX);
|
|
3507
|
+
maxX = Math.max(maxX, currentX);
|
|
3508
|
+
}
|
|
3509
|
+
break;
|
|
3510
|
+
case "h":
|
|
3511
|
+
if (numIndex < numbers.length) {
|
|
3512
|
+
currentX += numbers[numIndex++];
|
|
3513
|
+
minX = Math.min(minX, currentX);
|
|
3514
|
+
maxX = Math.max(maxX, currentX);
|
|
3515
|
+
}
|
|
3516
|
+
break;
|
|
3517
|
+
case "V":
|
|
3518
|
+
if (numIndex < numbers.length) {
|
|
3519
|
+
currentY = numbers[numIndex++];
|
|
3520
|
+
minY = Math.min(minY, currentY);
|
|
3521
|
+
maxY = Math.max(maxY, currentY);
|
|
3522
|
+
}
|
|
3523
|
+
break;
|
|
3524
|
+
case "v":
|
|
3525
|
+
if (numIndex < numbers.length) {
|
|
3526
|
+
currentY += numbers[numIndex++];
|
|
3527
|
+
minY = Math.min(minY, currentY);
|
|
3528
|
+
maxY = Math.max(maxY, currentY);
|
|
3529
|
+
}
|
|
3530
|
+
break;
|
|
3531
|
+
case "C":
|
|
3532
|
+
if (numIndex + 5 < numbers.length) {
|
|
3533
|
+
for (let j = 0; j < 3; j++) {
|
|
3534
|
+
const x = numbers[numIndex++];
|
|
3535
|
+
const y = numbers[numIndex++];
|
|
3536
|
+
minX = Math.min(minX, x);
|
|
3537
|
+
maxX = Math.max(maxX, x);
|
|
3538
|
+
minY = Math.min(minY, y);
|
|
3539
|
+
maxY = Math.max(maxY, y);
|
|
3540
|
+
if (j === 2) {
|
|
3541
|
+
currentX = x;
|
|
3542
|
+
currentY = y;
|
|
3543
|
+
}
|
|
3544
|
+
}
|
|
3545
|
+
}
|
|
3546
|
+
break;
|
|
3547
|
+
case "c":
|
|
3548
|
+
if (numIndex + 5 < numbers.length) {
|
|
3549
|
+
for (let j = 0; j < 3; j++) {
|
|
3550
|
+
const x = currentX + numbers[numIndex++];
|
|
3551
|
+
const y = currentY + numbers[numIndex++];
|
|
3552
|
+
minX = Math.min(minX, x);
|
|
3553
|
+
maxX = Math.max(maxX, x);
|
|
3554
|
+
minY = Math.min(minY, y);
|
|
3555
|
+
maxY = Math.max(maxY, y);
|
|
3556
|
+
if (j === 2) {
|
|
3557
|
+
currentX = x;
|
|
3558
|
+
currentY = y;
|
|
3559
|
+
}
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3562
|
+
break;
|
|
3563
|
+
case "S":
|
|
3564
|
+
case "Q":
|
|
3565
|
+
if (numIndex + 3 < numbers.length) {
|
|
3566
|
+
for (let j = 0; j < 2; j++) {
|
|
3567
|
+
const x = numbers[numIndex++];
|
|
3568
|
+
const y = numbers[numIndex++];
|
|
3569
|
+
minX = Math.min(minX, x);
|
|
3570
|
+
maxX = Math.max(maxX, x);
|
|
3571
|
+
minY = Math.min(minY, y);
|
|
3572
|
+
maxY = Math.max(maxY, y);
|
|
3573
|
+
if (j === 1) {
|
|
3574
|
+
currentX = x;
|
|
3575
|
+
currentY = y;
|
|
3576
|
+
}
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
break;
|
|
3580
|
+
case "s":
|
|
3581
|
+
case "q":
|
|
3582
|
+
if (numIndex + 3 < numbers.length) {
|
|
3583
|
+
for (let j = 0; j < 2; j++) {
|
|
3584
|
+
const x = currentX + numbers[numIndex++];
|
|
3585
|
+
const y = currentY + numbers[numIndex++];
|
|
3586
|
+
minX = Math.min(minX, x);
|
|
3587
|
+
maxX = Math.max(maxX, x);
|
|
3588
|
+
minY = Math.min(minY, y);
|
|
3589
|
+
maxY = Math.max(maxY, y);
|
|
3590
|
+
if (j === 1) {
|
|
3591
|
+
currentX = x;
|
|
3592
|
+
currentY = y;
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
}
|
|
3596
|
+
break;
|
|
3597
|
+
case "A":
|
|
3598
|
+
if (numIndex + 6 < numbers.length) {
|
|
3599
|
+
numIndex += 5;
|
|
3600
|
+
currentX = numbers[numIndex++];
|
|
3601
|
+
currentY = numbers[numIndex++];
|
|
3602
|
+
minX = Math.min(minX, currentX);
|
|
3603
|
+
maxX = Math.max(maxX, currentX);
|
|
3604
|
+
minY = Math.min(minY, currentY);
|
|
3605
|
+
maxY = Math.max(maxY, currentY);
|
|
3606
|
+
}
|
|
3607
|
+
break;
|
|
3608
|
+
case "a":
|
|
3609
|
+
if (numIndex + 6 < numbers.length) {
|
|
3610
|
+
numIndex += 5;
|
|
3611
|
+
currentX += numbers[numIndex++];
|
|
3612
|
+
currentY += numbers[numIndex++];
|
|
3613
|
+
minX = Math.min(minX, currentX);
|
|
3614
|
+
maxX = Math.max(maxX, currentX);
|
|
3615
|
+
minY = Math.min(minY, currentY);
|
|
3616
|
+
maxY = Math.max(maxY, currentY);
|
|
3617
|
+
}
|
|
3618
|
+
break;
|
|
3619
|
+
case "Z":
|
|
3620
|
+
case "z":
|
|
3621
|
+
break;
|
|
3622
|
+
}
|
|
3623
|
+
cmdIndex++;
|
|
3750
3624
|
}
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
const path = extractShapeAsPath(match[1], polygonToPath);
|
|
3754
|
-
if (path) paths.push(path);
|
|
3625
|
+
if (minX === Infinity) {
|
|
3626
|
+
return { x: 0, y: 0, w: 0, h: 0 };
|
|
3755
3627
|
}
|
|
3756
3628
|
return {
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3629
|
+
x: minX,
|
|
3630
|
+
y: minY,
|
|
3631
|
+
w: maxX - minX,
|
|
3632
|
+
h: maxY - minY
|
|
3761
3633
|
};
|
|
3762
3634
|
}
|
|
3763
|
-
function
|
|
3764
|
-
const
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
}
|
|
3779
|
-
|
|
3780
|
-
}
|
|
3781
|
-
function pathToAsset(path, width, height) {
|
|
3782
|
-
const asset = {
|
|
3783
|
-
type: "svg",
|
|
3784
|
-
shape: {
|
|
3785
|
-
type: "path",
|
|
3786
|
-
d: path.d
|
|
3787
|
-
}
|
|
3788
|
-
};
|
|
3789
|
-
const fillColor = parseColor(path.fill);
|
|
3790
|
-
if (fillColor) {
|
|
3791
|
-
asset.fill = {
|
|
3792
|
-
type: "solid",
|
|
3793
|
-
color: fillColor
|
|
3794
|
-
};
|
|
3795
|
-
if (path.fillOpacity !== void 0 && path.fillOpacity !== 1) {
|
|
3796
|
-
asset.fill.opacity = path.fillOpacity;
|
|
3797
|
-
}
|
|
3798
|
-
}
|
|
3799
|
-
const strokeColor = parseColor(path.stroke);
|
|
3800
|
-
if (strokeColor && path.strokeWidth && path.strokeWidth > 0) {
|
|
3801
|
-
asset.stroke = {
|
|
3802
|
-
color: strokeColor,
|
|
3803
|
-
width: path.strokeWidth
|
|
3804
|
-
};
|
|
3805
|
-
if (path.strokeOpacity !== void 0 && path.strokeOpacity !== 1) {
|
|
3806
|
-
asset.stroke.opacity = path.strokeOpacity;
|
|
3807
|
-
}
|
|
3808
|
-
}
|
|
3809
|
-
if (path.opacity !== void 0 && path.opacity !== 1) {
|
|
3810
|
-
asset.opacity = path.opacity;
|
|
3811
|
-
}
|
|
3812
|
-
if (width > 0) {
|
|
3813
|
-
asset.width = width;
|
|
3814
|
-
}
|
|
3815
|
-
if (height > 0) {
|
|
3816
|
-
asset.height = height;
|
|
3635
|
+
async function renderSvgAssetToPng(asset, options = {}) {
|
|
3636
|
+
const defaultWidth = options.defaultWidth ?? 1920;
|
|
3637
|
+
const defaultHeight = options.defaultHeight ?? 1080;
|
|
3638
|
+
let svgString;
|
|
3639
|
+
let targetWidth;
|
|
3640
|
+
let targetHeight;
|
|
3641
|
+
if (asset.src) {
|
|
3642
|
+
svgString = asset.src;
|
|
3643
|
+
const dimensions = extractSvgDimensions(svgString);
|
|
3644
|
+
targetWidth = dimensions.width || defaultWidth;
|
|
3645
|
+
targetHeight = dimensions.height || defaultHeight;
|
|
3646
|
+
} else if (asset.shape) {
|
|
3647
|
+
targetWidth = asset.width ?? defaultWidth;
|
|
3648
|
+
targetHeight = asset.height ?? defaultHeight;
|
|
3649
|
+
svgString = shapeToSvgString(asset, targetWidth, targetHeight);
|
|
3650
|
+
} else {
|
|
3651
|
+
throw new Error("Either 'src' or 'shape' must be provided");
|
|
3817
3652
|
}
|
|
3818
|
-
return
|
|
3653
|
+
return renderSvgToPng(svgString, {
|
|
3654
|
+
width: targetWidth,
|
|
3655
|
+
height: targetHeight,
|
|
3656
|
+
background: options.background
|
|
3657
|
+
});
|
|
3819
3658
|
}
|
|
3820
|
-
function
|
|
3821
|
-
const
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
}
|
|
3833
|
-
const combinedD = parsed.paths.map((p) => p.d).join(" ");
|
|
3834
|
-
const firstPathWithFill = parsed.paths.find((p) => p.fill && p.fill !== "none");
|
|
3835
|
-
const firstPathWithStroke = parsed.paths.find((p) => p.stroke && p.stroke !== "none");
|
|
3836
|
-
const asset = {
|
|
3837
|
-
type: "svg",
|
|
3838
|
-
shape: {
|
|
3839
|
-
type: "path",
|
|
3840
|
-
d: combinedD
|
|
3841
|
-
}
|
|
3842
|
-
};
|
|
3843
|
-
if (firstPathWithFill) {
|
|
3844
|
-
const fillColor = parseColor(firstPathWithFill.fill);
|
|
3845
|
-
if (fillColor) {
|
|
3846
|
-
asset.fill = {
|
|
3847
|
-
type: "solid",
|
|
3848
|
-
color: fillColor
|
|
3849
|
-
};
|
|
3850
|
-
if (firstPathWithFill.fillOpacity !== void 0 && firstPathWithFill.fillOpacity !== 1) {
|
|
3851
|
-
asset.fill.opacity = firstPathWithFill.fillOpacity;
|
|
3659
|
+
function extractSvgDimensions(svgString) {
|
|
3660
|
+
const widthMatch = svgString.match(/width\s*=\s*["']?(\d+(?:\.\d+)?)/i);
|
|
3661
|
+
const heightMatch = svgString.match(/height\s*=\s*["']?(\d+(?:\.\d+)?)/i);
|
|
3662
|
+
let width = widthMatch ? parseFloat(widthMatch[1]) : 0;
|
|
3663
|
+
let height = heightMatch ? parseFloat(heightMatch[1]) : 0;
|
|
3664
|
+
if (!width || !height) {
|
|
3665
|
+
const viewBoxMatch = svgString.match(/viewBox\s*=\s*["']([^"']+)["']/i);
|
|
3666
|
+
if (viewBoxMatch) {
|
|
3667
|
+
const parts = viewBoxMatch[1].trim().split(/[\s,]+/).map(parseFloat);
|
|
3668
|
+
if (parts.length === 4) {
|
|
3669
|
+
width = width || parts[2];
|
|
3670
|
+
height = height || parts[3];
|
|
3852
3671
|
}
|
|
3853
3672
|
}
|
|
3854
3673
|
}
|
|
3855
|
-
|
|
3856
|
-
const strokeColor = parseColor(firstPathWithStroke.stroke);
|
|
3857
|
-
if (strokeColor && firstPathWithStroke.strokeWidth && firstPathWithStroke.strokeWidth > 0) {
|
|
3858
|
-
asset.stroke = {
|
|
3859
|
-
color: strokeColor,
|
|
3860
|
-
width: firstPathWithStroke.strokeWidth
|
|
3861
|
-
};
|
|
3862
|
-
if (firstPathWithStroke.strokeOpacity !== void 0 && firstPathWithStroke.strokeOpacity !== 1) {
|
|
3863
|
-
asset.stroke.opacity = firstPathWithStroke.strokeOpacity;
|
|
3864
|
-
}
|
|
3865
|
-
}
|
|
3866
|
-
}
|
|
3867
|
-
const firstPathWithOpacity = parsed.paths.find((p) => p.opacity !== void 0 && p.opacity !== 1);
|
|
3868
|
-
if (firstPathWithOpacity) {
|
|
3869
|
-
asset.opacity = firstPathWithOpacity.opacity;
|
|
3870
|
-
}
|
|
3871
|
-
if (parsed.width > 0) {
|
|
3872
|
-
asset.width = parsed.width;
|
|
3873
|
-
}
|
|
3874
|
-
if (parsed.height > 0) {
|
|
3875
|
-
asset.height = parsed.height;
|
|
3876
|
-
}
|
|
3877
|
-
return asset;
|
|
3878
|
-
}
|
|
3879
|
-
function importSvg(svgString) {
|
|
3880
|
-
return svgToSingleAsset(svgString);
|
|
3674
|
+
return { width, height };
|
|
3881
3675
|
}
|
|
3882
3676
|
|
|
3883
3677
|
// src/env/entry.node.ts
|
|
@@ -4164,38 +3958,20 @@ async function createTextEngine(opts = {}) {
|
|
|
4164
3958
|
CanvasRichTextAssetSchema,
|
|
4165
3959
|
CanvasSvgAssetSchema,
|
|
4166
3960
|
arcToCubicBeziers,
|
|
4167
|
-
centerPath,
|
|
4168
3961
|
commandsToPathString,
|
|
4169
|
-
|
|
3962
|
+
computeSimplePathBounds,
|
|
4170
3963
|
createNodePainter,
|
|
4171
3964
|
createTextEngine,
|
|
4172
|
-
|
|
4173
|
-
generateCirclePath,
|
|
4174
|
-
generateCrossPath,
|
|
4175
|
-
generateEllipsePath,
|
|
4176
|
-
generateHeartPath,
|
|
4177
|
-
generateLinePath,
|
|
4178
|
-
generatePolygonPath,
|
|
4179
|
-
generatePolygonPoints,
|
|
4180
|
-
generateRectanglePath,
|
|
4181
|
-
generateRingPath,
|
|
4182
|
-
generateShapePath,
|
|
4183
|
-
generateStarPath,
|
|
4184
|
-
generateStarPoints,
|
|
4185
|
-
generateTrianglePath,
|
|
4186
|
-
importSvg,
|
|
3965
|
+
generateShapePathData,
|
|
4187
3966
|
isGlyphFill,
|
|
4188
3967
|
isShadowFill,
|
|
4189
3968
|
normalizePath,
|
|
4190
3969
|
normalizePathString,
|
|
4191
|
-
normalizePathToSize,
|
|
4192
|
-
parseSvgMarkup,
|
|
4193
3970
|
parseSvgPath,
|
|
4194
|
-
pointsToPath,
|
|
4195
3971
|
quadraticToCubic,
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
3972
|
+
renderSvgAssetToPng,
|
|
3973
|
+
renderSvgToPng,
|
|
3974
|
+
shapeToSvgString,
|
|
4199
3975
|
svgAssetSchema,
|
|
4200
3976
|
svgGradientStopSchema,
|
|
4201
3977
|
svgLinearGradientFillSchema,
|
|
@@ -4204,8 +3980,5 @@ async function createTextEngine(opts = {}) {
|
|
|
4204
3980
|
svgShapeSchema,
|
|
4205
3981
|
svgSolidFillSchema,
|
|
4206
3982
|
svgStrokeSchema,
|
|
4207
|
-
|
|
4208
|
-
svgToSingleAsset,
|
|
4209
|
-
svgTransformSchema,
|
|
4210
|
-
translatePath
|
|
3983
|
+
svgTransformSchema
|
|
4211
3984
|
});
|