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.
Files changed (129) hide show
  1. package/dist/cjs/ai/ApexModules.d.ts.map +1 -1
  2. package/dist/cjs/ai/ApexModules.js +56 -7
  3. package/dist/cjs/ai/ApexModules.js.map +1 -1
  4. package/dist/cjs/ai/functions/readFiles.js +1 -1
  5. package/dist/cjs/ai/functions/readFiles.js.map +1 -1
  6. package/dist/cjs/ai/modals-chat/electronHub/chatmodels.d.ts.map +1 -1
  7. package/dist/cjs/ai/modals-chat/electronHub/chatmodels.js +2 -1
  8. package/dist/cjs/ai/modals-chat/electronHub/chatmodels.js.map +1 -1
  9. package/dist/cjs/ai/modals-chat/electronHub/speechModels.d.ts.map +1 -1
  10. package/dist/cjs/ai/modals-chat/electronHub/speechModels.js +1 -1
  11. package/dist/cjs/ai/modals-chat/electronHub/speechModels.js.map +1 -1
  12. package/dist/cjs/canvas/ApexPainter.d.ts.map +1 -1
  13. package/dist/cjs/canvas/ApexPainter.js +27 -28
  14. package/dist/cjs/canvas/ApexPainter.js.map +1 -1
  15. package/dist/cjs/canvas/Themes/Level-Up/levelup.d.ts +11 -0
  16. package/dist/cjs/canvas/Themes/Level-Up/levelup.d.ts.map +1 -0
  17. package/dist/cjs/canvas/Themes/Level-Up/levelup.js +163 -0
  18. package/dist/cjs/canvas/Themes/Level-Up/levelup.js.map +1 -0
  19. package/dist/cjs/canvas/utils/Background/bg.d.ts +17 -10
  20. package/dist/cjs/canvas/utils/Background/bg.d.ts.map +1 -1
  21. package/dist/cjs/canvas/utils/Background/bg.js +102 -27
  22. package/dist/cjs/canvas/utils/Background/bg.js.map +1 -1
  23. package/dist/cjs/canvas/utils/Custom/customLines.d.ts.map +1 -1
  24. package/dist/cjs/canvas/utils/Custom/customLines.js +43 -19
  25. package/dist/cjs/canvas/utils/Custom/customLines.js.map +1 -1
  26. package/dist/cjs/canvas/utils/General/general functions.d.ts +6 -1
  27. package/dist/cjs/canvas/utils/General/general functions.d.ts.map +1 -1
  28. package/dist/cjs/canvas/utils/General/general functions.js +19 -20
  29. package/dist/cjs/canvas/utils/General/general functions.js.map +1 -1
  30. package/dist/cjs/canvas/utils/Image/imageProperties.d.ts +3 -9
  31. package/dist/cjs/canvas/utils/Image/imageProperties.d.ts.map +1 -1
  32. package/dist/cjs/canvas/utils/Image/imageProperties.js +220 -214
  33. package/dist/cjs/canvas/utils/Image/imageProperties.js.map +1 -1
  34. package/dist/cjs/canvas/utils/Texts/textProperties.d.ts +12 -14
  35. package/dist/cjs/canvas/utils/Texts/textProperties.d.ts.map +1 -1
  36. package/dist/cjs/canvas/utils/Texts/textProperties.js +100 -91
  37. package/dist/cjs/canvas/utils/Texts/textProperties.js.map +1 -1
  38. package/dist/cjs/canvas/utils/types.d.ts +89 -109
  39. package/dist/cjs/canvas/utils/types.d.ts.map +1 -1
  40. package/dist/cjs/canvas/utils/types.js.map +1 -1
  41. package/dist/cjs/canvas/utils/utils.d.ts +2 -4
  42. package/dist/cjs/canvas/utils/utils.d.ts.map +1 -1
  43. package/dist/cjs/canvas/utils/utils.js +2 -5
  44. package/dist/cjs/canvas/utils/utils.js.map +1 -1
  45. package/dist/cjs/index.d.ts.map +1 -1
  46. package/dist/cjs/index.js +31 -3
  47. package/dist/cjs/index.js.map +1 -1
  48. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  49. package/dist/esm/ai/ApexModules.d.ts.map +1 -1
  50. package/dist/esm/ai/ApexModules.js +56 -7
  51. package/dist/esm/ai/ApexModules.js.map +1 -1
  52. package/dist/esm/ai/functions/readFiles.js +1 -1
  53. package/dist/esm/ai/functions/readFiles.js.map +1 -1
  54. package/dist/esm/ai/modals-chat/electronHub/chatmodels.d.ts.map +1 -1
  55. package/dist/esm/ai/modals-chat/electronHub/chatmodels.js +2 -1
  56. package/dist/esm/ai/modals-chat/electronHub/chatmodels.js.map +1 -1
  57. package/dist/esm/ai/modals-chat/electronHub/speechModels.d.ts.map +1 -1
  58. package/dist/esm/ai/modals-chat/electronHub/speechModels.js +1 -1
  59. package/dist/esm/ai/modals-chat/electronHub/speechModels.js.map +1 -1
  60. package/dist/esm/canvas/ApexPainter.d.ts.map +1 -1
  61. package/dist/esm/canvas/ApexPainter.js +27 -28
  62. package/dist/esm/canvas/ApexPainter.js.map +1 -1
  63. package/dist/esm/canvas/Themes/Level-Up/levelup.d.ts +11 -0
  64. package/dist/esm/canvas/Themes/Level-Up/levelup.d.ts.map +1 -0
  65. package/dist/esm/canvas/Themes/Level-Up/levelup.js +163 -0
  66. package/dist/esm/canvas/Themes/Level-Up/levelup.js.map +1 -0
  67. package/dist/esm/canvas/utils/Background/bg.d.ts +17 -10
  68. package/dist/esm/canvas/utils/Background/bg.d.ts.map +1 -1
  69. package/dist/esm/canvas/utils/Background/bg.js +102 -27
  70. package/dist/esm/canvas/utils/Background/bg.js.map +1 -1
  71. package/dist/esm/canvas/utils/Custom/customLines.d.ts.map +1 -1
  72. package/dist/esm/canvas/utils/Custom/customLines.js +43 -19
  73. package/dist/esm/canvas/utils/Custom/customLines.js.map +1 -1
  74. package/dist/esm/canvas/utils/General/general functions.d.ts +6 -1
  75. package/dist/esm/canvas/utils/General/general functions.d.ts.map +1 -1
  76. package/dist/esm/canvas/utils/General/general functions.js +19 -20
  77. package/dist/esm/canvas/utils/General/general functions.js.map +1 -1
  78. package/dist/esm/canvas/utils/Image/imageProperties.d.ts +3 -9
  79. package/dist/esm/canvas/utils/Image/imageProperties.d.ts.map +1 -1
  80. package/dist/esm/canvas/utils/Image/imageProperties.js +220 -214
  81. package/dist/esm/canvas/utils/Image/imageProperties.js.map +1 -1
  82. package/dist/esm/canvas/utils/Texts/textProperties.d.ts +12 -14
  83. package/dist/esm/canvas/utils/Texts/textProperties.d.ts.map +1 -1
  84. package/dist/esm/canvas/utils/Texts/textProperties.js +100 -91
  85. package/dist/esm/canvas/utils/Texts/textProperties.js.map +1 -1
  86. package/dist/esm/canvas/utils/types.d.ts +89 -109
  87. package/dist/esm/canvas/utils/types.d.ts.map +1 -1
  88. package/dist/esm/canvas/utils/types.js.map +1 -1
  89. package/dist/esm/canvas/utils/utils.d.ts +2 -4
  90. package/dist/esm/canvas/utils/utils.d.ts.map +1 -1
  91. package/dist/esm/canvas/utils/utils.js +2 -5
  92. package/dist/esm/canvas/utils/utils.js.map +1 -1
  93. package/dist/esm/index.d.ts.map +1 -1
  94. package/dist/esm/index.js +31 -3
  95. package/dist/esm/index.js.map +1 -1
  96. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  97. package/lib/ai/ApexModules.ts +83 -11
  98. package/lib/ai/functions/readFiles.ts +1 -1
  99. package/lib/ai/modals-chat/electronHub/chatmodels.ts +4 -2
  100. package/lib/ai/modals-chat/electronHub/speechModels.ts +2 -1
  101. package/lib/canvas/ApexPainter.ts +52 -61
  102. package/lib/canvas/Themes/Level-Up/levelup.ts +183 -0
  103. package/lib/canvas/utils/Background/bg.ts +179 -65
  104. package/lib/canvas/utils/Custom/customLines.ts +53 -20
  105. package/lib/canvas/utils/General/general functions.ts +21 -29
  106. package/lib/canvas/utils/Image/imageProperties.ts +399 -318
  107. package/lib/canvas/utils/Texts/textProperties.ts +213 -162
  108. package/lib/canvas/utils/types.ts +74 -107
  109. package/lib/canvas/utils/utils.ts +2 -5
  110. package/lib/index.ts +38 -10
  111. package/package.json +3 -2
  112. package/dist/cjs/canvas/utils/Background/circular.d.ts +0 -3
  113. package/dist/cjs/canvas/utils/Background/circular.d.ts.map +0 -1
  114. package/dist/cjs/canvas/utils/Background/circular.js +0 -13
  115. package/dist/cjs/canvas/utils/Background/circular.js.map +0 -1
  116. package/dist/cjs/canvas/utils/Background/radius.d.ts +0 -18
  117. package/dist/cjs/canvas/utils/Background/radius.d.ts.map +0 -1
  118. package/dist/cjs/canvas/utils/Background/radius.js +0 -104
  119. package/dist/cjs/canvas/utils/Background/radius.js.map +0 -1
  120. package/dist/esm/canvas/utils/Background/circular.d.ts +0 -3
  121. package/dist/esm/canvas/utils/Background/circular.d.ts.map +0 -1
  122. package/dist/esm/canvas/utils/Background/circular.js +0 -13
  123. package/dist/esm/canvas/utils/Background/circular.js.map +0 -1
  124. package/dist/esm/canvas/utils/Background/radius.d.ts +0 -18
  125. package/dist/esm/canvas/utils/Background/radius.d.ts.map +0 -1
  126. package/dist/esm/canvas/utils/Background/radius.js +0 -104
  127. package/dist/esm/canvas/utils/Background/radius.js.map +0 -1
  128. package/lib/canvas/utils/Background/circular.ts +0 -17
  129. package/lib/canvas/utils/Background/radius.ts +0 -102
