apexify.js 4.9.25 → 4.9.27

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 (198) hide show
  1. package/README.md +358 -47
  2. package/dist/cjs/Canvas/ApexPainter.d.ts +189 -0
  3. package/dist/cjs/Canvas/ApexPainter.d.ts.map +1 -0
  4. package/dist/{esm/canvas → cjs/Canvas}/ApexPainter.js +461 -352
  5. package/dist/cjs/Canvas/ApexPainter.js.map +1 -0
  6. package/dist/cjs/Canvas/utils/Background/bg.d.ts +43 -0
  7. package/dist/cjs/Canvas/utils/Background/bg.d.ts.map +1 -0
  8. package/dist/cjs/Canvas/utils/Background/bg.js +228 -0
  9. package/dist/cjs/Canvas/utils/Background/bg.js.map +1 -0
  10. package/dist/cjs/{canvas → Canvas}/utils/Charts/charts.d.ts.map +1 -1
  11. package/dist/{esm/canvas → cjs/Canvas}/utils/Charts/charts.js.map +1 -1
  12. package/dist/cjs/{canvas → Canvas}/utils/Custom/customLines.d.ts.map +1 -1
  13. package/dist/{esm/canvas → cjs/Canvas}/utils/Custom/customLines.js +2 -2
  14. package/dist/cjs/Canvas/utils/Custom/customLines.js.map +1 -0
  15. package/dist/cjs/{canvas → Canvas}/utils/General/conversion.d.ts.map +1 -1
  16. package/dist/cjs/{canvas → Canvas}/utils/General/conversion.js.map +1 -1
  17. package/dist/cjs/{canvas → Canvas}/utils/General/general functions.d.ts.map +1 -1
  18. package/dist/{esm/canvas → cjs/Canvas}/utils/General/general functions.js.map +1 -1
  19. package/dist/cjs/Canvas/utils/Image/imageFilters.d.ts +11 -0
  20. package/dist/cjs/Canvas/utils/Image/imageFilters.d.ts.map +1 -0
  21. package/dist/cjs/Canvas/utils/Image/imageFilters.js +307 -0
  22. package/dist/cjs/Canvas/utils/Image/imageFilters.js.map +1 -0
  23. package/dist/cjs/Canvas/utils/Image/imageProperties.d.ts +50 -0
  24. package/dist/cjs/Canvas/utils/Image/imageProperties.d.ts.map +1 -0
  25. package/dist/cjs/Canvas/utils/Image/imageProperties.js +271 -0
  26. package/dist/cjs/Canvas/utils/Image/imageProperties.js.map +1 -0
  27. package/dist/cjs/Canvas/utils/Image/professionalImageFilters.d.ts +11 -0
  28. package/dist/cjs/Canvas/utils/Image/professionalImageFilters.d.ts.map +1 -0
  29. package/dist/cjs/Canvas/utils/Image/professionalImageFilters.js +351 -0
  30. package/dist/cjs/Canvas/utils/Image/professionalImageFilters.js.map +1 -0
  31. package/dist/cjs/Canvas/utils/Image/simpleProfessionalFilters.d.ts +11 -0
  32. package/dist/cjs/Canvas/utils/Image/simpleProfessionalFilters.d.ts.map +1 -0
  33. package/dist/cjs/Canvas/utils/Image/simpleProfessionalFilters.js +215 -0
  34. package/dist/cjs/Canvas/utils/Image/simpleProfessionalFilters.js.map +1 -0
  35. package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.d.ts +71 -0
  36. package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.d.ts.map +1 -0
  37. package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.js +392 -0
  38. package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.js.map +1 -0
  39. package/dist/cjs/Canvas/utils/Shapes/shapes.d.ts +29 -0
  40. package/dist/cjs/Canvas/utils/Shapes/shapes.d.ts.map +1 -0
  41. package/dist/cjs/Canvas/utils/Shapes/shapes.js +334 -0
  42. package/dist/cjs/Canvas/utils/Shapes/shapes.js.map +1 -0
  43. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts +127 -0
  44. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -0
  45. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js +365 -0
  46. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -0
  47. package/dist/cjs/{canvas → Canvas}/utils/Texts/textProperties.d.ts.map +1 -1
  48. package/dist/{esm/canvas → cjs/Canvas}/utils/Texts/textProperties.js.map +1 -1
  49. package/dist/{esm/canvas → cjs/Canvas}/utils/types.d.ts +227 -131
  50. package/dist/cjs/Canvas/utils/types.d.ts.map +1 -0
  51. package/dist/cjs/{canvas → Canvas}/utils/types.js +0 -1
  52. package/dist/cjs/Canvas/utils/types.js.map +1 -0
  53. package/dist/cjs/Canvas/utils/utils.d.ts +22 -0
  54. package/dist/cjs/Canvas/utils/utils.d.ts.map +1 -0
  55. package/dist/{esm/canvas → cjs/Canvas}/utils/utils.js +17 -7
  56. package/dist/cjs/Canvas/utils/utils.js.map +1 -0
  57. package/dist/cjs/index.d.ts +6 -3
  58. package/dist/cjs/index.d.ts.map +1 -1
  59. package/dist/cjs/index.js +8 -6
  60. package/dist/cjs/index.js.map +1 -1
  61. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  62. package/dist/cjs/utils.d.ts +1 -1
  63. package/dist/cjs/utils.js +1 -1
  64. package/dist/esm/Canvas/ApexPainter.d.ts +189 -0
  65. package/dist/esm/Canvas/ApexPainter.d.ts.map +1 -0
  66. package/dist/{cjs/canvas → esm/Canvas}/ApexPainter.js +461 -352
  67. package/dist/esm/Canvas/ApexPainter.js.map +1 -0
  68. package/dist/esm/Canvas/utils/Background/bg.d.ts +43 -0
  69. package/dist/esm/Canvas/utils/Background/bg.d.ts.map +1 -0
  70. package/dist/esm/Canvas/utils/Background/bg.js +228 -0
  71. package/dist/esm/Canvas/utils/Background/bg.js.map +1 -0
  72. package/dist/esm/{canvas → Canvas}/utils/Charts/charts.d.ts.map +1 -1
  73. package/dist/{cjs/canvas → esm/Canvas}/utils/Charts/charts.js.map +1 -1
  74. package/dist/esm/{canvas → Canvas}/utils/Custom/customLines.d.ts.map +1 -1
  75. package/dist/{cjs/canvas → esm/Canvas}/utils/Custom/customLines.js +2 -2
  76. package/dist/esm/Canvas/utils/Custom/customLines.js.map +1 -0
  77. package/dist/esm/{canvas → Canvas}/utils/General/conversion.d.ts.map +1 -1
  78. package/dist/esm/{canvas → Canvas}/utils/General/conversion.js.map +1 -1
  79. package/dist/esm/{canvas → Canvas}/utils/General/general functions.d.ts.map +1 -1
  80. package/dist/{cjs/canvas → esm/Canvas}/utils/General/general functions.js.map +1 -1
  81. package/dist/esm/Canvas/utils/Image/imageFilters.d.ts +11 -0
  82. package/dist/esm/Canvas/utils/Image/imageFilters.d.ts.map +1 -0
  83. package/dist/esm/Canvas/utils/Image/imageFilters.js +307 -0
  84. package/dist/esm/Canvas/utils/Image/imageFilters.js.map +1 -0
  85. package/dist/esm/Canvas/utils/Image/imageProperties.d.ts +50 -0
  86. package/dist/esm/Canvas/utils/Image/imageProperties.d.ts.map +1 -0
  87. package/dist/esm/Canvas/utils/Image/imageProperties.js +271 -0
  88. package/dist/esm/Canvas/utils/Image/imageProperties.js.map +1 -0
  89. package/dist/esm/Canvas/utils/Image/professionalImageFilters.d.ts +11 -0
  90. package/dist/esm/Canvas/utils/Image/professionalImageFilters.d.ts.map +1 -0
  91. package/dist/esm/Canvas/utils/Image/professionalImageFilters.js +351 -0
  92. package/dist/esm/Canvas/utils/Image/professionalImageFilters.js.map +1 -0
  93. package/dist/esm/Canvas/utils/Image/simpleProfessionalFilters.d.ts +11 -0
  94. package/dist/esm/Canvas/utils/Image/simpleProfessionalFilters.d.ts.map +1 -0
  95. package/dist/esm/Canvas/utils/Image/simpleProfessionalFilters.js +215 -0
  96. package/dist/esm/Canvas/utils/Image/simpleProfessionalFilters.js.map +1 -0
  97. package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.d.ts +71 -0
  98. package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.d.ts.map +1 -0
  99. package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.js +392 -0
  100. package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.js.map +1 -0
  101. package/dist/esm/Canvas/utils/Shapes/shapes.d.ts +29 -0
  102. package/dist/esm/Canvas/utils/Shapes/shapes.d.ts.map +1 -0
  103. package/dist/esm/Canvas/utils/Shapes/shapes.js +334 -0
  104. package/dist/esm/Canvas/utils/Shapes/shapes.js.map +1 -0
  105. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts +127 -0
  106. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -0
  107. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js +365 -0
  108. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -0
  109. package/dist/esm/{canvas → Canvas}/utils/Texts/textProperties.d.ts.map +1 -1
  110. package/dist/{cjs/canvas → esm/Canvas}/utils/Texts/textProperties.js.map +1 -1
  111. package/dist/{cjs/canvas → esm/Canvas}/utils/types.d.ts +227 -131
  112. package/dist/esm/Canvas/utils/types.d.ts.map +1 -0
  113. package/dist/esm/{canvas → Canvas}/utils/types.js +0 -1
  114. package/dist/esm/Canvas/utils/types.js.map +1 -0
  115. package/dist/esm/Canvas/utils/utils.d.ts +22 -0
  116. package/dist/esm/Canvas/utils/utils.d.ts.map +1 -0
  117. package/dist/{cjs/canvas → esm/Canvas}/utils/utils.js +17 -7
  118. package/dist/esm/Canvas/utils/utils.js.map +1 -0
  119. package/dist/esm/index.d.ts +6 -3
  120. package/dist/esm/index.d.ts.map +1 -1
  121. package/dist/esm/index.js +8 -6
  122. package/dist/esm/index.js.map +1 -1
  123. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  124. package/dist/esm/utils.d.ts +1 -1
  125. package/dist/esm/utils.js +1 -1
  126. package/lib/{canvas → Canvas}/ApexPainter.ts +1325 -1218
  127. package/lib/Canvas/utils/Background/bg.ts +285 -0
  128. package/lib/{canvas → Canvas}/utils/Custom/customLines.ts +3 -3
  129. package/lib/Canvas/utils/Image/imageFilters.ts +356 -0
  130. package/lib/Canvas/utils/Image/imageProperties.ts +382 -0
  131. package/lib/Canvas/utils/Image/professionalImageFilters.ts +391 -0
  132. package/lib/Canvas/utils/Image/simpleProfessionalFilters.ts +229 -0
  133. package/lib/Canvas/utils/Patterns/enhancedPatternRenderer.ts +444 -0
  134. package/lib/Canvas/utils/Shapes/shapes.ts +528 -0
  135. package/lib/Canvas/utils/Texts/enhancedTextRenderer.ts +478 -0
  136. package/lib/{canvas → Canvas}/utils/types.ts +301 -117
  137. package/lib/{canvas → Canvas}/utils/utils.ts +85 -72
  138. package/lib/index.ts +8 -9
  139. package/lib/utils.ts +1 -1
  140. package/package.json +107 -191
  141. package/dist/cjs/canvas/ApexPainter.d.ts +0 -145
  142. package/dist/cjs/canvas/ApexPainter.d.ts.map +0 -1
  143. package/dist/cjs/canvas/ApexPainter.js.map +0 -1
  144. package/dist/cjs/canvas/utils/Background/bg.d.ts +0 -31
  145. package/dist/cjs/canvas/utils/Background/bg.d.ts.map +0 -1
  146. package/dist/cjs/canvas/utils/Background/bg.js +0 -161
  147. package/dist/cjs/canvas/utils/Background/bg.js.map +0 -1
  148. package/dist/cjs/canvas/utils/Custom/customLines.js.map +0 -1
  149. package/dist/cjs/canvas/utils/Image/imageProperties.d.ts +0 -115
  150. package/dist/cjs/canvas/utils/Image/imageProperties.d.ts.map +0 -1
  151. package/dist/cjs/canvas/utils/Image/imageProperties.js +0 -602
  152. package/dist/cjs/canvas/utils/Image/imageProperties.js.map +0 -1
  153. package/dist/cjs/canvas/utils/types.d.ts.map +0 -1
  154. package/dist/cjs/canvas/utils/types.js.map +0 -1
  155. package/dist/cjs/canvas/utils/utils.d.ts +0 -19
  156. package/dist/cjs/canvas/utils/utils.d.ts.map +0 -1
  157. package/dist/cjs/canvas/utils/utils.js.map +0 -1
  158. package/dist/esm/canvas/ApexPainter.d.ts +0 -145
  159. package/dist/esm/canvas/ApexPainter.d.ts.map +0 -1
  160. package/dist/esm/canvas/ApexPainter.js.map +0 -1
  161. package/dist/esm/canvas/utils/Background/bg.d.ts +0 -31
  162. package/dist/esm/canvas/utils/Background/bg.d.ts.map +0 -1
  163. package/dist/esm/canvas/utils/Background/bg.js +0 -161
  164. package/dist/esm/canvas/utils/Background/bg.js.map +0 -1
  165. package/dist/esm/canvas/utils/Custom/customLines.js.map +0 -1
  166. package/dist/esm/canvas/utils/Image/imageProperties.d.ts +0 -115
  167. package/dist/esm/canvas/utils/Image/imageProperties.d.ts.map +0 -1
  168. package/dist/esm/canvas/utils/Image/imageProperties.js +0 -602
  169. package/dist/esm/canvas/utils/Image/imageProperties.js.map +0 -1
  170. package/dist/esm/canvas/utils/types.d.ts.map +0 -1
  171. package/dist/esm/canvas/utils/types.js.map +0 -1
  172. package/dist/esm/canvas/utils/utils.d.ts +0 -19
  173. package/dist/esm/canvas/utils/utils.d.ts.map +0 -1
  174. package/dist/esm/canvas/utils/utils.js.map +0 -1
  175. package/lib/canvas/utils/Background/bg.ts +0 -211
  176. package/lib/canvas/utils/Image/imageProperties.ts +0 -835
  177. /package/dist/cjs/{canvas → Canvas}/utils/Charts/charts.d.ts +0 -0
  178. /package/dist/cjs/{canvas → Canvas}/utils/Charts/charts.js +0 -0
  179. /package/dist/cjs/{canvas → Canvas}/utils/Custom/customLines.d.ts +0 -0
  180. /package/dist/cjs/{canvas → Canvas}/utils/General/conversion.d.ts +0 -0
  181. /package/dist/cjs/{canvas → Canvas}/utils/General/conversion.js +0 -0
  182. /package/dist/cjs/{canvas → Canvas}/utils/General/general functions.d.ts +0 -0
  183. /package/dist/cjs/{canvas → Canvas}/utils/General/general functions.js +0 -0
  184. /package/dist/cjs/{canvas → Canvas}/utils/Texts/textProperties.d.ts +0 -0
  185. /package/dist/cjs/{canvas → Canvas}/utils/Texts/textProperties.js +0 -0
  186. /package/dist/esm/{canvas → Canvas}/utils/Charts/charts.d.ts +0 -0
  187. /package/dist/esm/{canvas → Canvas}/utils/Charts/charts.js +0 -0
  188. /package/dist/esm/{canvas → Canvas}/utils/Custom/customLines.d.ts +0 -0
  189. /package/dist/esm/{canvas → Canvas}/utils/General/conversion.d.ts +0 -0
  190. /package/dist/esm/{canvas → Canvas}/utils/General/conversion.js +0 -0
  191. /package/dist/esm/{canvas → Canvas}/utils/General/general functions.d.ts +0 -0
  192. /package/dist/esm/{canvas → Canvas}/utils/General/general functions.js +0 -0
  193. /package/dist/esm/{canvas → Canvas}/utils/Texts/textProperties.d.ts +0 -0
  194. /package/dist/esm/{canvas → Canvas}/utils/Texts/textProperties.js +0 -0
  195. /package/lib/{canvas → Canvas}/utils/Charts/charts.ts +0 -0
  196. /package/lib/{canvas → Canvas}/utils/General/conversion.ts +0 -0
  197. /package/lib/{canvas → Canvas}/utils/General/general functions.ts +0 -0
  198. /package/lib/{canvas → Canvas}/utils/Texts/textProperties.ts +0 -0
