html2canvas-pro 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/dist/html2canvas-pro.esm.js +10226 -10526
  2. package/dist/html2canvas-pro.esm.js.map +1 -1
  3. package/dist/html2canvas-pro.js +10869 -11171
  4. package/dist/html2canvas-pro.js.map +1 -1
  5. package/dist/html2canvas-pro.min.js +8 -8
  6. package/dist/lib/config.js +0 -22
  7. package/dist/lib/core/cache-storage.js +3 -40
  8. package/dist/lib/core/constants.js +25 -0
  9. package/dist/lib/core/context.js +1 -0
  10. package/dist/lib/core/features.js +3 -2
  11. package/dist/lib/core/validator.js +3 -3
  12. package/dist/lib/css/grouped/background-styles.js +36 -0
  13. package/dist/lib/css/grouped/border-styles.js +75 -0
  14. package/dist/lib/css/grouped/font-styles.js +93 -0
  15. package/dist/lib/css/grouped/layout-styles.js +127 -0
  16. package/dist/lib/css/index.js +74 -46
  17. package/dist/lib/css/layout/text.js +7 -6
  18. package/dist/lib/css/property-descriptors/background-blend-mode.js +41 -0
  19. package/dist/lib/css/property-descriptors/border-image-repeat.js +42 -0
  20. package/dist/lib/css/property-descriptors/border-image-slice.js +45 -0
  21. package/dist/lib/css/property-descriptors/border-image-source.js +21 -0
  22. package/dist/lib/css/property-descriptors/border-radius.js +1 -1
  23. package/dist/lib/css/property-descriptors/box-decoration-break.js +18 -0
  24. package/dist/lib/css/property-descriptors/counter-increment.js +17 -12
  25. package/dist/lib/css/property-descriptors/counter-reset.js +4 -12
  26. package/dist/lib/css/property-descriptors/filter.js +76 -0
  27. package/dist/lib/css/property-descriptors/font-variant-ligatures.js +34 -0
  28. package/dist/lib/css/property-descriptors/object-fit.js +1 -1
  29. package/dist/lib/css/property-descriptors/object-position.js +42 -0
  30. package/dist/lib/css/property-descriptors/visibility.js +1 -1
  31. package/dist/lib/css/property-descriptors/zoom.js +18 -0
  32. package/dist/lib/css/syntax/parser.js +0 -1
  33. package/dist/lib/css/types/color.js +5 -1
  34. package/dist/lib/css/types/functions/repeating-linear-gradient.js +9 -0
  35. package/dist/lib/css/types/image.js +12 -2
  36. package/dist/lib/css/types/length-percentage.js +6 -2
  37. package/dist/lib/css/types/safe-eval.js +80 -0
  38. package/dist/lib/dom/document-cloner.js +23 -163
  39. package/dist/lib/dom/slot-cloner.js +176 -0
  40. package/dist/lib/index.js +1 -17
  41. package/dist/lib/render/canvas/background-renderer.js +169 -30
  42. package/dist/lib/render/canvas/border-image-renderer.js +153 -0
  43. package/dist/lib/render/canvas/canvas-renderer.js +39 -190
  44. package/dist/lib/render/canvas/content-renderer.js +202 -0
  45. package/dist/lib/render/canvas/effects-renderer.js +3 -0
  46. package/dist/lib/render/canvas/foreignobject-renderer.js +5 -1
  47. package/dist/lib/render/canvas/text/text-decoration-renderer.js +99 -0
  48. package/dist/lib/render/canvas/text-renderer.js +100 -224
  49. package/dist/lib/render/effects.js +38 -3
  50. package/dist/lib/render/object-fit.js +19 -15
  51. package/dist/lib/render/stacking-context.js +11 -0
  52. package/dist/types/config.d.ts +0 -10
  53. package/dist/types/core/cache-storage.d.ts +0 -24
  54. package/dist/types/core/constants.d.ts +22 -0
  55. package/dist/types/core/context.d.ts +3 -0
  56. package/dist/types/core/performance-monitor.d.ts +4 -4
  57. package/dist/types/core/validator.d.ts +6 -8
  58. package/dist/types/css/grouped/background-styles.d.ts +16 -0
  59. package/dist/types/css/grouped/border-styles.d.ts +31 -0
  60. package/dist/types/css/grouped/font-styles.d.ts +35 -0
  61. package/dist/types/css/grouped/layout-styles.d.ts +46 -0
  62. package/dist/types/css/index.d.ts +30 -0
  63. package/dist/types/css/property-descriptors/background-blend-mode.d.ts +23 -0
  64. package/dist/types/css/property-descriptors/border-image-repeat.d.ts +12 -0
  65. package/dist/types/css/property-descriptors/border-image-slice.d.ts +10 -0
  66. package/dist/types/css/property-descriptors/border-image-source.d.ts +4 -0
  67. package/dist/types/css/property-descriptors/box-decoration-break.d.ts +6 -0
  68. package/dist/types/css/property-descriptors/counter-increment.d.ts +3 -0
  69. package/dist/types/css/property-descriptors/filter.d.ts +3 -0
  70. package/dist/types/css/property-descriptors/font-variant-ligatures.d.ts +14 -0
  71. package/dist/types/css/property-descriptors/object-position.d.ts +4 -0
  72. package/dist/types/css/property-descriptors/zoom.d.ts +3 -0
  73. package/dist/types/css/types/functions/repeating-linear-gradient.d.ts +4 -0
  74. package/dist/types/css/types/image.d.ts +4 -2
  75. package/dist/types/css/types/safe-eval.d.ts +8 -0
  76. package/dist/types/dom/document-cloner.d.ts +3 -44
  77. package/dist/types/dom/slot-cloner.d.ts +66 -0
  78. package/dist/types/index.d.ts +3 -7
  79. package/dist/types/options.d.ts +11 -0
  80. package/dist/types/render/canvas/background-renderer.d.ts +23 -0
  81. package/dist/types/render/canvas/border-image-renderer.d.ts +18 -0
  82. package/dist/types/render/canvas/canvas-renderer.d.ts +1 -0
  83. package/dist/types/render/canvas/content-renderer.d.ts +44 -0
  84. package/dist/types/render/canvas/text/text-decoration-renderer.d.ts +18 -0
  85. package/dist/types/render/canvas/text-renderer.d.ts +12 -1
  86. package/dist/types/render/effects.d.ts +12 -2
  87. package/dist/types/render/object-fit.d.ts +2 -1
  88. package/dist/types/render/renderer-interface.d.ts +11 -9
  89. package/package.json +7 -20
  90. package/dist/lib/dom/replaced-elements/pseudo-elements.js +0 -0
  91. package/dist/lib/invariant.js +0 -9
  92. package/dist/types/dom/replaced-elements/pseudo-elements.d.ts +0 -0
  93. package/dist/types/invariant.d.ts +0 -1
  94. package/src/__tests__/index.ts +0 -99
  95. package/src/config.ts +0 -107
  96. package/src/core/__mocks__/cache-storage.ts +0 -1
  97. package/src/core/__mocks__/context.ts +0 -19
  98. package/src/core/__mocks__/features.ts +0 -8
  99. package/src/core/__mocks__/logger.ts +0 -17
  100. package/src/core/__tests__/cache-storage.test.ts +0 -205
  101. package/src/core/__tests__/cache-storage.ts +0 -278
  102. package/src/core/__tests__/logger.ts +0 -29
  103. package/src/core/__tests__/validator.ts +0 -359
  104. package/src/core/bitwise.ts +0 -1
  105. package/src/core/cache-storage.ts +0 -315
  106. package/src/core/context.ts +0 -31
  107. package/src/core/debugger.ts +0 -32
  108. package/src/core/features.ts +0 -222
  109. package/src/core/logger.ts +0 -64
  110. package/src/core/origin-checker.ts +0 -57
  111. package/src/core/performance-monitor.ts +0 -241
  112. package/src/core/render-element.ts +0 -272
  113. package/src/core/util.ts +0 -1
  114. package/src/core/validator.ts +0 -593
  115. package/src/css/index.ts +0 -427
  116. package/src/css/layout/__mocks__/bounds.ts +0 -6
  117. package/src/css/layout/bounds.ts +0 -79
  118. package/src/css/layout/text.ts +0 -161
  119. package/src/css/property-descriptor.ts +0 -49
  120. package/src/css/property-descriptors/__tests__/background-tests.ts +0 -65
  121. package/src/css/property-descriptors/__tests__/clip-path.test.ts +0 -280
  122. package/src/css/property-descriptors/__tests__/font-family.ts +0 -25
  123. package/src/css/property-descriptors/__tests__/image-rendering-integration.test.ts +0 -153
  124. package/src/css/property-descriptors/__tests__/image-rendering-performance.test.ts +0 -175
  125. package/src/css/property-descriptors/__tests__/image-rendering.test.ts +0 -72
  126. package/src/css/property-descriptors/__tests__/paint-order.ts +0 -87
  127. package/src/css/property-descriptors/__tests__/text-shadow.ts +0 -94
  128. package/src/css/property-descriptors/__tests__/transform-tests.ts +0 -18
  129. package/src/css/property-descriptors/background-clip.ts +0 -30
  130. package/src/css/property-descriptors/background-color.ts +0 -9
  131. package/src/css/property-descriptors/background-image.ts +0 -27
  132. package/src/css/property-descriptors/background-origin.ts +0 -31
  133. package/src/css/property-descriptors/background-position.ts +0 -38
  134. package/src/css/property-descriptors/background-repeat.ts +0 -44
  135. package/src/css/property-descriptors/background-size.ts +0 -27
  136. package/src/css/property-descriptors/border-color.ts +0 -13
  137. package/src/css/property-descriptors/border-radius.ts +0 -19
  138. package/src/css/property-descriptors/border-style.ts +0 -34
  139. package/src/css/property-descriptors/border-width.ts +0 -20
  140. package/src/css/property-descriptors/box-shadow.ts +0 -60
  141. package/src/css/property-descriptors/clip-path.ts +0 -271
  142. package/src/css/property-descriptors/color.ts +0 -9
  143. package/src/css/property-descriptors/content.ts +0 -26
  144. package/src/css/property-descriptors/counter-increment.ts +0 -43
  145. package/src/css/property-descriptors/counter-reset.ts +0 -36
  146. package/src/css/property-descriptors/direction.ts +0 -23
  147. package/src/css/property-descriptors/display.ts +0 -117
  148. package/src/css/property-descriptors/duration.ts +0 -14
  149. package/src/css/property-descriptors/float.ts +0 -29
  150. package/src/css/property-descriptors/font-family.ts +0 -38
  151. package/src/css/property-descriptors/font-size.ts +0 -9
  152. package/src/css/property-descriptors/font-style.ts +0 -25
  153. package/src/css/property-descriptors/font-variant.ts +0 -12
  154. package/src/css/property-descriptors/font-weight.ts +0 -26
  155. package/src/css/property-descriptors/image-rendering.ts +0 -33
  156. package/src/css/property-descriptors/letter-spacing.ts +0 -25
  157. package/src/css/property-descriptors/line-break.ts +0 -22
  158. package/src/css/property-descriptors/line-height.ts +0 -22
  159. package/src/css/property-descriptors/list-style-image.ts +0 -19
  160. package/src/css/property-descriptors/list-style-position.ts +0 -22
  161. package/src/css/property-descriptors/list-style-type.ts +0 -179
  162. package/src/css/property-descriptors/margin.ts +0 -13
  163. package/src/css/property-descriptors/mix-blend-mode.ts +0 -35
  164. package/src/css/property-descriptors/object-fit.ts +0 -39
  165. package/src/css/property-descriptors/opacity.ts +0 -15
  166. package/src/css/property-descriptors/overflow-wrap.ts +0 -22
  167. package/src/css/property-descriptors/overflow.ts +0 -34
  168. package/src/css/property-descriptors/padding.ts +0 -14
  169. package/src/css/property-descriptors/paint-order.ts +0 -42
  170. package/src/css/property-descriptors/position.ts +0 -30
  171. package/src/css/property-descriptors/quotes.ts +0 -57
  172. package/src/css/property-descriptors/rotate.ts +0 -34
  173. package/src/css/property-descriptors/text-align.ts +0 -26
  174. package/src/css/property-descriptors/text-decoration-color.ts +0 -9
  175. package/src/css/property-descriptors/text-decoration-line.ts +0 -38
  176. package/src/css/property-descriptors/text-decoration-style.ts +0 -32
  177. package/src/css/property-descriptors/text-decoration-thickness.ts +0 -30
  178. package/src/css/property-descriptors/text-overflow.ts +0 -23
  179. package/src/css/property-descriptors/text-shadow.ts +0 -52
  180. package/src/css/property-descriptors/text-transform.ts +0 -27
  181. package/src/css/property-descriptors/text-underline-offset.ts +0 -27
  182. package/src/css/property-descriptors/transform-origin.ts +0 -29
  183. package/src/css/property-descriptors/transform.ts +0 -74
  184. package/src/css/property-descriptors/visibility.ts +0 -25
  185. package/src/css/property-descriptors/webkit-line-clamp.ts +0 -30
  186. package/src/css/property-descriptors/webkit-text-stroke-color.ts +0 -8
  187. package/src/css/property-descriptors/webkit-text-stroke-width.ts +0 -15
  188. package/src/css/property-descriptors/word-break.ts +0 -25
  189. package/src/css/property-descriptors/writing-mode.ts +0 -37
  190. package/src/css/property-descriptors/z-index.ts +0 -27
  191. package/src/css/syntax/__tests__/tokernizer-tests.ts +0 -29
  192. package/src/css/syntax/parser.ts +0 -188
  193. package/src/css/syntax/tokenizer.ts +0 -822
  194. package/src/css/type-descriptor.ts +0 -7
  195. package/src/css/types/__tests__/color-tests.ts +0 -147
  196. package/src/css/types/__tests__/image-tests.ts +0 -239
  197. package/src/css/types/angle.ts +0 -86
  198. package/src/css/types/color-math.ts +0 -22
  199. package/src/css/types/color-spaces/a98.ts +0 -86
  200. package/src/css/types/color-spaces/p3.ts +0 -92
  201. package/src/css/types/color-spaces/pro-photo.ts +0 -87
  202. package/src/css/types/color-spaces/rec2020.ts +0 -90
  203. package/src/css/types/color-spaces/srgb.ts +0 -87
  204. package/src/css/types/color-utilities.ts +0 -452
  205. package/src/css/types/color.ts +0 -485
  206. package/src/css/types/functions/-prefix-linear-gradient.ts +0 -35
  207. package/src/css/types/functions/-prefix-radial-gradient.ts +0 -106
  208. package/src/css/types/functions/-webkit-gradient.ts +0 -69
  209. package/src/css/types/functions/__tests__/radial-gradient.ts +0 -69
  210. package/src/css/types/functions/counter.ts +0 -511
  211. package/src/css/types/functions/gradient.ts +0 -206
  212. package/src/css/types/functions/linear-gradient.ts +0 -28
  213. package/src/css/types/functions/radial-gradient.ts +0 -101
  214. package/src/css/types/image.ts +0 -120
  215. package/src/css/types/index.ts +0 -1
  216. package/src/css/types/length-percentage.ts +0 -137
  217. package/src/css/types/length.ts +0 -7
  218. package/src/css/types/time.ts +0 -20
  219. package/src/dom/__mocks__/document-cloner.ts +0 -22
  220. package/src/dom/__tests__/dom-normalizer.test.ts +0 -133
  221. package/src/dom/__tests__/element-container.test.ts +0 -129
  222. package/src/dom/document-cloner.ts +0 -929
  223. package/src/dom/dom-normalizer.ts +0 -133
  224. package/src/dom/element-container.ts +0 -75
  225. package/src/dom/elements/li-element-container.ts +0 -10
  226. package/src/dom/elements/ol-element-container.ts +0 -12
  227. package/src/dom/elements/select-element-container.ts +0 -10
  228. package/src/dom/elements/textarea-element-container.ts +0 -9
  229. package/src/dom/node-parser.ts +0 -177
  230. package/src/dom/node-type-guards.ts +0 -70
  231. package/src/dom/replaced-elements/canvas-element-container.ts +0 -15
  232. package/src/dom/replaced-elements/iframe-element-container.ts +0 -55
  233. package/src/dom/replaced-elements/image-element-container.ts +0 -16
  234. package/src/dom/replaced-elements/index.ts +0 -5
  235. package/src/dom/replaced-elements/input-element-container.ts +0 -105
  236. package/src/dom/replaced-elements/pseudo-elements.ts +0 -0
  237. package/src/dom/replaced-elements/svg-element-container.ts +0 -23
  238. package/src/dom/text-container.ts +0 -42
  239. package/src/global.d.ts +0 -19
  240. package/src/index.ts +0 -82
  241. package/src/invariant.ts +0 -5
  242. package/src/options.ts +0 -55
  243. package/src/render/__tests__/object-fit.test.ts +0 -85
  244. package/src/render/background.ts +0 -298
  245. package/src/render/bezier-curve.ts +0 -47
  246. package/src/render/border.ts +0 -165
  247. package/src/render/bound-curves.ts +0 -388
  248. package/src/render/box-sizing.ts +0 -31
  249. package/src/render/canvas/__tests__/background-renderer.test.ts +0 -72
  250. package/src/render/canvas/__tests__/border-renderer.test.ts +0 -24
  251. package/src/render/canvas/__tests__/effects-renderer.test.ts +0 -32
  252. package/src/render/canvas/__tests__/text-renderer.test.ts +0 -471
  253. package/src/render/canvas/background-renderer.ts +0 -271
  254. package/src/render/canvas/border-renderer.ts +0 -224
  255. package/src/render/canvas/canvas-path.ts +0 -31
  256. package/src/render/canvas/canvas-renderer.ts +0 -641
  257. package/src/render/canvas/effects-renderer.ts +0 -130
  258. package/src/render/canvas/foreignobject-renderer.ts +0 -53
  259. package/src/render/canvas/text-renderer.ts +0 -700
  260. package/src/render/effects.ts +0 -75
  261. package/src/render/font-metrics.ts +0 -72
  262. package/src/render/object-fit.ts +0 -100
  263. package/src/render/path.ts +0 -37
  264. package/src/render/renderer-interface.ts +0 -28
  265. package/src/render/stacking-context.ts +0 -386
  266. package/src/render/vector.ts +0 -19