@@ -34,13 +34,15 @@ export function applyShadow(
34
34
  width,
35
35
  height,
36
36
  shadow.borderRadius ?? 2,
37
- shadow.borderPosition
38
37
  );
39
38
 
40
39
  ctx.fillStyle = shadow.gradient
41
- ? createGradient(ctx, shadow.gradient, x, y, x + width, y + height)
42
- : shadow.color || "transparent";
43
-
40
+ ? createGradient(
41
+ ctx, shadow.gradient,
42
+ shadowX, shadowY,
43
+ shadowX + width, shadowY + height
44
+ )
45
+ : shadow.color || "transparent";
44
46
  ctx.fill();
45
47
  }
46
48
 
@@ -68,62 +70,101 @@ export function applyZoom(
68
70
  ctx.translate(-zoomX, -zoomY);
69
71
  }
70
72
 
71
- /**
72
- * Applies stroke to the canvas context with support for selective side strokes.
73
- * If stroke.borderPosition is "all", it uses the full rounded path.
74
- * Otherwise, it constructs individual segments for the specified sides.
75
- *
76
- * @param ctx The canvas rendering context.
77
- * @param stroke The stroke properties.
78
- * @param x The x-coordinate of the shape.
79
- * @param y The y-coordinate of the shape.
80
- * @param width The width of the shape.
81
- * @param height The height of the shape.
82
- */
83
- export function applyStroke(
84
- ctx: SKRSContext2D,
85
- stroke: ImageProperties['stroke'],
86
- x: number,
87
- y: number,
88
- width: number,
89
- height: number
90
- ): void {
91
- if (!stroke) return;
92
-
93
- ctx.save();
94
- ctx.beginPath();
95
-
96
- ctx.strokeStyle = stroke.gradient
97
- ? createGradient(ctx, stroke.gradient, x, y, x + width, y + height)
98
- : stroke.color || "transparent";
99
-
100
- ctx.lineWidth = stroke.width && stroke.width > 0 ? stroke.width : 2;
101
-
102
- const positionOffset = stroke.position ?? 0;
103
- const halfStroke = ctx.lineWidth / 2;
104
- const totalOffset = positionOffset > 0 ? positionOffset + halfStroke : 0;
105
-
106
- const adjustedBorderRadius = stroke.borderRadius === "circular"
107
- ? "circular"
108
- : (stroke.borderRadius ?? 2) + halfStroke;
109
-
110
- const adjustedX = x - totalOffset;
111
- const adjustedY = y - totalOffset;
112
- const adjustedWidth = width + totalOffset * 2;
113
- const adjustedHeight = height + totalOffset * 2;
114
-
115
- objectRadius(ctx, adjustedX, adjustedY, adjustedWidth, adjustedHeight, adjustedBorderRadius, "all");
116
-
117
- ctx.stroke();
118
- ctx.restore();
119
- }
120
-
73
+
121
74
  /**
122
- * Draws a shape on the canvas context based on the provided settings.
123
- * Supports built‑in shapes as well as a custom polygon.
124
- * @param ctx - The canvas rendering context.
125
- * @param shapeSettings - The settings for the shape.
75
+ * Applies stroke to the canvas context with support for selective side strokes.
76
+ * Supports optional blur effect on the stroke.
77
+ *
78
+ * @param ctx The canvas rendering context.
79
+ * @param stroke The stroke properties.
80
+ * @param x The x-coordinate of the shape.
81
+ * @param y The y-coordinate of the shape.
82
+ * @param width The width of the shape.
83
+ * @param height The height of the shape.
84
+ * @param blur Optional blur effect on the stroke.
126
85
  */