@@ -0,0 +1,382 @@
1
+ import type { SKRSContext2D } from "@napi-rs/canvas";
2
+ import type { borderPosition } from "../types";
3
+
4
+ export function buildPath(
5
+ ctx: SKRSContext2D,
6
+ x: number, y: number, w: number, h: number,
7
+ radius: number | "circular" = 0,
8
+ borderPos: borderPosition = "all"
9
+ ): void {
10
+ ctx.beginPath();
11
+
12
+ if (radius === "circular") {
13
+ const r = Math.min(w, h) / 2;
14
+ ctx.arc(x + w / 2, y + h / 2, r, 0, Math.PI * 2);
15
+ ctx.closePath();
16
+ return;
17
+ }
18
+
19
+ if (!radius || radius <= 0) {
20
+ ctx.rect(x, y, w, h);
21
+ ctx.closePath();
22
+ return;
23
+ }
24
+
25
+ const br = Math.min(radius, w / 2, h / 2);
26
+ const sel = new Set(borderPos.toLowerCase().split(",").map(s => s.trim()));
27
+
28
+ const has = (name: string) =>
29
+ sel.has("all") || sel.has(name) ||
30
+ (name === "top-left" && (sel.has("top") || sel.has("left"))) ||
31
+ (name === "top-right" && (sel.has("top") || sel.has("right"))) ||
32
+ (name === "bottom-right" && (sel.has("bottom") || sel.has("right"))) ||
33
+ (name === "bottom-left" && (sel.has("bottom") || sel.has("left")));
34
+
35
+ const tl = has("top-left") ? br : 0;
36
+ const tr = has("top-right") ? br : 0;
37
+ const brR= has("bottom-right") ? br : 0;
38
+ const bl = has("bottom-left") ? br : 0;
39
+
40
+ ctx.moveTo(x + tl, y);
41
+ ctx.lineTo(x + w - tr, y);
42
+ if (tr) ctx.arcTo(x + w, y, x + w, y + tr, tr);
43
+ ctx.lineTo(x + w, y + h - brR);
44
+ if (brR) ctx.arcTo(x + w, y + h, x + w - brR, y + h, brR);
45
+ ctx.lineTo(x + bl, y + h);
46
+ if (bl) ctx.arcTo(x, y + h, x, y + h - bl, bl);
47
+ ctx.lineTo(x, y + tl);
48
+ if (tl) ctx.arcTo(x, y, x + tl, y, tl);
49
+
50
+ ctx.closePath();
51
+ }
52
+
53
+ export function applyRotation(
54
+ ctx: SKRSContext2D,
55
+ deg: number | undefined,
56
+ x: number, y: number, w: number, h: number
57
+ ) {
58
+ if (!deg) return;
59
+ const cx = x + w / 2, cy = y + h / 2;
60
+ ctx.translate(cx, cy);
61
+ ctx.rotate((deg * Math.PI) / 180);
62
+ ctx.translate(-cx, -cy);
63
+ }
64
+
65
+
66
+ function rotatePoint(
67
+ x: number, y: number, px: number, py: number, deg = 0
68
+ ): [number, number] {
69
+ if (!deg) return [x, y];
70
+ const a = (deg * Math.PI) / 180;
71
+ const dx = x - px, dy = y - py;
72
+ return [px + dx * Math.cos(a) - dy * Math.sin(a),
73
+ py + dx * Math.sin(a) + dy * Math.cos(a)];
74
+ }
75
+
76
+ /**
77
+ * Build a gradient in **rect-local coordinates**:
78
+ * - Defaults for coords use rect {w,h}
79
+ * - Rotation pivot defaults to rect center
80
+ * - Offsets are applied by adding rect.x/rect.y to all points
81
+ */
82
+ export function createGradientFill(
83
+ ctx: SKRSContext2D,
84
+ g: gradient,
85
+ rect: { x: number; y: number; w: number; h: number }
86
+ ): CanvasGradient {
87
+ const { x, y, w, h } = rect;
88
+
89
+ if (g.type === "linear") {
90
+ const {
91
+ startX = 0, startY = 0,
92
+ endX = w, endY = 0,
93
+ rotate = 0,
94
+ pivotX = w / 2, pivotY = h / 2,
95
+ colors
96
+ } = g;
97
+
98
+ const [sx, sy] = rotatePoint(startX, startY, pivotX, pivotY, rotate);
99
+ const [ex, ey] = rotatePoint(endX, endY, pivotX, pivotY, rotate);
100
+
101
+ const grad = ctx.createLinearGradient(x + sx, y + sy, x + ex, y + ey);
102
+ colors.forEach(cs => grad.addColorStop(cs.stop, cs.color));
103
+ return grad;
104
+ }
105
+
106
+ // radial
107
+ const {
108
+ startX = w / 2, startY = h / 2, startRadius = 0,
109
+ endX = w / 2, endY = h / 2, endRadius = Math.max(w, h) / 2,
110
+ rotate = 0,
111
+ pivotX = w / 2, pivotY = h / 2,
112
+ colors
113
+ } = g;
114
+
115
+ const [sx, sy] = rotatePoint(startX, startY, pivotX, pivotY, rotate);
116
+ const [ex, ey] = rotatePoint(endX, endY, pivotX, pivotY, rotate);
117
+
118
+ const grad = ctx.createRadialGradient(
119
+ x + sx, y + sy, startRadius,
120
+ x + ex, y + ey, endRadius
121
+ );
122
+ colors.forEach(cs => grad.addColorStop(cs.stop, cs.color));
123
+ return grad;
124
+ }
125
+
126
+ // utils/imageMath.ts
127
+ import type { AlignMode, FitMode } from "../types";
128
+
129
+ export function fitInto(
130
+ boxX: number, boxY: number, boxW: number, boxH: number,
131
+ imgW: number, imgH: number,
132
+ fit: FitMode = "fill",
133
+ align: AlignMode = "center"
134
+ ) {
135
+ let dx = boxX, dy = boxY, dw = boxW, dh = boxH, sx = 0, sy = 0, sw = imgW, sh = imgH;
136
+
137
+ if (fit === "fill") {
138
+ return { dx, dy, dw, dh, sx, sy, sw, sh };
139
+ }
140
+
141
+ const s = fit === "contain"
142
+ ? Math.min(boxW / imgW, boxH / imgH)
143
+ : Math.max(boxW / imgW, boxH / imgH);
144
+
145
+ dw = imgW * s;
146
+ dh = imgH * s;
147
+
148
+ const cx = boxX + (boxW - dw) / 2;
149
+ const cy = boxY + (boxH - dh) / 2;
150
+
151
+ switch (align) {
152
+ case "top-left": dx = boxX; dy = boxY; break;
153
+ case "top": dx = cx; dy = boxY; break;
154
+ case "top-right": dx = boxX + boxW - dw; dy = boxY; break;
155
+ case "left": dx = boxX; dy = cy; break;
156
+ case "center": dx = cx; dy = cy; break;
157
+ case "right": dx = boxX + boxW - dw; dy = cy; break;
158
+ case "bottom-left": dx = boxX; dy = boxY + boxH - dh; break;
159
+ case "bottom": dx = cx; dy = boxY + boxH - dh; break;
160
+ case "bottom-right": dx = boxX + boxW - dw; dy = boxY + boxH - dh; break;
161
+ default: dx = cx; dy = cy; break;
162
+ }
163
+
164
+ return { dx, dy, dw, dh, sx, sy, sw, sh };
165
+ }
166
+
167
+
168
+ // utils/imageCache.ts
169
+ import { loadImage, type Image } from "@napi-rs/canvas";
170
+ import path from "path";
171
+
172
+ const cache = new Map<string, Promise<Image>>();
173
+
174
+ export function loadImageCached(src: string | Buffer): Promise<Image> {
175
+ if (Buffer.isBuffer(src)) return loadImage(src);
176
+ const key = src.startsWith("http") ? src : path.resolve(process.cwd(), src);
177
+ if (!cache.has(key)) cache.set(key, loadImage(key));
178
+ return cache.get(key)!;
179
+ }
180
+
181
+
182
+ // utils/drawPasses.ts
183
+
184
+ import type { BoxBackground, ShadowOptions, StrokeOptions, gradient } from "../types";
185
+
186
+ /** Shadow pass (independent) — supports solid color or gradient fill */
187
+ // Shared rect type
188
+ type Rect = { x: number; y: number; w: number; h: number };
189
+
190
+ /* ---------------------------------------------
191
+ SHADOW — overloaded to support both call styles
192
+ --------------------------------------------- */
193
+
194
+ // Overload 1: rect-first (new style)
195
+ export function applyShadow(
196
+ ctx: SKRSContext2D,
197
+ rect: Rect,
198
+ shadow?: ShadowOptions
199
+ ): void;
200
+
201
+ // Overload 2: positional (legacy createCanvas style)
202
+ export function applyShadow(
203
+ ctx: SKRSContext2D,
204
+ shadow: ShadowOptions | undefined,
205
+ x: number, y: number, width: number, height: number,
206
+ borderRadius?: number | "circular",
207
+ borderPosition?: borderPosition
208
+ ): void;
209
+
210
+ // Single implementation handling both
211
+ export function applyShadow(
212
+ ctx: SKRSContext2D,
213
+ a: any,
214
+ b?: any,
215
+ c?: any, d?: any, e?: any, f?: any, g?: any
216
+ ): void {
217
+ let rect: Rect;
218
+ let shadow: ShadowOptions | undefined;
219
+ let radius: number | "circular" | undefined;
220
+ let borderPos: borderPosition | undefined;
221
+
222
+ // Detect which overload we’re in
223
+ if (typeof a === "object" && "x" in a && "w" in a) {
224
+ // (ctx, rect, shadow)
225
+ rect = a as Rect;
226
+ shadow = b as ShadowOptions | undefined;
227
+ radius = shadow?.borderRadius ?? 0;
228
+ borderPos = shadow?.borderPosition ?? "all";
229
+ } else {
230
+ // (ctx, shadow, x, y, w, h, radius?, borderPos?)
231
+ shadow = a as ShadowOptions | undefined;
232
+ rect = { x: b as number, y: c as number, w: d as number, h: e as number };
233
+ radius = (f as number | "circular") ?? shadow?.borderRadius ?? 0;
234
+ borderPos = (g as borderPosition) ?? shadow?.borderPosition ?? "all";
235
+ }
236
+
237
+ if (!shadow) return;
238
+
239
+ const {
240
+ color = "rgba(0,0,0,1)",
241
+ gradient,
242
+ opacity = 0.4,
243
+ offsetX = 0,
244
+ offsetY = 0,
245
+ blur = 20
246
+ } = shadow;
247
+
248
+ const r = { x: rect.x + offsetX, y: rect.y + offsetY, w: rect.w, h: rect.h };
249
+
250
+ ctx.save();
251
+ ctx.globalAlpha = opacity;
252
+ if (blur > 0) ctx.filter = `blur(${blur}px)`;
253
+
254
+ buildPath(ctx, r.x, r.y, r.w, r.h, radius!, borderPos!);
255
+
256
+ if (gradient) {
257
+ const gfill = createGradientFill(ctx, gradient, r);
258
+ ctx.fillStyle = gfill;
259
+ } else {
260
+ ctx.fillStyle = color;
261
+ }
262
+ ctx.fill();
263
+
264
+ ctx.filter = "none";
265
+ ctx.globalAlpha = 1;
266
+ ctx.restore();
267
+ }
268
+
269
+
270
+ /* ---------------------------------------------
271
+ STROKE — overloaded to support both call styles
272
+ --------------------------------------------- */
273
+
274
+ // Overload 1: rect-first (new style)
275
+ export function applyStroke(
276
+ ctx: SKRSContext2D,
277
+ rect: Rect,
278
+ stroke?: StrokeOptions
279
+ ): void;
280
+
281
+ // Overload 2: positional (legacy createCanvas style)
282
+ export function applyStroke(
283
+ ctx: SKRSContext2D,
284
+ stroke: StrokeOptions | undefined,
285
+ x: number, y: number, width: number, height: number,
286
+ borderRadius?: number | "circular",
287
+ borderPosition?: borderPosition
288
+ ): void;
289
+
290
+ // Single implementation handling both
291
+ export function applyStroke(
292
+ ctx: SKRSContext2D,
293
+ a: any,
294
+ b?: any,
295
+ c?: any, d?: any, e?: any, f?: any, g?: any
296
+ ): void {
297
+ let rect: Rect;
298
+ let stroke: StrokeOptions | undefined;
299
+ let radius: number | "circular" | undefined;
300
+ let borderPos: borderPosition | undefined;
301
+
302
+ if (typeof a === "object" && "x" in a && "w" in a) {
303
+ // (ctx, rect, stroke)
304
+ rect = a as Rect;
305
+ stroke = b as StrokeOptions | undefined;
306
+ radius = stroke?.borderRadius ?? 0;
307
+ borderPos = stroke?.borderPosition ?? "all";
308
+ } else {
309
+ // (ctx, stroke, x, y, w, h, radius?, borderPos?)
310
+ stroke = a as StrokeOptions | undefined;
311
+ rect = { x: b as number, y: c as number, w: d as number, h: e as number };
312
+ radius = (f as number | "circular") ?? stroke?.borderRadius ?? 0;
313
+ borderPos = (g as borderPosition) ?? stroke?.borderPosition ?? "all";
314
+ }
315
+
316
+ if (!stroke) return;
317
+
318
+ const {
319
+ color = "#000",
320
+ gradient,
321
+ width = 2,
322
+ position = 0,
323
+ blur = 0,
324
+ opacity = 1
325
+ } = stroke;
326
+
327
+ // expand/shrink by `position`
328
+ const r = {
329
+ x: rect.x - position,
330
+ y: rect.y - position,
331
+ w: rect.w + position * 2,
332
+ h: rect.h + position * 2
333
+ };
334
+
335
+ ctx.save();
336
+ if (blur > 0) ctx.filter = `blur(${blur}px)`;
337
+ ctx.globalAlpha = opacity;
338
+
339
+ buildPath(ctx, r.x, r.y, r.w, r.h, radius!, borderPos!);
340
+
341
+ ctx.lineWidth = width;
342
+
343
+ if (gradient) {
344
+ const gstroke = createGradientFill(ctx, gradient, r);
345
+ ctx.strokeStyle = gstroke as any;
346
+ } else {
347
+ ctx.strokeStyle = color;
348
+ }
349
+ ctx.stroke();
350
+
351
+ ctx.filter = "none";
352
+ ctx.globalAlpha = 1;
353
+ ctx.restore();
354
+ }
355
+
356
+ /** Optional “box background” under the bitmap, inside the image clip */
357
+ export function drawBoxBackground(
358
+ ctx: SKRSContext2D,
359
+ rect: { x: number; y: number; w: number; h: number },
360
+ boxBg?: BoxBackground,
361
+ borderRadius?: number | "circular",
362
+ borderPosition?: string
363
+ ) {
364
+ if (!boxBg) return;
365
+ const { color, gradient } = boxBg;
366
+
367
+ // clip to the box radius, then fill
368
+ ctx.save();
369
+ buildPath(ctx, rect.x, rect.y, rect.w, rect.h, borderRadius ?? 0, borderPosition ?? "all");
370
+ ctx.clip();
371
+
372
+ if (gradient) {
373
+ const g = createGradientFill(ctx, gradient, rect);
374
+ ctx.fillStyle = g as any;
375
+ ctx.fillRect(rect.x, rect.y, rect.w, rect.h);
376
+ } else if (color && color !== "transparent") {
377
+ ctx.fillStyle = color;
378
+ ctx.fillRect(rect.x, rect.y, rect.w, rect.h);
379
+ }
380
+
381
+ ctx.restore();
382
+ }