apexify.js 4.5.54 → 4.5.56
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/ApexAI.d.ts +1 -164
- package/dist/cjs/ai/ApexAI.d.ts.map +1 -1
- package/dist/cjs/ai/ApexAI.js +190 -373
- package/dist/cjs/ai/ApexAI.js.map +1 -1
- package/dist/cjs/ai/ApexModules.d.ts +1 -1
- package/dist/cjs/ai/ApexModules.d.ts.map +1 -1
- package/dist/cjs/ai/ApexModules.js +6 -18
- package/dist/cjs/ai/ApexModules.js.map +1 -1
- package/dist/cjs/ai/functions/draw.d.ts.map +1 -1
- package/dist/cjs/ai/functions/draw.js +6 -6
- package/dist/cjs/ai/functions/draw.js.map +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/imageModels.d.ts +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/imageModels.d.ts.map +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/imageModels.js +1 -4
- package/dist/cjs/ai/modals-chat/electronHub/imageModels.js.map +1 -1
- package/dist/cjs/ai/utils.d.ts +1 -4
- package/dist/cjs/ai/utils.d.ts.map +1 -1
- package/dist/cjs/ai/utils.js +1 -7
- package/dist/cjs/ai/utils.js.map +1 -1
- package/dist/cjs/canvas/ApexPainter.d.ts +17 -14
- package/dist/cjs/canvas/ApexPainter.d.ts.map +1 -1
- package/dist/cjs/canvas/ApexPainter.js +29 -11
- package/dist/cjs/canvas/ApexPainter.js.map +1 -1
- package/dist/cjs/canvas/utils/Background/bg.d.ts +24 -0
- package/dist/cjs/canvas/utils/Background/bg.d.ts.map +1 -0
- package/dist/{esm/canvas/utils → cjs/canvas/utils/Background}/bg.js +27 -52
- package/dist/cjs/canvas/utils/Background/bg.js.map +1 -0
- package/dist/cjs/canvas/utils/Background/circular.d.ts +3 -0
- package/dist/cjs/canvas/utils/Background/circular.d.ts.map +1 -0
- package/dist/{esm/canvas/utils → cjs/canvas/utils/Background}/circular.js +0 -8
- package/dist/cjs/canvas/utils/{circular.js.map → Background/circular.js.map} +1 -1
- package/dist/cjs/canvas/utils/Background/radius.d.ts +18 -0
- package/dist/cjs/canvas/utils/Background/radius.d.ts.map +1 -0
- package/dist/cjs/canvas/utils/Background/radius.js +115 -0
- package/dist/cjs/canvas/utils/Background/radius.js.map +1 -0
- package/dist/cjs/canvas/utils/{charts.d.ts → Charts/charts.d.ts} +1 -1
- package/dist/cjs/canvas/utils/Charts/charts.d.ts.map +1 -0
- package/dist/cjs/canvas/utils/Charts/charts.js.map +1 -0
- package/dist/cjs/canvas/utils/Custom/customLines.d.ts +3 -0
- package/dist/cjs/canvas/utils/Custom/customLines.d.ts.map +1 -0
- package/dist/cjs/canvas/utils/Custom/customLines.js.map +1 -0
- package/dist/cjs/canvas/utils/General/conversion.d.ts.map +1 -0
- package/dist/cjs/canvas/utils/General/conversion.js.map +1 -0
- package/dist/cjs/canvas/utils/{general functions.d.ts → General/general functions.d.ts } +18 -4
- package/dist/cjs/canvas/utils/General/general functions.d.ts.map +1 -0
- package/dist/{esm/canvas/utils → cjs/canvas/utils/General}/general functions.js +89 -58
- package/dist/cjs/canvas/utils/General/general functions.js.map +1 -0
- package/dist/cjs/canvas/utils/Image/imageProperties.d.ts +81 -0
- package/dist/cjs/canvas/utils/Image/imageProperties.d.ts.map +1 -0
- package/dist/{esm/canvas/utils → cjs/canvas/utils/Image}/imageProperties.js +224 -45
- package/dist/cjs/canvas/utils/Image/imageProperties.js.map +1 -0
- package/dist/{esm/canvas/utils → cjs/canvas/utils/Texts}/textProperties.d.ts +1 -1
- package/dist/cjs/canvas/utils/Texts/textProperties.d.ts.map +1 -0
- package/dist/cjs/canvas/utils/Texts/textProperties.js.map +1 -0
- package/dist/cjs/canvas/utils/types.d.ts +41 -1
- 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 +11 -11
- package/dist/cjs/canvas/utils/utils.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/utils.js +11 -10
- package/dist/cjs/canvas/utils/utils.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/ai/ApexAI.d.ts +1 -164
- package/dist/esm/ai/ApexAI.d.ts.map +1 -1
- package/dist/esm/ai/ApexAI.js +190 -373
- package/dist/esm/ai/ApexAI.js.map +1 -1
- package/dist/esm/ai/ApexModules.d.ts +1 -1
- package/dist/esm/ai/ApexModules.d.ts.map +1 -1
- package/dist/esm/ai/ApexModules.js +6 -18
- package/dist/esm/ai/ApexModules.js.map +1 -1
- package/dist/esm/ai/functions/draw.d.ts.map +1 -1
- package/dist/esm/ai/functions/draw.js +6 -6
- package/dist/esm/ai/functions/draw.js.map +1 -1
- package/dist/esm/ai/modals-chat/electronHub/imageModels.d.ts +1 -1
- package/dist/esm/ai/modals-chat/electronHub/imageModels.d.ts.map +1 -1
- package/dist/esm/ai/modals-chat/electronHub/imageModels.js +1 -4
- package/dist/esm/ai/modals-chat/electronHub/imageModels.js.map +1 -1
- package/dist/esm/ai/utils.d.ts +1 -4
- package/dist/esm/ai/utils.d.ts.map +1 -1
- package/dist/esm/ai/utils.js +1 -7
- package/dist/esm/ai/utils.js.map +1 -1
- package/dist/esm/canvas/ApexPainter.d.ts +17 -14
- package/dist/esm/canvas/ApexPainter.d.ts.map +1 -1
- package/dist/esm/canvas/ApexPainter.js +29 -11
- package/dist/esm/canvas/ApexPainter.js.map +1 -1
- package/dist/esm/canvas/utils/Background/bg.d.ts +24 -0
- package/dist/esm/canvas/utils/Background/bg.d.ts.map +1 -0
- package/dist/{cjs/canvas/utils → esm/canvas/utils/Background}/bg.js +27 -52
- package/dist/esm/canvas/utils/Background/bg.js.map +1 -0
- package/dist/esm/canvas/utils/Background/circular.d.ts +3 -0
- package/dist/esm/canvas/utils/Background/circular.d.ts.map +1 -0
- package/dist/{cjs/canvas/utils → esm/canvas/utils/Background}/circular.js +0 -8
- package/dist/esm/canvas/utils/{circular.js.map → Background/circular.js.map} +1 -1
- package/dist/esm/canvas/utils/Background/radius.d.ts +18 -0
- package/dist/esm/canvas/utils/Background/radius.d.ts.map +1 -0
- package/dist/esm/canvas/utils/Background/radius.js +115 -0
- package/dist/esm/canvas/utils/Background/radius.js.map +1 -0
- package/dist/esm/canvas/utils/{charts.d.ts → Charts/charts.d.ts} +1 -1
- package/dist/esm/canvas/utils/Charts/charts.d.ts.map +1 -0
- package/dist/esm/canvas/utils/Charts/charts.js.map +1 -0
- package/dist/esm/canvas/utils/Custom/customLines.d.ts +3 -0
- package/dist/esm/canvas/utils/Custom/customLines.d.ts.map +1 -0
- package/dist/esm/canvas/utils/Custom/customLines.js.map +1 -0
- package/dist/esm/canvas/utils/General/conversion.d.ts.map +1 -0
- package/dist/esm/canvas/utils/General/conversion.js.map +1 -0
- package/dist/esm/canvas/utils/{general functions.d.ts → General/general functions.d.ts } +18 -4
- package/dist/esm/canvas/utils/General/general functions.d.ts.map +1 -0
- package/dist/{cjs/canvas/utils → esm/canvas/utils/General}/general functions.js +89 -58
- package/dist/esm/canvas/utils/General/general functions.js.map +1 -0
- package/dist/esm/canvas/utils/Image/imageProperties.d.ts +81 -0
- package/dist/esm/canvas/utils/Image/imageProperties.d.ts.map +1 -0
- package/dist/{cjs/canvas/utils → esm/canvas/utils/Image}/imageProperties.js +224 -45
- package/dist/esm/canvas/utils/Image/imageProperties.js.map +1 -0
- package/dist/{cjs/canvas/utils → esm/canvas/utils/Texts}/textProperties.d.ts +1 -1
- package/dist/esm/canvas/utils/Texts/textProperties.d.ts.map +1 -0
- package/dist/esm/canvas/utils/Texts/textProperties.js.map +1 -0
- package/dist/esm/canvas/utils/types.d.ts +41 -1
- 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 +11 -11
- package/dist/esm/canvas/utils/utils.d.ts.map +1 -1
- package/dist/esm/canvas/utils/utils.js +11 -10
- package/dist/esm/canvas/utils/utils.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/ai/ApexAI.ts +195 -697
- package/lib/ai/ApexModules.ts +7 -17
- package/lib/ai/functions/draw.ts +6 -8
- package/lib/ai/modals-chat/electronHub/imageModels.ts +2 -5
- package/lib/ai/utils.ts +0 -6
- package/lib/canvas/ApexPainter.ts +73 -38
- package/lib/canvas/utils/Background/bg.ts +97 -0
- package/lib/canvas/utils/Background/circular.ts +17 -0
- package/lib/canvas/utils/Background/radius.ts +113 -0
- package/lib/canvas/utils/{charts.ts → Charts/charts.ts} +1 -1
- package/lib/canvas/utils/{customLines.ts → Custom/customLines.ts} +1 -1
- package/lib/canvas/utils/{conversion.ts → General/conversion.ts} +1 -1
- package/lib/canvas/utils/{general functions.ts → General/general functions.ts } +143 -121
- package/lib/canvas/utils/Image/imageProperties.ts +631 -0
- package/lib/canvas/utils/{textProperties.ts → Texts/textProperties.ts} +1 -1
- package/lib/canvas/utils/types.ts +45 -2
- package/lib/canvas/utils/utils.ts +14 -11
- package/package.json +1 -4
- package/dist/cjs/ai/functions/generateVoiceResponse.d.ts +0 -10
- package/dist/cjs/ai/functions/generateVoiceResponse.d.ts.map +0 -1
- package/dist/cjs/ai/functions/generateVoiceResponse.js +0 -161
- package/dist/cjs/ai/functions/generateVoiceResponse.js.map +0 -1
- package/dist/cjs/ai/modals-chat/gemini/Gemini-flash.d.ts +0 -13
- package/dist/cjs/ai/modals-chat/gemini/Gemini-flash.d.ts.map +0 -1
- package/dist/cjs/ai/modals-chat/gemini/Gemini-flash.js +0 -185
- package/dist/cjs/ai/modals-chat/gemini/Gemini-flash.js.map +0 -1
- package/dist/cjs/ai/modals-chat/gemini/Gemini-pro.d.ts +0 -13
- package/dist/cjs/ai/modals-chat/gemini/Gemini-pro.d.ts.map +0 -1
- package/dist/cjs/ai/modals-chat/gemini/Gemini-pro.js +0 -185
- package/dist/cjs/ai/modals-chat/gemini/Gemini-pro.js.map +0 -1
- package/dist/cjs/ai/modals-chat/gemini/config.d.ts +0 -5
- package/dist/cjs/ai/modals-chat/gemini/config.d.ts.map +0 -1
- package/dist/cjs/ai/modals-chat/gemini/config.js +0 -13
- package/dist/cjs/ai/modals-chat/gemini/config.js.map +0 -1
- package/dist/cjs/ai/modals-chat/gemini/geminiFast.d.ts +0 -15
- package/dist/cjs/ai/modals-chat/gemini/geminiFast.d.ts.map +0 -1
- package/dist/cjs/ai/modals-chat/gemini/geminiFast.js +0 -146
- package/dist/cjs/ai/modals-chat/gemini/geminiFast.js.map +0 -1
- package/dist/cjs/canvas/utils/bg.d.ts +0 -23
- package/dist/cjs/canvas/utils/bg.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/bg.js.map +0 -1
- package/dist/cjs/canvas/utils/charts.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/charts.js.map +0 -1
- package/dist/cjs/canvas/utils/circular.d.ts +0 -10
- package/dist/cjs/canvas/utils/circular.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/conversion.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/conversion.js.map +0 -1
- package/dist/cjs/canvas/utils/customLines.d.ts +0 -3
- package/dist/cjs/canvas/utils/customLines.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/customLines.js.map +0 -1
- package/dist/cjs/canvas/utils/general functions.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/general functions.js.map +0 -1
- package/dist/cjs/canvas/utils/imageProperties.d.ts +0 -62
- package/dist/cjs/canvas/utils/imageProperties.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/imageProperties.js.map +0 -1
- package/dist/cjs/canvas/utils/radius.d.ts +0 -10
- package/dist/cjs/canvas/utils/radius.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/radius.js +0 -30
- package/dist/cjs/canvas/utils/radius.js.map +0 -1
- package/dist/cjs/canvas/utils/textProperties.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/textProperties.js.map +0 -1
- package/dist/esm/ai/functions/generateVoiceResponse.d.ts +0 -10
- package/dist/esm/ai/functions/generateVoiceResponse.d.ts.map +0 -1
- package/dist/esm/ai/functions/generateVoiceResponse.js +0 -161
- package/dist/esm/ai/functions/generateVoiceResponse.js.map +0 -1
- package/dist/esm/ai/modals-chat/gemini/Gemini-flash.d.ts +0 -13
- package/dist/esm/ai/modals-chat/gemini/Gemini-flash.d.ts.map +0 -1
- package/dist/esm/ai/modals-chat/gemini/Gemini-flash.js +0 -185
- package/dist/esm/ai/modals-chat/gemini/Gemini-flash.js.map +0 -1
- package/dist/esm/ai/modals-chat/gemini/Gemini-pro.d.ts +0 -13
- package/dist/esm/ai/modals-chat/gemini/Gemini-pro.d.ts.map +0 -1
- package/dist/esm/ai/modals-chat/gemini/Gemini-pro.js +0 -185
- package/dist/esm/ai/modals-chat/gemini/Gemini-pro.js.map +0 -1
- package/dist/esm/ai/modals-chat/gemini/config.d.ts +0 -5
- package/dist/esm/ai/modals-chat/gemini/config.d.ts.map +0 -1
- package/dist/esm/ai/modals-chat/gemini/config.js +0 -13
- package/dist/esm/ai/modals-chat/gemini/config.js.map +0 -1
- package/dist/esm/ai/modals-chat/gemini/geminiFast.d.ts +0 -15
- package/dist/esm/ai/modals-chat/gemini/geminiFast.d.ts.map +0 -1
- package/dist/esm/ai/modals-chat/gemini/geminiFast.js +0 -146
- package/dist/esm/ai/modals-chat/gemini/geminiFast.js.map +0 -1
- package/dist/esm/canvas/utils/bg.d.ts +0 -23
- package/dist/esm/canvas/utils/bg.d.ts.map +0 -1
- package/dist/esm/canvas/utils/bg.js.map +0 -1
- package/dist/esm/canvas/utils/charts.d.ts.map +0 -1
- package/dist/esm/canvas/utils/charts.js.map +0 -1
- package/dist/esm/canvas/utils/circular.d.ts +0 -10
- package/dist/esm/canvas/utils/circular.d.ts.map +0 -1
- package/dist/esm/canvas/utils/conversion.d.ts.map +0 -1
- package/dist/esm/canvas/utils/conversion.js.map +0 -1
- package/dist/esm/canvas/utils/customLines.d.ts +0 -3
- package/dist/esm/canvas/utils/customLines.d.ts.map +0 -1
- package/dist/esm/canvas/utils/customLines.js.map +0 -1
- package/dist/esm/canvas/utils/general functions.d.ts.map +0 -1
- package/dist/esm/canvas/utils/general functions.js.map +0 -1
- package/dist/esm/canvas/utils/imageProperties.d.ts +0 -62
- package/dist/esm/canvas/utils/imageProperties.d.ts.map +0 -1
- package/dist/esm/canvas/utils/imageProperties.js.map +0 -1
- package/dist/esm/canvas/utils/radius.d.ts +0 -10
- package/dist/esm/canvas/utils/radius.d.ts.map +0 -1
- package/dist/esm/canvas/utils/radius.js +0 -30
- package/dist/esm/canvas/utils/radius.js.map +0 -1
- package/dist/esm/canvas/utils/textProperties.d.ts.map +0 -1
- package/dist/esm/canvas/utils/textProperties.js.map +0 -1
- package/lib/ai/functions/generateVoiceResponse.ts +0 -186
- package/lib/ai/modals-chat/gemini/Gemini-flash.ts +0 -200
- package/lib/ai/modals-chat/gemini/Gemini-pro.ts +0 -203
- package/lib/ai/modals-chat/gemini/config.ts +0 -11
- package/lib/ai/modals-chat/gemini/geminiFast.ts +0 -169
- package/lib/canvas/utils/bg.ts +0 -120
- package/lib/canvas/utils/circular.ts +0 -17
- package/lib/canvas/utils/imageProperties.ts +0 -418
- package/lib/canvas/utils/radius.ts +0 -26
- /package/dist/cjs/canvas/utils/{charts.js → Charts/charts.js} +0 -0
- /package/dist/cjs/canvas/utils/{customLines.js → Custom/customLines.js} +0 -0
- /package/dist/cjs/canvas/utils/{conversion.d.ts → General/conversion.d.ts} +0 -0
- /package/dist/cjs/canvas/utils/{conversion.js → General/conversion.js} +0 -0
- /package/dist/cjs/canvas/utils/{textProperties.js → Texts/textProperties.js} +0 -0
- /package/dist/esm/canvas/utils/{charts.js → Charts/charts.js} +0 -0
- /package/dist/esm/canvas/utils/{customLines.js → Custom/customLines.js} +0 -0
- /package/dist/esm/canvas/utils/{conversion.d.ts → General/conversion.d.ts} +0 -0
- /package/dist/esm/canvas/utils/{conversion.js → General/conversion.js} +0 -0
- /package/dist/esm/canvas/utils/{textProperties.js → Texts/textProperties.js} +0 -0
|
@@ -0,0 +1,631 @@
|
|
|
1
|
+
import { SKRSContext2D } from "@napi-rs/canvas";
|
|
2
|
+
import { ImageProperties } from "../utils";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Applies shadow to the canvas context.
|
|
6
|
+
* @param ctx The canvas rendering context.
|
|
7
|
+
* @param shadow The shadow properties.
|
|
8
|
+
* @param x The x-coordinate of the shape.
|
|
9
|
+
* @param y The y-coordinate of the shape.
|
|
10
|
+
* @param width The width of the shape.
|
|
11
|
+
* @param height The height of the shape.
|
|
12
|
+
*/
|
|
13
|
+
export function applyShadow(
|
|
14
|
+
ctx: SKRSContext2D,
|
|
15
|
+
shadow: ImageProperties['shadow'],
|
|
16
|
+
x: number,
|
|
17
|
+
y: number,
|
|
18
|
+
width: number,
|
|
19
|
+
height: number
|
|
20
|
+
): void {
|
|
21
|
+
ctx.save();
|
|
22
|
+
|
|
23
|
+
if (shadow) {
|
|
24
|
+
ctx.globalAlpha = shadow.opacity ?? 1;
|
|
25
|
+
ctx.filter = `blur(${shadow.blur ?? 0}px)`;
|
|
26
|
+
|
|
27
|
+
const shadowX = x + (shadow.offsetX ?? 0);
|
|
28
|
+
const shadowY = y + (shadow.offsetY ?? 0);
|
|
29
|
+
|
|
30
|
+
objectRadius(
|
|
31
|
+
ctx,
|
|
32
|
+
shadowX,
|
|
33
|
+
shadowY,
|
|
34
|
+
width,
|
|
35
|
+
height,
|
|
36
|
+
shadow.borderRadius ?? 2,
|
|
37
|
+
shadow.borderPosition
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
ctx.fillStyle = shadow.color || "transparent";
|
|
41
|
+
ctx.fill();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
ctx.filter = "none";
|
|
45
|
+
ctx.globalAlpha = 1;
|
|
46
|
+
ctx.restore();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Applies zoom (scaling) to the canvas context around a specified point.
|
|
51
|
+
* @param ctx The canvas rendering context.
|
|
52
|
+
* @param zoom An object with scale (zoom factor) and the x/y coordinates that act as the zoom origin.
|
|
53
|
+
*/
|
|
54
|
+
export function applyZoom(
|
|
55
|
+
ctx: SKRSContext2D,
|
|
56
|
+
zoom?: { scale?: number; x?: number; y?: number }
|
|
57
|
+
): void {
|
|
58
|
+
if (!zoom) return;
|
|
59
|
+
const scale = zoom.scale ?? 1;
|
|
60
|
+
const zoomX = zoom.x ?? 0;
|
|
61
|
+
const zoomY = zoom.y ?? 0;
|
|
62
|
+
|
|
63
|
+
// Translate to the zoom origin, apply the scaling, then translate back.
|
|
64
|
+
ctx.translate(zoomX, zoomY);
|
|
65
|
+
ctx.scale(scale, scale);
|
|
66
|
+
ctx.translate(-zoomX, -zoomY);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Applies stroke to the canvas context with support for selective side strokes.
|
|
71
|
+
* If stroke.borderPosition is "all", it uses the full rounded path.
|
|
72
|
+
* Otherwise, it constructs individual segments for the specified sides.
|
|
73
|
+
*
|
|
74
|
+
* @param ctx The canvas rendering context.
|
|
75
|
+
* @param stroke The stroke properties.
|
|
76
|
+
* @param x The x-coordinate of the shape.
|
|
77
|
+
* @param y The y-coordinate of the shape.
|
|
78
|
+
* @param width The width of the shape.
|
|
79
|
+
* @param height The height of the shape.
|
|
80
|
+
*/
|
|
81
|
+
export function applyStroke(
|
|
82
|
+
ctx: SKRSContext2D,
|
|
83
|
+
stroke: ImageProperties['stroke'],
|
|
84
|
+
x: number,
|
|
85
|
+
y: number,
|
|
86
|
+
width: number,
|
|
87
|
+
height: number
|
|
88
|
+
): void {
|
|
89
|
+
if (!stroke) return;
|
|
90
|
+
|
|
91
|
+
ctx.save();
|
|
92
|
+
|
|
93
|
+
// Set stroke style: use gradient if provided, otherwise solid color.
|
|
94
|
+
ctx.strokeStyle = stroke.gradient
|
|
95
|
+
? createGradient(ctx, stroke.gradient, x, y, x + width, y + height)
|
|
96
|
+
: stroke.color || "transparent";
|
|
97
|
+
|
|
98
|
+
// Set the stroke width.
|
|
99
|
+
ctx.lineWidth = stroke.width ?? 0;
|
|
100
|
+
|
|
101
|
+
// Calculate offset: stroke.position plus half the stroke width ensures the stroke is drawn outside.
|
|
102
|
+
const positionOffset = stroke.position ?? 0;
|
|
103
|
+
const halfStroke = ctx.lineWidth / 2;
|
|
104
|
+
const totalOffset = positionOffset + halfStroke;
|
|
105
|
+
|
|
106
|
+
// Adjust the drawing rectangle to accommodate the stroke.
|
|
107
|
+
const adjustedX = x - totalOffset;
|
|
108
|
+
const adjustedY = y - totalOffset;
|
|
109
|
+
const adjustedWidth = width + totalOffset * 2;
|
|
110
|
+
const adjustedHeight = height + totalOffset * 2;
|
|
111
|
+
|
|
112
|
+
// If the border position is "all" (or not provided), draw a complete rounded rectangle.
|
|
113
|
+
if (!stroke.borderPosition || stroke.borderPosition.trim().toLowerCase() === "all") {
|
|
114
|
+
objectRadius(
|
|
115
|
+
ctx,
|
|
116
|
+
adjustedX,
|
|
117
|
+
adjustedY,
|
|
118
|
+
adjustedWidth,
|
|
119
|
+
adjustedHeight,
|
|
120
|
+
stroke.borderRadius ?? 2,
|
|
121
|
+
"all"
|
|
122
|
+
);
|
|
123
|
+
ctx.stroke();
|
|
124
|
+
ctx.restore();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Otherwise, draw only the segments corresponding to the specified sides/corners.
|
|
129
|
+
const bp = stroke.borderPosition.toLowerCase();
|
|
130
|
+
const positions = bp.split(',').map(s => s.trim());
|
|
131
|
+
// For convenience, if a simple keyword (like "top") is used, it indicates the entire edge.
|
|
132
|
+
// We'll allow individual corners as well.
|
|
133
|
+
|
|
134
|
+
ctx.beginPath();
|
|
135
|
+
|
|
136
|
+
// --- Top Edge ---
|
|
137
|
+
if (
|
|
138
|
+
positions.includes("top") ||
|
|
139
|
+
positions.includes("top-left") ||
|
|
140
|
+
positions.includes("top-right")
|
|
141
|
+
) {
|
|
142
|
+
// Determine rounding for the top-left and top-right corners.
|
|
143
|
+
const tl = positions.includes("top-left") || positions.includes("top")
|
|
144
|
+
? (stroke.borderRadius ? +stroke.borderRadius : 0)
|
|
145
|
+
: 0;
|
|
146
|
+
const tr = positions.includes("top-right") || positions.includes("top")
|
|
147
|
+
? (stroke.borderRadius ? +stroke.borderRadius : 0)
|
|
148
|
+
: 0;
|
|
149
|
+
ctx.moveTo(adjustedX + tl, adjustedY);
|
|
150
|
+
ctx.lineTo(adjustedX + adjustedWidth - tr, adjustedY);
|
|
151
|
+
if (tr > 0) {
|
|
152
|
+
ctx.quadraticCurveTo(adjustedX + adjustedWidth, adjustedY, adjustedX + adjustedWidth, adjustedY + tr);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// --- Right Edge ---
|
|
157
|
+
if (
|
|
158
|
+
positions.includes("right") ||
|
|
159
|
+
positions.includes("top-right") ||
|
|
160
|
+
positions.includes("bottom-right")
|
|
161
|
+
) {
|
|
162
|
+
const tr = positions.includes("top-right") || positions.includes("right")
|
|
163
|
+
? (stroke.borderRadius ? +stroke.borderRadius : 0)
|
|
164
|
+
: 0;
|
|
165
|
+
const br = positions.includes("bottom-right") || positions.includes("right")
|
|
166
|
+
? (stroke.borderRadius ? +stroke.borderRadius : 0)
|
|
167
|
+
: 0;
|
|
168
|
+
ctx.moveTo(adjustedX + adjustedWidth, adjustedY + tr);
|
|
169
|
+
ctx.lineTo(adjustedX + adjustedWidth, adjustedY + adjustedHeight - br);
|
|
170
|
+
if (br > 0) {
|
|
171
|
+
ctx.quadraticCurveTo(adjustedX + adjustedWidth, adjustedY + adjustedHeight, adjustedX + adjustedWidth - br, adjustedY + adjustedHeight);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// --- Bottom Edge ---
|
|
176
|
+
if (
|
|
177
|
+
positions.includes("bottom") ||
|
|
178
|
+
positions.includes("bottom-left") ||
|
|
179
|
+
positions.includes("bottom-right")
|
|
180
|
+
) {
|
|
181
|
+
const bl = positions.includes("bottom-left") || positions.includes("bottom")
|
|
182
|
+
? (stroke.borderRadius ? +stroke.borderRadius : 0)
|
|
183
|
+
: 0;
|
|
184
|
+
const br = positions.includes("bottom-right") || positions.includes("bottom")
|
|
185
|
+
? (stroke.borderRadius ? +stroke.borderRadius : 0)
|
|
186
|
+
: 0;
|
|
187
|
+
ctx.moveTo(adjustedX + bl, adjustedY + adjustedHeight);
|
|
188
|
+
ctx.lineTo(adjustedX + adjustedWidth - br, adjustedY + adjustedHeight);
|
|
189
|
+
if (br > 0) {
|
|
190
|
+
ctx.quadraticCurveTo(adjustedX + adjustedWidth, adjustedY + adjustedHeight, adjustedX + adjustedWidth, adjustedY + adjustedHeight - br);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// --- Left Edge ---
|
|
195
|
+
if (
|
|
196
|
+
positions.includes("left") ||
|
|
197
|
+
positions.includes("top-left") ||
|
|
198
|
+
positions.includes("bottom-left")
|
|
199
|
+
) {
|
|
200
|
+
const tl = positions.includes("top-left") || positions.includes("left")
|
|
201
|
+
? (stroke.borderRadius ? +stroke.borderRadius : 0)
|
|
202
|
+
: 0;
|
|
203
|
+
const bl = positions.includes("bottom-left") || positions.includes("left")
|
|
204
|
+
? (stroke.borderRadius ? +stroke.borderRadius : 0)
|
|
205
|
+
: 0;
|
|
206
|
+
ctx.moveTo(adjustedX, adjustedY + tl);
|
|
207
|
+
ctx.lineTo(adjustedX, adjustedY + adjustedHeight - bl);
|
|
208
|
+
if (bl > 0) {
|
|
209
|
+
ctx.quadraticCurveTo(adjustedX, adjustedY + adjustedHeight, adjustedX + bl, adjustedY + adjustedHeight);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
ctx.stroke();
|
|
214
|
+
ctx.restore();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Draws a shape on the canvas context.
|
|
219
|
+
* @param ctx The canvas rendering context.
|
|
220
|
+
* @param shapeSettings The settings for the shape.
|
|
221
|
+
*/
|
|
222
|
+
export function drawShape(ctx: any, shapeSettings: any) {
|
|
223
|
+
const { source, x, y, width, height, rotation, borderRadius, borderPosition, stroke, shadow, isFilled, color, gradient } = shapeSettings;
|
|
224
|
+
|
|
225
|
+
const shapeName = source.toLowerCase();
|
|
226
|
+
|
|
227
|
+
switch (shapeName) {
|
|
228
|
+
case 'circle':
|
|
229
|
+
ctx.save();
|
|
230
|
+
applyShadow(ctx, shadow, x, y, width, height);
|
|
231
|
+
applyRotation(ctx, rotation, x, y, width, height);
|
|
232
|
+
ctx.beginPath();
|
|
233
|
+
ctx.arc(x + width / 2, y + height / 2, width / 2, 0, Math.PI * 2);
|
|
234
|
+
break;
|
|
235
|
+
case 'square':
|
|
236
|
+
ctx.save();
|
|
237
|
+
applyRotation(ctx, rotation, x, y, width, height);
|
|
238
|
+
applyShadow(ctx, shadow, x, y, width, height);
|
|
239
|
+
break;
|
|
240
|
+
case 'triangle':
|
|
241
|
+
ctx.save();
|
|
242
|
+
applyRotation(ctx, rotation, x, y, width, height);
|
|
243
|
+
applyShadow(ctx, shadow, x, y, width, height);
|
|
244
|
+
ctx.beginPath();
|
|
245
|
+
ctx.moveTo(x, y + height);
|
|
246
|
+
ctx.lineTo(x + width / 2, y);
|
|
247
|
+
ctx.lineTo(x + width, y + height);
|
|
248
|
+
ctx.closePath();
|
|
249
|
+
break;
|
|
250
|
+
case 'pentagon':
|
|
251
|
+
ctx.save();
|
|
252
|
+
applyRotation(ctx, rotation, x, y, width, height);
|
|
253
|
+
applyShadow(ctx, shadow, x, y, width, height);
|
|
254
|
+
ctx.beginPath();
|
|
255
|
+
for (let i = 0; i < 5; i++) {
|
|
256
|
+
ctx.lineTo(x + width / 2 + width / 2 * Math.sin(i * 2 * Math.PI / 5),
|
|
257
|
+
y + height / 2 - height / 2 * Math.cos(i * 2 * Math.PI / 5));
|
|
258
|
+
}
|
|
259
|
+
ctx.closePath();
|
|
260
|
+
break;
|
|
261
|
+
case 'hexagon':
|
|
262
|
+
ctx.save();
|
|
263
|
+
applyRotation(ctx, rotation, x, y, width, height);
|
|
264
|
+
applyShadow(ctx, shadow, x, y, width, height);
|
|
265
|
+
ctx.beginPath();
|
|
266
|
+
for (let i = 0; i < 6; i++) {
|
|
267
|
+
ctx.lineTo(x + width / 2 + width / 2 * Math.sin(i * 2 * Math.PI / 6),
|
|
268
|
+
y + height / 2 - height / 2 * Math.cos(i * 2 * Math.PI / 6));
|
|
269
|
+
}
|
|
270
|
+
ctx.closePath();
|
|
271
|
+
break;
|
|
272
|
+
case 'heptagon':
|
|
273
|
+
ctx.save();
|
|
274
|
+
applyRotation(ctx, rotation, x, y, width, height);
|
|
275
|
+
applyShadow(ctx, shadow, x, y, width, height);
|
|
276
|
+
ctx.beginPath();
|
|
277
|
+
for (let i = 0; i < 7; i++) {
|
|
278
|
+
ctx.lineTo(x + width / 2 + width / 2 * Math.sin(i * 2 * Math.PI / 7),
|
|
279
|
+
y + height / 2 - height / 2 * Math.cos(i * 2 * Math.PI / 7));
|
|
280
|
+
}
|
|
281
|
+
ctx.closePath();
|
|
282
|
+
break;
|
|
283
|
+
case 'octagon':
|
|
284
|
+
ctx.save();
|
|
285
|
+
applyRotation(ctx, rotation, x, y, width, height);
|
|
286
|
+
applyShadow(ctx, shadow, x, y, width, height);
|
|
287
|
+
ctx.beginPath();
|
|
288
|
+
for (let i = 0; i < 8; i++) {
|
|
289
|
+
ctx.lineTo(x + width / 2 + width / 2 * Math.sin(i * 2 * Math.PI / 8),
|
|
290
|
+
y + height / 2 - height / 2 * Math.cos(i * 2 * Math.PI / 8));
|
|
291
|
+
}
|
|
292
|
+
ctx.closePath();
|
|
293
|
+
case 'star':
|
|
294
|
+
ctx.save();
|
|
295
|
+
applyRotation(ctx, rotation, x, y, width, height);
|
|
296
|
+
applyShadow(ctx, shadow, x, y, width, height);
|
|
297
|
+
ctx.beginPath();
|
|
298
|
+
const numPoints = 5;
|
|
299
|
+
const outerRadius = Math.min(width, height) / 2;
|
|
300
|
+
const innerRadius = outerRadius / 2;
|
|
301
|
+
for (let i = 0; i < numPoints * 2; i++) {
|
|
302
|
+
const radius = i % 2 === 0 ? outerRadius : innerRadius;
|
|
303
|
+
const angle = Math.PI / numPoints * i;
|
|
304
|
+
ctx.lineTo(x + width / 2 + radius * Math.sin(angle),
|
|
305
|
+
y + height / 2 - radius * Math.cos(angle));
|
|
306
|
+
}
|
|
307
|
+
ctx.closePath();
|
|
308
|
+
break;
|
|
309
|
+
case 'oval':
|
|
310
|
+
ctx.save();
|
|
311
|
+
applyRotation(ctx, rotation, x, y, width, height);
|
|
312
|
+
applyShadow(ctx, shadow, x, y, width, height);
|
|
313
|
+
|
|
314
|
+
ctx.beginPath();
|
|
315
|
+
ctx.ellipse(x + width / 2, y + height / 2, width / 2, height / 2, 0, 0, Math.PI * 2);
|
|
316
|
+
ctx.closePath();
|
|
317
|
+
if (isFilled) {
|
|
318
|
+
ctx.fillStyle = color;
|
|
319
|
+
ctx.fill();
|
|
320
|
+
} else {
|
|
321
|
+
applyStroke(ctx, stroke, x, y, width, height);
|
|
322
|
+
}
|
|
323
|
+
ctx.restore();
|
|
324
|
+
break;
|
|
325
|
+
default:
|
|
326
|
+
throw new Error(`Unsupported shape: ${shapeName}`);
|
|
327
|
+
}
|
|
328
|
+
if (isFilled) {
|
|
329
|
+
if (borderRadius) {
|
|
330
|
+
objectRadius(ctx, x, y, width, height, borderRadius, borderPosition);
|
|
331
|
+
if (gradient) {
|
|
332
|
+
const gradientFill = createGradient(
|
|
333
|
+
ctx,
|
|
334
|
+
gradient,
|
|
335
|
+
x,
|
|
336
|
+
y,
|
|
337
|
+
x + width,
|
|
338
|
+
y + height,
|
|
339
|
+
);
|
|
340
|
+
ctx.fillStyle = gradientFill;
|
|
341
|
+
} else {
|
|
342
|
+
ctx.fillStyle = color || "transparent";
|
|
343
|
+
}
|
|
344
|
+
ctx.fill();
|
|
345
|
+
} else {
|
|
346
|
+
if (gradient) {
|
|
347
|
+
const gradientFill = createGradient(
|
|
348
|
+
ctx,
|
|
349
|
+
gradient,
|
|
350
|
+
x,
|
|
351
|
+
y,
|
|
352
|
+
x + width,
|
|
353
|
+
y + height,
|
|
354
|
+
);
|
|
355
|
+
ctx.fillStyle = gradientFill;
|
|
356
|
+
} else {
|
|
357
|
+
ctx.fillStyle = color || "transparent";
|
|
358
|
+
}
|
|
359
|
+
if (shapeName === 'square') {
|
|
360
|
+
ctx.fillRect(x, y, width, height);
|
|
361
|
+
} else if (shapeName === 'circle') {
|
|
362
|
+
ctx.fill();
|
|
363
|
+
} else {
|
|
364
|
+
ctx.fill()
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
applyStroke(ctx, stroke, x, y, width, height);
|
|
368
|
+
} else {
|
|
369
|
+
if (gradient) {
|
|
370
|
+
const gradientFill = createGradient(
|
|
371
|
+
ctx,
|
|
372
|
+
gradient,
|
|
373
|
+
x,
|
|
374
|
+
y,
|
|
375
|
+
x + width,
|
|
376
|
+
y + height,
|
|
377
|
+
);
|
|
378
|
+
ctx.fillStyle = gradientFill;
|
|
379
|
+
}
|
|
380
|
+
applyStroke(ctx, stroke, x, y, width, height);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
ctx.restore();
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export function createGradient(ctx: any, gradientOptions: any, startX: number, startY: number, endX: number, endY: number) {
|
|
387
|
+
if (!gradientOptions || !gradientOptions.type || !gradientOptions.colors) {
|
|
388
|
+
throw new Error("Invalid gradient options. Provide a valid object with type and colors properties.");
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (!Array.isArray(gradientOptions.colors)) {
|
|
392
|
+
throw new Error("Invalid gradient options. The colors property should be an array of color stops.");
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (gradientOptions.type === "linear") {
|
|
396
|
+
if (
|
|
397
|
+
typeof startX !== "number" ||
|
|
398
|
+
typeof startY !== "number" ||
|
|
399
|
+
typeof endX !== "number" ||
|
|
400
|
+
typeof endY !== "number"
|
|
401
|
+
) {
|
|
402
|
+
throw new Error("Invalid gradient options for linear gradient. Numeric values are required for startX, startY, endX, and endY.");
|
|
403
|
+
}
|
|
404
|
+
const gradient = ctx.createLinearGradient(startX, startY, endX, endY);
|
|
405
|
+
|
|
406
|
+
for (const colorStop of gradientOptions.colors) {
|
|
407
|
+
if (typeof colorStop.stop !== "number" || typeof colorStop.color !== "string") {
|
|
408
|
+
throw new Error("Invalid color stop. Each color stop should have a numeric stop value and a color string.");
|
|
409
|
+
}
|
|
410
|
+
gradient.addColorStop(colorStop.stop, colorStop.color);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return gradient;
|
|
414
|
+
|
|
415
|
+
} else if (gradientOptions.type === "radial") {
|
|
416
|
+
if (
|
|
417
|
+
typeof gradientOptions.startX !== "number" ||
|
|
418
|
+
typeof gradientOptions.startY !== "number" ||
|
|
419
|
+
typeof gradientOptions.startRadius !== "number" ||
|
|
420
|
+
typeof gradientOptions.endX !== "number" ||
|
|
421
|
+
typeof gradientOptions.endY !== "number" ||
|
|
422
|
+
typeof gradientOptions.endRadius !== "number"
|
|
423
|
+
) {
|
|
424
|
+
throw new Error("Invalid gradient options for radial gradient. Numeric values are required for startX, startY, startRadius, endX, endY, and endRadius.");
|
|
425
|
+
}
|
|
426
|
+
const gradient = ctx.createRadialGradient(
|
|
427
|
+
gradientOptions.startX,
|
|
428
|
+
gradientOptions.startY,
|
|
429
|
+
gradientOptions.startRadius,
|
|
430
|
+
gradientOptions.endX,
|
|
431
|
+
gradientOptions.endY,
|
|
432
|
+
gradientOptions.endRadius
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
for (const colorStop of gradientOptions.colors) {
|
|
436
|
+
if (typeof colorStop.stop !== "number" || typeof colorStop.color !== "string") {
|
|
437
|
+
throw new Error("Invalid color stop. Each color stop should have a numeric stop value and a color string.");
|
|
438
|
+
}
|
|
439
|
+
gradient.addColorStop(colorStop.stop, colorStop.color);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
return gradient;
|
|
443
|
+
|
|
444
|
+
} else {
|
|
445
|
+
throw new Error('Unsupported gradient type. Use "linear" or "radial".');
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Applies rotation to the canvas context.
|
|
452
|
+
* @param ctx The canvas rendering context.
|
|
453
|
+
* @param rotation The rotation angle in degrees.
|
|
454
|
+
* @param x The x-coordinate of the center of rotation.
|
|
455
|
+
* @param y The y-coordinate of the center of rotation.
|
|
456
|
+
* @param width The width of the shape.
|
|
457
|
+
* @param height The height of the shape.
|
|
458
|
+
*/
|
|
459
|
+
export function applyRotation(
|
|
460
|
+
ctx: SKRSContext2D,
|
|
461
|
+
rotation: number,
|
|
462
|
+
x: number,
|
|
463
|
+
y: number,
|
|
464
|
+
width: number,
|
|
465
|
+
height: number
|
|
466
|
+
): void {
|
|
467
|
+
// Check is not really necessary since 0 is valid.
|
|
468
|
+
const rotationX = x + width / 2;
|
|
469
|
+
const rotationY = y + height / 2;
|
|
470
|
+
ctx.translate(rotationX, rotationY);
|
|
471
|
+
ctx.rotate((rotation * Math.PI) / 180);
|
|
472
|
+
ctx.translate(-rotationX, -rotationY);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Applies border radius to the canvas context.
|
|
478
|
+
* @param ctx The canvas rendering context.
|
|
479
|
+
* @param image The image properties containing the border radius.
|
|
480
|
+
* @param x The x-coordinate of the shape.
|
|
481
|
+
* @param y The y-coordinate of the shape.
|
|
482
|
+
* @param width The width of the shape.
|
|
483
|
+
* @param height The height of the shape.
|
|
484
|
+
* @param borderRadius The border radius value.
|
|
485
|
+
* @param borderPosition The border radius position to be applied on.
|
|
486
|
+
*/
|
|
487
|
+
export function imageRadius(ctx: any, image: any, x: number, y: number, width: number, height: number, borderRadius: any, borderPosition: string = 'all'): void {
|
|
488
|
+
ctx.save();
|
|
489
|
+
ctx.beginPath();
|
|
490
|
+
|
|
491
|
+
if (borderRadius === "circular") {
|
|
492
|
+
const circleRadius = Math.min(width, height) / 2;
|
|
493
|
+
ctx.arc(x + width / 2, y + height / 2, circleRadius, 0, 2 * Math.PI);
|
|
494
|
+
} else {
|
|
495
|
+
ctx.moveTo(x + borderRadius, y);
|
|
496
|
+
ctx.lineTo(x + width - borderRadius, y);
|
|
497
|
+
ctx.quadraticCurveTo(x + width, y, x + width, y + borderRadius);
|
|
498
|
+
ctx.lineTo(x + width, y + height - borderRadius);
|
|
499
|
+
ctx.quadraticCurveTo(
|
|
500
|
+
x + width,
|
|
501
|
+
y + height,
|
|
502
|
+
x + width - borderRadius,
|
|
503
|
+
y + height,
|
|
504
|
+
);
|
|
505
|
+
ctx.lineTo(x + borderRadius, y + height);
|
|
506
|
+
ctx.quadraticCurveTo(x, y + height, x, y + height - borderRadius);
|
|
507
|
+
ctx.lineTo(x, y + borderRadius);
|
|
508
|
+
ctx.quadraticCurveTo(x, y, x + borderRadius, y);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
ctx.closePath();
|
|
512
|
+
ctx.clip();
|
|
513
|
+
ctx.drawImage(image, x, y, width, height);
|
|
514
|
+
ctx.restore();
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Creates a rounded rectangle (or circular) path on the canvas context.
|
|
520
|
+
*
|
|
521
|
+
* @param ctx The canvas rendering context.
|
|
522
|
+
* @param x The x-coordinate of the rectangle.
|
|
523
|
+
* @param y The y-coordinate of the rectangle.
|
|
524
|
+
* @param width The width of the rectangle.
|
|
525
|
+
* @param height The height of the rectangle.
|
|
526
|
+
* @param borderRadius The radius for rounding. Use a number (or string "circular" for a circle).
|
|
527
|
+
* @param borderPosition Which sides/corners to round. Valid values include:
|
|
528
|
+
* - "all" (default)
|
|
529
|
+
* - "top", "bottom", "left", "right"
|
|
530
|
+
* - "top-left", "top-right", "bottom-left", "bottom-right"
|
|
531
|
+
* - Or a comma-separated list, e.g. "top-left, bottom-right" or "top, left, bottom"
|
|
532
|
+
*/
|
|
533
|
+
export function objectRadius(
|
|
534
|
+
ctx: SKRSContext2D,
|
|
535
|
+
x: number,
|
|
536
|
+
y: number,
|
|
537
|
+
width: number,
|
|
538
|
+
height: number,
|
|
539
|
+
borderRadius: number | "circular" = 0.1,
|
|
540
|
+
borderPosition: string = 'all'
|
|
541
|
+
): void {
|
|
542
|
+
if (borderRadius === "circular") {
|
|
543
|
+
// Draw a circular path based on the smallest dimension.
|
|
544
|
+
const circleRadius = Math.min(width, height) / 2;
|
|
545
|
+
ctx.beginPath();
|
|
546
|
+
ctx.arc(x + width / 2, y + height / 2, circleRadius, 0, 2 * Math.PI);
|
|
547
|
+
ctx.closePath();
|
|
548
|
+
} else if (borderRadius) {
|
|
549
|
+
// Determine which corners to round.
|
|
550
|
+
let roundTopLeft = false;
|
|
551
|
+
let roundTopRight = false;
|
|
552
|
+
let roundBottomRight = false;
|
|
553
|
+
let roundBottomLeft = false;
|
|
554
|
+
|
|
555
|
+
const bp = borderPosition.trim().toLowerCase();
|
|
556
|
+
|
|
557
|
+
// If a simple keyword is provided, handle those cases:
|
|
558
|
+
if (bp === 'all') {
|
|
559
|
+
roundTopLeft = roundTopRight = roundBottomRight = roundBottomLeft = true;
|
|
560
|
+
} else if (bp === 'top') {
|
|
561
|
+
roundTopLeft = roundTopRight = true;
|
|
562
|
+
} else if (bp === 'bottom') {
|
|
563
|
+
roundBottomLeft = roundBottomRight = true;
|
|
564
|
+
} else if (bp === 'left') {
|
|
565
|
+
roundTopLeft = roundBottomLeft = true;
|
|
566
|
+
} else if (bp === 'right') {
|
|
567
|
+
roundTopRight = roundBottomRight = true;
|
|
568
|
+
} else if (bp === 'top-left') {
|
|
569
|
+
roundTopLeft = true;
|
|
570
|
+
} else if (bp === 'top-right') {
|
|
571
|
+
roundTopRight = true;
|
|
572
|
+
} else if (bp === 'bottom-left') {
|
|
573
|
+
roundBottomLeft = true;
|
|
574
|
+
} else if (bp === 'bottom-right') {
|
|
575
|
+
roundBottomRight = true;
|
|
576
|
+
} else {
|
|
577
|
+
// For a comma-separated list of values.
|
|
578
|
+
const positions = bp.split(',').map(s => s.trim());
|
|
579
|
+
roundTopLeft = positions.includes('top-left') || (positions.includes('top') && positions.includes('left'));
|
|
580
|
+
roundTopRight = positions.includes('top-right') || (positions.includes('top') && positions.includes('right'));
|
|
581
|
+
roundBottomRight = positions.includes('bottom-right') || (positions.includes('bottom') && positions.includes('right'));
|
|
582
|
+
roundBottomLeft = positions.includes('bottom-left') || (positions.includes('bottom') && positions.includes('left'));
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// Determine the radius for each corner.
|
|
586
|
+
const tl = roundTopLeft ? +borderRadius : 0;
|
|
587
|
+
const tr = roundTopRight ? +borderRadius : 0;
|
|
588
|
+
const br = roundBottomRight ? +borderRadius : 0;
|
|
589
|
+
const bl = roundBottomLeft ? +borderRadius : 0;
|
|
590
|
+
|
|
591
|
+
// Construct the path.
|
|
592
|
+
ctx.beginPath();
|
|
593
|
+
// Start at top-left (with offset for rounding)
|
|
594
|
+
ctx.moveTo(x + tl, y);
|
|
595
|
+
// Top edge to top-right corner.
|
|
596
|
+
ctx.lineTo(x + width - tr, y);
|
|
597
|
+
if (tr > 0) {
|
|
598
|
+
ctx.quadraticCurveTo(x + width, y, x + width, y + tr);
|
|
599
|
+
} else {
|
|
600
|
+
ctx.lineTo(x + width, y);
|
|
601
|
+
}
|
|
602
|
+
// Right edge to bottom-right corner.
|
|
603
|
+
ctx.lineTo(x + width, y + height - br);
|
|
604
|
+
if (br > 0) {
|
|
605
|
+
ctx.quadraticCurveTo(x + width, y + height, x + width - br, y + height);
|
|
606
|
+
} else {
|
|
607
|
+
ctx.lineTo(x + width, y + height);
|
|
608
|
+
}
|
|
609
|
+
// Bottom edge to bottom-left corner.
|
|
610
|
+
ctx.lineTo(x + bl, y + height);
|
|
611
|
+
if (bl > 0) {
|
|
612
|
+
ctx.quadraticCurveTo(x, y + height, x, y + height - bl);
|
|
613
|
+
} else {
|
|
614
|
+
ctx.lineTo(x, y + height);
|
|
615
|
+
}
|
|
616
|
+
// Left edge back to top-left.
|
|
617
|
+
ctx.lineTo(x, y + tl);
|
|
618
|
+
if (tl > 0) {
|
|
619
|
+
ctx.quadraticCurveTo(x, y, x + tl, y);
|
|
620
|
+
} else {
|
|
621
|
+
ctx.lineTo(x, y);
|
|
622
|
+
}
|
|
623
|
+
ctx.closePath();
|
|
624
|
+
} else {
|
|
625
|
+
// If no borderRadius is provided, simply use a rectangle.
|
|
626
|
+
ctx.beginPath();
|
|
627
|
+
ctx.rect(x, y, width, height);
|
|
628
|
+
ctx.closePath();
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|