86
+ export function applyStroke(
87
+ ctx: SKRSContext2D,
88
+ stroke: ImageProperties["stroke"],
89
+ x: number,
90
+ y: number,
91
+ width: number,
92
+ height: number,
93
+ shapeName?: string,
94
+ isImage?: boolean
95
+ ): void {
96
+ if (!stroke) return;
97
+
98
+ ctx.save();
99
+
100
+ if (stroke.blur && stroke.blur > 0) {
101
+ ctx.filter = `blur(${stroke.blur}px)`;
102
+ }
103
+
104
+ ctx.strokeStyle = stroke.gradient
105
+ ? createGradient(ctx, stroke.gradient, x, y, x + width, y + height)
106
+ : stroke.color || "transparent";
107
+
108
+ ctx.lineWidth = stroke.width && stroke.width > 0 ? stroke.width : 2;
109
+
110
+ ctx.beginPath();
111
+
112
+ if (isImage) {
113
+ ctx.globalCompositeOperation = "source-atop";
114
+ ctx.rect(x, y, width, height);
115
+ } else if (["heart", "arrow", "circle", "star", "pentagon", "hexagon", "heptagon", "octagon", "diamond", "trapezoid", "kite"].includes(shapeName as string)) {
116
+ switch (shapeName) {
117
+ case "circle":
118
+ ctx.arc(x + width / 2, y + height / 2, width / 2, 0, Math.PI * 2);
119
+ break;
120
+ case "star":
121
+ drawStar(ctx, x, y, width, height);
122
+ break;
123
+ case "arrow":
124
+ drawArrow(ctx, x, y, width, height);
125
+ break;
126
+ case "pentagon": case "hexagon": case "heptagon": case "octagon":
127
+ const sides = parseInt(shapeName.replace(/\D/g, ""), 10);
128
+ drawPolygon(ctx, x, y, width, height, sides);
129
+ break;
130
+ case "diamond":
131
+ ctx.moveTo(x + width / 2, y);
132
+ ctx.lineTo(x + width, y + height / 2);
133
+ ctx.lineTo(x + width / 2, y + height);
134
+ ctx.lineTo(x, y + height / 2);
135
+ ctx.closePath();
136
+ break;
137
+ case "trapezoid":
138
+ const topWidth = width * 0.6;
139
+ const offset = (width - topWidth) / 2;
140
+ ctx.moveTo(x + offset, y);
141
+ ctx.lineTo(x + offset + topWidth, y);
142
+ ctx.lineTo(x + width, y + height);
143
+ ctx.lineTo(x, y + height);
144
+ ctx.closePath();
145
+ break;
146
+ case "heart":
147
+ drawHeart(ctx, x , y, width, height);
148
+ break;
149
+ case "kite":
150
+ ctx.moveTo(x + width / 2, y);
151
+ ctx.lineTo(x + width, y + height / 2);
152
+ ctx.lineTo(x + width / 2, y + height);
153
+ ctx.lineTo(x, y + height / 2);
154
+ ctx.closePath();
155
+ break;
156
+ }
157
+ } else {
158
+ objectRadius(ctx, x, y, width, height, stroke.borderRadius || 2, "all");
159
+ }
160
+
161
+ ctx.stroke();
162
+ ctx.filter = "none";
163
+ ctx.restore();
164
+ }
165
+
166
+
167
+
127
168
  export function drawShape(ctx: SKRSContext2D, shapeSettings: any): void {
128
169
  const {
129
170
  source,
@@ -139,10 +180,10 @@ export function drawShape(ctx: SKRSContext2D, shapeSettings: any): void {
139
180
  isFilled = false,
140
181
  color = "transparent",
141
182
  gradient,
183
+ filling,
142
184
  } = shapeSettings;
143
185
 
144
186
  const shapeName = source.toLowerCase();
145
-
146
187
  ctx.save();
147
188
 
148
189
  applyRotation(ctx, rotation, x, y, width, height);
@@ -166,40 +207,13 @@ export function drawShape(ctx: SKRSContext2D, shapeSettings: any): void {
166
207
  ctx.closePath();
167
208
  break;
168
209
  }
169
- case 'pentagon': {
170
- drawPolygon(ctx, x, y, width, height, 5);
171
- break;
172
- }
173
- case 'hexagon': {
174
- drawPolygon(ctx, x, y, width, height, 6);
175
- break;
176
- }
177
- case 'heptagon': {
178
- drawPolygon(ctx, x, y, width, height, 7);
179
- break;
180
- }
181
- case 'octagon': {
182
- drawPolygon(ctx, x, y, width, height, 8);
210
+ case 'pentagon': case 'hexagon': case 'heptagon': case 'octagon': {
211
+ const sides = parseInt(shapeName.replace(/\D/g, ""), 10);
212
+ drawPolygon(ctx, x, y, width, height, sides);
183
213
  break;
184
214
  }
185
215
  case 'star': {
186
- {
187
- const cx = x + width / 2;
188
- const cy = y + height / 2;
189
- const outerRadius = Math.min(width, height) / 2;
190
- const innerRadius = outerRadius / 2;
191
- const step = Math.PI / 5;
192
- for (let i = 0; i < 10; i++) {
193
- const r = i % 2 === 0 ? outerRadius : innerRadius;
194
- const angle = i * step - Math.PI / 2;
195
- if (i === 0) {
196
- ctx.moveTo(cx + r * Math.cos(angle), cy + r * Math.sin(angle));
197
- } else {
198
- ctx.lineTo(cx + r * Math.cos(angle), cy + r * Math.sin(angle));
199
- }
200
- }
201
- ctx.closePath();
202
- }
216
+ drawStar(ctx, x, y, width, height);
203
217
  break;
204
218
  }
205
219
  case 'kite': {
@@ -214,31 +228,12 @@ export function drawShape(ctx: SKRSContext2D, shapeSettings: any): void {
214
228
  ctx.ellipse(x + width / 2, y + height / 2, width / 2, height / 2, 0, 0, Math.PI * 2);
215
229
  break;
216
230
  }
217
- case 'heart': {
218
- ctx.moveTo(x + width / 2, y + height * 0.75);
219
- ctx.bezierCurveTo(
220
- x + width * 0.1, y + height * 0.5,
221
- x, y + height * 0.2,
222
- x + width / 2, y + height * 0.3
223
- );
224
- ctx.bezierCurveTo(
225
- x + width, y + height * 0.2,
226
- x + width * 0.9, y + height * 0.5,
227
- x + width / 2, y + height * 0.75
228
- );
229
- ctx.closePath();
231
+ case 'arrow': {
232
+ drawArrow(ctx, x, y, width, height);
230
233
  break;
231
234
  }
232
- case 'arrow': {
233
- const arrowHeadWidth = width * 0.3;
234
- ctx.moveTo(x, y + height / 2);
235
- ctx.lineTo(x + width - arrowHeadWidth, y + height / 2);
236
- ctx.lineTo(x + width - arrowHeadWidth, y);
237
- ctx.lineTo(x + width, y + height / 2);
238
- ctx.lineTo(x + width - arrowHeadWidth, y + height);
239
- ctx.lineTo(x + width - arrowHeadWidth, y + height / 2);
240
- ctx.lineTo(x, y + height / 2);
241
- ctx.closePath();
235
+ case 'heart': {
236
+ drawHeart(ctx, x, y, width, height);
242
237
  break;
243
238
  }
244
239
  case 'diamond': {
@@ -259,17 +254,6 @@ export function drawShape(ctx: SKRSContext2D, shapeSettings: any): void {
259
254
  ctx.closePath();
260
255
  break;
261
256
  }
262
- case 'cloud': {
263
- const radius = width / 5;
264
- ctx.moveTo(x + radius, y + height / 2);
265
- ctx.arc(x + radius, y + height / 2, radius, Math.PI * 0.5, Math.PI * 1.5);
266
- ctx.arc(x + width / 2, y + height / 2 - radius, radius, Math.PI, 0);
267
- ctx.arc(x + width - radius, y + height / 2, radius, Math.PI * 1.5, Math.PI * 0.5);
268
- ctx.lineTo(x + width, y + height);
269
- ctx.lineTo(x, y + height);
270
- ctx.closePath();
271
- break;
272
- }
273
257
  default: {
274
258
  ctx.restore();
275
259
  throw new Error(`Unsupported shape: ${shapeName}`);
@@ -280,108 +264,262 @@ export function drawShape(ctx: SKRSContext2D, shapeSettings: any): void {
280
264
  if (borderRadius && shapeName !== 'circle' && shapeName !== 'oval') {
281
265
  objectRadius(ctx, x, y, width, height, borderRadius, borderPosition);
282
266
  }
267
+
268
+ let fillStyle: string | CanvasGradient = color;
269
+
283
270
  if (gradient) {
284
- const gradFill = createGradient(ctx, gradient, x, y, x + width, y + height);
285
- ctx.fillStyle = gradFill;
271
+ fillStyle = createGradient(ctx, gradient, x, y, x + width, y + height);
272
+ }
273
+
274
+ if (filling && filling.percentage <= 100) {
275
+ ctx.save();
276
+
277
+ const isCustomShape = ["heart", "arrow", "star", "pentagon", "hexagon", "heptagon", "octagon", "diamond", "trapezoid", "kite", "oval", "circle"].includes(shapeName);
278
+
279
+ if (isCustomShape) {
280
+ ctx.clip();
281
+ }
282
+
283
+ let fillX = x;
284
+ let fillY = y;
285
+ let fillWidth = width;
286
+ let fillHeight = height;
287
+
288
+ switch (filling.rotation) {
289
+ case 0:
290
+ fillHeight = (filling.percentage / 100) * height;
291
+ fillY = y + height - fillHeight;
292
+ break;
293
+
294
+ case 180:
295
+ fillHeight = (filling.percentage / 100) * height;
296
+ break;
297
+
298
+ case 90:
299
+ fillWidth = (filling.percentage / 100) * width;
300
+ break;
301
+
302
+ case 270:
303
+ fillWidth = (filling.percentage / 100) * width;
304
+ fillX = x + width - fillWidth;
305
+ break;
306
+
307
+ default:
308
+ console.warn(`Unsupported filling rotation: ${filling.rotation}, defaulting to 0 (Bottom to Top).`);
309
+ fillHeight = (filling.percentage / 100) * height;
310
+ fillY = y + height - fillHeight;
311
+ }
312
+
313
+ ctx.beginPath();
314
+ ctx.rect(fillX, fillY, fillWidth, fillHeight);
315
+ ctx.fillStyle = fillStyle;
316
+ ctx.fill();
317
+
318
+ ctx.restore();
286
319
  } else {
287
- ctx.fillStyle = color;
320
+ ctx.fillStyle = fillStyle;
321
+ ctx.fill();
288
322
  }
289
- ctx.fill();
290
323
  }
324
+
291
325
 
292
326
  if (stroke) {
293
- applyStroke(ctx, stroke, x, y, width, height);
327
+ applyStroke(ctx, stroke, x, y, width, height, shapeName, false);
294
328
  }
295
329
 
296
330
  ctx.restore();
297
331
  }
298
332
 
299
- /**
300
- * Helper function to draw a regular polygon.
301
- * Inscribes a polygon with a given number of sides inside the rectangle defined by (x, y, width, height).
302
- * @param ctx - The canvas rendering context.
303
- * @param x - The x-coordinate of the bounding rectangle.
304
- * @param y - The y-coordinate of the bounding rectangle.
305
- * @param width - The width of the bounding rectangle.
306
- * @param height - The height of the bounding rectangle.
307
- * @param sides - The number of sides ( 3).
308
- */
333
+ function drawHeart(ctx: SKRSContext2D, x: number, y: number, width: number, height: number): void {
334
+ ctx.beginPath();
335
+
336
+ ctx.moveTo(x + width / 2, y + height * 0.9);
337
+
338
+ ctx.bezierCurveTo(
339
+ x + (width * 35) / 100, y + (height * 60) / 100,
340
+ x + (width * 10) / 100, y + (height * 55) / 100,
341
+ x + (width * 10) / 100, y + (height * 33.33) / 100
342
+ );
343
+
344
+ ctx.bezierCurveTo(
345
+ x + (width * 10) / 100, y + (height * 10) / 100,
346
+ x + (width * 50) / 100, y + (height * 5) / 100,
347
+ x + (width * 50) / 100, y + (height * 33.33) / 100
348
+ );
349
+
350
+ ctx.bezierCurveTo(
351
+ x + (width * 50) / 100, y + (height * 5) / 100,
352
+ x + (width * 90) / 100, y + (height * 10) / 100,
353
+ x + (width * 90) / 100, y + (height * 33.33) / 100
354
+ );
355
+
356
+ ctx.bezierCurveTo(
357
+ x + (width * 90) / 100, y + (height * 55) / 100,
358
+ x + (width * 65) / 100, y + (height * 60) / 100,
359
+ x + width / 2, y + height * 0.9
360
+ );
361
+
362
+ ctx.closePath();
363
+ }
364
+
365
+
366
+ /** Draws a polygon with a given number of sides */
309
367
  function drawPolygon(ctx: SKRSContext2D, x: number, y: number, width: number, height: number, sides: number): void {
310
368
  const cx = x + width / 2;
311
369
  const cy = y + height / 2;
312
370
  const radius = Math.min(width, height) / 2;
313
- for (let i = 0; i < sides; i++) {
314
- const angle = (2 * Math.PI * i) / sides - Math.PI / 2;
315
- if (i === 0) {
316
- ctx.moveTo(cx + radius * Math.cos(angle), cy + radius * Math.sin(angle));
317
- } else {
318
- ctx.lineTo(cx + radius * Math.cos(angle), cy + radius * Math.sin(angle));
319
- }
371
+ ctx.moveTo(cx + radius, cy);
372
+ for (let i = 1; i <= sides; i++) {
373
+ const angle = (Math.PI * 2 * i) / sides;
374
+ ctx.lineTo(cx + radius * Math.cos(angle), cy + radius * Math.sin(angle));
375
+ }
376
+ ctx.closePath();
377
+ }
378
+
379
+ function drawArrow(ctx: SKRSContext2D, x: number, y: number, width: number, height: number) {
380
+ const shaftWidth = width * 0.25;
381
+ const headWidth = width * 0.5;
382
+ const headHeight = height * 0.6;
383
+
384
+ ctx.beginPath();
385
+
386
+ ctx.moveTo(x, y + height / 2 - shaftWidth / 2);
387
+ ctx.lineTo(x + width - headWidth, y + height / 2 - shaftWidth / 2);
388
+ ctx.lineTo(x + width - headWidth, y);
389
+
390
+ ctx.lineTo(x + width, y + height / 2);
391
+
392
+ ctx.lineTo(x + width - headWidth, y + height);
393
+ ctx.lineTo(x + width - headWidth, y + height / 2 + shaftWidth / 2);
394
+
395
+ ctx.lineTo(x, y + height / 2 + shaftWidth / 2);
396
+ ctx.closePath();
397
+ }
398
+
399
+
400
+ function drawStar(ctx: SKRSContext2D, x: number, y: number, width: number, height: number): void {
401
+ const cx = x + width / 2;
402
+ const cy = y + height / 2;
403
+
404
+ const size = Math.min(width, height);
405
+
406
+ const outerRadius = size / 2;
407
+ const innerRadius = outerRadius * 0.5;
408
+ const rotationOffset = -Math.PI / 2;
409
+
410
+ ctx.beginPath();
411
+
412
+ for (let i = 0; i < 5; i++) {
413
+ let angle = (i * (Math.PI * 2)) / 5 + rotationOffset;
414
+ ctx.lineTo(cx + outerRadius * Math.cos(angle), cy + outerRadius * Math.sin(angle));
415
+
416
+ angle += Math.PI / 5;
417
+ ctx.lineTo(cx + innerRadius * Math.cos(angle), cy + innerRadius * Math.sin(angle));
320
418
  }
419
+
321
420
  ctx.closePath();
322
421
  }
323
422
 
324
- export function createGradient(ctx: any, gradientOptions: any, startX: number, startY: number, endX: number, endY: number) {
325
- if (!gradientOptions || !gradientOptions.type || !gradientOptions.colors) {
326
- throw new Error("Invalid gradient options. Provide a valid object with type and colors properties.");
423
+ export function createGradient(
424
+ ctx: any,
425
+ gradientOptions: any,
426
+ startX: number,
427
+ startY: number,
428
+ endX: number,
429
+ endY: number
430
+ ) {
431
+ if (!gradientOptions || !gradientOptions.type || !gradientOptions.colors) {
432
+ throw new Error(
433
+ "Invalid gradient options. Provide a valid object with type and colors properties."
434
+ );
435
+ }
436
+
437
+ if (!Array.isArray(gradientOptions.colors)) {
438
+ throw new Error(
439
+ "Invalid gradient options. The colors property should be an array of color stops."
440
+ );
441
+ }
442
+
443
+ if (gradientOptions.type === "linear") {
444
+ if (
445
+ typeof startX !== "number" ||
446
+ typeof startY !== "number" ||
447
+ typeof endX !== "number" ||
448
+ typeof endY !== "number"
449
+ ) {
450
+ throw new Error(
451
+ "Invalid gradient options for linear gradient. Numeric values are required for startX, startY, endX, and endY."
452
+ );
327
453
  }
328
454
 
329
- if (!Array.isArray(gradientOptions.colors)) {
330
- throw new Error("Invalid gradient options. The colors property should be an array of color stops.");
455
+ if (typeof gradientOptions.rotate === "number") {
456
+ const centerX = (startX + endX) / 2;
457
+ const centerY = (startY + endY) / 2;
458
+ const dx = endX - startX;
459
+ const dy = endY - startY;
460
+ const length = Math.sqrt(dx * dx + dy * dy);
461
+ const angleRad = (gradientOptions.rotate * Math.PI) / 180;
462
+
463
+ startX = centerX - (length / 2) * Math.cos(angleRad);
464
+ startY = centerY - (length / 2) * Math.sin(angleRad);
465
+ endX = centerX + (length / 2) * Math.cos(angleRad);
466
+ endY = centerY + (length / 2) * Math.sin(angleRad);
331
467
  }
332
468
 
333
- if (gradientOptions.type === "linear") {
334
- if (
335
- typeof startX !== "number" ||
336
- typeof startY !== "number" ||
337
- typeof endX !== "number" ||
338
- typeof endY !== "number"
339
- ) {
340
- throw new Error("Invalid gradient options for linear gradient. Numeric values are required for startX, startY, endX, and endY.");
341
- }
342
- const gradient = ctx.createLinearGradient(startX, startY, endX, endY);
343
-
344
- for (const colorStop of gradientOptions.colors) {
345
- if (typeof colorStop.stop !== "number" || typeof colorStop.color !== "string") {
346
- throw new Error("Invalid color stop. Each color stop should have a numeric stop value and a color string.");
347
- }
348
- gradient.addColorStop(colorStop.stop, colorStop.color);
349
- }
350
-
351
- return gradient;
352
-
353
- } else if (gradientOptions.type === "radial") {
354
- if (
355
- typeof gradientOptions.startX !== "number" ||
356
- typeof gradientOptions.startY !== "number" ||
357
- typeof gradientOptions.startRadius !== "number" ||
358
- typeof gradientOptions.endX !== "number" ||
359
- typeof gradientOptions.endY !== "number" ||
360
- typeof gradientOptions.endRadius !== "number"
361
- ) {
362
- throw new Error("Invalid gradient options for radial gradient. Numeric values are required for startX, startY, startRadius, endX, endY, and endRadius.");
363
- }
364
- const gradient = ctx.createRadialGradient(
365
- gradientOptions.startX,
366
- gradientOptions.startY,
367
- gradientOptions.startRadius,
368
- gradientOptions.endX,
369
- gradientOptions.endY,
370
- gradientOptions.endRadius
469
+ const gradient = ctx.createLinearGradient(startX, startY, endX, endY);
470
+
471
+ for (const colorStop of gradientOptions.colors) {
472
+ if (
473
+ typeof colorStop.stop !== "number" ||
474
+ typeof colorStop.color !== "string"
475
+ ) {
476
+ throw new Error(
477
+ "Invalid color stop. Each color stop should have a numeric stop value and a color string."
371
478
  );
479
+ }
480
+ gradient.addColorStop(colorStop.stop, colorStop.color);
481
+ }
372
482
 
373
- for (const colorStop of gradientOptions.colors) {
374
- if (typeof colorStop.stop !== "number" || typeof colorStop.color !== "string") {
375
- throw new Error("Invalid color stop. Each color stop should have a numeric stop value and a color string.");
376
- }
377
- gradient.addColorStop(colorStop.stop, colorStop.color);
378
- }
483
+ return gradient;
484
+ } else if (gradientOptions.type === "radial") {
485
+ if (
486
+ typeof gradientOptions.startX !== "number" ||
487
+ typeof gradientOptions.startY !== "number" ||
488
+ typeof gradientOptions.startRadius !== "number" ||
489
+ typeof gradientOptions.endX !== "number" ||
490
+ typeof gradientOptions.endY !== "number" ||
491
+ typeof gradientOptions.endRadius !== "number"
492
+ ) {
493
+ throw new Error(
494
+ "Invalid gradient options for radial gradient. Numeric values are required for startX, startY, startRadius, endX, endY, and endRadius."
495
+ );
496
+ }
379
497
 
380
- return gradient;
498
+ const gradient = ctx.createRadialGradient(
499
+ gradientOptions.startX,
500
+ gradientOptions.startY,
501
+ gradientOptions.startRadius,
502
+ gradientOptions.endX,
503
+ gradientOptions.endY,
504
+ gradientOptions.endRadius
505
+ );
381
506
 
382
- } else {
383
- throw new Error('Unsupported gradient type. Use "linear" or "radial".');
507
+ for (const colorStop of gradientOptions.colors) {
508
+ if (
509
+ typeof colorStop.stop !== "number" ||
510
+ typeof colorStop.color !== "string"
511
+ ) {
512
+ throw new Error(
513
+ "Invalid color stop. Each color stop should have a numeric stop value and a color string."
514
+ );
515
+ }
516
+ gradient.addColorStop(colorStop.stop, colorStop.color);
384
517
  }
518
+
519
+ return gradient;
520
+ } else {
521
+ throw new Error('Unsupported gradient type. Use "linear" or "radial".');
522
+ }
385
523
  }
386
524
 
387
525
 
@@ -442,17 +580,15 @@ export function applyRotation(
442
580
  if (borderRadius === "circular") {
443
581
  const circleRadius = Math.min(width, height) / 2;
444
582
  ctx.arc(x + width / 2, y + height / 2, circleRadius, 0, 2 * Math.PI);
445
- ctx.closePath();
446
- } else {
447
- const br: number = typeof borderRadius === "number" ? borderRadius : 0;
448
- const bp = borderPosition.trim().toLowerCase();
449
-
450
- const selectedCorners = new Set(bp.split(",").map((s) => s.trim()));
583
+ ctx.clip();
584
+ } else if (typeof borderRadius === "number" && borderRadius > 0) {
585
+ const br: number = Math.min(borderRadius, width / 2, height / 2);
586
+ const selectedPositions = new Set(borderPosition.toLowerCase().split(",").map((s) => s.trim()));
451
587
 
452
- const roundTopLeft = selectedCorners.has("all") || selectedCorners.has("top-left") || (selectedCorners.has("top") && selectedCorners.has("left"));
453
- const roundTopRight = selectedCorners.has("all") || selectedCorners.has("top-right") || (selectedCorners.has("top") && selectedCorners.has("right"));
454
- const roundBottomRight = selectedCorners.has("all") || selectedCorners.has("bottom-right") || (selectedCorners.has("bottom") && selectedCorners.has("right"));
455
- const roundBottomLeft = selectedCorners.has("all") || selectedCorners.has("bottom-left") || (selectedCorners.has("bottom") && selectedCorners.has("left"));
588
+ const roundTopLeft = selectedPositions.has("all") || selectedPositions.has("top-left") || (selectedPositions.has("top") && selectedPositions.has("left"));
589
+ const roundTopRight = selectedPositions.has("all") || selectedPositions.has("top-right") || (selectedPositions.has("top") && selectedPositions.has("right"));
590
+ const roundBottomRight = selectedPositions.has("all") || selectedPositions.has("bottom-right") || (selectedPositions.has("bottom") && selectedPositions.has("right"));
591
+ const roundBottomLeft = selectedPositions.has("all") || selectedPositions.has("bottom-left") || (selectedPositions.has("bottom") && selectedPositions.has("left"));
456
592
 
457
593
  const tl = roundTopLeft ? br : 0;
458
594
  const tr = roundTopRight ? br : 0;
@@ -460,43 +596,28 @@ export function applyRotation(
460
596
  const bl = roundBottomLeft ? br : 0;
461
597
 
462
598
  ctx.moveTo(x + tl, y);
463
-
464
- if (roundTopLeft && roundTopRight) {
465
- ctx.arcTo(x, y, x + width, y, tl);
466
- } else if (roundTopLeft) {
467
- ctx.arcTo(x, y, x + width, y, tl);
468
- } else {
469
- ctx.lineTo(x, y);
470
- ctx.lineTo(x + width, y);
471
- }
472
-
473
- if (tr > 0) {
474
- ctx.arcTo(x + width, y, x + width, y + height, tr);
475
- }
476
-
599
+ ctx.lineTo(x + width - tr, y);
600
+ if (tr > 0) ctx.arc(x + width - tr, y + tr, tr, -Math.PI / 2, 0, false);
477
601
  ctx.lineTo(x + width, y + height - brR);
478
- if (brR > 0) {
479
- ctx.arcTo(x + width, y + height, x, y + height, brR);
480
- }
481
-
602
+ if (brR > 0) ctx.arc(x + width - brR, y + height - brR, brR, 0, Math.PI / 2, false);
482
603
  ctx.lineTo(x + bl, y + height);
483
- if (bl > 0) {
484
- ctx.arcTo(x, y + height, x, y, bl);
485
- }
486
-
604
+ if (bl > 0) ctx.arc(x + bl, y + height - bl, bl, Math.PI / 2, Math.PI, false);
487
605
  ctx.lineTo(x, y + tl);
488
- if (tl > 0) {
489
- ctx.arcTo(x, y, x + tl, y, tl);
490
- }
606
+ if (tl > 0) ctx.arc(x + tl, y + tl, tl, Math.PI, -Math.PI / 2, false);
491
607
 
492
608
  ctx.closePath();
609
+ ctx.clip();
610
+ } else {
611
+ ctx.rect(x, y, width, height);
612
+ ctx.clip();
493
613
  }
494
614
 
495
- ctx.clip();
496
615
  ctx.drawImage(image, x, y, width, height);
616
+
497
617
  ctx.restore();
498
618
  }
499
619
 
620
+
500
621
 
501
622
  /**
502
623
  * Creates a rounded rectangle (or circular) path on the canvas context.
@@ -514,91 +635,51 @@ export function applyRotation(
514
635
  * - Or a comma-separated list, e.g. "top-left, bottom-right" or "top, left, bottom"
515
636
  */
516
637
  export function objectRadius(
517
- ctx: SKRSContext2D,
518
- x: number,
519
- y: number,
520
- width: number,
521
- height: number,
522
- borderRadius: number | "circular" = 0.1,
523
- borderPosition: string = 'all'
524
- ): void {
525
- if (borderRadius === "circular") {
526
- const circleRadius = Math.min(width, height) / 2;
527
- ctx.beginPath();
528
- ctx.arc(x + width / 2, y + height / 2, circleRadius, 0, 2 * Math.PI);
529
- ctx.closePath();
530
- } else if (borderRadius) {
531
- let roundTopLeft = false;
532
- let roundTopRight = false;
533
- let roundBottomRight = false;
534
- let roundBottomLeft = false;
535
-
536
- const bp = borderPosition.trim().toLowerCase();
537
-
538
- if (bp === 'all') {
539
- roundTopLeft = roundTopRight = roundBottomRight = roundBottomLeft = true;
540
- } else if (bp === 'top') {
541
- roundTopLeft = roundTopRight = true;
542
- } else if (bp === 'bottom') {
543
- roundBottomLeft = roundBottomRight = true;
544
- } else if (bp === 'left') {
545
- roundTopLeft = roundBottomLeft = true;
546
- } else if (bp === 'right') {
547
- roundTopRight = roundBottomRight = true;
548
- } else if (bp === 'top-left') {
549
- roundTopLeft = true;
550
- } else if (bp === 'top-right') {
551
- roundTopRight = true;
552
- } else if (bp === 'bottom-left') {
553
- roundBottomLeft = true;
554
- } else if (bp === 'bottom-right') {
555
- roundBottomRight = true;
556
- } else {
557
- const positions = bp.split(',').map(s => s.trim());
558
- roundTopLeft = positions.includes('top-left') || (positions.includes('top') && positions.includes('left'));
559
- roundTopRight = positions.includes('top-right') || (positions.includes('top') && positions.includes('right'));
560
- roundBottomRight = positions.includes('bottom-right') || (positions.includes('bottom') && positions.includes('right'));
561
- roundBottomLeft = positions.includes('bottom-left') || (positions.includes('bottom') && positions.includes('left'));
562
- }
563
-
564
- const tl = roundTopLeft ? +borderRadius : 0;
565
- const tr = roundTopRight ? +borderRadius : 0;
566
- const br = roundBottomRight ? +borderRadius : 0;
567
- const bl = roundBottomLeft ? +borderRadius : 0;
568
-
569
- ctx.beginPath();
570
- ctx.moveTo(x + tl, y);
571
- ctx.lineTo(x + width - tr, y);
572
- if (tr > 0) {
573
- ctx.quadraticCurveTo(x + width, y, x + width, y + tr);
574
- } else {
575
- ctx.lineTo(x + width, y);
576
- }
577
- ctx.lineTo(x + width, y + height - br);
578
- if (br > 0) {
579
- ctx.quadraticCurveTo(x + width, y + height, x + width - br, y + height);
580
- } else {
581
- ctx.lineTo(x + width, y + height);
582
- }
583
- ctx.lineTo(x + bl, y + height);
584
- if (bl > 0) {
585
- ctx.quadraticCurveTo(x, y + height, x, y + height - bl);
586
- } else {
587
- ctx.lineTo(x, y + height);
588
- }
589
- ctx.lineTo(x, y + tl);
590
- if (tl > 0) {
591
- ctx.quadraticCurveTo(x, y, x + tl, y);
592
- } else {
593
- ctx.lineTo(x, y);
594
- }
595
- ctx.closePath();
596
- } else {
597
- ctx.beginPath();
598
- ctx.rect(x, y, width, height);
599
- ctx.closePath();
600
- }
638
+ ctx: SKRSContext2D,
639
+ x: number,
640
+ y: number,
641
+ width: number,
642
+ height: number,
643
+ borderRadius: number | "circular" = 0.1,
644
+ borderPosition: string = "all"
645
+ ): void {
646
+ ctx.beginPath();
647
+
648
+ if (borderRadius === "circular") {
649
+ const circleRadius = Math.min(width, height) / 2;
650
+ ctx.arc(x + width / 2, y + height / 2, circleRadius, 0, 2 * Math.PI);
651
+ } else if (borderRadius > 0) {
652
+ const br: number = Math.min(borderRadius, width / 2, height / 2);
653
+ const selectedPositions = new Set(
654
+ borderPosition.toLowerCase().split(",").map((s) => s.trim())
655
+ );
656
+
657
+ const roundTopLeft = selectedPositions.has("all") || selectedPositions.has("top-left") || (selectedPositions.has("top") && selectedPositions.has("left"));
658
+ const roundTopRight = selectedPositions.has("all") || selectedPositions.has("top-right") || (selectedPositions.has("top") && selectedPositions.has("right"));
659
+ const roundBottomRight = selectedPositions.has("all") || selectedPositions.has("bottom-right") || (selectedPositions.has("bottom") && selectedPositions.has("right"));
660
+ const roundBottomLeft = selectedPositions.has("all") || selectedPositions.has("bottom-left") || (selectedPositions.has("bottom") && selectedPositions.has("left"));
661
+
662
+ const tl = roundTopLeft ? br : 0;
663
+ const tr = roundTopRight ? br : 0;
664
+ const brR = roundBottomRight ? br : 0;
665
+ const bl = roundBottomLeft ? br : 0;
666
+
667
+ ctx.moveTo(x + tl, y);
668
+ ctx.lineTo(x + width - tr, y);
669
+ if (tr > 0) ctx.arc(x + width - tr, y + tr, tr, -Math.PI / 2, 0, false);
670
+ ctx.lineTo(x + width, y + height - brR);
671
+ if (brR > 0) ctx.arc(x + width - brR, y + height - brR, brR, 0, Math.PI / 2, false);
672
+ ctx.lineTo(x + bl, y + height);
673
+ if (bl > 0) ctx.arc(x + bl, y + height - bl, bl, Math.PI / 2, Math.PI, false);
674
+ ctx.lineTo(x, y + tl);
675
+ if (tl > 0) ctx.arc(x + tl, y + tl, tl, Math.PI, -Math.PI / 2, false);
676
+ } else {
677
+ ctx.rect(x, y, width, height);
601
678
  }
679
+
680
+ ctx.closePath();
681
+ }
682
+
602
683
 
603
684
 
604
685
  /**