apexify.js 5.1.1 → 5.2.1

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 (236) hide show
  1. package/CHANGELOG.md +240 -0
  2. package/README.md +244 -1101
  3. package/dist/cjs/Canvas/ApexPainter.d.ts +183 -204
  4. package/dist/cjs/Canvas/ApexPainter.d.ts.map +1 -1
  5. package/dist/cjs/Canvas/ApexPainter.js +524 -1282
  6. package/dist/cjs/Canvas/ApexPainter.js.map +1 -1
  7. package/dist/cjs/Canvas/extended/CanvasCreator.d.ts +33 -0
  8. package/dist/cjs/Canvas/extended/CanvasCreator.d.ts.map +1 -0
  9. package/dist/cjs/Canvas/extended/CanvasCreator.js +223 -0
  10. package/dist/cjs/Canvas/extended/CanvasCreator.js.map +1 -0
  11. package/dist/cjs/Canvas/extended/ChartCreator.d.ts +26 -0
  12. package/dist/cjs/Canvas/extended/ChartCreator.d.ts.map +1 -0
  13. package/dist/cjs/Canvas/extended/ChartCreator.js +50 -0
  14. package/dist/cjs/Canvas/extended/ChartCreator.js.map +1 -0
  15. package/dist/cjs/Canvas/extended/GIFCreator.d.ts +43 -0
  16. package/dist/cjs/Canvas/extended/GIFCreator.d.ts.map +1 -0
  17. package/dist/cjs/Canvas/extended/GIFCreator.js +157 -0
  18. package/dist/cjs/Canvas/extended/GIFCreator.js.map +1 -0
  19. package/dist/cjs/Canvas/extended/ImageCreator.d.ts +83 -0
  20. package/dist/cjs/Canvas/extended/ImageCreator.d.ts.map +1 -0
  21. package/dist/cjs/Canvas/extended/ImageCreator.js +479 -0
  22. package/dist/cjs/Canvas/extended/ImageCreator.js.map +1 -0
  23. package/dist/cjs/Canvas/extended/TextCreator.d.ts +35 -0
  24. package/dist/cjs/Canvas/extended/TextCreator.d.ts.map +1 -0
  25. package/dist/cjs/Canvas/extended/TextCreator.js +98 -0
  26. package/dist/cjs/Canvas/extended/TextCreator.js.map +1 -0
  27. package/dist/cjs/Canvas/extended/VideoCreator.d.ts +370 -0
  28. package/dist/cjs/Canvas/extended/VideoCreator.d.ts.map +1 -0
  29. package/dist/cjs/Canvas/extended/VideoCreator.js +478 -0
  30. package/dist/cjs/Canvas/extended/VideoCreator.js.map +1 -0
  31. package/dist/cjs/Canvas/utils/Background/bg.d.ts +1 -1
  32. package/dist/cjs/Canvas/utils/Background/bg.d.ts.map +1 -1
  33. package/dist/cjs/Canvas/utils/Background/bg.js +43 -7
  34. package/dist/cjs/Canvas/utils/Background/bg.js.map +1 -1
  35. package/dist/cjs/Canvas/utils/Charts/barchart.d.ts +230 -0
  36. package/dist/cjs/Canvas/utils/Charts/barchart.d.ts.map +1 -0
  37. package/dist/cjs/Canvas/utils/Charts/barchart.js +1891 -0
  38. package/dist/cjs/Canvas/utils/Charts/barchart.js.map +1 -0
  39. package/dist/cjs/Canvas/utils/Charts/comparisonchart.d.ts +103 -0
  40. package/dist/cjs/Canvas/utils/Charts/comparisonchart.d.ts.map +1 -0
  41. package/dist/cjs/Canvas/utils/Charts/comparisonchart.js +368 -0
  42. package/dist/cjs/Canvas/utils/Charts/comparisonchart.js.map +1 -0
  43. package/dist/cjs/Canvas/utils/Charts/horizontalbarchart.d.ts +181 -0
  44. package/dist/cjs/Canvas/utils/Charts/horizontalbarchart.d.ts.map +1 -0
  45. package/dist/cjs/Canvas/utils/Charts/horizontalbarchart.js +1389 -0
  46. package/dist/cjs/Canvas/utils/Charts/horizontalbarchart.js.map +1 -0
  47. package/dist/cjs/Canvas/utils/Charts/index.d.ts +45 -0
  48. package/dist/cjs/Canvas/utils/Charts/index.d.ts.map +1 -0
  49. package/dist/cjs/Canvas/utils/Charts/index.js +17 -0
  50. package/dist/cjs/Canvas/utils/Charts/index.js.map +1 -0
  51. package/dist/cjs/Canvas/utils/Charts/linechart.d.ts +216 -0
  52. package/dist/cjs/Canvas/utils/Charts/linechart.d.ts.map +1 -0
  53. package/dist/cjs/Canvas/utils/Charts/linechart.js +1761 -0
  54. package/dist/cjs/Canvas/utils/Charts/linechart.js.map +1 -0
  55. package/dist/cjs/Canvas/utils/Charts/piechart.d.ts +167 -0
  56. package/dist/cjs/Canvas/utils/Charts/piechart.d.ts.map +1 -0
  57. package/dist/cjs/Canvas/utils/Charts/piechart.js +794 -0
  58. package/dist/cjs/Canvas/utils/Charts/piechart.js.map +1 -0
  59. package/dist/cjs/Canvas/utils/General/batchOperations.d.ts.map +1 -1
  60. package/dist/cjs/Canvas/utils/General/batchOperations.js +3 -4
  61. package/dist/cjs/Canvas/utils/General/batchOperations.js.map +1 -1
  62. package/dist/cjs/Canvas/utils/General/general functions.d.ts.map +1 -1
  63. package/dist/cjs/Canvas/utils/General/general functions.js +62 -33
  64. package/dist/cjs/Canvas/utils/General/general functions.js.map +1 -1
  65. package/dist/cjs/Canvas/utils/General/imageStitching.d.ts.map +1 -1
  66. package/dist/cjs/Canvas/utils/General/imageStitching.js +3 -6
  67. package/dist/cjs/Canvas/utils/General/imageStitching.js.map +1 -1
  68. package/dist/cjs/Canvas/utils/Image/imageMasking.d.ts.map +1 -1
  69. package/dist/cjs/Canvas/utils/Image/imageMasking.js +5 -12
  70. package/dist/cjs/Canvas/utils/Image/imageMasking.js.map +1 -1
  71. package/dist/cjs/Canvas/utils/Image/imageProperties.d.ts +4 -4
  72. package/dist/cjs/Canvas/utils/Image/imageProperties.d.ts.map +1 -1
  73. package/dist/cjs/Canvas/utils/Image/imageProperties.js +44 -9
  74. package/dist/cjs/Canvas/utils/Image/imageProperties.js.map +1 -1
  75. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts +5 -0
  76. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -1
  77. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js +48 -5
  78. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -1
  79. package/dist/cjs/Canvas/utils/Texts/textProperties.d.ts +1 -1
  80. package/dist/cjs/Canvas/utils/Texts/textProperties.d.ts.map +1 -1
  81. package/dist/cjs/Canvas/utils/Texts/textProperties.js +48 -5
  82. package/dist/cjs/Canvas/utils/Texts/textProperties.js.map +1 -1
  83. package/dist/cjs/Canvas/utils/Video/videoHelpers.d.ts +489 -0
  84. package/dist/cjs/Canvas/utils/Video/videoHelpers.d.ts.map +1 -0
  85. package/dist/cjs/Canvas/utils/Video/videoHelpers.js +1835 -0
  86. package/dist/cjs/Canvas/utils/Video/videoHelpers.js.map +1 -0
  87. package/dist/cjs/Canvas/utils/errorUtils.d.ts +15 -0
  88. package/dist/cjs/Canvas/utils/errorUtils.d.ts.map +1 -0
  89. package/dist/cjs/Canvas/utils/errorUtils.js +26 -0
  90. package/dist/cjs/Canvas/utils/errorUtils.js.map +1 -0
  91. package/dist/cjs/Canvas/utils/types.d.ts +17 -178
  92. package/dist/cjs/Canvas/utils/types.d.ts.map +1 -1
  93. package/dist/cjs/Canvas/utils/types.js.map +1 -1
  94. package/dist/cjs/Canvas/utils/utils.d.ts +4 -3
  95. package/dist/cjs/Canvas/utils/utils.d.ts.map +1 -1
  96. package/dist/cjs/Canvas/utils/utils.js +40 -6
  97. package/dist/cjs/Canvas/utils/utils.js.map +1 -1
  98. package/dist/cjs/index.d.ts +1 -8
  99. package/dist/cjs/index.d.ts.map +1 -1
  100. package/dist/cjs/index.js +14 -45
  101. package/dist/cjs/index.js.map +1 -1
  102. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  103. package/dist/esm/Canvas/ApexPainter.d.ts +183 -204
  104. package/dist/esm/Canvas/ApexPainter.d.ts.map +1 -1
  105. package/dist/esm/Canvas/ApexPainter.js +524 -1282
  106. package/dist/esm/Canvas/ApexPainter.js.map +1 -1
  107. package/dist/esm/Canvas/extended/CanvasCreator.d.ts +33 -0
  108. package/dist/esm/Canvas/extended/CanvasCreator.d.ts.map +1 -0
  109. package/dist/esm/Canvas/extended/CanvasCreator.js +223 -0
  110. package/dist/esm/Canvas/extended/CanvasCreator.js.map +1 -0
  111. package/dist/esm/Canvas/extended/ChartCreator.d.ts +26 -0
  112. package/dist/esm/Canvas/extended/ChartCreator.d.ts.map +1 -0
  113. package/dist/esm/Canvas/extended/ChartCreator.js +50 -0
  114. package/dist/esm/Canvas/extended/ChartCreator.js.map +1 -0
  115. package/dist/esm/Canvas/extended/GIFCreator.d.ts +43 -0
  116. package/dist/esm/Canvas/extended/GIFCreator.d.ts.map +1 -0
  117. package/dist/esm/Canvas/extended/GIFCreator.js +157 -0
  118. package/dist/esm/Canvas/extended/GIFCreator.js.map +1 -0
  119. package/dist/esm/Canvas/extended/ImageCreator.d.ts +83 -0
  120. package/dist/esm/Canvas/extended/ImageCreator.d.ts.map +1 -0
  121. package/dist/esm/Canvas/extended/ImageCreator.js +479 -0
  122. package/dist/esm/Canvas/extended/ImageCreator.js.map +1 -0
  123. package/dist/esm/Canvas/extended/TextCreator.d.ts +35 -0
  124. package/dist/esm/Canvas/extended/TextCreator.d.ts.map +1 -0
  125. package/dist/esm/Canvas/extended/TextCreator.js +98 -0
  126. package/dist/esm/Canvas/extended/TextCreator.js.map +1 -0
  127. package/dist/esm/Canvas/extended/VideoCreator.d.ts +370 -0
  128. package/dist/esm/Canvas/extended/VideoCreator.d.ts.map +1 -0
  129. package/dist/esm/Canvas/extended/VideoCreator.js +478 -0
  130. package/dist/esm/Canvas/extended/VideoCreator.js.map +1 -0
  131. package/dist/esm/Canvas/utils/Background/bg.d.ts +1 -1
  132. package/dist/esm/Canvas/utils/Background/bg.d.ts.map +1 -1
  133. package/dist/esm/Canvas/utils/Background/bg.js +43 -7
  134. package/dist/esm/Canvas/utils/Background/bg.js.map +1 -1
  135. package/dist/esm/Canvas/utils/Charts/barchart.d.ts +230 -0
  136. package/dist/esm/Canvas/utils/Charts/barchart.d.ts.map +1 -0
  137. package/dist/esm/Canvas/utils/Charts/barchart.js +1891 -0
  138. package/dist/esm/Canvas/utils/Charts/barchart.js.map +1 -0
  139. package/dist/esm/Canvas/utils/Charts/comparisonchart.d.ts +103 -0
  140. package/dist/esm/Canvas/utils/Charts/comparisonchart.d.ts.map +1 -0
  141. package/dist/esm/Canvas/utils/Charts/comparisonchart.js +368 -0
  142. package/dist/esm/Canvas/utils/Charts/comparisonchart.js.map +1 -0
  143. package/dist/esm/Canvas/utils/Charts/horizontalbarchart.d.ts +181 -0
  144. package/dist/esm/Canvas/utils/Charts/horizontalbarchart.d.ts.map +1 -0
  145. package/dist/esm/Canvas/utils/Charts/horizontalbarchart.js +1389 -0
  146. package/dist/esm/Canvas/utils/Charts/horizontalbarchart.js.map +1 -0
  147. package/dist/esm/Canvas/utils/Charts/index.d.ts +45 -0
  148. package/dist/esm/Canvas/utils/Charts/index.d.ts.map +1 -0
  149. package/dist/esm/Canvas/utils/Charts/index.js +17 -0
  150. package/dist/esm/Canvas/utils/Charts/index.js.map +1 -0
  151. package/dist/esm/Canvas/utils/Charts/linechart.d.ts +216 -0
  152. package/dist/esm/Canvas/utils/Charts/linechart.d.ts.map +1 -0
  153. package/dist/esm/Canvas/utils/Charts/linechart.js +1761 -0
  154. package/dist/esm/Canvas/utils/Charts/linechart.js.map +1 -0
  155. package/dist/esm/Canvas/utils/Charts/piechart.d.ts +167 -0
  156. package/dist/esm/Canvas/utils/Charts/piechart.d.ts.map +1 -0
  157. package/dist/esm/Canvas/utils/Charts/piechart.js +794 -0
  158. package/dist/esm/Canvas/utils/Charts/piechart.js.map +1 -0
  159. package/dist/esm/Canvas/utils/General/batchOperations.d.ts.map +1 -1
  160. package/dist/esm/Canvas/utils/General/batchOperations.js +3 -4
  161. package/dist/esm/Canvas/utils/General/batchOperations.js.map +1 -1
  162. package/dist/esm/Canvas/utils/General/general functions.d.ts.map +1 -1
  163. package/dist/esm/Canvas/utils/General/general functions.js +62 -33
  164. package/dist/esm/Canvas/utils/General/general functions.js.map +1 -1
  165. package/dist/esm/Canvas/utils/General/imageStitching.d.ts.map +1 -1
  166. package/dist/esm/Canvas/utils/General/imageStitching.js +3 -6
  167. package/dist/esm/Canvas/utils/General/imageStitching.js.map +1 -1
  168. package/dist/esm/Canvas/utils/Image/imageMasking.d.ts.map +1 -1
  169. package/dist/esm/Canvas/utils/Image/imageMasking.js +5 -12
  170. package/dist/esm/Canvas/utils/Image/imageMasking.js.map +1 -1
  171. package/dist/esm/Canvas/utils/Image/imageProperties.d.ts +4 -4
  172. package/dist/esm/Canvas/utils/Image/imageProperties.d.ts.map +1 -1
  173. package/dist/esm/Canvas/utils/Image/imageProperties.js +44 -9
  174. package/dist/esm/Canvas/utils/Image/imageProperties.js.map +1 -1
  175. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts +5 -0
  176. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -1
  177. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js +48 -5
  178. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -1
  179. package/dist/esm/Canvas/utils/Texts/textProperties.d.ts +1 -1
  180. package/dist/esm/Canvas/utils/Texts/textProperties.d.ts.map +1 -1
  181. package/dist/esm/Canvas/utils/Texts/textProperties.js +48 -5
  182. package/dist/esm/Canvas/utils/Texts/textProperties.js.map +1 -1
  183. package/dist/esm/Canvas/utils/Video/videoHelpers.d.ts +489 -0
  184. package/dist/esm/Canvas/utils/Video/videoHelpers.d.ts.map +1 -0
  185. package/dist/esm/Canvas/utils/Video/videoHelpers.js +1835 -0
  186. package/dist/esm/Canvas/utils/Video/videoHelpers.js.map +1 -0
  187. package/dist/esm/Canvas/utils/errorUtils.d.ts +15 -0
  188. package/dist/esm/Canvas/utils/errorUtils.d.ts.map +1 -0
  189. package/dist/esm/Canvas/utils/errorUtils.js +26 -0
  190. package/dist/esm/Canvas/utils/errorUtils.js.map +1 -0
  191. package/dist/esm/Canvas/utils/types.d.ts +17 -178
  192. package/dist/esm/Canvas/utils/types.d.ts.map +1 -1
  193. package/dist/esm/Canvas/utils/types.js.map +1 -1
  194. package/dist/esm/Canvas/utils/utils.d.ts +4 -3
  195. package/dist/esm/Canvas/utils/utils.d.ts.map +1 -1
  196. package/dist/esm/Canvas/utils/utils.js +40 -6
  197. package/dist/esm/Canvas/utils/utils.js.map +1 -1
  198. package/dist/esm/index.d.ts +1 -8
  199. package/dist/esm/index.d.ts.map +1 -1
  200. package/dist/esm/index.js +14 -45
  201. package/dist/esm/index.js.map +1 -1
  202. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  203. package/package.json +235 -198
  204. package/dist/cjs/Canvas/utils/Charts/charts.d.ts +0 -13
  205. package/dist/cjs/Canvas/utils/Charts/charts.d.ts.map +0 -1
  206. package/dist/cjs/Canvas/utils/Charts/charts.js +0 -466
  207. package/dist/cjs/Canvas/utils/Charts/charts.js.map +0 -1
  208. package/dist/esm/Canvas/utils/Charts/charts.d.ts +0 -13
  209. package/dist/esm/Canvas/utils/Charts/charts.d.ts.map +0 -1
  210. package/dist/esm/Canvas/utils/Charts/charts.js +0 -466
  211. package/dist/esm/Canvas/utils/Charts/charts.js.map +0 -1
  212. package/lib/Canvas/ApexPainter.ts +0 -5414
  213. package/lib/Canvas/utils/Background/bg.ts +0 -285
  214. package/lib/Canvas/utils/Charts/charts.ts +0 -548
  215. package/lib/Canvas/utils/Custom/advancedLines.ts +0 -387
  216. package/lib/Canvas/utils/Custom/customLines.ts +0 -206
  217. package/lib/Canvas/utils/General/batchOperations.ts +0 -103
  218. package/lib/Canvas/utils/General/conversion.ts +0 -34
  219. package/lib/Canvas/utils/General/general functions.ts +0 -726
  220. package/lib/Canvas/utils/General/imageCompression.ts +0 -316
  221. package/lib/Canvas/utils/General/imageStitching.ts +0 -252
  222. package/lib/Canvas/utils/Image/imageEffects.ts +0 -175
  223. package/lib/Canvas/utils/Image/imageFilters.ts +0 -356
  224. package/lib/Canvas/utils/Image/imageMasking.ts +0 -335
  225. package/lib/Canvas/utils/Image/imageProperties.ts +0 -587
  226. package/lib/Canvas/utils/Image/professionalImageFilters.ts +0 -391
  227. package/lib/Canvas/utils/Image/simpleProfessionalFilters.ts +0 -229
  228. package/lib/Canvas/utils/Patterns/enhancedPatternRenderer.ts +0 -455
  229. package/lib/Canvas/utils/Shapes/shapes.ts +0 -528
  230. package/lib/Canvas/utils/Texts/enhancedTextRenderer.ts +0 -716
  231. package/lib/Canvas/utils/Texts/textPathRenderer.ts +0 -320
  232. package/lib/Canvas/utils/Texts/textProperties.ts +0 -231
  233. package/lib/Canvas/utils/types.ts +0 -983
  234. package/lib/Canvas/utils/utils.ts +0 -135
  235. package/lib/index.ts +0 -81
  236. package/lib/utils.ts +0 -5