@@ -1,271 +0,0 @@
1
- /**
2
- * Background Renderer
3
- *
4
- * Handles rendering of element backgrounds including:
5
- * - Background colors
6
- * - Background images (URL)
7
- * - Linear gradients
8
- * - Radial gradients
9
- * - Background patterns and repeats
10
- */
11
-
12
- import { Context } from '../../core/context';
13
- import { ElementContainer } from '../../dom/element-container';
14
- import { Path } from '../path';
15
- import {
16
- CSSImageType,
17
- CSSLinearGradientImage,
18
- CSSRadialGradientImage,
19
- CSSURLImage,
20
- isLinearGradient,
21
- isRadialGradient
22
- } from '../../css/types/image';
23
- import { calculateBackgroundRendering } from '../background';
24
- import { calculateGradientDirection, calculateRadius, processColorStops } from '../../css/types/functions/gradient';
25
- import { FIFTY_PERCENT, getAbsoluteValue } from '../../css/types/length-percentage';
26
- import { asString } from '../../css/types/color-utilities';
27
- import { IMAGE_RENDERING } from '../../css/property-descriptors/image-rendering';
28
- import { createCanvasPath } from './canvas-path';
29
-
30
- /**
31
- * Dependencies required for BackgroundRenderer
32
- */
33
- export interface BackgroundRendererDependencies {
34
- ctx: CanvasRenderingContext2D;
35
- context: Context;
36
- canvas: HTMLCanvasElement;
37
- options: {
38
- width: number;
39
- height: number;
40
- scale: number;
41
- };
42
- }
43
-
44
- /**
45
- * Background Renderer
46
- *
47
- * Specialized renderer for element backgrounds.
48
- * Extracted from CanvasRenderer to improve code organization and maintainability.
49
- */
50
- export class BackgroundRenderer {
51
- private readonly ctx: CanvasRenderingContext2D;
52
- private readonly context: Context;
53
- private readonly canvas: HTMLCanvasElement;
54
-
55
- constructor(deps: BackgroundRendererDependencies) {
56
- this.ctx = deps.ctx;
57
- this.context = deps.context;
58
- this.canvas = deps.canvas;
59
- // Options stored in deps but not needed as instance property
60
- }
61
-
62
- /**
63
- * Render background images for a container
64
- * Supports URL images, linear gradients, and radial gradients
65
- *
66
- * @param container - Element container with background styles
67
- */
68
- async renderBackgroundImage(container: ElementContainer): Promise<void> {
69
- let index = container.styles.backgroundImage.length - 1;
70
- for (const backgroundImage of container.styles.backgroundImage.slice(0).reverse()) {
71
- if (backgroundImage.type === CSSImageType.URL) {
72
- await this.renderBackgroundURLImage(container, backgroundImage as CSSURLImage, index);
73
- } else if (isLinearGradient(backgroundImage)) {
74
- this.renderLinearGradient(container, backgroundImage, index);
75
- } else if (isRadialGradient(backgroundImage)) {
76
- this.renderRadialGradient(container, backgroundImage, index);
77
- }
78
- index--;
79
- }
80
- }
81
-
82
- /**
83
- * Render a URL-based background image
84
- */
85
- private async renderBackgroundURLImage(
86
- container: ElementContainer,
87
- backgroundImage: CSSURLImage,
88
- index: number
89
- ): Promise<void> {
90
- let image;
91
- const url = backgroundImage.url;
92
- try {
93
- image = await this.context.cache.match(url);
94
- } catch (e) {
95
- this.context.logger.error(`Error loading background-image ${url}`);
96
- }
97
-
98
- if (image) {
99
- const imageWidth = isNaN(image.width) || image.width === 0 ? 1 : image.width;
100
- const imageHeight = isNaN(image.height) || image.height === 0 ? 1 : image.height;
101
- const [path, x, y, width, height] = calculateBackgroundRendering(container, index, [
102
- imageWidth,
103
- imageHeight,
104
- imageWidth / imageHeight
105
- ]);
106
- const pattern = this.ctx.createPattern(
107
- this.resizeImage(image as HTMLImageElement, width, height, container.styles.imageRendering),
108
- 'repeat'
109
- ) as CanvasPattern;
110
- this.renderRepeat(path, pattern, x, y);
111
- }
112
- }
113
-
114
- /**
115
- * Render a linear gradient background
116
- */
117
- private renderLinearGradient(
118
- container: ElementContainer,
119
- backgroundImage: CSSLinearGradientImage,
120
- index: number
121
- ): void {
122
- const [path, x, y, width, height] = calculateBackgroundRendering(container, index, [null, null, null]);
123
- const [lineLength, x0, x1, y0, y1] = calculateGradientDirection(backgroundImage.angle, width, height);
124
-
125
- const ownerDocument = this.canvas.ownerDocument ?? document;
126
- const canvas = ownerDocument.createElement('canvas');
127
- canvas.width = width;
128
- canvas.height = height;
129
- const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
130
- const gradient = ctx.createLinearGradient(x0, y0, x1, y1);
131
-
132
- processColorStops(backgroundImage.stops, lineLength || 1).forEach((colorStop) =>
133
- gradient.addColorStop(colorStop.stop, asString(colorStop.color))
134
- );
135
-
136
- ctx.fillStyle = gradient;
137
- ctx.fillRect(0, 0, width, height);
138
- if (width > 0 && height > 0) {
139
- const pattern = this.ctx.createPattern(canvas, 'repeat') as CanvasPattern;
140
- this.renderRepeat(path, pattern, x, y);
141
- }
142
- }
143
-
144
- /**
145
- * Render a radial gradient background
146
- */
147
- private renderRadialGradient(
148
- container: ElementContainer,
149
- backgroundImage: CSSRadialGradientImage,
150
- index: number
151
- ): void {
152
- const [path, left, top, width, height] = calculateBackgroundRendering(container, index, [null, null, null]);
153
- const position = backgroundImage.position.length === 0 ? [FIFTY_PERCENT] : backgroundImage.position;
154
- const x = getAbsoluteValue(position[0], width);
155
- const y = getAbsoluteValue(position[position.length - 1], height);
156
-
157
- let [rx, ry] = calculateRadius(backgroundImage, x, y, width, height);
158
- // Handle edge case where radial gradient size is 0
159
- // Use a minimum value of 0.01 to ensure gradient is still rendered
160
- if (rx === 0 || ry === 0) {
161
- rx = Math.max(rx, 0.01);
162
- ry = Math.max(ry, 0.01);
163
- }
164
- if (rx > 0 && ry > 0) {
165
- const radialGradient = this.ctx.createRadialGradient(left + x, top + y, 0, left + x, top + y, rx);
166
-
167
- processColorStops(backgroundImage.stops, rx * 2).forEach((colorStop) =>
168
- radialGradient.addColorStop(colorStop.stop, asString(colorStop.color))
169
- );
170
-
171
- this.path(path);
172
- this.ctx.fillStyle = radialGradient;
173
- if (rx !== ry) {
174
- // transforms for elliptical radial gradient
175
- const midX = container.bounds.left + 0.5 * container.bounds.width;
176
- const midY = container.bounds.top + 0.5 * container.bounds.height;
177
- const f = ry / rx;
178
- const invF = 1 / f;
179
-
180
- this.ctx.save();
181
- this.ctx.translate(midX, midY);
182
- this.ctx.transform(1, 0, 0, f, 0, 0);
183
- this.ctx.translate(-midX, -midY);
184
-
185
- this.ctx.fillRect(left, invF * (top - midY) + midY, width, height * invF);
186
- this.ctx.restore();
187
- } else {
188
- this.ctx.fill();
189
- }
190
- }
191
- }
192
-
193
- /**
194
- * Render a repeating pattern with offset
195
- *
196
- * @param path - Path to fill
197
- * @param pattern - Canvas pattern or gradient
198
- * @param offsetX - X offset for pattern
199
- * @param offsetY - Y offset for pattern
200
- */
201
- private renderRepeat(
202
- path: Path[],
203
- pattern: CanvasPattern | CanvasGradient,
204
- offsetX: number,
205
- offsetY: number
206
- ): void {
207
- this.path(path);
208
- this.ctx.fillStyle = pattern;
209
- this.ctx.translate(offsetX, offsetY);
210
- this.ctx.fill();
211
- this.ctx.translate(-offsetX, -offsetY);
212
- }
213
-
214
- /**
215
- * Resize an image to target dimensions
216
- *
217
- * @param image - Source image
218
- * @param width - Target width
219
- * @param height - Target height
220
- * @param imageRendering - CSS image-rendering property value
221
- * @returns Resized canvas or original image
222
- */
223
- private resizeImage(
224
- image: HTMLImageElement,
225
- width: number,
226
- height: number,
227
- imageRendering: IMAGE_RENDERING
228
- ): HTMLCanvasElement | HTMLImageElement {
229
- // https://github.com/niklasvh/html2canvas/pull/2911
230
- // if (image.width === width && image.height === height) {
231
- // return image;
232
- // }
233
-
234
- const ownerDocument = this.canvas.ownerDocument ?? document;
235
- const canvas = ownerDocument.createElement('canvas');
236
- canvas.width = Math.max(1, width);
237
- canvas.height = Math.max(1, height);
238
- const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
239
-
240
- // Apply image smoothing based on CSS image-rendering property
241
- if (imageRendering === IMAGE_RENDERING.PIXELATED || imageRendering === IMAGE_RENDERING.CRISP_EDGES) {
242
- this.context.logger.debug(`Disabling image smoothing for background image due to CSS image-rendering`);
243
- ctx.imageSmoothingEnabled = false;
244
- } else if (imageRendering === IMAGE_RENDERING.SMOOTH) {
245
- this.context.logger.debug(
246
- `Enabling image smoothing for background image due to CSS image-rendering: smooth`
247
- );
248
- ctx.imageSmoothingEnabled = true;
249
- } else {
250
- // AUTO: inherit from main renderer context
251
- ctx.imageSmoothingEnabled = this.ctx.imageSmoothingEnabled;
252
- }
253
-
254
- // Inherit quality setting
255
- if (this.ctx.imageSmoothingQuality) {
256
- ctx.imageSmoothingQuality = this.ctx.imageSmoothingQuality;
257
- }
258
-
259
- ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, width, height);
260
- return canvas;
261
- }
262
-
263
- /**
264
- * Create a canvas path from path array
265
- *
266
- * @param paths - Array of path points
267
- */
268
- private path(paths: Path[]): void {
269
- createCanvasPath(this.ctx, paths);
270
- }
271
- }
@@ -1,224 +0,0 @@
1
- /**
2
- * Border Renderer
3
- *
4
- * Handles rendering of element borders including:
5
- * - Solid borders
6
- * - Double borders
7
- * - Dashed borders
8
- * - Dotted borders
9
- */
10
-
11
- import { Color } from '../../css/types/color';
12
- import { asString } from '../../css/types/color-utilities';
13
- import { BoundCurves } from '../bound-curves';
14
- import { BORDER_STYLE } from '../../css/property-descriptors/border-style';
15
- import {
16
- parsePathForBorder,
17
- parsePathForBorderDoubleInner,
18
- parsePathForBorderDoubleOuter,
19
- parsePathForBorderStroke
20
- } from '../border';
21
- import { isBezierCurve, BezierCurve } from '../bezier-curve';
22
- import { Vector } from '../vector';
23
- import { Path } from '../path';
24
-
25
- /**
26
- * Dependencies required for BorderRenderer
27
- */
28
- export interface BorderRendererDependencies {
29
- ctx: CanvasRenderingContext2D;
30
- }
31
-
32
- /**
33
- * Path creation callbacks
34
- * The main CanvasRenderer retains path() and formatPath() methods,
35
- * so we inject them as callbacks to avoid duplication
36
- */
37
- export interface PathCallbacks {
38
- path(paths: Path[]): void;
39
- formatPath(paths: Path[]): void;
40
- }
41
-
42
- /**
43
- * Border Renderer
44
- *
45
- * Specialized renderer for element borders.
46
- * Extracted from CanvasRenderer to improve code organization and maintainability.
47
- */
48
- export class BorderRenderer {
49
- private readonly ctx: CanvasRenderingContext2D;
50
- private pathCallbacks: PathCallbacks;
51
-
52
- constructor(deps: BorderRendererDependencies, pathCallbacks: PathCallbacks) {
53
- this.ctx = deps.ctx;
54
- this.pathCallbacks = pathCallbacks;
55
- }
56
-
57
- /**
58
- * Render a solid border
59
- *
60
- * @param color - Border color
61
- * @param side - Border side (0=top, 1=right, 2=bottom, 3=left)
62
- * @param curvePoints - Border curve points
63
- */
64
- async renderSolidBorder(color: Color, side: number, curvePoints: BoundCurves): Promise<void> {
65
- this.pathCallbacks.path(parsePathForBorder(curvePoints, side));
66
- this.ctx.fillStyle = asString(color);
67
- this.ctx.fill();
68
- }
69
-
70
- /**
71
- * Render a double border
72
- * Falls back to solid border if width is too small
73
- *
74
- * @param color - Border color
75
- * @param width - Border width
76
- * @param side - Border side (0=top, 1=right, 2=bottom, 3=left)
77
- * @param curvePoints - Border curve points
78
- */
79
- async renderDoubleBorder(color: Color, width: number, side: number, curvePoints: BoundCurves): Promise<void> {
80
- if (width < 3) {
81
- await this.renderSolidBorder(color, side, curvePoints);
82
- return;
83
- }
84
-
85
- const outerPaths = parsePathForBorderDoubleOuter(curvePoints, side);
86
- this.pathCallbacks.path(outerPaths);
87
- this.ctx.fillStyle = asString(color);
88
- this.ctx.fill();
89
- const innerPaths = parsePathForBorderDoubleInner(curvePoints, side);
90
- this.pathCallbacks.path(innerPaths);
91
- this.ctx.fill();
92
- }
93
-
94
- /**
95
- * Render a dashed or dotted border
96
- *
97
- * @param color - Border color
98
- * @param width - Border width
99
- * @param side - Border side (0=top, 1=right, 2=bottom, 3=left)
100
- * @param curvePoints - Border curve points
101
- * @param style - Border style (DASHED or DOTTED)
102
- */
103
- async renderDashedDottedBorder(
104
- color: Color,
105
- width: number,
106
- side: number,
107
- curvePoints: BoundCurves,
108
- style: BORDER_STYLE
109
- ): Promise<void> {
110
- this.ctx.save();
111
-
112
- const strokePaths = parsePathForBorderStroke(curvePoints, side);
113
- const boxPaths = parsePathForBorder(curvePoints, side);
114
-
115
- if (style === BORDER_STYLE.DASHED) {
116
- this.pathCallbacks.path(boxPaths);
117
- this.ctx.clip();
118
- }
119
-
120
- // Extract start and end coordinates
121
- let startX, startY, endX, endY;
122
- if (isBezierCurve(boxPaths[0])) {
123
- startX = (boxPaths[0] as BezierCurve).start.x;
124
- startY = (boxPaths[0] as BezierCurve).start.y;
125
- } else {
126
- startX = (boxPaths[0] as Vector).x;
127
- startY = (boxPaths[0] as Vector).y;
128
- }
129
- if (isBezierCurve(boxPaths[1])) {
130
- endX = (boxPaths[1] as BezierCurve).end.x;
131
- endY = (boxPaths[1] as BezierCurve).end.y;
132
- } else {
133
- endX = (boxPaths[1] as Vector).x;
134
- endY = (boxPaths[1] as Vector).y;
135
- }
136
-
137
- // Calculate border length
138
- let length;
139
- if (side === 0 || side === 2) {
140
- length = Math.abs(startX - endX);
141
- } else {
142
- length = Math.abs(startY - endY);
143
- }
144
-
145
- this.ctx.beginPath();
146
- if (style === BORDER_STYLE.DOTTED) {
147
- this.pathCallbacks.formatPath(strokePaths);
148
- } else {
149
- this.pathCallbacks.formatPath(boxPaths.slice(0, 2));
150
- }
151
-
152
- // Calculate dash and space lengths
153
- let dashLength = width < 3 ? width * 3 : width * 2;
154
- let spaceLength = width < 3 ? width * 2 : width;
155
- if (style === BORDER_STYLE.DOTTED) {
156
- dashLength = width;
157
- spaceLength = width;
158
- }
159
-
160
- // Adjust dash pattern for border length
161
- let useLineDash = true;
162
- if (length <= dashLength * 2) {
163
- useLineDash = false;
164
- } else if (length <= dashLength * 2 + spaceLength) {
165
- const multiplier = length / (2 * dashLength + spaceLength);
166
- dashLength *= multiplier;
167
- spaceLength *= multiplier;
168
- } else {
169
- const numberOfDashes = Math.floor((length + spaceLength) / (dashLength + spaceLength));
170
- const minSpace = (length - numberOfDashes * dashLength) / (numberOfDashes - 1);
171
- const maxSpace = (length - (numberOfDashes + 1) * dashLength) / numberOfDashes;
172
- spaceLength =
173
- maxSpace <= 0 || Math.abs(spaceLength - minSpace) < Math.abs(spaceLength - maxSpace)
174
- ? minSpace
175
- : maxSpace;
176
- }
177
-
178
- // Apply line dash pattern
179
- if (useLineDash) {
180
- if (style === BORDER_STYLE.DOTTED) {
181
- this.ctx.setLineDash([0, dashLength + spaceLength]);
182
- } else {
183
- this.ctx.setLineDash([dashLength, spaceLength]);
184
- }
185
- }
186
-
187
- // Set line style and stroke
188
- if (style === BORDER_STYLE.DOTTED) {
189
- this.ctx.lineCap = 'round';
190
- this.ctx.lineWidth = width;
191
- } else {
192
- this.ctx.lineWidth = width * 2 + 1.1;
193
- }
194
- this.ctx.strokeStyle = asString(color);
195
- this.ctx.stroke();
196
- this.ctx.setLineDash([]);
197
-
198
- // Fill dashed round edge gaps
199
- if (style === BORDER_STYLE.DASHED) {
200
- if (isBezierCurve(boxPaths[0])) {
201
- const path1 = boxPaths[3] as BezierCurve;
202
- const path2 = boxPaths[0] as BezierCurve;
203
- this.ctx.beginPath();
204
- this.pathCallbacks.formatPath([
205
- new Vector(path1.end.x, path1.end.y),
206
- new Vector(path2.start.x, path2.start.y)
207
- ]);
208
- this.ctx.stroke();
209
- }
210
- if (isBezierCurve(boxPaths[1])) {
211
- const path1 = boxPaths[1] as BezierCurve;
212
- const path2 = boxPaths[2] as BezierCurve;
213
- this.ctx.beginPath();
214
- this.pathCallbacks.formatPath([
215
- new Vector(path1.end.x, path1.end.y),
216
- new Vector(path2.start.x, path2.start.y)
217
- ]);
218
- this.ctx.stroke();
219
- }
220
- }
221
-
222
- this.ctx.restore();
223
- }
224
- }
@@ -1,31 +0,0 @@
1
- import { isBezierCurve } from '../bezier-curve';
2
- import { Path } from '../path';
3
- import { Vector } from '../vector';
4
-
5
- export const formatCanvasPath = (ctx: CanvasRenderingContext2D, paths: Path[]): void => {
6
- paths.forEach((point, index) => {
7
- const start: Vector = isBezierCurve(point) ? point.start : point;
8
- if (index === 0) {
9
- ctx.moveTo(start.x, start.y);
10
- } else {
11
- ctx.lineTo(start.x, start.y);
12
- }
13
-
14
- if (isBezierCurve(point)) {
15
- ctx.bezierCurveTo(
16
- point.startControl.x,
17
- point.startControl.y,
18
- point.endControl.x,
19
- point.endControl.y,
20
- point.end.x,
21
- point.end.y
22
- );
23
- }
24
- });
25
- };
26
-
27
- export const createCanvasPath = (ctx: CanvasRenderingContext2D, paths: Path[]): void => {
28
- ctx.beginPath();
29
- formatCanvasPath(ctx, paths);
30
- ctx.closePath();
31
- };