apexify.js 4.6.2 → 4.7.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/cjs/ai/ApexModules.d.ts.map +1 -1
- package/dist/cjs/ai/ApexModules.js +56 -7
- package/dist/cjs/ai/ApexModules.js.map +1 -1
- package/dist/cjs/ai/functions/readFiles.js +1 -1
- package/dist/cjs/ai/functions/readFiles.js.map +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/chatmodels.d.ts.map +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/chatmodels.js +2 -1
- package/dist/cjs/ai/modals-chat/electronHub/chatmodels.js.map +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/speechModels.d.ts.map +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/speechModels.js +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/speechModels.js.map +1 -1
- package/dist/cjs/canvas/ApexPainter.d.ts.map +1 -1
- package/dist/cjs/canvas/ApexPainter.js +27 -28
- package/dist/cjs/canvas/ApexPainter.js.map +1 -1
- package/dist/cjs/canvas/Themes/Level-Up/levelup.d.ts +11 -0
- package/dist/cjs/canvas/Themes/Level-Up/levelup.d.ts.map +1 -0
- package/dist/cjs/canvas/Themes/Level-Up/levelup.js +163 -0
- package/dist/cjs/canvas/Themes/Level-Up/levelup.js.map +1 -0
- package/dist/cjs/canvas/utils/Background/bg.d.ts +17 -10
- package/dist/cjs/canvas/utils/Background/bg.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/Background/bg.js +102 -27
- package/dist/cjs/canvas/utils/Background/bg.js.map +1 -1
- package/dist/cjs/canvas/utils/Custom/customLines.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/Custom/customLines.js +43 -19
- package/dist/cjs/canvas/utils/Custom/customLines.js.map +1 -1
- package/dist/cjs/canvas/utils/General/general functions.d.ts +6 -1
- package/dist/cjs/canvas/utils/General/general functions.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/General/general functions.js +19 -20
- package/dist/cjs/canvas/utils/General/general functions.js.map +1 -1
- package/dist/cjs/canvas/utils/Image/imageProperties.d.ts +3 -9
- package/dist/cjs/canvas/utils/Image/imageProperties.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/Image/imageProperties.js +220 -214
- package/dist/cjs/canvas/utils/Image/imageProperties.js.map +1 -1
- package/dist/cjs/canvas/utils/Texts/textProperties.d.ts +12 -14
- package/dist/cjs/canvas/utils/Texts/textProperties.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/Texts/textProperties.js +100 -91
- package/dist/cjs/canvas/utils/Texts/textProperties.js.map +1 -1
- package/dist/cjs/canvas/utils/types.d.ts +89 -109
- package/dist/cjs/canvas/utils/types.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/types.js.map +1 -1
- package/dist/cjs/canvas/utils/utils.d.ts +2 -4
- package/dist/cjs/canvas/utils/utils.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/utils.js +2 -5
- package/dist/cjs/canvas/utils/utils.js.map +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +31 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/ai/ApexModules.d.ts.map +1 -1
- package/dist/esm/ai/ApexModules.js +56 -7
- package/dist/esm/ai/ApexModules.js.map +1 -1
- package/dist/esm/ai/functions/readFiles.js +1 -1
- package/dist/esm/ai/functions/readFiles.js.map +1 -1
- package/dist/esm/ai/modals-chat/electronHub/chatmodels.d.ts.map +1 -1
- package/dist/esm/ai/modals-chat/electronHub/chatmodels.js +2 -1
- package/dist/esm/ai/modals-chat/electronHub/chatmodels.js.map +1 -1
- package/dist/esm/ai/modals-chat/electronHub/speechModels.d.ts.map +1 -1
- package/dist/esm/ai/modals-chat/electronHub/speechModels.js +1 -1
- package/dist/esm/ai/modals-chat/electronHub/speechModels.js.map +1 -1
- package/dist/esm/canvas/ApexPainter.d.ts.map +1 -1
- package/dist/esm/canvas/ApexPainter.js +27 -28
- package/dist/esm/canvas/ApexPainter.js.map +1 -1
- package/dist/esm/canvas/Themes/Level-Up/levelup.d.ts +11 -0
- package/dist/esm/canvas/Themes/Level-Up/levelup.d.ts.map +1 -0
- package/dist/esm/canvas/Themes/Level-Up/levelup.js +163 -0
- package/dist/esm/canvas/Themes/Level-Up/levelup.js.map +1 -0
- package/dist/esm/canvas/utils/Background/bg.d.ts +17 -10
- package/dist/esm/canvas/utils/Background/bg.d.ts.map +1 -1
- package/dist/esm/canvas/utils/Background/bg.js +102 -27
- package/dist/esm/canvas/utils/Background/bg.js.map +1 -1
- package/dist/esm/canvas/utils/Custom/customLines.d.ts.map +1 -1
- package/dist/esm/canvas/utils/Custom/customLines.js +43 -19
- package/dist/esm/canvas/utils/Custom/customLines.js.map +1 -1
- package/dist/esm/canvas/utils/General/general functions.d.ts +6 -1
- package/dist/esm/canvas/utils/General/general functions.d.ts.map +1 -1
- package/dist/esm/canvas/utils/General/general functions.js +19 -20
- package/dist/esm/canvas/utils/General/general functions.js.map +1 -1
- package/dist/esm/canvas/utils/Image/imageProperties.d.ts +3 -9
- package/dist/esm/canvas/utils/Image/imageProperties.d.ts.map +1 -1
- package/dist/esm/canvas/utils/Image/imageProperties.js +220 -214
- package/dist/esm/canvas/utils/Image/imageProperties.js.map +1 -1
- package/dist/esm/canvas/utils/Texts/textProperties.d.ts +12 -14
- package/dist/esm/canvas/utils/Texts/textProperties.d.ts.map +1 -1
- package/dist/esm/canvas/utils/Texts/textProperties.js +100 -91
- package/dist/esm/canvas/utils/Texts/textProperties.js.map +1 -1
- package/dist/esm/canvas/utils/types.d.ts +89 -109
- package/dist/esm/canvas/utils/types.d.ts.map +1 -1
- package/dist/esm/canvas/utils/types.js.map +1 -1
- package/dist/esm/canvas/utils/utils.d.ts +2 -4
- package/dist/esm/canvas/utils/utils.d.ts.map +1 -1
- package/dist/esm/canvas/utils/utils.js +2 -5
- package/dist/esm/canvas/utils/utils.js.map +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +31 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/ai/ApexModules.ts +83 -11
- package/lib/ai/functions/readFiles.ts +1 -1
- package/lib/ai/modals-chat/electronHub/chatmodels.ts +4 -2
- package/lib/ai/modals-chat/electronHub/speechModels.ts +2 -1
- package/lib/canvas/ApexPainter.ts +52 -61
- package/lib/canvas/Themes/Level-Up/levelup.ts +183 -0
- package/lib/canvas/utils/Background/bg.ts +179 -65
- package/lib/canvas/utils/Custom/customLines.ts +53 -20
- package/lib/canvas/utils/General/general functions.ts +21 -29
- package/lib/canvas/utils/Image/imageProperties.ts +399 -318
- package/lib/canvas/utils/Texts/textProperties.ts +213 -162
- package/lib/canvas/utils/types.ts +74 -107
- package/lib/canvas/utils/utils.ts +2 -5
- package/lib/index.ts +38 -10
- package/package.json +3 -2
- package/dist/cjs/canvas/utils/Background/circular.d.ts +0 -3
- package/dist/cjs/canvas/utils/Background/circular.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/Background/circular.js +0 -13
- package/dist/cjs/canvas/utils/Background/circular.js.map +0 -1
- package/dist/cjs/canvas/utils/Background/radius.d.ts +0 -18
- package/dist/cjs/canvas/utils/Background/radius.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/Background/radius.js +0 -104
- package/dist/cjs/canvas/utils/Background/radius.js.map +0 -1
- package/dist/esm/canvas/utils/Background/circular.d.ts +0 -3
- package/dist/esm/canvas/utils/Background/circular.d.ts.map +0 -1
- package/dist/esm/canvas/utils/Background/circular.js +0 -13
- package/dist/esm/canvas/utils/Background/circular.js.map +0 -1
- package/dist/esm/canvas/utils/Background/radius.d.ts +0 -18
- package/dist/esm/canvas/utils/Background/radius.d.ts.map +0 -1
- package/dist/esm/canvas/utils/Background/radius.js +0 -104
- package/dist/esm/canvas/utils/Background/radius.js.map +0 -1
- package/lib/canvas/utils/Background/circular.ts +0 -17
- package/lib/canvas/utils/Background/radius.ts +0 -102
|
@@ -1,97 +1,211 @@
|
|
|
1
1
|
import { loadImage, SKRSContext2D } from "@napi-rs/canvas";
|
|
2
|
-
import { CanvasConfig } from
|
|
3
|
-
import path from
|
|
2
|
+
import { CanvasConfig } from "../types";
|
|
3
|
+
import path from "path";
|
|
4
4
|
|
|
5
|
+
interface ZoomConfig {
|
|
6
|
+
scale?: number;
|
|
7
|
+
x?: number;
|
|
8
|
+
y?: number;
|
|
9
|
+
}
|
|
5
10
|
|
|
6
11
|
/**
|
|
7
|
-
* Draws a gradient background on the canvas.
|
|
8
|
-
* No zoom logic is applied.
|
|
12
|
+
* Draws a gradient background on the canvas with optional zoom support.
|
|
9
13
|
* @param ctx The canvas rendering context.
|
|
10
14
|
* @param canvas The canvas configuration object.
|
|
15
|
+
* @param zoom Optional zoom configuration.
|
|
11
16
|
*/
|
|
12
|
-
export async function drawBackgroundGradient(
|
|
17
|
+
export async function drawBackgroundGradient(
|
|
18
|
+
ctx: SKRSContext2D,
|
|
19
|
+
canvas: CanvasConfig,
|
|
20
|
+
zoom?: ZoomConfig,
|
|
21
|
+
blur?: number
|
|
22
|
+
): Promise<void> {
|
|
13
23
|
if (canvas.gradientBg) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
const {
|
|
25
|
+
type,
|
|
26
|
+
startX = 0,
|
|
27
|
+
startY = 0,
|
|
28
|
+
endX = canvas.width || 500,
|
|
29
|
+
endY = canvas.height || 500,
|
|
30
|
+
startRadius = 0,
|
|
31
|
+
endRadius = 0,
|
|
32
|
+
colors
|
|
33
|
+
} = canvas.gradientBg;
|
|
34
|
+
|
|
35
|
+
if (!colors || colors.length === 0) {
|
|
36
|
+
throw new Error("You need to provide colors for the gradient.");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let gradient;
|
|
40
|
+
if (type === "linear" || type === undefined) {
|
|
41
|
+
let finalStartX = startX, finalStartY = startY, finalEndX = endX, finalEndY = endY;
|
|
42
|
+
|
|
43
|
+
if (zoom) {
|
|
44
|
+
const scale = Math.max(1, zoom.scale || 1);
|
|
45
|
+
finalStartX = (zoom.x || 0) - (endX - startX) / (2 * scale);
|
|
46
|
+
finalStartY = (zoom.y || 0) - (endY - startY) / (2 * scale);
|
|
47
|
+
finalEndX = (zoom.x || 0) + (endX - startX) / (2 * scale);
|
|
48
|
+
finalEndY = (zoom.y || 0) + (endY - startY) / (2 * scale);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
gradient = ctx.createLinearGradient(finalStartX, finalStartY, finalEndX, finalEndY);
|
|
52
|
+
} else if (type === "radial") {
|
|
53
|
+
gradient = ctx.createRadialGradient(startX, startY, startRadius, endX, endY, endRadius);
|
|
54
|
+
} else {
|
|
55
|
+
throw new Error("Unsupported gradient type.");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
for (const { stop, color } of colors) {
|
|
59
|
+
gradient.addColorStop(stop as number, color as string);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (blur) {
|
|
63
|
+
ctx.filter = `blur(${blur}px)`;
|
|
40
64
|
}
|
|
41
|
-
|
|
42
|
-
const canvasWidth = canvas.width || 500;
|
|
43
|
-
const canvasHeight = canvas.height || 500;
|
|
65
|
+
|
|
44
66
|
ctx.fillStyle = gradient;
|
|
45
|
-
ctx.fillRect(0, 0,
|
|
67
|
+
ctx.fillRect(0, 0, canvas.width || 500, canvas.height || 500);
|
|
68
|
+
|
|
69
|
+
ctx.filter = "none";
|
|
46
70
|
}
|
|
47
71
|
}
|
|
48
|
-
|
|
72
|
+
|
|
49
73
|
/**
|
|
50
|
-
* Draws a solid background color on the canvas.
|
|
51
|
-
* No zoom logic is applied.
|
|
74
|
+
* Draws a solid background color on the canvas with optional zoom effect.
|
|
52
75
|
* @param ctx The canvas rendering context.
|
|
53
76
|
* @param canvas The canvas configuration object.
|
|
77
|
+
* @param zoom Optional zoom configuration.
|
|
54
78
|
*/
|
|
55
|
-
export async function drawBackgroundColor(
|
|
79
|
+
export async function drawBackgroundColor(
|
|
80
|
+
ctx: SKRSContext2D,
|
|
81
|
+
canvas: CanvasConfig,
|
|
82
|
+
zoom?: ZoomConfig,
|
|
83
|
+
blur?: number
|
|
84
|
+
): Promise<void> {
|
|
56
85
|
const canvasWidth = canvas.width || 500;
|
|
57
86
|
const canvasHeight = canvas.height || 500;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
87
|
+
|
|
88
|
+
ctx.save();
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
if (blur) {
|
|
92
|
+
ctx.filter = `blur(${blur}px)`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (zoom) {
|
|
96
|
+
const scale = Math.max(1, zoom.scale || 1);
|
|
97
|
+
const zoomedWidth = canvasWidth / scale;
|
|
98
|
+
const zoomedHeight = canvasHeight / scale;
|
|
99
|
+
|
|
100
|
+
ctx.scale(scale, scale);
|
|
101
|
+
ctx.translate((zoom.x || 0) + zoomedWidth / 2, (zoom.y || 0) + zoomedHeight / 2);
|
|
63
102
|
}
|
|
103
|
+
|
|
104
|
+
if (canvas.colorBg !== "transparent") {
|
|
105
|
+
ctx.fillStyle = canvas.colorBg as string;
|
|
106
|
+
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
ctx.filter = "none";
|
|
110
|
+
ctx.restore();
|
|
64
111
|
}
|
|
65
112
|
|
|
66
113
|
/**
|
|
67
|
-
* Draws a custom background image on the canvas.
|
|
68
|
-
* No zoom logic is applied.
|
|
114
|
+
* Draws a custom background image on the canvas with optional zoom functionality.
|
|
69
115
|
* @param ctx The canvas rendering context.
|
|
70
116
|
* @param canvas The canvas configuration object.
|
|
117
|
+
* @param zoom Optional zoom configuration.
|
|
71
118
|
*/
|
|
72
|
-
export async function customBackground(
|
|
119
|
+
export async function customBackground(
|
|
120
|
+
ctx: SKRSContext2D,
|
|
121
|
+
canvas: CanvasConfig,
|
|
122
|
+
zoom?: ZoomConfig,
|
|
123
|
+
blur?: number
|
|
124
|
+
): Promise<void> {
|
|
73
125
|
if (canvas.customBg) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
126
|
+
try {
|
|
127
|
+
let imageBuffer: string;
|
|
128
|
+
|
|
129
|
+
if (canvas.customBg.startsWith("http")) {
|
|
130
|
+
imageBuffer = canvas.customBg;
|
|
131
|
+
} else {
|
|
132
|
+
imageBuffer = path.join(process.cwd(), canvas.customBg);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const image = await loadImage(imageBuffer);
|
|
136
|
+
const imgWidth = image.width;
|
|
137
|
+
const imgHeight = image.height;
|
|
138
|
+
const canvasWidth = canvas.width || imgWidth;
|
|
139
|
+
const canvasHeight = canvas.height || imgHeight;
|
|
140
|
+
|
|
141
|
+
if (blur) {
|
|
142
|
+
ctx.filter = `blur(${blur}px)`;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (zoom) {
|
|
146
|
+
const scale = Math.max(1, zoom.scale || 1);
|
|
147
|
+
const cropWidth = imgWidth / scale;
|
|
148
|
+
const cropHeight = imgHeight / scale;
|
|
149
|
+
|
|
150
|
+
let sx = (zoom.x || 0) - cropWidth / 2;
|
|
151
|
+
let sy = (zoom.y || 0) - cropHeight / 2;
|
|
152
|
+
|
|
153
|
+
sx = Math.max(0, Math.min(sx, imgWidth - cropWidth));
|
|
154
|
+
sy = Math.max(0, Math.min(sy, imgHeight - cropHeight));
|
|
155
|
+
|
|
156
|
+
ctx.drawImage(image, sx, sy, cropWidth, cropHeight, 0, 0, canvasWidth, canvasHeight);
|
|
157
|
+
} else {
|
|
158
|
+
ctx.drawImage(image, 0, 0, canvasWidth, canvasHeight);
|
|
159
|
+
}
|
|
160
|
+
ctx.filter = "none";
|
|
161
|
+
} catch (error: any) {
|
|
162
|
+
console.error("Error loading custom background image:", error.message);
|
|
81
163
|
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function backgroundRadius(
|
|
168
|
+
ctx: SKRSContext2D,
|
|
169
|
+
x: number,
|
|
170
|
+
y: number,
|
|
171
|
+
width: number,
|
|
172
|
+
height: number,
|
|
173
|
+
borderRadius: number | "circular",
|
|
174
|
+
borderPosition: string = "all"
|
|
175
|
+
): void {
|
|
176
|
+
ctx.beginPath();
|
|
82
177
|
|
|
83
|
-
|
|
178
|
+
if (borderRadius === "circular") {
|
|
179
|
+
const circleRadius = Math.min(width, height) / 2;
|
|
180
|
+
ctx.arc(x + width / 2, y + height / 2, circleRadius, 0, 2 * Math.PI);
|
|
181
|
+
} else if (typeof borderRadius === "number" && borderRadius > 0) {
|
|
182
|
+
const br: number = Math.min(borderRadius, width / 2, height / 2);
|
|
183
|
+
const selectedPositions = new Set(borderPosition.toLowerCase().split(",").map((s) => s.trim()));
|
|
84
184
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
185
|
+
const roundTopLeft = selectedPositions.has("all") || selectedPositions.has("top-left") || (selectedPositions.has("top") && selectedPositions.has("left"));
|
|
186
|
+
const roundTopRight = selectedPositions.has("all") || selectedPositions.has("top-right") || (selectedPositions.has("top") && selectedPositions.has("right"));
|
|
187
|
+
const roundBottomRight = selectedPositions.has("all") || selectedPositions.has("bottom-right") || (selectedPositions.has("bottom") && selectedPositions.has("right"));
|
|
188
|
+
const roundBottomLeft = selectedPositions.has("all") || selectedPositions.has("bottom-left") || (selectedPositions.has("bottom") && selectedPositions.has("left"));
|
|
89
189
|
|
|
90
|
-
|
|
91
|
-
|
|
190
|
+
const tl = roundTopLeft ? br : 0;
|
|
191
|
+
const tr = roundTopRight ? br : 0;
|
|
192
|
+
const brR = roundBottomRight ? br : 0;
|
|
193
|
+
const bl = roundBottomLeft ? br : 0;
|
|
92
194
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
195
|
+
ctx.moveTo(x + tl, y);
|
|
196
|
+
ctx.lineTo(x + width - tr, y);
|
|
197
|
+
if (tr > 0) ctx.arc(x + width - tr, y + tr, tr, -Math.PI / 2, 0, false);
|
|
198
|
+
ctx.lineTo(x + width, y + height - brR);
|
|
199
|
+
if (brR > 0) ctx.arc(x + width - brR, y + height - brR, brR, 0, Math.PI / 2, false);
|
|
200
|
+
ctx.lineTo(x + bl, y + height);
|
|
201
|
+
if (bl > 0) ctx.arc(x + bl, y + height - bl, bl, Math.PI / 2, Math.PI, false);
|
|
202
|
+
ctx.lineTo(x, y + tl);
|
|
203
|
+
if (tl > 0) ctx.arc(x + tl, y + tl, tl, Math.PI, -Math.PI / 2, false);
|
|
204
|
+
} else {
|
|
205
|
+
ctx.rect(x, y, width, height);
|
|
96
206
|
}
|
|
97
|
-
|
|
207
|
+
|
|
208
|
+
ctx.closePath();
|
|
209
|
+
ctx.clip();
|
|
210
|
+
}
|
|
211
|
+
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createGradient } from "../Image/imageProperties";
|
|
1
2
|
import { CustomOptions } from "../types";
|
|
2
3
|
|
|
3
4
|
export function customLines(ctx: any, options: CustomOptions[]) {
|
|
@@ -19,7 +20,7 @@ export function customLines(ctx: any, options: CustomOptions[]) {
|
|
|
19
20
|
|
|
20
21
|
if (!isSingleLine && inSingleLineSequence) {
|
|
21
22
|
ctx.stroke();
|
|
22
|
-
|
|
23
|
+
applyStroke(ctx, currentStyle, startCoordinates, endCoordinates);
|
|
23
24
|
inSingleLineSequence = false;
|
|
24
25
|
currentStyle = null;
|
|
25
26
|
}
|
|
@@ -37,7 +38,13 @@ export function customLines(ctx: any, options: CustomOptions[]) {
|
|
|
37
38
|
|
|
38
39
|
const appliedStyle = inSingleLineSequence ? currentStyle : lineStyle;
|
|
39
40
|
ctx.lineWidth = appliedStyle?.width || 1;
|
|
40
|
-
|
|
41
|
+
|
|
42
|
+
if (appliedStyle?.gradient) {
|
|
43
|
+
ctx.strokeStyle = createGradient(ctx, appliedStyle.gradient, start.x, start.y, endCoordinates.x, endCoordinates.y);
|
|
44
|
+
} else {
|
|
45
|
+
ctx.strokeStyle = appliedStyle?.color || 'black';
|
|
46
|
+
}
|
|
47
|
+
|
|
41
48
|
ctx.lineJoin = appliedStyle?.lineJoin || 'miter';
|
|
42
49
|
ctx.lineCap = appliedStyle?.lineCap || 'butt';
|
|
43
50
|
|
|
@@ -48,31 +55,36 @@ export function customLines(ctx: any, options: CustomOptions[]) {
|
|
|
48
55
|
ctx.setLineDash([]);
|
|
49
56
|
}
|
|
50
57
|
|
|
51
|
-
if (typeof appliedStyle?.lineRadius === 'number') {
|
|
52
|
-
const
|
|
58
|
+
if (typeof appliedStyle?.lineRadius === 'number' && appliedStyle.lineRadius > 0) {
|
|
59
|
+
const radius = appliedStyle.lineRadius;
|
|
53
60
|
const dx = endCoordinates.x - start.x;
|
|
54
61
|
const dy = endCoordinates.y - start.y;
|
|
55
62
|
const angle = Math.atan2(dy, dx);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
ctx.
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
|
|
64
|
+
ctx.lineCap = "round";
|
|
65
|
+
ctx.stroke();
|
|
66
|
+
|
|
67
|
+
ctx.beginPath();
|
|
68
|
+
ctx.arc(start.x, start.y, radius, angle + Math.PI / 2, angle - Math.PI / 2, true);
|
|
69
|
+
ctx.arc(endCoordinates.x, endCoordinates.y, radius, angle - Math.PI / 2, angle + Math.PI / 2, false);
|
|
70
|
+
ctx.fill();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
else if (appliedStyle?.lineRadius === 'circular') {
|
|
61
74
|
const dx = endCoordinates.x - start.x;
|
|
62
75
|
const dy = endCoordinates.y - start.y;
|
|
63
76
|
const length = Math.sqrt(dx * dx + dy * dy);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
ctx.
|
|
67
|
-
ctx.
|
|
68
|
-
ctx.lineTo(endCoordinates.x + Math.cos(angle + Math.PI / 2) * halfWidth, endCoordinates.y + Math.sin(angle + Math.PI / 2) * halfWidth);
|
|
69
|
-
ctx.arc(endCoordinates.x, endCoordinates.y, length / 2, angle + Math.PI / 2, angle - Math.PI / 2, true);
|
|
77
|
+
|
|
78
|
+
ctx.beginPath();
|
|
79
|
+
ctx.arcTo(start.x, start.y, endCoordinates.x, endCoordinates.y, length / 2);
|
|
80
|
+
ctx.arcTo(endCoordinates.x, endCoordinates.y, start.x, start.y, length / 2);
|
|
70
81
|
ctx.closePath();
|
|
82
|
+
ctx.stroke();
|
|
71
83
|
}
|
|
72
84
|
|
|
73
85
|
if (!inSingleLineSequence || i === options.length - 1) {
|
|
74
86
|
ctx.stroke();
|
|
75
|
-
|
|
87
|
+
applyStroke(ctx, appliedStyle, startCoordinates, endCoordinates);
|
|
76
88
|
}
|
|
77
89
|
|
|
78
90
|
previousEndCoordinates = endCoordinates;
|
|
@@ -84,11 +96,32 @@ export function customLines(ctx: any, options: CustomOptions[]) {
|
|
|
84
96
|
}
|
|
85
97
|
}
|
|
86
98
|
|
|
87
|
-
function
|
|
99
|
+
function applyStroke(ctx: any, style: any, start: any, end: any) {
|
|
88
100
|
if (style.stroke) {
|
|
89
|
-
const { color, width } = style.stroke;
|
|
90
|
-
ctx.strokeStyle
|
|
91
|
-
ctx.lineWidth
|
|
101
|
+
const { color, width, gradient, lineRadius, lineCap } = style.stroke;
|
|
102
|
+
const prevStrokeStyle = ctx.strokeStyle;
|
|
103
|
+
const prevLineWidth = ctx.lineWidth;
|
|
104
|
+
const prevLineCap = ctx.lineCap;
|
|
105
|
+
|
|
106
|
+
if (gradient) {
|
|
107
|
+
ctx.strokeStyle = createGradient(ctx, gradient, start.x, start.y, end.x, end.y);
|
|
108
|
+
} else {
|
|
109
|
+
ctx.strokeStyle = color || prevStrokeStyle;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
ctx.lineWidth = width || prevLineWidth;
|
|
113
|
+
ctx.lineCap = lineCap || prevLineCap;
|
|
92
114
|
ctx.stroke();
|
|
115
|
+
|
|
116
|
+
if (typeof lineRadius === 'number' && lineRadius > 0) {
|
|
117
|
+
ctx.beginPath();
|
|
118
|
+
ctx.arc(start.x, start.y, lineRadius, 0, Math.PI * 2);
|
|
119
|
+
ctx.arc(end.x, end.y, lineRadius, 0, Math.PI * 2);
|
|
120
|
+
ctx.fill();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
ctx.strokeStyle = prevStrokeStyle;
|
|
124
|
+
ctx.lineWidth = prevLineWidth;
|
|
125
|
+
ctx.lineCap = prevLineCap;
|
|
93
126
|
}
|
|
94
127
|
}
|
|
@@ -31,7 +31,6 @@ export async function loadImages(imagePath: string) {
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Resizes an image using Sharp with additional options for quality, kernel, and withoutEnlargement.
|
|
34
|
-
*
|
|
35
34
|
* @param resizeOptions - The options for resizing.
|
|
36
35
|
* @returns A Promise that resolves with the resized image as a Buffer.
|
|
37
36
|
*/
|
|
@@ -41,14 +40,8 @@ export async function resizingImg(resizeOptions: ResizeOptions): Promise<Buffer>
|
|
|
41
40
|
throw new Error("Image path is required for resizing.");
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
absoluteImagePath = resizeOptions.imagePath;
|
|
47
|
-
} else {
|
|
48
|
-
absoluteImagePath = path.join(process.cwd(), resizeOptions.imagePath);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const image = sharp(absoluteImagePath);
|
|
43
|
+
// ✅ Use `loadImages()` instead of handling the fetch manually
|
|
44
|
+
const image = await loadImages(resizeOptions.imagePath);
|
|
52
45
|
|
|
53
46
|
const resizeOptionsForSharp: sharp.ResizeOptions = {
|
|
54
47
|
width: resizeOptions.size?.width || 500,
|
|
@@ -60,21 +53,18 @@ export async function resizingImg(resizeOptions: ResizeOptions): Promise<Buffer>
|
|
|
60
53
|
|
|
61
54
|
const quality = resizeOptions.quality ?? 90;
|
|
62
55
|
|
|
63
|
-
const resizedBuffer: Buffer =
|
|
56
|
+
const resizedBuffer: Buffer = await image
|
|
64
57
|
.resize(resizeOptionsForSharp)
|
|
65
58
|
.png({ quality })
|
|
66
59
|
.toBuffer();
|
|
67
|
-
|
|
68
60
|
|
|
69
61
|
return resizedBuffer;
|
|
70
|
-
|
|
71
62
|
} catch (error) {
|
|
72
63
|
console.error("Error resizing image:", error);
|
|
73
64
|
throw new Error("Failed to resize image");
|
|
74
65
|
}
|
|
75
66
|
}
|
|
76
67
|
|
|
77
|
-
|
|
78
68
|
export async function converter(imagePath: string, newExtension: string) {
|
|
79
69
|
try {
|
|
80
70
|
const validExtensions: (keyof sharp.FormatEnum)[] = ['jpeg', 'png', 'webp', 'tiff', 'gif', 'avif', 'heif', 'raw', 'pdf', 'svg'];
|
|
@@ -382,53 +372,55 @@ export async function cropOuter(options: cropOptions): Promise<Buffer> {
|
|
|
382
372
|
}
|
|
383
373
|
|
|
384
374
|
|
|
375
|
+
/**
|
|
376
|
+
* Detects dominant colors from an image.
|
|
377
|
+
*
|
|
378
|
+
* @param imagePath - Local path or URL of the image.
|
|
379
|
+
* @returns A sorted array of dominant colors with their frequency.
|
|
380
|
+
*/
|
|
385
381
|
export async function detectColors(imagePath: string): Promise<{ color: string; frequency: string }[]> {
|
|
386
382
|
try {
|
|
387
383
|
let image: any;
|
|
384
|
+
|
|
388
385
|
if (imagePath.startsWith('http')) {
|
|
389
386
|
const response = await fetch(imagePath);
|
|
390
|
-
if (!response.ok) {
|
|
391
|
-
throw new Error("Failed to fetch image.");
|
|
392
|
-
}
|
|
387
|
+
if (!response.ok) throw new Error(`Failed to fetch image: ${response.statusText}`);
|
|
393
388
|
const buffer = await response.arrayBuffer();
|
|
394
389
|
image = await loadImage(Buffer.from(buffer));
|
|
395
390
|
} else {
|
|
396
|
-
const localImagePath = path.
|
|
391
|
+
const localImagePath = path.resolve(imagePath);
|
|
397
392
|
image = await loadImage(localImagePath);
|
|
398
393
|
}
|
|
399
394
|
|
|
400
395
|
const canvas = createCanvas(image.width, image.height);
|
|
401
|
-
const ctx = canvas.getContext('2d')
|
|
402
|
-
|
|
396
|
+
const ctx = canvas.getContext('2d');
|
|
403
397
|
ctx.drawImage(image, 0, 0, image.width, image.height);
|
|
404
398
|
|
|
405
399
|
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
406
400
|
const data = imageData.data;
|
|
407
401
|
|
|
408
402
|
const colorFrequency: { [color: string]: number } = {};
|
|
409
|
-
|
|
410
403
|
for (let i = 0; i < data.length; i += 4) {
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
const blue = data[i + 2];
|
|
414
|
-
|
|
415
|
-
const color = `${red},${green},${blue}`;
|
|
404
|
+
const [r, g, b, a] = [data[i], data[i + 1], data[i + 2], data[i + 3]];
|
|
405
|
+
if (a < 50) continue;
|
|
416
406
|
|
|
407
|
+
const color = `${r},${g},${b}`;
|
|
417
408
|
colorFrequency[color] = (colorFrequency[color] || 0) + 1;
|
|
418
409
|
}
|
|
419
410
|
|
|
420
411
|
const totalPixels = canvas.width * canvas.height;
|
|
421
412
|
|
|
422
413
|
const dominantColors = Object.entries(colorFrequency)
|
|
423
|
-
.
|
|
424
|
-
.map(([color, frequency]: [string, number]) => ({
|
|
414
|
+
.map(([color, frequency]) => ({
|
|
425
415
|
color,
|
|
426
416
|
frequency: ((frequency / totalPixels) * 100).toFixed(2),
|
|
427
|
-
}))
|
|
417
|
+
}))
|
|
418
|
+
.filter(colorObj => parseFloat(colorObj.frequency) >= 0.1)
|
|
419
|
+
.sort((a, b) => parseFloat(b.frequency) - parseFloat(a.frequency));
|
|
428
420
|
|
|
429
421
|
return dominantColors;
|
|
430
422
|
} catch (error) {
|
|
431
|
-
console.error(
|
|
423
|
+
console.error("❌ Error detecting colors:", error);
|
|
432
424
|
return [];
|
|
433
425
|
}
|
|
434
426
|
}
|