@@ -1,716 +0,0 @@
1
- import { SKRSContext2D } from '@napi-rs/canvas';
2
- import { TextProperties, gradient } from '../types';
3
- import { GlobalFonts } from '@napi-rs/canvas';
4
- import path from 'path';
5
-
6
- /**
7
- * Enhanced text renderer with comprehensive styling options
8
- */
9
- export class EnhancedTextRenderer {
10
- /**
11
- * Renders text with all enhanced features
12
- * @param ctx - Canvas 2D context
13
- * @param textProps - Text properties configuration
14
- */
15
- static async renderText(ctx: SKRSContext2D, textProps: TextProperties): Promise<void> {
16
- ctx.save();
17
-
18
- try {
19
- // 1. Register custom font if provided (support both new and legacy properties)
20
- const fontPath = textProps.font?.path || textProps.fontPath;
21
- const fontName = textProps.font?.name || textProps.fontName;
22
-
23
- if (fontPath) {
24
- await this.registerCustomFont(fontPath, fontName || 'customFont');
25
- }
26
-
27
- // 2. Apply transformations
28
- this.applyTransformations(ctx, textProps);
29
-
30
- // 3. Setup font and spacing
31
- this.setupFont(ctx, textProps);
32
-
33
- // 4. Apply text alignment
34
- this.setupAlignment(ctx, textProps);
35
-
36
- // 5. Handle text wrapping or single line rendering
37
- if (textProps.maxWidth) {
38
- await this.renderWrappedText(ctx, textProps);
39
- } else {
40
- await this.renderSingleLine(ctx, textProps);
41
- }
42
-
43
- } finally {
44
- ctx.restore();
45
- }
46
- }
47
-
48
- /**
49
- * Registers a custom font from file path
50
- * @param fontPath - Path to font file
51
- * @param fontName - Name to register the font as
52
- */
53
- private static async registerCustomFont(fontPath: string, fontName: string): Promise<void> {
54
- try {
55
- const fullPath = path.join(process.cwd(), fontPath);
56
- GlobalFonts.registerFromPath(fullPath, fontName);
57
- } catch (error) {
58
- console.warn(`Failed to register font from path: ${fontPath}`, error);
59
- }
60
- }
61
-
62
- /**
63
- * Applies transformations (rotation, opacity)
64
- * @param ctx - Canvas 2D context
65
- * @param textProps - Text properties
66
- */
67
- private static applyTransformations(ctx: SKRSContext2D, textProps: TextProperties): void {
68
- // Apply rotation
69
- if (textProps.rotation && textProps.rotation !== 0) {
70
- ctx.translate(textProps.x, textProps.y);
71
- ctx.rotate((textProps.rotation * Math.PI) / 180);
72
- ctx.translate(-textProps.x, -textProps.y);
73
- }
74
-
75
- // Apply global opacity
76
- if (textProps.opacity !== undefined) {
77
- ctx.globalAlpha = Math.max(0, Math.min(1, textProps.opacity));
78
- }
79
- }
80
-
81
- /**
82
- * Sets up font properties and spacing
83
- * @param ctx - Canvas 2D context
84
- * @param textProps - Text properties
85
- */
86
- private static setupFont(ctx: SKRSContext2D, textProps: TextProperties): void {
87
- // Support both new font object and legacy properties
88
- const fontSize = textProps.font?.size || textProps.fontSize || 16;
89
- const fontFamily = textProps.font?.name || textProps.fontName || textProps.font?.family || textProps.fontFamily || 'Arial';
90
-
91
- // Build font string with decorations
92
- let fontString = '';
93
-
94
- if (textProps.bold) fontString += 'bold ';
95
- if (textProps.italic) fontString += 'italic ';
96
-
97
- fontString += `${fontSize}px "${fontFamily}"`;
98
-
99
- ctx.font = fontString;
100
-
101
- // Apply letter spacing
102
- if (textProps.letterSpacing !== undefined) {
103
- ctx.letterSpacing = `${textProps.letterSpacing}px`;
104
- }
105
-
106
- // Apply word spacing
107
- if (textProps.wordSpacing !== undefined) {
108
- ctx.wordSpacing = `${textProps.wordSpacing}px`;
109
- }
110
- }
111
-
112
- /**
113
- * Sets up text alignment
114
- * @param ctx - Canvas 2D context
115
- * @param textProps - Text properties
116
- */
117
- private static setupAlignment(ctx: SKRSContext2D, textProps: TextProperties): void {
118
- ctx.textAlign = textProps.textAlign || 'left';
119
- ctx.textBaseline = textProps.textBaseline || 'alphabetic';
120
- }
121
-
122
- /**
123
- * Renders wrapped text with all effects
124
- * @param ctx - Canvas 2D context
125
- * @param textProps - Text properties
126
- */
127
- private static async renderWrappedText(ctx: SKRSContext2D, textProps: TextProperties): Promise<void> {
128
- const fontSize = textProps.font?.size || textProps.fontSize || 16;
129
- const lineHeight = (textProps.lineHeight || 1.4) * fontSize;
130
- const maxHeight = textProps.maxHeight;
131
- const maxLines = maxHeight ? Math.floor(maxHeight / lineHeight) : Infinity;
132
-
133
- // Split text into words and wrap
134
- const words = textProps.text.split(' ');
135
- const lines: string[] = [];
136
- let currentLine = '';
137
-
138
- for (const word of words) {
139
- const testLine = currentLine ? currentLine + ' ' + word : word;
140
- const testWidth = ctx.measureText(testLine).width;
141
-
142
- if (testWidth > (textProps.maxWidth || Infinity) && currentLine) {
143
- lines.push(currentLine);
144
- currentLine = word;
145
-
146
- if (lines.length >= maxLines) {
147
- currentLine = '...';
148
- break;
149
- }
150
- } else {
151
- currentLine = testLine;
152
- }
153
- }
154
-
155
- if (currentLine && lines.length < maxLines) {
156
- lines.push(currentLine);
157
- }
158
-
159
- // Render each line
160
- for (let i = 0; i < lines.length; i++) {
161
- const y = textProps.y + (i * lineHeight);
162
- await this.renderTextLine(ctx, lines[i], textProps.x, y, textProps);
163
- }
164
- }
165
-
166
- /**
167
- * Renders single line text with all effects
168
- * @param ctx - Canvas 2D context
169
- * @param textProps - Text properties
170
- */
171
- private static async renderSingleLine(ctx: SKRSContext2D, textProps: TextProperties): Promise<void> {
172
- await this.renderTextLine(ctx, textProps.text, textProps.x, textProps.y, textProps);
173
- }
174
-
175
- /**
176
- * Renders a single line of text with all effects applied
177
- * @param ctx - Canvas 2D context
178
- * @param text - Text to render
179
- * @param x - X position
180
- * @param y - Y position
181
- * @param textProps - Text properties
182
- */
183
- private static async renderTextLine(
184
- ctx: SKRSContext2D,
185
- text: string,
186
- x: number,
187
- y: number,
188
- textProps: TextProperties
189
- ): Promise<void> {
190
- // Calculate text dimensions
191
- const metrics = ctx.measureText(text);
192
- const textWidth = metrics.width;
193
- const fontSize = textProps.font?.size || textProps.fontSize || 16;
194
- const textHeight = fontSize;
195
-
196
- // Apply highlight background
197
- if (textProps.highlight) {
198
- this.renderHighlight(ctx, x, y, textWidth, textHeight, textProps.highlight);
199
- }
200
-
201
- // Apply glow effect
202
- if (textProps.glow) {
203
- this.renderGlow(ctx, text, x, y, textProps.glow);
204
- }
205
-
206
- // Apply shadow effect
207
- if (textProps.shadow) {
208
- this.renderShadow(ctx, text, x, y, textProps.shadow);
209
- }
210
-
211
- // Apply stroke
212
- if (textProps.stroke) {
213
- this.renderStroke(ctx, text, x, y, textProps.stroke);
214
- }
215
-
216
- // Apply fill
217
- this.renderFill(ctx, text, x, y, textProps);
218
-
219
- // Apply text decorations
220
- this.renderDecorations(ctx, text, x, y, textWidth, textHeight, textProps);
221
- }
222
-
223
- /**
224
- * Renders highlight background
225
- * @param ctx - Canvas 2D context
226
- * @param x - X position
227
- * @param y - Y position
228
- * @param width - Text width
229
- * @param height - Text height
230
- * @param highlight - Highlight options
231
- */
232
- private static renderHighlight(
233
- ctx: SKRSContext2D,
234
- x: number,
235
- y: number,
236
- width: number,
237
- height: number,
238
- highlight: { color?: string; gradient?: gradient; opacity?: number }
239
- ): void {
240
- ctx.save();
241
-
242
- const opacity = highlight.opacity !== undefined ? highlight.opacity : 0.3;
243
- ctx.globalAlpha = opacity;
244
-
245
- // Set fill style (gradient or color)
246
- if (highlight.gradient) {
247
- ctx.fillStyle = this.createGradient(ctx, highlight.gradient, x, y, x + width, y + height);
248
- } else {
249
- ctx.fillStyle = highlight.color || '#ffff00';
250
- }
251
-
252
- // Adjust highlight position based on text baseline
253
- const highlightY = y - height * 0.8; // Adjust for different baselines
254
- ctx.fillRect(x, highlightY, width, height);
255
-
256
- ctx.restore();
257
- }
258
-
259
- /**
260
- * Renders glow effect
261
- * @param ctx - Canvas 2D context
262
- * @param text - Text to render
263
- * @param x - X position
264
- * @param y - Y position
265
- * @param glow - Glow options
266
- */
267
- private static renderGlow(
268
- ctx: SKRSContext2D,
269
- text: string,
270
- x: number,
271
- y: number,
272
- glow: { color?: string; gradient?: gradient; intensity?: number; opacity?: number }
273
- ): void {
274
- ctx.save();
275
-
276
- const intensity = glow.intensity || 10;
277
- const opacity = glow.opacity !== undefined ? glow.opacity : 0.8;
278
-
279
- // For glow, we need to use shadowColor which only supports solid colors
280
- // So we'll render the glow with the base color and then overlay with gradient if needed
281
- if (glow.gradient) {
282
- // First render with shadow for glow effect
283
- ctx.shadowColor = '#ffffff'; // Use white as base for glow
284
- ctx.shadowBlur = intensity;
285
- ctx.globalAlpha = opacity;
286
- ctx.fillText(text, x, y);
287
-
288
- // Then overlay with gradient
289
- ctx.shadowColor = 'transparent';
290
- ctx.shadowBlur = 0;
291
- ctx.fillStyle = this.createGradient(ctx, glow.gradient, x, y, x + ctx.measureText(text).width, y);
292
- ctx.fillText(text, x, y);
293
- } else {
294
- ctx.shadowColor = glow.color || '#ffffff';
295
- ctx.shadowBlur = intensity;
296
- ctx.globalAlpha = opacity;
297
- ctx.fillText(text, x, y);
298
- }
299
-
300
- ctx.restore();
301
- }
302
-
303
- /**
304
- * Renders shadow effect
305
- * @param ctx - Canvas 2D context
306
- * @param text - Text to render
307
- * @param x - X position
308
- * @param y - Y position
309
- * @param shadow - Shadow options
310
- */
311
- private static renderShadow(
312
- ctx: SKRSContext2D,
313
- text: string,
314
- x: number,
315
- y: number,
316
- shadow: { color?: string; offsetX?: number; offsetY?: number; blur?: number; opacity?: number }
317
- ): void {
318
- ctx.save();
319
-
320
- ctx.shadowColor = shadow.color || 'rgba(0, 0, 0, 0.5)';
321
- ctx.shadowOffsetX = shadow.offsetX || 2;
322
- ctx.shadowOffsetY = shadow.offsetY || 2;
323
- ctx.shadowBlur = shadow.blur || 4;
324
-
325
- if (shadow.opacity !== undefined) {
326
- ctx.globalAlpha = shadow.opacity;
327
- }
328
-
329
- ctx.fillText(text, x, y);
330
-
331
- ctx.restore();
332
- }
333
-
334
- /**
335
- * Renders stroke/outline
336
- * @param ctx - Canvas 2D context
337
- * @param text - Text to render
338
- * @param x - X position
339
- * @param y - Y position
340
- * @param stroke - Stroke options
341
- */
342
- private static renderStroke(
343
- ctx: SKRSContext2D,
344
- text: string,
345
- x: number,
346
- y: number,
347
- stroke: { color?: string; width?: number; gradient?: gradient; opacity?: number; style?: 'solid' | 'dashed' | 'dotted' | 'groove' | 'ridge' | 'double' }
348
- ): void {
349
- ctx.save();
350
-
351
- const strokeWidth = stroke.width || 1;
352
- const strokeStyle = stroke.style || 'solid';
353
-
354
- ctx.lineWidth = strokeWidth;
355
-
356
- if (stroke.gradient) {
357
- ctx.strokeStyle = this.createGradient(ctx, stroke.gradient, x, y, x + ctx.measureText(text).width, y);
358
- } else {
359
- ctx.strokeStyle = stroke.color || '#000000';
360
- }
361
-
362
- if (stroke.opacity !== undefined) {
363
- ctx.globalAlpha = stroke.opacity;
364
- }
365
-
366
- // Apply stroke style
367
- this.applyTextStrokeStyle(ctx, strokeStyle, strokeWidth);
368
-
369
- // Handle complex stroke styles
370
- if (strokeStyle === 'groove' || strokeStyle === 'ridge' || strokeStyle === 'double') {
371
- this.renderComplexTextStroke(ctx, text, x, y, strokeStyle, strokeWidth, stroke.color, stroke.gradient);
372
- } else {
373
- ctx.strokeText(text, x, y);
374
- }
375
-
376
- ctx.restore();
377
- }
378
-
379
- /**
380
- * Renders text fill
381
- * @param ctx - Canvas 2D context
382
- * @param text - Text to render
383
- * @param x - X position
384
- * @param y - Y position
385
- * @param textProps - Text properties
386
- */
387
- private static renderFill(
388
- ctx: SKRSContext2D,
389
- text: string,
390
- x: number,
391
- y: number,
392
- textProps: TextProperties
393
- ): void {
394
- ctx.save();
395
-
396
- if (textProps.gradient) {
397
- ctx.fillStyle = this.createGradient(ctx, textProps.gradient, x, y, x + ctx.measureText(text).width, y);
398
- } else {
399
- ctx.fillStyle = textProps.color || '#000000';
400
- }
401
-
402
- ctx.fillText(text, x, y);
403
-
404
- ctx.restore();
405
- }
406
-
407
- /**
408
- * Renders text decorations (underline, overline, strikethrough)
409
- * @param ctx - Canvas 2D context
410
- * @param text - Text to render
411
- * @param x - X position
412
- * @param y - Y position
413
- * @param width - Text width
414
- * @param height - Text height
415
- * @param textProps - Text properties
416
- */
417
- private static renderDecorations(
418
- ctx: SKRSContext2D,
419
- text: string,
420
- x: number,
421
- y: number,
422
- width: number,
423
- height: number,
424
- textProps: TextProperties
425
- ): void {
426
- const hasDecorations = textProps.underline || textProps.overline || textProps.strikethrough;
427
- if (!hasDecorations) {
428
- return;
429
- }
430
-
431
- ctx.save();
432
-
433
- const fontSize = textProps.font?.size || textProps.fontSize || 16;
434
- const defaultColor = textProps.color || '#000000';
435
-
436
- // Helper function to render a decoration line
437
- const renderDecorationLine = (
438
- decorationY: number,
439
- decoration: boolean | { color?: string; gradient?: gradient; width?: number } | undefined,
440
- lineName: string
441
- ) => {
442
- if (!decoration) return;
443
-
444
- ctx.save();
445
-
446
- let decorationColor = defaultColor;
447
- let decorationWidth = Math.max(1, fontSize * 0.05); // 5% of font size
448
-
449
- if (typeof decoration === 'object') {
450
- decorationColor = decoration.color || defaultColor;
451
- decorationWidth = decoration.width || decorationWidth;
452
-
453
- // Set stroke style (gradient or color)
454
- if (decoration.gradient) {
455
- ctx.strokeStyle = this.createGradient(ctx, decoration.gradient, x, decorationY, x + width, decorationY);
456
- } else {
457
- ctx.strokeStyle = decorationColor;
458
- }
459
- } else {
460
- ctx.strokeStyle = decorationColor;
461
- }
462
-
463
- ctx.lineWidth = decorationWidth;
464
-
465
- ctx.beginPath();
466
- ctx.moveTo(x, decorationY);
467
- ctx.lineTo(x + width, decorationY);
468
- ctx.stroke();
469
-
470
- ctx.restore();
471
- };
472
-
473
- // Underline
474
- if (textProps.underline) {
475
- const underlineY = y + fontSize * 0.1;
476
- renderDecorationLine(underlineY, textProps.underline, 'underline');
477
- }
478
-
479
- // Overline
480
- if (textProps.overline) {
481
- const overlineY = y - fontSize * 0.8;
482
- renderDecorationLine(overlineY, textProps.overline, 'overline');
483
- }
484
-
485
- // Strikethrough
486
- if (textProps.strikethrough) {
487
- const strikethroughY = y - fontSize * 0.3;
488
- renderDecorationLine(strikethroughY, textProps.strikethrough, 'strikethrough');
489
- }
490
-
491
- ctx.restore();
492
- }
493
-
494
- /**
495
- * Creates a gradient for text fill or stroke
496
- * @param ctx - Canvas 2D context
497
- * @param gradientOptions - Gradient configuration
498
- * @param startX - Start X position
499
- * @param startY - Start Y position
500
- * @param endX - End X position
501
- * @param endY - End Y position
502
- * @returns Canvas gradient
503
- */
504
- private static createGradient(
505
- ctx: SKRSContext2D,
506
- gradientOptions: gradient,
507
- startX: number,
508
- startY: number,
509
- endX: number,
510
- endY: number
511
- ): CanvasGradient {
512
- if (!gradientOptions || !gradientOptions.type || !gradientOptions.colors) {
513
- throw new Error("Invalid gradient options. Provide a valid object with type and colors properties.");
514
- }
515
-
516
- let gradient: CanvasGradient;
517
-
518
- if (gradientOptions.type === "linear") {
519
- gradient = ctx.createLinearGradient(startX, startY, endX, endY);
520
- } else if (gradientOptions.type === "radial") {
521
- gradient = ctx.createRadialGradient(
522
- gradientOptions.startX || startX,
523
- gradientOptions.startY || startY,
524
- gradientOptions.startRadius || 0,
525
- gradientOptions.endX || endX,
526
- gradientOptions.endY || endY,
527
- gradientOptions.endRadius || 0
528
- );
529
- } else {
530
- throw new Error('Unsupported gradient type. Use "linear" or "radial".');
531
- }
532
-
533
- for (const colorStop of gradientOptions.colors) {
534
- gradient.addColorStop(colorStop.stop, colorStop.color);
535
- }
536
-
537
- return gradient;
538
- }
539
-
540
- /**
541
- * Applies stroke style to text context
542
- * @param ctx - Canvas 2D context
543
- * @param style - Stroke style type
544
- * @param width - Stroke width for calculating dash patterns
545
- */
546
- private static applyTextStrokeStyle(
547
- ctx: SKRSContext2D,
548
- style: 'solid' | 'dashed' | 'dotted' | 'groove' | 'ridge' | 'double',
549
- width: number
550
- ): void {
551
- switch (style) {
552
- case 'solid':
553
- ctx.setLineDash([]);
554
- ctx.lineCap = 'butt';
555
- ctx.lineJoin = 'miter';
556
- break;
557
-
558
- case 'dashed':
559
- ctx.setLineDash([width * 3, width * 2]);
560
- ctx.lineCap = 'butt';
561
- ctx.lineJoin = 'miter';
562
- break;
563
-
564
- case 'dotted':
565
- ctx.setLineDash([width, width]);
566
- ctx.lineCap = 'round';
567
- ctx.lineJoin = 'round';
568
- break;
569
-
570
- case 'groove':
571
- case 'ridge':
572
- case 'double':
573
- ctx.setLineDash([]);
574
- ctx.lineCap = 'butt';
575
- ctx.lineJoin = 'miter';
576
- break;
577
-
578
- default:
579
- ctx.setLineDash([]);
580
- ctx.lineCap = 'butt';
581
- ctx.lineJoin = 'miter';
582
- break;
583
- }
584
- }
585
-
586
- /**
587
- * Renders complex text stroke styles that require multiple passes
588
- * @param ctx - Canvas 2D context
589
- * @param text - Text to render
590
- * @param x - X position
591
- * @param y - Y position
592
- * @param style - Complex stroke style type
593
- * @param width - Stroke width
594
- * @param color - Base stroke color
595
- * @param gradient - Optional gradient
596
- */
597
- private static renderComplexTextStroke(
598
- ctx: SKRSContext2D,
599
- text: string,
600
- x: number,
601
- y: number,
602
- style: 'groove' | 'ridge' | 'double',
603
- width: number,
604
- color?: string,
605
- gradient?: gradient
606
- ): void {
607
- const halfWidth = width / 2;
608
- const textWidth = ctx.measureText(text).width;
609
-
610
- switch (style) {
611
- case 'groove':
612
- // Groove: dark outer, light inner
613
- ctx.lineWidth = halfWidth;
614
-
615
- // Outer dark stroke
616
- if (gradient) {
617
- ctx.strokeStyle = this.createGradient(ctx, gradient, x, y, x + textWidth, y);
618
- } else {
619
- ctx.strokeStyle = this.darkenColor(color || '#000000', 0.3);
620
- }
621
- ctx.strokeText(text, x, y);
622
-
623
- // Inner light stroke
624
- ctx.lineWidth = halfWidth;
625
- if (gradient) {
626
- ctx.strokeStyle = this.createGradient(ctx, gradient, x, y, x + textWidth, y);
627
- } else {
628
- ctx.strokeStyle = this.lightenColor(color || '#000000', 0.3);
629
- }
630
- ctx.strokeText(text, x, y);
631
- break;
632
-
633
- case 'ridge':
634
- // Ridge: light outer, dark inner
635
- ctx.lineWidth = halfWidth;
636
-
637
- // Outer light stroke
638
- if (gradient) {
639
- ctx.strokeStyle = this.createGradient(ctx, gradient, x, y, x + textWidth, y);
640
- } else {
641
- ctx.strokeStyle = this.lightenColor(color || '#000000', 0.3);
642
- }
643
- ctx.strokeText(text, x, y);
644
-
645
- // Inner dark stroke
646
- ctx.lineWidth = halfWidth;
647
- if (gradient) {
648
- ctx.strokeStyle = this.createGradient(ctx, gradient, x, y, x + textWidth, y);
649
- } else {
650
- ctx.strokeStyle = this.darkenColor(color || '#000000', 0.3);
651
- }
652
- ctx.strokeText(text, x, y);
653
- break;
654
-
655
- case 'double':
656
- // Double: two parallel strokes
657
- ctx.lineWidth = halfWidth;
658
-
659
- // First stroke (outer)
660
- if (gradient) {
661
- ctx.strokeStyle = this.createGradient(ctx, gradient, x, y, x + textWidth, y);
662
- } else {
663
- ctx.strokeStyle = color || '#000000';
664
- }
665
- ctx.strokeText(text, x, y);
666
-
667
- // Second stroke (inner)
668
- ctx.lineWidth = halfWidth;
669
- if (gradient) {
670
- ctx.strokeStyle = this.createGradient(ctx, gradient, x, y, x + textWidth, y);
671
- } else {
672
- ctx.strokeStyle = color || '#000000';
673
- }
674
- ctx.strokeText(text, x, y);
675
- break;
676
- }
677
- }
678
-
679
- /**
680
- * Darkens a color by a factor
681
- * @param color - Color string
682
- * @param factor - Darkening factor (0-1)
683
- * @returns Darkened color string
684
- */
685
- private static darkenColor(color: string, factor: number): string {
686
- // Simple darkening for hex colors
687
- if (color.startsWith('#')) {
688
- const hex = color.slice(1);
689
- const num = parseInt(hex, 16);
690
- const r = Math.max(0, Math.floor((num >> 16) * (1 - factor)));
691
- const g = Math.max(0, Math.floor(((num >> 8) & 0x00FF) * (1 - factor)));
692
- const b = Math.max(0, Math.floor((num & 0x0000FF) * (1 - factor)));
693
- return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;
694
- }
695
- return color; // Return original for non-hex colors
696
- }
697
-
698
- /**
699
- * Lightens a color by a factor
700
- * @param color - Color string
701
- * @param factor - Lightening factor (0-1)
702
- * @returns Lightened color string
703
- */
704
- private static lightenColor(color: string, factor: number): string {
705
- // Simple lightening for hex colors
706
- if (color.startsWith('#')) {
707
- const hex = color.slice(1);
708
- const num = parseInt(hex, 16);
709
- const r = Math.min(255, Math.floor((num >> 16) + (255 - (num >> 16)) * factor));
710
- const g = Math.min(255, Math.floor(((num >> 8) & 0x00FF) + (255 - ((num >> 8) & 0x00FF)) * factor));
711
- const b = Math.min(255, Math.floor((num & 0x0000FF) + (255 - (num & 0x0000FF)) * factor));
712
- return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;
713
- }
714
- return color; // Return original for non-hex colors
715
- }
716
- }