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
@@ -1,835 +0,0 @@
1
- import { Image, 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
- );
38
-
39
- ctx.fillStyle = shadow.gradient
40
- ? createGradient(
41
- ctx, shadow.gradient,
42
- shadowX, shadowY,
43
- shadowX + width, shadowY + height
44
- )
45
- : shadow.color || "transparent";
46
- ctx.fill();
47
- }
48
-
49
- ctx.filter = "none";
50
- ctx.globalAlpha = 1;
51
- ctx.restore();
52
- }
53
-
54
- /**
55
- * Applies zoom (scaling) to the canvas context around a specified point.
56
- * @param ctx The canvas rendering context.
57
- * @param zoom An object with scale (zoom factor) and the x/y coordinates that act as the zoom origin.
58
- */
59
- export function applyZoom(
60
- ctx: SKRSContext2D,
61
- zoom?: { scale?: number; x?: number; y?: number }
62
- ): void {
63
- if (!zoom) return;
64
- const scale = zoom.scale ?? 1;
65
- const zoomX = zoom.x ?? 0;
66
- const zoomY = zoom.y ?? 0;
67
-
68
- ctx.translate(zoomX, zoomY);
69
- ctx.scale(scale, scale);
70
- ctx.translate(-zoomX, -zoomY);
71
- }
72
-
73
-
74
- /**
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.
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
- ): void {
95
- if (!stroke) return;
96
-
97
- ctx.save();
98
-
99
- if (stroke.blur && stroke.blur > 0) {
100
- ctx.filter = `blur(${stroke.blur}px)`;
101
- }
102
-
103
- ctx.strokeStyle = stroke.gradient
104
- ? createGradient(ctx, stroke.gradient, x, y, x + width, y + height)
105
- : stroke.color || "transparent";
106
-
107
- ctx.lineWidth = stroke.width && stroke.width > 0 ? stroke.width : 2;
108
-
109
- ctx.beginPath();
110
- const borderPos = stroke.position || 0;
111
-
112
- // Adjust the bounding box by borderPos
113
- // - Positive borderPos moves stroke outward
114
- // - Negative borderPos moves stroke inward
115
- const offsetX = x - borderPos;
116
- const offsetY = y - borderPos;
117
- const offsetW = width + 2 * borderPos;
118
- const offsetH = height + 2 * borderPos;
119
-
120
- ctx.beginPath();
121
-
122
- // For known shapes (circle, star, etc.), re-draw with adjusted bounding box
123
- if (
124
- [
125
- "heart", "arrow", "circle", "star",
126
- "pentagon", "hexagon", "heptagon", "octagon",
127
- "diamond", "trapezoid", "kite",
128
- ].includes(shapeName as string)
129
- ) {
130
- switch (shapeName) {
131
- case "circle":
132
- // Circle centered in the new bounding box
133
- ctx.arc(
134
- offsetX + offsetW / 2,
135
- offsetY + offsetH / 2,
136
- offsetW / 2, // radius
137
- 0,
138
- Math.PI * 2
139
- );
140
- break;
141
-
142
- case "star":
143
- drawStar(ctx, offsetX, offsetY, offsetW, offsetH);
144
- break;
145
-
146
- case "arrow":
147
- drawArrow(ctx, offsetX, offsetY, offsetW, offsetH);
148
- break;
149
-
150
- case "pentagon":
151
- case "hexagon":
152
- case "heptagon":
153
- case "octagon": {
154
- const sides = parseInt(shapeName.replace(/\D/g, ""), 10);
155
- drawPolygon(ctx, offsetX, offsetY, offsetW, offsetH, sides);
156
- break;
157
- }
158
-
159
- case "diamond":
160
- ctx.moveTo(offsetX + offsetW / 2, offsetY);
161
- ctx.lineTo(offsetX + offsetW, offsetY + offsetH / 2);
162
- ctx.lineTo(offsetX + offsetW / 2, offsetY + offsetH);
163
- ctx.lineTo(offsetX, offsetY + offsetH / 2);
164
- ctx.closePath();
165
- break;
166
-
167
- case "trapezoid": {
168
- const topWidth = offsetW * 0.6;
169
- const offsetVal = (offsetW - topWidth) / 2;
170
- ctx.moveTo(offsetX + offsetVal, offsetY);
171
- ctx.lineTo(offsetX + offsetVal + topWidth, offsetY);
172
- ctx.lineTo(offsetX + offsetW, offsetY + offsetH);
173
- ctx.lineTo(offsetX, offsetY + offsetH);
174
- ctx.closePath();
175
- break;
176
- }
177
-
178
- case "heart":
179
- drawHeart(ctx, offsetX, offsetY, offsetW, offsetH);
180
- break;
181
-
182
- case "kite":
183
- ctx.moveTo(offsetX + offsetW / 2, offsetY);
184
- ctx.lineTo(offsetX + offsetW, offsetY + offsetH / 2);
185
- ctx.lineTo(offsetX + offsetW / 2, offsetY + offsetH);
186
- ctx.lineTo(offsetX, offsetY + offsetH / 2);
187
- ctx.closePath();
188
- break;
189
- }
190
- } else {
191
- ctx.globalCompositeOperation = "source-atop";
192
- objectRadius(ctx, offsetX, offsetY, offsetW, offsetH, stroke.borderRadius || 2, stroke.borderPosition);
193
- }
194
-
195
- ctx.stroke();
196
- ctx.filter = "none";
197
- ctx.restore();
198
- }
199
-
200
-
201
-
202
- export function drawShape(ctx: SKRSContext2D, shapeSettings: any): void {
203
- const {
204
- source,
205
- x,
206
- y,
207
- width,
208
- height,
209
- opacity,
210
- rotation = 0,
211
- borderRadius = 0,
212
- borderPosition = 'all',
213
- stroke,
214
- shadow,
215
- isFilled = false,
216
- color = "transparent",
217
- gradient,
218
- filling,
219
- } = shapeSettings;
220
-
221
- const shapeName = source.toLowerCase();
222
- ctx.save();
223
-
224
- applyRotation(ctx, rotation, x, y, width, height);
225
- applyShadow(ctx, shadow, x, y, width, height);
226
-
227
- ctx.beginPath();
228
-
229
- ctx.globalAlpha = opacity as number;
230
-
231
- switch (shapeName) {
232
- case 'circle': {
233
- ctx.arc(x + width / 2, y + height / 2, width / 2, 0, Math.PI * 2);
234
- break;
235
- }
236
- case 'square': {
237
- ctx.rect(x, y, width, height);
238
- break;
239
- }
240
- case 'triangle': {
241
- ctx.moveTo(x + width / 2, y);
242
- ctx.lineTo(x, y + height);
243
- ctx.lineTo(x + width, y + height);
244
- ctx.closePath();
245
- break;
246
- }
247
- case 'pentagon': case 'hexagon': case 'heptagon': case 'octagon': {
248
- const sides = parseInt(shapeName.replace(/\D/g, ""), 10);
249
- drawPolygon(ctx, x, y, width, height, sides);
250
- break;
251
- }
252
- case 'star': {
253
- drawStar(ctx, x, y, width, height);
254
- break;
255
- }
256
- case 'kite': {
257
- ctx.moveTo(x + width / 2, y);
258
- ctx.lineTo(x + width, y + height / 2);
259
- ctx.lineTo(x + width / 2, y + height);
260
- ctx.lineTo(x, y + height / 2);
261
- ctx.closePath();
262
- break;
263
- }
264
- case 'oval': {
265
- ctx.ellipse(x + width / 2, y + height / 2, width / 2, height / 2, 0, 0, Math.PI * 2);
266
- break;
267
- }
268
- case 'arrow': {
269
- drawArrow(ctx, x, y, width, height);
270
- break;
271
- }
272
- case 'heart': {
273
- drawHeart(ctx, x, y, width, height);
274
- break;
275
- }
276
- case 'diamond': {
277
- ctx.moveTo(x + width / 2, y);
278
- ctx.lineTo(x + width, y + height / 2);
279
- ctx.lineTo(x + width / 2, y + height);
280
- ctx.lineTo(x, y + height / 2);
281
- ctx.closePath();
282
- break;
283
- }
284
- case 'trapezoid': {
285
- const topWidth = width * 0.6;
286
- const offset = (width - topWidth) / 2;
287
- ctx.moveTo(x + offset, y);
288
- ctx.lineTo(x + offset + topWidth, y);
289
- ctx.lineTo(x + width, y + height);
290
- ctx.lineTo(x, y + height);
291
- ctx.closePath();
292
- break;
293
- }
294
- default: {
295
- ctx.restore();
296
- throw new Error(`Unsupported shape: ${shapeName}`);
297
- }
298
- }
299
-
300
- if (isFilled) {
301
- if (borderRadius && shapeName !== 'circle' && shapeName !== 'oval') {
302
- objectRadius(ctx, x, y, width, height, borderRadius, borderPosition);
303
- }
304
-
305
- let fillStyle: string | CanvasGradient = color;
306
-
307
- if (gradient) {
308
- fillStyle = createGradient(ctx, gradient, x, y, x + width, y + height);
309
- }
310
-
311
- if (filling && filling.percentage <= 100) {
312
- ctx.save();
313
-
314
- const isCustomShape = ["heart", "arrow", "star", "pentagon", "hexagon", "heptagon", "octagon", "diamond", "trapezoid", "kite", "oval", "circle"].includes(shapeName);
315
-
316
- if (isCustomShape) {
317
- ctx.clip();
318
- }
319
-
320
- let fillX = x;
321
- let fillY = y;
322
- let fillWidth = width;
323
- let fillHeight = height;
324
-
325
- switch (filling.rotation) {
326
- case 0:
327
- fillHeight = (filling.percentage / 100) * height;
328
- fillY = y + height - fillHeight;
329
- break;
330
-
331
- case 180:
332
- fillHeight = (filling.percentage / 100) * height;
333
- break;
334
-
335
- case 90:
336
- fillWidth = (filling.percentage / 100) * width;
337
- break;
338
-
339
- case 270:
340
- fillWidth = (filling.percentage / 100) * width;
341
- fillX = x + width - fillWidth;
342
- break;
343
-
344
- default:
345
- console.warn(`Unsupported filling rotation: ${filling.rotation}, defaulting to 0 (Bottom to Top).`);
346
- fillHeight = (filling.percentage / 100) * height;
347
- fillY = y + height - fillHeight;
348
- }
349
-
350
- ctx.beginPath();
351
- ctx.rect(fillX, fillY, fillWidth, fillHeight);
352
- ctx.fillStyle = fillStyle;
353
- ctx.fill();
354
-
355
- ctx.restore();
356
- } else {
357
- ctx.fillStyle = fillStyle;
358
- ctx.fill();
359
- }
360
- }
361
-
362
- ctx.globalAlpha = 1.0;
363
-
364
- if (stroke) {
365
- if (stroke?.opacity) ctx.globalAlpha = stroke.opacity as number;
366
- applyStroke(ctx, stroke, x, y, width, height, shapeName);
367
- ctx.globalAlpha = 1.0;
368
- }
369
-
370
- ctx.restore();
371
- }
372
-
373
- function drawHeart(ctx: SKRSContext2D, x: number, y: number, width: number, height: number): void {
374
- ctx.beginPath();
375
-
376
- ctx.moveTo(x + width / 2, y + height * 0.9);
377
-
378
- ctx.bezierCurveTo(
379
- x + (width * 35) / 100, y + (height * 60) / 100,
380
- x + (width * 10) / 100, y + (height * 55) / 100,
381
- x + (width * 10) / 100, y + (height * 33.33) / 100
382
- );
383
-
384
- ctx.bezierCurveTo(
385
- x + (width * 10) / 100, y + (height * 10) / 100,
386
- x + (width * 50) / 100, y + (height * 5) / 100,
387
- x + (width * 50) / 100, y + (height * 33.33) / 100
388
- );
389
-
390
- ctx.bezierCurveTo(
391
- x + (width * 50) / 100, y + (height * 5) / 100,
392
- x + (width * 90) / 100, y + (height * 10) / 100,
393
- x + (width * 90) / 100, y + (height * 33.33) / 100
394
- );
395
-
396
- ctx.bezierCurveTo(
397
- x + (width * 90) / 100, y + (height * 55) / 100,
398
- x + (width * 65) / 100, y + (height * 60) / 100,
399
- x + width / 2, y + height * 0.9
400
- );
401
-
402
- ctx.closePath();
403
- }
404
-
405
-
406
- /** Draws a polygon with a given number of sides */
407
- function drawPolygon(ctx: SKRSContext2D, x: number, y: number, width: number, height: number, sides: number): void {
408
- const cx = x + width / 2;
409
- const cy = y + height / 2;
410
- const radius = Math.min(width, height) / 2;
411
- ctx.moveTo(cx + radius, cy);
412
- for (let i = 1; i <= sides; i++) {
413
- const angle = (Math.PI * 2 * i) / sides;
414
- ctx.lineTo(cx + radius * Math.cos(angle), cy + radius * Math.sin(angle));
415
- }
416
- ctx.closePath();
417
- }
418
-
419
- function drawArrow(ctx: SKRSContext2D, x: number, y: number, width: number, height: number) {
420
- const shaftWidth = width * 0.25;
421
- const headWidth = width * 0.5;
422
- const headHeight = height * 0.6;
423
-
424
- ctx.beginPath();
425
-
426
- ctx.moveTo(x, y + height / 2 - shaftWidth / 2);
427
- ctx.lineTo(x + width - headWidth, y + height / 2 - shaftWidth / 2);
428
- ctx.lineTo(x + width - headWidth, y);
429
-
430
- ctx.lineTo(x + width, y + height / 2);
431
-
432
- ctx.lineTo(x + width - headWidth, y + height);
433
- ctx.lineTo(x + width - headWidth, y + height / 2 + shaftWidth / 2);
434
-
435
- ctx.lineTo(x, y + height / 2 + shaftWidth / 2);
436
- ctx.closePath();
437
- }
438
-
439
-
440
- function drawStar(ctx: SKRSContext2D, x: number, y: number, width: number, height: number): void {
441
- const cx = x + width / 2;
442
- const cy = y + height / 2;
443
-
444
- const size = Math.min(width, height);
445
-
446
- const outerRadius = size / 2;
447
- const innerRadius = outerRadius * 0.5;
448
- const rotationOffset = -Math.PI / 2;
449
-
450
- ctx.beginPath();
451
-
452
- for (let i = 0; i < 5; i++) {
453
- let angle = (i * (Math.PI * 2)) / 5 + rotationOffset;
454
- ctx.lineTo(cx + outerRadius * Math.cos(angle), cy + outerRadius * Math.sin(angle));
455
-
456
- angle += Math.PI / 5;
457
- ctx.lineTo(cx + innerRadius * Math.cos(angle), cy + innerRadius * Math.sin(angle));
458
- }
459
-
460
- ctx.closePath();
461
- }
462
-
463
- export function createGradient(
464
- ctx: any,
465
- gradientOptions: any,
466
- startX: number,
467
- startY: number,
468
- endX: number,
469
- endY: number
470
- ) {
471
- if (!gradientOptions || !gradientOptions.type || !gradientOptions.colors) {
472
- throw new Error(
473
- "Invalid gradient options. Provide a valid object with type and colors properties."
474
- );
475
- }
476
-
477
- if (!Array.isArray(gradientOptions.colors)) {
478
- throw new Error(
479
- "Invalid gradient options. The colors property should be an array of color stops."
480
- );
481
- }
482
-
483
- if (gradientOptions.type === "linear") {
484
- if (
485
- typeof startX !== "number" ||
486
- typeof startY !== "number" ||
487
- typeof endX !== "number" ||
488
- typeof endY !== "number"
489
- ) {
490
- throw new Error(
491
- "Invalid gradient options for linear gradient. Numeric values are required for startX, startY, endX, and endY."
492
- );
493
- }
494
-
495
- if (typeof gradientOptions.rotate === "number") {
496
- const centerX = (startX + endX) / 2;
497
- const centerY = (startY + endY) / 2;
498
- const dx = endX - startX;
499
- const dy = endY - startY;
500
- const length = Math.sqrt(dx * dx + dy * dy);
501
- const angleRad = (gradientOptions.rotate * Math.PI) / 180;
502
-
503
- startX = centerX - (length / 2) * Math.cos(angleRad);
504
- startY = centerY - (length / 2) * Math.sin(angleRad);
505
- endX = centerX + (length / 2) * Math.cos(angleRad);
506
- endY = centerY + (length / 2) * Math.sin(angleRad);
507
- }
508
-
509
- const gradient = ctx.createLinearGradient(startX, startY, endX, endY);
510
-
511
- for (const colorStop of gradientOptions.colors) {
512
- if (
513
- typeof colorStop.stop !== "number" ||
514
- typeof colorStop.color !== "string"
515
- ) {
516
- throw new Error(
517
- "Invalid color stop. Each color stop should have a numeric stop value and a color string."
518
- );
519
- }
520
- gradient.addColorStop(colorStop.stop, colorStop.color);
521
- }
522
-
523
- return gradient;
524
- } else if (gradientOptions.type === "radial") {
525
- if (
526
- typeof gradientOptions.startX !== "number" ||
527
- typeof gradientOptions.startY !== "number" ||
528
- typeof gradientOptions.startRadius !== "number" ||
529
- typeof gradientOptions.endX !== "number" ||
530
- typeof gradientOptions.endY !== "number" ||
531
- typeof gradientOptions.endRadius !== "number"
532
- ) {
533
- throw new Error(
534
- "Invalid gradient options for radial gradient. Numeric values are required for startX, startY, startRadius, endX, endY, and endRadius."
535
- );
536
- }
537
-
538
- const gradient = ctx.createRadialGradient(
539
- gradientOptions.startX,
540
- gradientOptions.startY,
541
- gradientOptions.startRadius,
542
- gradientOptions.endX,
543
- gradientOptions.endY,
544
- gradientOptions.endRadius
545
- );
546
-
547
- for (const colorStop of gradientOptions.colors) {
548
- if (
549
- typeof colorStop.stop !== "number" ||
550
- typeof colorStop.color !== "string"
551
- ) {
552
- throw new Error(
553
- "Invalid color stop. Each color stop should have a numeric stop value and a color string."
554
- );
555
- }
556
- gradient.addColorStop(colorStop.stop, colorStop.color);
557
- }
558
-
559
- return gradient;
560
- } else {
561
- throw new Error('Unsupported gradient type. Use "linear" or "radial".');
562
- }
563
- }
564
-
565
-
566
- /**
567
- * Applies rotation to the canvas context.
568
- * @param ctx The canvas rendering context.
569
- * @param rotation The rotation angle in degrees.
570
- * @param x The x-coordinate of the center of rotation.
571
- * @param y The y-coordinate of the center of rotation.
572
- * @param width The width of the shape.
573
- * @param height The height of the shape.
574
- */
575
- export function applyRotation(
576
- ctx: SKRSContext2D,
577
- rotation: number,
578
- x: number,
579
- y: number,
580
- width: number,
581
- height: number
582
- ): void {
583
- const rotationX = x + width / 2;
584
- const rotationY = y + height / 2;
585
- ctx.translate(rotationX, rotationY);
586
- ctx.rotate((rotation * Math.PI) / 180);
587
- ctx.translate(-rotationX, -rotationY);
588
- }
589
-
590
- /**
591
- * Applies border radius to the canvas context with selective corner support.
592
- *
593
- * @param ctx The canvas rendering context.
594
- * @param image The image to be drawn (will be drawn after clipping).
595
- * @param x The x-coordinate of the shape.
596
- * @param y The y-coordinate of the shape.
597
- * @param width The width of the shape.
598
- * @param height The height of the shape.
599
- * @param borderRadius The border radius value (number or "circular").
600
- * @param borderPosition The sides or corners to round.
601
- * Valid values include:
602
- * - "all"
603
- * - "top", "bottom", "left", "right"
604
- * - "top-left", "top-right", "bottom-left", "bottom-right"
605
- * - Or a comma‑separated list (e.g., "top, left, bottom")
606
- */
607
- export function imageRadius(
608
- ctx: SKRSContext2D,
609
- image: any,
610
- x: number,
611
- y: number,
612
- width: number,
613
- height: number,
614
- borderRadius: number | "circular",
615
- borderPosition: string = "all"
616
- ): void {
617
- ctx.save();
618
- ctx.beginPath();
619
-
620
- if (borderRadius === "circular") {
621
- const circleRadius = Math.min(width, height) / 2;
622
- ctx.arc(x + width / 2, y + height / 2, circleRadius, 0, 2 * Math.PI);
623
- ctx.clip();
624
- } else if (typeof borderRadius === "number" && borderRadius > 0) {
625
- const br: number = Math.min(borderRadius, width / 2, height / 2);
626
- const selectedPositions = new Set(borderPosition.toLowerCase().split(",").map((s) => s.trim()));
627
-
628
- const roundTopLeft = selectedPositions.has("all") || selectedPositions.has("top-left") || (selectedPositions.has("top") && selectedPositions.has("left"));
629
- const roundTopRight = selectedPositions.has("all") || selectedPositions.has("top-right") || (selectedPositions.has("top") && selectedPositions.has("right"));
630
- const roundBottomRight = selectedPositions.has("all") || selectedPositions.has("bottom-right") || (selectedPositions.has("bottom") && selectedPositions.has("right"));
631
- const roundBottomLeft = selectedPositions.has("all") || selectedPositions.has("bottom-left") || (selectedPositions.has("bottom") && selectedPositions.has("left"));
632
-
633
- const tl = roundTopLeft ? br : 0;
634
- const tr = roundTopRight ? br : 0;
635
- const brR = roundBottomRight ? br : 0;
636
- const bl = roundBottomLeft ? br : 0;
637
-
638
- ctx.moveTo(x + tl, y);
639
- ctx.lineTo(x + width - tr, y);
640
- if (tr > 0) ctx.arc(x + width - tr, y + tr, tr, -Math.PI / 2, 0, false);
641
- ctx.lineTo(x + width, y + height - brR);
642
- if (brR > 0) ctx.arc(x + width - brR, y + height - brR, brR, 0, Math.PI / 2, false);
643
- ctx.lineTo(x + bl, y + height);
644
- if (bl > 0) ctx.arc(x + bl, y + height - bl, bl, Math.PI / 2, Math.PI, false);
645
- ctx.lineTo(x, y + tl);
646
- if (tl > 0) ctx.arc(x + tl, y + tl, tl, Math.PI, -Math.PI / 2, false);
647
-
648
- ctx.closePath();
649
- ctx.clip();
650
- } else {
651
- ctx.rect(x, y, width, height);
652
- ctx.clip();
653
- }
654
-
655
- ctx.drawImage(image, x, y, width, height);
656
-
657
- ctx.restore();
658
- }
659
-
660
-
661
-
662
- /**
663
- * Creates a rounded rectangle (or circular) path on the canvas context.
664
- *
665
- * @param ctx The canvas rendering context.
666
- * @param x The x-coordinate of the rectangle.
667
- * @param y The y-coordinate of the rectangle.
668
- * @param width The width of the rectangle.
669
- * @param height The height of the rectangle.
670
- * @param borderRadius The radius for rounding. Use a number (or string "circular" for a circle).
671
- * @param borderPosition Which sides/corners to round. Valid values include:
672
- * - "all" (default)
673
- * - "top", "bottom", "left", "right"
674
- * - "top-left", "top-right", "bottom-left", "bottom-right"
675
- * - Or a comma-separated list, e.g. "top-left, bottom-right" or "top, left, bottom"
676
- */
677
- export function objectRadius(
678
- ctx: SKRSContext2D,
679
- x: number,
680
- y: number,
681
- width: number,
682
- height: number,
683
- borderRadius: number | "circular" = 0.1,
684
- borderPosition: string = "all"
685
- ): void {
686
- ctx.beginPath();
687
-
688
- if (borderRadius === "circular") {
689
- // Draw a circular shape
690
- const circleRadius = Math.min(width, height) / 2;
691
- ctx.arc(x + width / 2, y + height / 2, circleRadius, 0, 2 * Math.PI);
692
- } else if (borderRadius > 0) {
693
- const br: number = Math.min(borderRadius, width / 2, height / 2);
694
- const selectedPositions = new Set(
695
- borderPosition.toLowerCase().split(",").map((s) => s.trim())
696
- );
697
-
698
- // **Correct Grouping**
699
- const roundTopLeft = selectedPositions.has("all") ||
700
- selectedPositions.has("top-left") ||
701
- selectedPositions.has("top") ||
702
- selectedPositions.has("left");
703
-
704
- const roundTopRight = selectedPositions.has("all") ||
705
- selectedPositions.has("top-right") ||
706
- selectedPositions.has("top") ||
707
- selectedPositions.has("right");
708
-
709
- const roundBottomRight = selectedPositions.has("all") ||
710
- selectedPositions.has("bottom-right") ||
711
- selectedPositions.has("bottom") ||
712
- selectedPositions.has("right");
713
-
714
- const roundBottomLeft = selectedPositions.has("all") ||
715
- selectedPositions.has("bottom-left") ||
716
- selectedPositions.has("bottom") ||
717
- selectedPositions.has("left");
718
-
719
- // **Assign correct radii**
720
- const tl = roundTopLeft ? br : 0;
721
- const tr = roundTopRight ? br : 0;
722
- const brR = roundBottomRight ? br : 0;
723
- const bl = roundBottomLeft ? br : 0;
724
-
725
- // **Draw rounded rectangle**
726
- ctx.moveTo(x + tl, y);
727
- ctx.lineTo(x + width - tr, y);
728
- if (tr > 0) ctx.arc(x + width - tr, y + tr, tr, -Math.PI / 2, 0, false);
729
- ctx.lineTo(x + width, y + height - brR);
730
- if (brR > 0) ctx.arc(x + width - brR, y + height - brR, brR, 0, Math.PI / 2, false);
731
- ctx.lineTo(x + bl, y + height);
732
- if (bl > 0) ctx.arc(x + bl, y + height - bl, bl, Math.PI / 2, Math.PI, false);
733
- ctx.lineTo(x, y + tl);
734
- if (tl > 0) ctx.arc(x + tl, y + tl, tl, Math.PI, -Math.PI / 2, false);
735
- } else {
736
- // Default: Draw normal rectangle
737
- ctx.rect(x, y, width, height);
738
- }
739
-
740
- ctx.closePath();
741
- }
742
-
743
-
744
-
745
- /**
746
- * Performs bilinear interpolation on four corners.
747
- * @param corners The four corners (topLeft, topRight, bottomRight, bottomLeft).
748
- * @param t Horizontal interpolation factor (0 to 1).
749
- * @param u Vertical interpolation factor (0 to 1).
750
- * @returns The interpolated point.
751
- */
752
- function bilinearInterpolate(corners: [{ x: number, y: number }, { x: number, y: number }, { x: number, y: number }, { x: number, y: number }], t: number, u: number): { x: number, y: number } {
753
- const top: { x: number, y: number } = {
754
- x: corners[0].x * (1 - t) + corners[1].x * t,
755
- y: corners[0].y * (1 - t) + corners[1].y * t,
756
- };
757
- const bottom: { x: number, y: number } = {
758
- x: corners[3].x * (1 - t) + corners[2].x * t,
759
- y: corners[3].y * (1 - t) + corners[2].y * t,
760
- };
761
- return {
762
- x: top.x * (1 - u) + bottom.x * u,
763
- y: top.y * (1 - u) + bottom.y * u,
764
- };
765
- }
766
-
767
- /**
768
- * Applies a perspective warp to the given image by subdividing the source rectangle
769
- * and drawing each cell with an affine transform approximating the local perspective.
770
- *
771
- * @param ctx The canvas rendering context.
772
- * @param image The source image.
773
- * @param x The x-coordinate where the image is drawn.
774
- * @param y The y-coordinate where the image is drawn.
775
- * @param width The width of the region to draw.
776
- * @param height The height of the region to draw.
777
- * @param perspective An object containing four destination corners:
778
- * { topLeft, topRight, bottomRight, bottomLeft }.
779
- * @param gridCols Number of columns to subdivide (default: 10).
780
- * @param gridRows Number of rows to subdivide (default: 10).
781
- */
782
- export async function applyPerspective(
783
- ctx: SKRSContext2D,
784
- image: Image,
785
- x: number,
786
- y: number,
787
- width: number,
788
- height: number,
789
- perspective: { topLeft: { x: number, y: number }; topRight: { x: number, y: number }; bottomRight: { x: number, y: number }; bottomLeft: { x: number, y: number }; },
790
- gridCols: number = 10,
791
- gridRows: number = 10
792
- ): Promise<void> {
793
- const cellWidth = width / gridCols;
794
- const cellHeight = height / gridRows;
795
-
796
- for (let row = 0; row < gridRows; row++) {
797
- for (let col = 0; col < gridCols; col++) {
798
- const sx = x + col * cellWidth;
799
- const sy = y + row * cellHeight;
800
-
801
- const t0 = col / gridCols;
802
- const t1 = (col + 1) / gridCols;
803
- const u0 = row / gridRows;
804
- const u1 = (row + 1) / gridRows;
805
-
806
- const destTL = bilinearInterpolate(
807
- [perspective.topLeft, perspective.topRight, perspective.bottomRight, perspective.bottomLeft],
808
- t0,
809
- u0
810
- );
811
- const destTR = bilinearInterpolate(
812
- [perspective.topLeft, perspective.topRight, perspective.bottomRight, perspective.bottomLeft],
813
- t1,
814
- u0
815
- );
816
- const destBL = bilinearInterpolate(
817
- [perspective.topLeft, perspective.topRight, perspective.bottomRight, perspective.bottomLeft],
818
- t0,
819
- u1
820
- );
821
-
822
- const a = (destTR.x - destTL.x) / cellWidth;
823
- const b = (destTR.y - destTL.y) / cellWidth;
824
- const c = (destBL.x - destTL.x) / cellHeight;
825
- const d = (destBL.y - destTL.y) / cellHeight;
826
- const e = destTL.x;
827
- const f = destTL.y;
828
-
829
- ctx.save();
830
- ctx.setTransform(a, b, c, d, e, f);
831
- ctx.drawImage(image, sx, sy, cellWidth, cellHeight, 0, 0, cellWidth, cellHeight);
832
- ctx.restore();
833
- }
834
- }
835
- }