fabric 5.3.0 → 6.0.0-beta3

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 (604) hide show
  1. package/.babelrc +11 -0
  2. package/.babelrcAlt +19 -0
  3. package/.browserslistrc +5 -0
  4. package/.eslintignore +3 -0
  5. package/.eslintrc.js +43 -0
  6. package/.eslintrc.json +38 -46
  7. package/.eslintrc_tests +12 -0
  8. package/.gitattributes +2 -0
  9. package/.gitpod.yml +17 -1
  10. package/.prettierignore +19 -0
  11. package/.prettierrc +4 -0
  12. package/CHANGELOG.md +532 -189
  13. package/CONTRIBUTING.md +224 -59
  14. package/README.md +200 -235
  15. package/bower.json +1 -3
  16. package/dist/fabric.d.ts +42 -0
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.js +27582 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/index.min.js +1 -0
  21. package/dist/index.mjs +27519 -0
  22. package/dist/index.mjs.map +1 -0
  23. package/dist/index.node.cjs +27663 -0
  24. package/dist/index.node.cjs.map +1 -0
  25. package/dist/index.node.d.ts +14 -0
  26. package/dist/index.node.mjs +27606 -0
  27. package/dist/index.node.mjs.map +1 -0
  28. package/dist/src/ClassRegistry.d.ts +13 -0
  29. package/dist/src/Collection.d.ts +136 -0
  30. package/dist/src/CommonMethods.d.ts +32 -0
  31. package/dist/src/EventTypeDefs.d.ts +227 -0
  32. package/dist/src/Intersection.d.ts +112 -0
  33. package/dist/src/Observable.d.ts +60 -0
  34. package/dist/src/Pattern.d.ts +113 -0
  35. package/dist/src/Point.d.ts +232 -0
  36. package/dist/src/Shadow.d.ts +97 -0
  37. package/dist/src/brushes/BaseBrush.d.ts +105 -0
  38. package/dist/src/brushes/CircleBrush.d.ts +49 -0
  39. package/dist/src/brushes/PatternBrush.d.ts +23 -0
  40. package/dist/src/brushes/PencilBrush.d.ts +92 -0
  41. package/dist/src/brushes/SprayBrush.d.ts +79 -0
  42. package/dist/src/cache.d.ts +47 -0
  43. package/dist/src/canvas/Canvas.d.ts +548 -0
  44. package/dist/src/canvas/SelectableCanvas.d.ts +754 -0
  45. package/dist/src/canvas/StaticCanvas.d.ts +778 -0
  46. package/dist/src/canvas/TextEditingManager.d.ts +17 -0
  47. package/dist/src/canvas/canvas_gestures.mixin.d.ts +2 -0
  48. package/dist/src/color/Color.d.ts +174 -0
  49. package/dist/src/color/color_map.d.ts +155 -0
  50. package/dist/src/color/constants.d.ts +22 -0
  51. package/dist/src/color/util.d.ts +12 -0
  52. package/dist/src/config.d.ts +115 -0
  53. package/dist/src/constants.d.ts +14 -0
  54. package/dist/src/controls/Control.d.ts +228 -0
  55. package/dist/src/controls/changeWidth.d.ts +13 -0
  56. package/dist/src/controls/commonControls.d.ts +28 -0
  57. package/dist/src/controls/controlRendering.d.ts +29 -0
  58. package/dist/src/controls/drag.d.ts +12 -0
  59. package/dist/src/controls/index.d.ts +13 -0
  60. package/dist/src/controls/polyControl.d.ts +5 -0
  61. package/dist/src/controls/rotate.d.ts +12 -0
  62. package/dist/src/controls/scale.d.ts +47 -0
  63. package/dist/src/controls/scaleSkew.d.ts +39 -0
  64. package/dist/src/controls/skew.d.ts +33 -0
  65. package/dist/src/controls/util.d.ts +41 -0
  66. package/dist/src/controls/wrapWithFireEvent.d.ts +8 -0
  67. package/dist/src/controls/wrapWithFixedAnchor.d.ts +9 -0
  68. package/dist/src/env/browser.d.ts +3 -0
  69. package/dist/src/env/index.d.ts +15 -0
  70. package/dist/src/env/node.d.ts +5 -0
  71. package/dist/src/env/types.d.ts +15 -0
  72. package/dist/src/filters/BaseFilter.d.ts +153 -0
  73. package/dist/src/filters/BlendColor.d.ts +80 -0
  74. package/dist/src/filters/BlendImage.d.ts +92 -0
  75. package/dist/src/filters/Blur.d.ts +51 -0
  76. package/dist/src/filters/Boilerplate.d.ts +48 -0
  77. package/dist/src/filters/Brightness.d.ts +47 -0
  78. package/dist/src/filters/Canvas2dFilterBackend.d.ts +27 -0
  79. package/dist/src/filters/ColorMatrix.d.ts +63 -0
  80. package/dist/src/filters/ColorMatrixFilters.d.ts +545 -0
  81. package/dist/src/filters/Composed.d.ts +45 -0
  82. package/dist/src/filters/Contrast.d.ts +45 -0
  83. package/dist/src/filters/Convolute.d.ts +82 -0
  84. package/dist/src/filters/FilterBackend.d.ts +14 -0
  85. package/dist/src/filters/GLProbes/GLProbe.d.ts +11 -0
  86. package/dist/src/filters/GLProbes/NodeGLProbe.d.ts +11 -0
  87. package/dist/src/filters/GLProbes/WebGLProbe.d.ts +20 -0
  88. package/dist/src/filters/Gamma.d.ts +54 -0
  89. package/dist/src/filters/Grayscale.d.ts +46 -0
  90. package/dist/src/filters/HueRotation.d.ts +24 -0
  91. package/dist/src/filters/Invert.d.ts +55 -0
  92. package/dist/src/filters/Noise.d.ts +54 -0
  93. package/dist/src/filters/Pixelate.d.ts +44 -0
  94. package/dist/src/filters/RemoveColor.d.ts +63 -0
  95. package/dist/src/filters/Resize.d.ts +136 -0
  96. package/dist/src/filters/Saturation.d.ts +48 -0
  97. package/dist/src/filters/Vibrance.d.ts +48 -0
  98. package/dist/src/filters/WebGLFilterBackend.d.ts +126 -0
  99. package/dist/src/filters/filters.d.ts +21 -0
  100. package/dist/src/filters/index.d.ts +5 -0
  101. package/dist/src/filters/shaders/baseFilter.d.ts +4 -0
  102. package/dist/src/filters/shaders/blendColor.d.ts +13 -0
  103. package/dist/src/filters/shaders/blendImage.d.ts +3 -0
  104. package/dist/src/filters/shaders/blur.d.ts +2 -0
  105. package/dist/src/filters/shaders/brightness.d.ts +2 -0
  106. package/dist/src/filters/shaders/colorMatrix.d.ts +2 -0
  107. package/dist/src/filters/shaders/constrast.d.ts +2 -0
  108. package/dist/src/filters/shaders/convolute.d.ts +11 -0
  109. package/dist/src/filters/shaders/gamma.d.ts +2 -0
  110. package/dist/src/filters/shaders/grayscale.d.ts +3 -0
  111. package/dist/src/filters/shaders/invert.d.ts +2 -0
  112. package/dist/src/filters/shaders/noise.d.ts +2 -0
  113. package/dist/src/filters/shaders/pixelate.d.ts +2 -0
  114. package/dist/src/filters/shaders/removeColor.d.ts +2 -0
  115. package/dist/src/filters/shaders/saturation.d.ts +2 -0
  116. package/dist/src/filters/shaders/vibrance.d.ts +2 -0
  117. package/dist/src/filters/typedefs.d.ts +49 -0
  118. package/dist/src/gradient/Gradient.d.ts +149 -0
  119. package/dist/src/gradient/constants.d.ts +15 -0
  120. package/dist/src/gradient/parser/index.d.ts +4 -0
  121. package/dist/src/gradient/parser/misc.d.ts +4 -0
  122. package/dist/src/gradient/parser/parseColorStops.d.ts +3 -0
  123. package/dist/src/gradient/parser/parseCoords.d.ts +17 -0
  124. package/dist/src/gradient/typedefs.d.ts +93 -0
  125. package/dist/src/mixins/eraser_brush.mixin.d.ts +2 -0
  126. package/dist/src/parkinglot/canvas_animation.mixin.d.ts +2 -0
  127. package/dist/src/parkinglot/straighten.d.ts +2 -0
  128. package/dist/src/parser/applyViewboxTransform.d.ts +5 -0
  129. package/dist/src/parser/attributes.d.ts +6 -0
  130. package/dist/src/parser/constants.d.ts +53 -0
  131. package/dist/src/parser/doesSomeParentMatch.d.ts +2 -0
  132. package/dist/src/parser/elementById.d.ts +6 -0
  133. package/dist/src/parser/elementMatchesRule.d.ts +5 -0
  134. package/dist/src/parser/elements_parser.d.ts +3 -0
  135. package/dist/src/parser/getCSSRules.d.ts +7 -0
  136. package/dist/src/parser/getGlobalStylesForElement.d.ts +5 -0
  137. package/dist/src/parser/getGradientDefs.d.ts +7 -0
  138. package/dist/src/parser/getMultipleNodes.d.ts +2 -0
  139. package/dist/src/parser/getSvgRegex.d.ts +2 -0
  140. package/dist/src/parser/hasAncestorWithNodeName.d.ts +2 -0
  141. package/dist/src/parser/index.d.ts +10 -0
  142. package/dist/src/parser/loadSVGFromString.d.ts +12 -0
  143. package/dist/src/parser/loadSVGFromURL.d.ts +13 -0
  144. package/dist/src/parser/normalizeAttr.d.ts +2 -0
  145. package/dist/src/parser/normalizeValue.d.ts +2 -0
  146. package/dist/src/parser/parseAttributes.d.ts +9 -0
  147. package/dist/src/parser/parseElements.d.ts +11 -0
  148. package/dist/src/parser/parseFontDeclaration.d.ts +10 -0
  149. package/dist/src/parser/parsePointsAttribute.d.ts +12 -0
  150. package/dist/src/parser/parseSVGDocument.d.ts +15 -0
  151. package/dist/src/parser/parseStyleAttribute.d.ts +9 -0
  152. package/dist/src/parser/parseStyleObject.d.ts +2 -0
  153. package/dist/src/parser/parseStyleString.d.ts +2 -0
  154. package/dist/src/parser/parseTransformAttribute.d.ts +10 -0
  155. package/dist/src/parser/parseUseDirectives.d.ts +2 -0
  156. package/dist/src/parser/percent.d.ts +9 -0
  157. package/dist/src/parser/recursivelyParseGradientsXlink.d.ts +2 -0
  158. package/dist/src/parser/rotateMatrix.d.ts +2 -0
  159. package/dist/src/parser/scaleMatrix.d.ts +2 -0
  160. package/dist/src/parser/selectorMatches.d.ts +2 -0
  161. package/dist/src/parser/setStrokeFillOpacity.d.ts +6 -0
  162. package/dist/src/parser/skewMatrix.d.ts +2 -0
  163. package/dist/src/parser/translateMatrix.d.ts +2 -0
  164. package/dist/src/shapes/ActiveSelection.d.ts +82 -0
  165. package/dist/src/shapes/Circle.d.ts +99 -0
  166. package/dist/src/shapes/Ellipse.d.ts +84 -0
  167. package/dist/src/shapes/Group.d.ts +408 -0
  168. package/dist/src/shapes/IText/DraggableTextDelegate.d.ts +78 -0
  169. package/dist/src/shapes/IText/IText.d.ts +335 -0
  170. package/dist/src/shapes/IText/ITextBehavior.d.ts +287 -0
  171. package/dist/src/shapes/IText/ITextClickBehavior.d.ts +83 -0
  172. package/dist/src/shapes/IText/ITextKeyBehavior.d.ts +195 -0
  173. package/dist/src/shapes/IText/constants.d.ts +13 -0
  174. package/dist/src/shapes/Image.d.ts +311 -0
  175. package/dist/src/shapes/Line.d.ts +126 -0
  176. package/dist/src/shapes/Object/AnimatableObject.d.ts +33 -0
  177. package/dist/src/shapes/Object/FabricObject.d.ts +11 -0
  178. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.d.ts +74 -0
  179. package/dist/src/shapes/Object/InteractiveObject.d.ts +296 -0
  180. package/dist/src/shapes/Object/Object.d.ts +594 -0
  181. package/dist/src/shapes/Object/ObjectGeometry.d.ts +327 -0
  182. package/dist/src/shapes/Object/ObjectOrigin.d.ts +109 -0
  183. package/dist/src/shapes/Object/StackedObject.d.ts +72 -0
  184. package/dist/src/shapes/Object/defaultValues.d.ts +76 -0
  185. package/dist/src/shapes/Object/types/BaseProps.d.ts +84 -0
  186. package/dist/src/shapes/Object/types/BorderProps.d.ts +37 -0
  187. package/dist/src/shapes/Object/types/ControlProps.d.ts +62 -0
  188. package/dist/src/shapes/Object/types/FabricObjectProps.d.ts +96 -0
  189. package/dist/src/shapes/Object/types/FillStrokeProps.d.ts +80 -0
  190. package/dist/src/shapes/Object/types/LockInteractionProps.d.ts +51 -0
  191. package/dist/src/shapes/Object/types/ObjectProps.d.ts +42 -0
  192. package/dist/src/shapes/Object/types/SerializedObjectProps.d.ts +66 -0
  193. package/dist/src/shapes/Object/types/index.d.ts +6 -0
  194. package/dist/src/shapes/Path.d.ts +130 -0
  195. package/dist/src/shapes/Polygon.d.ts +9 -0
  196. package/dist/src/shapes/Polyline.d.ts +140 -0
  197. package/dist/src/shapes/Rect.d.ts +76 -0
  198. package/dist/src/shapes/Text/StyledText.d.ts +119 -0
  199. package/dist/src/shapes/Text/Text.d.ts +673 -0
  200. package/dist/src/shapes/Text/TextSVGExportMixin.d.ts +32 -0
  201. package/dist/src/shapes/Text/constants.d.ts +7 -0
  202. package/dist/src/shapes/Textbox.d.ts +185 -0
  203. package/dist/src/shapes/Triangle.d.ts +25 -0
  204. package/dist/src/typedefs.d.ts +90 -0
  205. package/dist/src/util/animation/AnimationBase.d.ts +54 -0
  206. package/dist/src/util/animation/AnimationFrameProvider.d.ts +3 -0
  207. package/dist/src/util/animation/AnimationRegistry.d.ts +29 -0
  208. package/dist/src/util/animation/ArrayAnimation.d.ts +10 -0
  209. package/dist/src/util/animation/ColorAnimation.d.ts +11 -0
  210. package/dist/src/util/animation/ValueAnimation.d.ts +10 -0
  211. package/dist/src/util/animation/animate.d.ts +37 -0
  212. package/dist/src/util/animation/easing.d.ts +130 -0
  213. package/dist/src/util/animation/types.d.ts +87 -0
  214. package/dist/src/util/applyMixins.d.ts +8 -0
  215. package/dist/src/util/dom_event.d.ts +5 -0
  216. package/dist/src/util/dom_misc.d.ts +39 -0
  217. package/dist/src/util/dom_request.d.ts +14 -0
  218. package/dist/src/util/dom_style.d.ts +7 -0
  219. package/dist/src/util/fireEvent.d.ts +3 -0
  220. package/dist/src/util/index.d.ts +35 -0
  221. package/dist/src/util/internals/cloneDeep.d.ts +2 -0
  222. package/dist/src/util/internals/getRandomInt.d.ts +8 -0
  223. package/dist/src/util/internals/ifNaN.d.ts +8 -0
  224. package/dist/src/util/internals/index.d.ts +4 -0
  225. package/dist/src/util/internals/removeFromArray.d.ts +9 -0
  226. package/dist/src/util/internals/uid.d.ts +2 -0
  227. package/dist/src/util/lang_string.d.ts +22 -0
  228. package/dist/src/util/misc/boundingBoxFromPoints.d.ts +9 -0
  229. package/dist/src/util/misc/capValue.d.ts +2 -0
  230. package/dist/src/util/misc/cos.d.ts +10 -0
  231. package/dist/src/util/misc/dom.d.ts +28 -0
  232. package/dist/src/util/misc/findScaleTo.d.ts +29 -0
  233. package/dist/src/util/misc/groupSVGElements.d.ts +9 -0
  234. package/dist/src/util/misc/isTransparent.d.ts +11 -0
  235. package/dist/src/util/misc/matrix.d.ts +92 -0
  236. package/dist/src/util/misc/mergeClipPaths.d.ts +23 -0
  237. package/dist/src/util/misc/objectEnlive.d.ts +56 -0
  238. package/dist/src/util/misc/objectTransforms.d.ts +68 -0
  239. package/dist/src/util/misc/pick.d.ts +9 -0
  240. package/dist/src/util/misc/planeChange.d.ts +84 -0
  241. package/dist/src/util/misc/projectStroke/StrokeLineCapProjections.d.ts +51 -0
  242. package/dist/src/util/misc/projectStroke/StrokeLineJoinProjections.d.ts +81 -0
  243. package/dist/src/util/misc/projectStroke/StrokeProjectionsBase.d.ts +25 -0
  244. package/dist/src/util/misc/projectStroke/index.d.ts +11 -0
  245. package/dist/src/util/misc/projectStroke/types.d.ts +23 -0
  246. package/dist/src/util/misc/radiansDegreesConversion.d.ts +14 -0
  247. package/dist/src/util/misc/resolveOrigin.d.ts +9 -0
  248. package/dist/src/util/misc/rotatePoint.d.ts +12 -0
  249. package/dist/src/util/misc/sin.d.ts +10 -0
  250. package/dist/src/util/misc/svgParsing.d.ts +53 -0
  251. package/dist/src/util/misc/textStyles.d.ts +32 -0
  252. package/dist/src/util/misc/toFixed.d.ts +8 -0
  253. package/dist/src/util/misc/vectors.d.ts +57 -0
  254. package/dist/src/util/path/index.d.ts +96 -0
  255. package/dist/src/util/path/regex.d.ts +3 -0
  256. package/dist/src/util/path/typechecks.d.ts +24 -0
  257. package/dist/src/util/path/typedefs.d.ts +220 -0
  258. package/dist/src/util/transform_matrix_removal.d.ts +14 -0
  259. package/dist/src/util/types.d.ts +19 -0
  260. package/fabric.ts +51 -0
  261. package/index.node.ts +37 -0
  262. package/index.ts +1 -0
  263. package/package.json +100 -40
  264. package/publish.js +0 -26
  265. package/rollup.config.mjs +91 -0
  266. package/rollup.test.config.js +24 -0
  267. package/scripts/build.mjs +50 -0
  268. package/scripts/buildLock.mjs +115 -0
  269. package/scripts/buildReporter.mjs +15 -0
  270. package/scripts/buildStats.mjs +139 -0
  271. package/scripts/dirname.mjs +14 -0
  272. package/scripts/git.mjs +36 -0
  273. package/scripts/index.mjs +564 -0
  274. package/scripts/sandbox.mjs +149 -0
  275. package/src/ClassRegistry.ts +56 -0
  276. package/src/Collection.ts +346 -0
  277. package/src/CommonMethods.ts +63 -0
  278. package/src/EventTypeDefs.ts +296 -0
  279. package/src/Intersection.ts +302 -0
  280. package/src/Observable.ts +181 -0
  281. package/src/Pattern.ts +227 -0
  282. package/src/Point.ts +388 -0
  283. package/src/Shadow.ts +214 -0
  284. package/src/brushes/{base_brush.class.js → BaseBrush.ts} +65 -42
  285. package/src/brushes/CircleBrush.ts +145 -0
  286. package/src/brushes/PatternBrush.ts +70 -0
  287. package/src/brushes/PencilBrush.ts +300 -0
  288. package/src/brushes/SprayBrush.ts +219 -0
  289. package/src/cache.ts +90 -0
  290. package/src/canvas/Canvas.ts +1607 -0
  291. package/src/canvas/SelectableCanvas.ts +1608 -0
  292. package/src/canvas/StaticCanvas.ts +1734 -0
  293. package/src/canvas/TextEditingManager.ts +48 -0
  294. package/src/canvas/canvas_gestures.mixin.ts +207 -0
  295. package/src/color/Color.ts +404 -0
  296. package/src/color/color_map.ts +154 -0
  297. package/src/color/constants.ts +26 -0
  298. package/src/color/util.ts +32 -0
  299. package/src/config.ts +159 -0
  300. package/src/constants.ts +20 -0
  301. package/src/controls/Control.ts +380 -0
  302. package/src/controls/changeWidth.ts +52 -0
  303. package/src/controls/commonControls.ts +105 -0
  304. package/src/controls/controlRendering.ts +138 -0
  305. package/src/controls/drag.ts +31 -0
  306. package/src/controls/index.ts +22 -0
  307. package/src/controls/polyControl.ts +135 -0
  308. package/src/controls/rotate.ts +87 -0
  309. package/src/controls/scale.ts +277 -0
  310. package/src/controls/scaleSkew.ts +92 -0
  311. package/src/controls/skew.ts +242 -0
  312. package/src/controls/util.ts +154 -0
  313. package/src/controls/wrapWithFireEvent.ts +25 -0
  314. package/src/controls/wrapWithFixedAnchor.ts +20 -0
  315. package/src/env/browser.ts +32 -0
  316. package/src/env/index.ts +24 -0
  317. package/src/env/node.ts +56 -0
  318. package/src/env/types.ts +15 -0
  319. package/src/filters/{base_filter.class.js → BaseFilter.ts} +192 -151
  320. package/src/filters/BlendColor.ts +217 -0
  321. package/src/filters/BlendImage.ts +228 -0
  322. package/src/filters/Blur.ts +179 -0
  323. package/src/filters/Boilerplate.ts +94 -0
  324. package/src/filters/Brightness.ts +83 -0
  325. package/src/filters/Canvas2dFilterBackend.ts +65 -0
  326. package/src/filters/ColorMatrix.ts +145 -0
  327. package/src/filters/ColorMatrixFilters.ts +77 -0
  328. package/src/filters/Composed.ts +76 -0
  329. package/src/filters/Contrast.ts +82 -0
  330. package/src/filters/Convolute.ts +184 -0
  331. package/src/filters/FilterBackend.ts +34 -0
  332. package/src/filters/GLProbes/GLProbe.ts +11 -0
  333. package/src/filters/GLProbes/NodeGLProbe.ts +15 -0
  334. package/src/filters/GLProbes/WebGLProbe.ts +46 -0
  335. package/src/filters/Gamma.ts +110 -0
  336. package/src/filters/Grayscale.ts +102 -0
  337. package/src/filters/HueRotation.ts +62 -0
  338. package/src/filters/Invert.ts +99 -0
  339. package/src/filters/Noise.ts +94 -0
  340. package/src/filters/Pixelate.ts +96 -0
  341. package/src/filters/RemoveColor.ts +135 -0
  342. package/src/filters/Resize.ts +538 -0
  343. package/src/filters/Saturation.ts +87 -0
  344. package/src/filters/Vibrance.ts +88 -0
  345. package/src/filters/WebGLFilterBackend.ts +430 -0
  346. package/src/filters/filters.ts +28 -0
  347. package/src/filters/index.ts +5 -0
  348. package/src/filters/shaders/baseFilter.ts +19 -0
  349. package/src/filters/shaders/blendColor.ts +33 -0
  350. package/src/filters/shaders/blendImage.ts +32 -0
  351. package/src/filters/shaders/blur.ts +24 -0
  352. package/src/filters/shaders/brightness.ts +11 -0
  353. package/src/filters/shaders/colorMatrix.ts +12 -0
  354. package/src/filters/shaders/constrast.ts +11 -0
  355. package/src/filters/shaders/convolute.ts +154 -0
  356. package/src/filters/shaders/gamma.ts +15 -0
  357. package/src/filters/shaders/grayscale.ts +36 -0
  358. package/src/filters/shaders/invert.ts +19 -0
  359. package/src/filters/shaders/noise.ts +16 -0
  360. package/src/filters/shaders/pixelate.ts +19 -0
  361. package/src/filters/shaders/removeColor.ts +13 -0
  362. package/src/filters/shaders/saturation.ts +15 -0
  363. package/src/filters/shaders/vibrance.ts +16 -0
  364. package/src/filters/typedefs.ts +65 -0
  365. package/src/gradient/Gradient.ts +406 -0
  366. package/src/gradient/constants.ts +12 -0
  367. package/src/gradient/parser/index.ts +3 -0
  368. package/src/gradient/parser/misc.ts +13 -0
  369. package/src/gradient/parser/parseColorStops.ts +56 -0
  370. package/src/gradient/parser/parseCoords.ts +73 -0
  371. package/src/gradient/typedefs.ts +104 -0
  372. package/src/mixins/{eraser_brush.mixin.js → eraser_brush.mixin.ts} +350 -239
  373. package/src/parkinglot/canvas_animation.mixin.ts +121 -0
  374. package/src/parkinglot/straighten.ts +58 -0
  375. package/src/parser/applyViewboxTransform.ts +157 -0
  376. package/src/parser/attributes.ts +25 -0
  377. package/src/parser/constants.ts +115 -0
  378. package/src/parser/doesSomeParentMatch.ts +19 -0
  379. package/src/parser/elementById.ts +21 -0
  380. package/src/parser/elementMatchesRule.ts +16 -0
  381. package/src/parser/elements_parser.ts +191 -0
  382. package/src/parser/getCSSRules.ts +62 -0
  383. package/src/parser/getGlobalStylesForElement.ts +19 -0
  384. package/src/parser/getGradientDefs.ts +31 -0
  385. package/src/parser/getMultipleNodes.ts +15 -0
  386. package/src/parser/getSvgRegex.ts +5 -0
  387. package/src/parser/hasAncestorWithNodeName.ts +14 -0
  388. package/src/parser/index.ts +9 -0
  389. package/src/parser/loadSVGFromString.ts +26 -0
  390. package/src/parser/loadSVGFromURL.ts +40 -0
  391. package/src/parser/normalizeAttr.ts +10 -0
  392. package/src/parser/normalizeValue.ts +63 -0
  393. package/src/parser/parseAttributes.ts +90 -0
  394. package/src/parser/parseElements.ts +28 -0
  395. package/src/parser/parseFontDeclaration.ts +44 -0
  396. package/src/parser/parsePointsAttribute.ts +34 -0
  397. package/src/parser/parseSVGDocument.ts +93 -0
  398. package/src/parser/parseStyleAttribute.ts +27 -0
  399. package/src/parser/parseStyleObject.ts +15 -0
  400. package/src/parser/parseStyleString.ts +16 -0
  401. package/src/parser/parseTransformAttribute.ts +155 -0
  402. package/src/parser/parseUseDirectives.ts +78 -0
  403. package/src/parser/percent.ts +27 -0
  404. package/src/parser/recursivelyParseGradientsXlink.ts +42 -0
  405. package/src/parser/rotateMatrix.ts +21 -0
  406. package/src/parser/scaleMatrix.ts +9 -0
  407. package/src/parser/selectorMatches.ts +25 -0
  408. package/src/parser/setStrokeFillOpacity.ts +40 -0
  409. package/src/parser/skewMatrix.ts +6 -0
  410. package/src/parser/translateMatrix.ts +8 -0
  411. package/src/shapes/ActiveSelection.ts +189 -0
  412. package/src/shapes/Circle.ts +242 -0
  413. package/src/shapes/Ellipse.ts +179 -0
  414. package/src/shapes/Group.ts +1100 -0
  415. package/src/shapes/IText/DraggableTextDelegate.ts +382 -0
  416. package/src/shapes/IText/IText.ts +693 -0
  417. package/src/shapes/IText/ITextBehavior.ts +1064 -0
  418. package/src/shapes/IText/ITextClickBehavior.ts +325 -0
  419. package/src/shapes/IText/ITextKeyBehavior.ts +685 -0
  420. package/src/shapes/IText/constants.ts +47 -0
  421. package/src/shapes/Image.ts +841 -0
  422. package/src/shapes/Line.ts +346 -0
  423. package/src/shapes/Object/AnimatableObject.ts +106 -0
  424. package/src/shapes/Object/FabricObject.ts +29 -0
  425. package/src/shapes/Object/FabricObjectSVGExportMixin.ts +277 -0
  426. package/src/shapes/Object/InteractiveObject.ts +672 -0
  427. package/src/shapes/Object/Object.ts +1561 -0
  428. package/src/shapes/Object/ObjectGeometry.ts +813 -0
  429. package/src/shapes/Object/ObjectOrigin.ts +276 -0
  430. package/src/shapes/Object/StackedObject.ts +206 -0
  431. package/src/shapes/Object/defaultValues.ts +108 -0
  432. package/src/shapes/Object/types/BaseProps.ts +96 -0
  433. package/src/shapes/Object/types/BorderProps.ts +40 -0
  434. package/src/shapes/Object/types/ControlProps.ts +69 -0
  435. package/src/shapes/Object/types/FabricObjectProps.ts +111 -0
  436. package/src/shapes/Object/types/FillStrokeProps.ts +90 -0
  437. package/src/shapes/Object/types/LockInteractionProps.ts +57 -0
  438. package/src/shapes/Object/types/ObjectProps.ts +46 -0
  439. package/src/shapes/Object/types/SerializedObjectProps.ts +73 -0
  440. package/src/shapes/Object/types/index.ts +8 -0
  441. package/src/shapes/Path.ts +416 -0
  442. package/src/shapes/Polygon.ts +20 -0
  443. package/src/shapes/Polyline.ts +359 -0
  444. package/src/shapes/Rect.ts +233 -0
  445. package/src/shapes/Text/StyledText.ts +329 -0
  446. package/src/shapes/Text/Text.ts +1884 -0
  447. package/src/shapes/Text/TextSVGExportMixin.ts +288 -0
  448. package/src/shapes/Text/constants.ts +91 -0
  449. package/src/shapes/Textbox.ts +477 -0
  450. package/src/shapes/Triangle.ts +60 -0
  451. package/src/typedefs.ts +115 -0
  452. package/src/util/animation/AnimationBase.ts +166 -0
  453. package/src/util/animation/AnimationFrameProvider.ts +9 -0
  454. package/src/util/animation/AnimationRegistry.ts +58 -0
  455. package/src/util/animation/ArrayAnimation.ts +27 -0
  456. package/src/util/animation/ColorAnimation.ts +74 -0
  457. package/src/util/animation/ValueAnimation.ts +29 -0
  458. package/src/util/animation/animate.ts +74 -0
  459. package/src/util/animation/easing.ts +327 -0
  460. package/src/util/animation/types.ts +136 -0
  461. package/src/util/applyMixins.ts +22 -0
  462. package/src/util/dom_event.ts +28 -0
  463. package/src/util/dom_misc.ts +121 -0
  464. package/src/util/dom_request.ts +64 -0
  465. package/src/util/dom_style.ts +20 -0
  466. package/src/util/fireEvent.ts +15 -0
  467. package/src/util/index.ts +102 -0
  468. package/src/util/internals/cloneDeep.ts +2 -0
  469. package/src/util/internals/getRandomInt.ts +8 -0
  470. package/src/util/internals/ifNaN.ts +9 -0
  471. package/src/util/internals/index.ts +3 -0
  472. package/src/util/internals/removeFromArray.ts +14 -0
  473. package/src/util/internals/uid.ts +3 -0
  474. package/src/util/lang_string.ts +79 -0
  475. package/src/util/misc/boundingBoxFromPoints.ts +37 -0
  476. package/src/util/misc/capValue.ts +2 -0
  477. package/src/util/misc/cos.ts +24 -0
  478. package/src/util/misc/dom.ts +50 -0
  479. package/src/util/misc/findScaleTo.ts +44 -0
  480. package/src/util/misc/groupSVGElements.ts +15 -0
  481. package/src/util/misc/isTransparent.ts +28 -0
  482. package/src/util/misc/matrix.ts +207 -0
  483. package/src/util/misc/mergeClipPaths.ts +40 -0
  484. package/src/util/misc/objectEnlive.ts +189 -0
  485. package/src/util/misc/objectTransforms.ts +129 -0
  486. package/src/util/misc/pick.ts +29 -0
  487. package/src/util/misc/planeChange.ts +136 -0
  488. package/src/util/misc/projectStroke/StrokeLineCapProjections.ts +112 -0
  489. package/src/util/misc/projectStroke/StrokeLineJoinProjections.ts +226 -0
  490. package/src/util/misc/projectStroke/StrokeProjectionsBase.ts +75 -0
  491. package/src/util/misc/projectStroke/index.ts +53 -0
  492. package/src/util/misc/projectStroke/types.ts +24 -0
  493. package/src/util/misc/radiansDegreesConversion.ts +18 -0
  494. package/src/util/misc/resolveOrigin.ts +22 -0
  495. package/src/util/misc/rotatePoint.ts +15 -0
  496. package/src/util/misc/sin.ts +26 -0
  497. package/src/util/misc/svgParsing.ts +181 -0
  498. package/src/util/misc/textStyles.ts +134 -0
  499. package/src/util/misc/toFixed.ts +8 -0
  500. package/src/util/misc/vectors.ts +82 -0
  501. package/src/util/path/index.ts +1038 -0
  502. package/src/util/path/regex.ts +41 -0
  503. package/src/util/path/typechecks.ts +145 -0
  504. package/src/util/path/typedefs.ts +305 -0
  505. package/src/util/transform_matrix_removal.ts +60 -0
  506. package/src/util/types.ts +78 -0
  507. package/tsconfig.json +106 -0
  508. package/HEADER.js +0 -203
  509. package/build.js +0 -287
  510. package/dist/fabric.js +0 -31187
  511. package/dist/fabric.min.js +0 -1
  512. package/old-travis-reference.yml +0 -97
  513. package/src/brushes/circle_brush.class.js +0 -144
  514. package/src/brushes/pattern_brush.class.js +0 -61
  515. package/src/brushes/pencil_brush.class.js +0 -310
  516. package/src/brushes/spray_brush.class.js +0 -219
  517. package/src/canvas.class.js +0 -1312
  518. package/src/color.class.js +0 -636
  519. package/src/control.class.js +0 -339
  520. package/src/controls.actions.js +0 -740
  521. package/src/controls.render.js +0 -99
  522. package/src/elements_parser.js +0 -152
  523. package/src/filters/2d_backend.class.js +0 -65
  524. package/src/filters/blendcolor_filter.class.js +0 -251
  525. package/src/filters/blendimage_filter.class.js +0 -247
  526. package/src/filters/blur_filter.class.js +0 -217
  527. package/src/filters/brightness_filter.class.js +0 -113
  528. package/src/filters/colormatrix_filter.class.js +0 -159
  529. package/src/filters/composed_filter.class.js +0 -72
  530. package/src/filters/contrast_filter.class.js +0 -113
  531. package/src/filters/convolute_filter.class.js +0 -352
  532. package/src/filters/filter_boilerplate.js +0 -111
  533. package/src/filters/filter_generator.js +0 -85
  534. package/src/filters/gamma_filter.class.js +0 -136
  535. package/src/filters/grayscale_filter.class.js +0 -154
  536. package/src/filters/hue_rotation.class.js +0 -107
  537. package/src/filters/invert_filter.class.js +0 -111
  538. package/src/filters/noise_filter.class.js +0 -134
  539. package/src/filters/pixelate_filter.class.js +0 -137
  540. package/src/filters/removecolor_filter.class.js +0 -173
  541. package/src/filters/resize_filter.class.js +0 -490
  542. package/src/filters/saturate_filter.class.js +0 -119
  543. package/src/filters/vibrance_filter.class.js +0 -122
  544. package/src/filters/webgl_backend.class.js +0 -396
  545. package/src/globalFabric.js +0 -4
  546. package/src/gradient.class.js +0 -490
  547. package/src/intersection.class.js +0 -172
  548. package/src/log.js +0 -11
  549. package/src/mixins/animation.mixin.js +0 -231
  550. package/src/mixins/canvas_dataurl_exporter.mixin.js +0 -97
  551. package/src/mixins/canvas_events.mixin.js +0 -974
  552. package/src/mixins/canvas_gestures.mixin.js +0 -149
  553. package/src/mixins/canvas_grouping.mixin.js +0 -177
  554. package/src/mixins/canvas_serialization.mixin.js +0 -228
  555. package/src/mixins/collection.mixin.js +0 -170
  556. package/src/mixins/default_controls.js +0 -114
  557. package/src/mixins/itext.svg_export.js +0 -241
  558. package/src/mixins/itext_behavior.mixin.js +0 -940
  559. package/src/mixins/itext_click_behavior.mixin.js +0 -278
  560. package/src/mixins/itext_key_behavior.mixin.js +0 -694
  561. package/src/mixins/object.svg_export.js +0 -258
  562. package/src/mixins/object_geometry.mixin.js +0 -683
  563. package/src/mixins/object_interactivity.mixin.js +0 -314
  564. package/src/mixins/object_origin.mixin.js +0 -255
  565. package/src/mixins/object_stacking.mixin.js +0 -80
  566. package/src/mixins/object_straightening.mixin.js +0 -80
  567. package/src/mixins/observable.mixin.js +0 -141
  568. package/src/mixins/shared_methods.mixin.js +0 -94
  569. package/src/mixins/stateful.mixin.js +0 -107
  570. package/src/mixins/text_style.mixin.js +0 -324
  571. package/src/parser.js +0 -1090
  572. package/src/pattern.class.js +0 -189
  573. package/src/point.class.js +0 -337
  574. package/src/shadow.class.js +0 -195
  575. package/src/shapes/active_selection.class.js +0 -155
  576. package/src/shapes/circle.class.js +0 -210
  577. package/src/shapes/ellipse.class.js +0 -181
  578. package/src/shapes/group.class.js +0 -593
  579. package/src/shapes/image.class.js +0 -764
  580. package/src/shapes/itext.class.js +0 -526
  581. package/src/shapes/line.class.js +0 -324
  582. package/src/shapes/object.class.js +0 -2008
  583. package/src/shapes/path.class.js +0 -384
  584. package/src/shapes/polygon.class.js +0 -81
  585. package/src/shapes/polyline.class.js +0 -268
  586. package/src/shapes/rect.class.js +0 -187
  587. package/src/shapes/text.class.js +0 -1696
  588. package/src/shapes/textbox.class.js +0 -461
  589. package/src/shapes/triangle.class.js +0 -93
  590. package/src/static_canvas.class.js +0 -1881
  591. package/src/util/anim_ease.js +0 -398
  592. package/src/util/animate.js +0 -254
  593. package/src/util/animate_color.js +0 -74
  594. package/src/util/dom_event.js +0 -50
  595. package/src/util/dom_misc.js +0 -300
  596. package/src/util/dom_request.js +0 -54
  597. package/src/util/dom_style.js +0 -70
  598. package/src/util/lang_array.js +0 -94
  599. package/src/util/lang_class.js +0 -115
  600. package/src/util/lang_object.js +0 -75
  601. package/src/util/lang_string.js +0 -110
  602. package/src/util/misc.js +0 -1330
  603. package/src/util/named_accessors.mixin.js +0 -428
  604. package/src/util/path.js +0 -829
@@ -0,0 +1,1734 @@
1
+ import { getDocument, getEnv } from '../env';
2
+ import { config } from '../config';
3
+ import { iMatrix, VERSION } from '../constants';
4
+ import type { CanvasEvents, StaticCanvasEvents } from '../EventTypeDefs';
5
+ import type { Gradient } from '../gradient/Gradient';
6
+ import { createCollectionMixin } from '../Collection';
7
+ import { CommonMethods } from '../CommonMethods';
8
+ import type { Pattern } from '../Pattern';
9
+ import { Point } from '../Point';
10
+ import type { BaseFabricObject as FabricObject } from '../EventTypeDefs';
11
+ import type { TCachedFabricObject } from '../shapes/Object/Object';
12
+ import type { Rect } from '../shapes/Rect';
13
+ import {
14
+ Constructor,
15
+ ImageFormat,
16
+ TCornerPoint,
17
+ TDataUrlOptions,
18
+ TFiller,
19
+ TMat2D,
20
+ TSize,
21
+ TSVGReviver,
22
+ TToCanvasElementOptions,
23
+ TValidToObjectMethod,
24
+ } from '../typedefs';
25
+ import {
26
+ cancelAnimFrame,
27
+ requestAnimFrame,
28
+ } from '../util/animation/AnimationFrameProvider';
29
+ import { getElementOffset } from '../util/dom_misc';
30
+ import { uid } from '../util/internals/uid';
31
+ import { createCanvasElement, isHTMLCanvas, toDataURL } from '../util/misc/dom';
32
+ import { invertTransform, transformPoint } from '../util/misc/matrix';
33
+ import {
34
+ enlivenObjectEnlivables,
35
+ EnlivenObjectOptions,
36
+ enlivenObjects,
37
+ } from '../util/misc/objectEnlive';
38
+ import { pick } from '../util/misc/pick';
39
+ import { matrixToSVG } from '../util/misc/svgParsing';
40
+ import { toFixed } from '../util/misc/toFixed';
41
+ import { isCollection, isFiller, isPattern, isTextObject } from '../util/types';
42
+
43
+ type TDestroyed<T, K extends keyof any> = {
44
+ // @ts-expect-error TS doesn't recognize protected/private fields using the `keyof` directive so we use `keyof any`
45
+ [R in K | keyof T]: R extends K ? T[R] | undefined | null : T[R];
46
+ };
47
+
48
+ export type TDestroyedCanvas<T extends StaticCanvas> = TDestroyed<
49
+ T,
50
+ | 'contextTop'
51
+ | 'pixelFindContext'
52
+ | 'lowerCanvasEl'
53
+ | 'upperCanvasEl'
54
+ | 'pixelFindCanvasEl'
55
+ | 'wrapperEl'
56
+ | '_activeSelection'
57
+ >;
58
+
59
+ const CANVAS_INIT_ERROR = 'Could not initialize `canvas` element';
60
+
61
+ export type TCanvasSizeOptions = {
62
+ backstoreOnly?: boolean;
63
+ cssOnly?: boolean;
64
+ };
65
+
66
+ export type TSVGExportOptions = {
67
+ suppressPreamble?: boolean;
68
+ viewBox?: {
69
+ x: number;
70
+ y: number;
71
+ width: number;
72
+ height: number;
73
+ };
74
+ encoding?: 'UTF-8'; // test Encoding type and see what happens
75
+ width?: string;
76
+ height?: string;
77
+ reviver?: TSVGReviver;
78
+ };
79
+
80
+ type TCanvasHydrationOption = {
81
+ signal?: AbortSignal;
82
+ };
83
+
84
+ export const StaticCanvasDefaults = {
85
+ backgroundColor: '',
86
+ backgroundImage: null,
87
+ overlayColor: '',
88
+ overlayImage: null,
89
+ includeDefaultValues: true,
90
+ renderOnAddRemove: true,
91
+ controlsAboveOverlay: false,
92
+ allowTouchScrolling: false,
93
+ imageSmoothingEnabled: true,
94
+ viewportTransform: iMatrix.concat(),
95
+ backgroundVpt: true,
96
+ overlayVpt: true,
97
+ enableRetinaScaling: true,
98
+ svgViewportTransformation: true,
99
+ skipOffscreen: true,
100
+ clipPath: undefined,
101
+ };
102
+
103
+ /**
104
+ * Static canvas class
105
+ * @see {@link http://fabricjs.com/static_canvas|StaticCanvas demo}
106
+ * @fires before:render
107
+ * @fires after:render
108
+ * @fires canvas:cleared
109
+ * @fires object:added
110
+ * @fires object:removed
111
+ */
112
+ // TODO: fix `EventSpec` inheritance https://github.com/microsoft/TypeScript/issues/26154#issuecomment-1366616260
113
+ export class StaticCanvas<
114
+ EventSpec extends StaticCanvasEvents = StaticCanvasEvents
115
+ > extends createCollectionMixin(CommonMethods<CanvasEvents>) {
116
+ /**
117
+ * Background color of canvas instance.
118
+ * @type {(String|TFiller)}
119
+ * @default
120
+ */
121
+ declare backgroundColor: TFiller | string;
122
+
123
+ /**
124
+ * Background image of canvas instance.
125
+ * since 2.4.0 image caching is active, please when putting an image as background, add to the
126
+ * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom
127
+ * vale. As an alternative you can disable image objectCaching
128
+ * @type FabricObject
129
+ * @default
130
+ */
131
+ declare backgroundImage: FabricObject | null;
132
+
133
+ /**
134
+ * Overlay color of canvas instance.
135
+ * @since 1.3.9
136
+ * @type {(String|TFiller)}
137
+ * @default
138
+ */
139
+ declare overlayColor: TFiller | string;
140
+
141
+ /**
142
+ * Overlay image of canvas instance.
143
+ * since 2.4.0 image caching is active, please when putting an image as overlay, add to the
144
+ * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom
145
+ * vale. As an alternative you can disable image objectCaching
146
+ * @type FabricObject
147
+ * @default
148
+ */
149
+ declare overlayImage: FabricObject | null;
150
+
151
+ /**
152
+ * Indicates whether toObject/toDatalessObject should include default values
153
+ * if set to false, takes precedence over the object value.
154
+ * @type Boolean
155
+ * @default
156
+ */
157
+ declare includeDefaultValues: boolean;
158
+
159
+ /**
160
+ * Indicates whether {@link add}, {@link insertAt} and {@link remove},
161
+ * {@link moveTo}, {@link clear} and many more, should also re-render canvas.
162
+ * Disabling this option will not give a performance boost when adding/removing a lot of objects to/from canvas at once
163
+ * since the renders are queued and executed one per frame.
164
+ * Disabling is suggested anyway and managing the renders of the app manually is not a big effort ( canvas.requestRenderAll() )
165
+ * Left default to true to do not break documentation and old app, fiddles.
166
+ * @type Boolean
167
+ * @default
168
+ */
169
+ declare renderOnAddRemove: boolean;
170
+
171
+ /**
172
+ * Indicates whether object controls (borders/controls) are rendered above overlay image
173
+ * @type Boolean
174
+ * @default
175
+ */
176
+ declare controlsAboveOverlay: boolean;
177
+
178
+ /**
179
+ * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas
180
+ * @type Boolean
181
+ * @default
182
+ */
183
+ declare allowTouchScrolling: boolean;
184
+
185
+ /**
186
+ * Indicates whether this canvas will use image smoothing, this is on by default in browsers
187
+ * @type Boolean
188
+ * @default
189
+ */
190
+ declare imageSmoothingEnabled: boolean;
191
+
192
+ /**
193
+ * The transformation (a Canvas 2D API transform matrix) which focuses the viewport
194
+ * @type Array
195
+ * @example <caption>Default transform</caption>
196
+ * canvas.viewportTransform = [1, 0, 0, 1, 0, 0];
197
+ * @example <caption>Scale by 70% and translate toward bottom-right by 50, without skewing</caption>
198
+ * canvas.viewportTransform = [0.7, 0, 0, 0.7, 50, 50];
199
+ * @default
200
+ */
201
+ declare viewportTransform: TMat2D;
202
+
203
+ /**
204
+ * if set to false background image is not affected by viewport transform
205
+ * @since 1.6.3
206
+ * @type Boolean
207
+ * @todo we should really find a different way to do this
208
+ * @default
209
+ */
210
+ declare backgroundVpt: boolean;
211
+
212
+ /**
213
+ * if set to false overlya image is not affected by viewport transform
214
+ * @since 1.6.3
215
+ * @type Boolean
216
+ * @todo we should really find a different way to do this
217
+ * @default
218
+ */
219
+ declare overlayVpt: boolean;
220
+
221
+ /**
222
+ * When true, canvas is scaled by devicePixelRatio for better rendering on retina screens
223
+ * @type Boolean
224
+ * @default
225
+ */
226
+ declare enableRetinaScaling: boolean;
227
+
228
+ /**
229
+ * Describe canvas element extension over design
230
+ * properties are tl,tr,bl,br.
231
+ * if canvas is not zoomed/panned those points are the four corner of canvas
232
+ * if canvas is viewportTransformed you those points indicate the extension
233
+ * of canvas element in plain untrasformed coordinates
234
+ * The coordinates get updated with @method calcViewportBoundaries.
235
+ */
236
+ declare vptCoords: TCornerPoint;
237
+
238
+ /**
239
+ * Based on vptCoords and object.aCoords, skip rendering of objects that
240
+ * are not included in current viewport.
241
+ * May greatly help in applications with crowded canvas and use of zoom/pan
242
+ * If One of the corner of the bounding box of the object is on the canvas
243
+ * the objects get rendered.
244
+ * @type Boolean
245
+ * @default
246
+ */
247
+ declare skipOffscreen: boolean;
248
+
249
+ /**
250
+ * a fabricObject that, without stroke define a clipping area with their shape. filled in black
251
+ * the clipPath object gets used when the canvas has rendered, and the context is placed in the
252
+ * top left corner of the canvas.
253
+ * clipPath will clip away controls, if you do not want this to happen use controlsAboveOverlay = true
254
+ * @type FabricObject
255
+ */
256
+ declare clipPath: FabricObject;
257
+
258
+ /**
259
+ * A reference to the canvas actual HTMLCanvasElement.
260
+ * Can be use to read the raw pixels, but never write or manipulate
261
+ * @type HTMLCanvasElement
262
+ */
263
+ declare lowerCanvasEl: HTMLCanvasElement;
264
+
265
+ declare contextContainer: CanvasRenderingContext2D;
266
+
267
+ /**
268
+ * Width in virtual/logical pixels of the canvas.
269
+ * The canvas can be larger than width if retina scaling is active
270
+ * @type number
271
+ */
272
+ declare width: number;
273
+
274
+ /**
275
+ * Height in virtual/logical pixels of the canvas.
276
+ * The canvas can be taller than width if retina scaling is active
277
+ * @type height
278
+ */
279
+ declare height: number;
280
+
281
+ /**
282
+ * If true the Canvas is in the process or has been disposed/destroyed.
283
+ * No more rendering operation will be executed on this canvas.
284
+ * @type boolean
285
+ */
286
+ declare destroyed?: boolean;
287
+
288
+ /**
289
+ * Started the process of disposing but not done yet.
290
+ * WIll likely complete the render cycle already scheduled but stopping adding more.
291
+ * @type boolean
292
+ */
293
+ declare disposed?: boolean;
294
+
295
+ /**
296
+ * Keeps a copy of the canvas style before setting retina scaling and other potions
297
+ * in order to return it to original state on dispose
298
+ * @type string
299
+ */
300
+ declare _originalCanvasStyle?: string;
301
+
302
+ declare _offset: { left: number; top: number };
303
+ protected declare hasLostContext: boolean;
304
+ protected declare nextRenderHandle: number;
305
+
306
+ static ownDefaults: Record<string, any> = StaticCanvasDefaults;
307
+
308
+ // reference to
309
+ protected declare __cleanupTask?: {
310
+ (): void;
311
+ kill: (reason?: any) => void;
312
+ };
313
+
314
+ static getDefaults(): Record<string, any> {
315
+ return StaticCanvas.ownDefaults;
316
+ }
317
+
318
+ constructor(el: string | HTMLCanvasElement, options = {}) {
319
+ super();
320
+ Object.assign(
321
+ this,
322
+ (this.constructor as typeof StaticCanvas).getDefaults()
323
+ );
324
+ this.set(options);
325
+ this.initElements(el);
326
+ this._setDimensionsImpl({
327
+ width: this.width || this.lowerCanvasEl.width || 0,
328
+ height: this.height || this.lowerCanvasEl.height || 0,
329
+ });
330
+ this.viewportTransform = [...this.viewportTransform];
331
+ this.calcViewportBoundaries();
332
+ }
333
+
334
+ protected initElements(el: string | HTMLCanvasElement) {
335
+ this._createLowerCanvas(el);
336
+ this._originalCanvasStyle = this.lowerCanvasEl.style.cssText;
337
+ }
338
+
339
+ add(...objects: FabricObject[]) {
340
+ const size = super.add(...objects);
341
+ objects.length > 0 && this.renderOnAddRemove && this.requestRenderAll();
342
+ return size;
343
+ }
344
+
345
+ insertAt(index: number, ...objects: FabricObject[]) {
346
+ const size = super.insertAt(index, ...objects);
347
+ objects.length > 0 && this.renderOnAddRemove && this.requestRenderAll();
348
+ return size;
349
+ }
350
+
351
+ remove(...objects: FabricObject[]) {
352
+ const removed = super.remove(...objects);
353
+ removed.length > 0 && this.renderOnAddRemove && this.requestRenderAll();
354
+ return removed;
355
+ }
356
+
357
+ _onObjectAdded(obj: FabricObject) {
358
+ if (obj.canvas && obj.canvas !== this) {
359
+ /* _DEV_MODE_START_ */
360
+ console.warn(
361
+ 'fabric.Canvas: trying to add an object that belongs to a different canvas.\n' +
362
+ 'Resulting to default behavior: removing object from previous canvas and adding to new canvas'
363
+ );
364
+ /* _DEV_MODE_END_ */
365
+ obj.canvas.remove(obj);
366
+ }
367
+ obj._set('canvas', this);
368
+ obj.setCoords();
369
+ this.fire('object:added', { target: obj });
370
+ obj.fire('added', { target: this });
371
+ }
372
+
373
+ _onObjectRemoved(obj: FabricObject) {
374
+ obj._set('canvas', undefined);
375
+ this.fire('object:removed', { target: obj });
376
+ obj.fire('removed', { target: this });
377
+ }
378
+
379
+ _onStackOrderChanged() {
380
+ this.renderOnAddRemove && this.requestRenderAll();
381
+ }
382
+
383
+ /**
384
+ * @private
385
+ */
386
+ _isRetinaScaling() {
387
+ return config.devicePixelRatio > 1 && this.enableRetinaScaling;
388
+ }
389
+
390
+ /**
391
+ * @private
392
+ * @return {Number} retinaScaling if applied, otherwise 1;
393
+ */
394
+ getRetinaScaling() {
395
+ return this._isRetinaScaling() ? Math.max(1, config.devicePixelRatio) : 1;
396
+ }
397
+
398
+ protected _initRetinaScaling() {
399
+ this.__initRetinaScaling(this.lowerCanvasEl, this.contextContainer);
400
+ }
401
+
402
+ protected __initRetinaScaling(
403
+ canvas: HTMLCanvasElement,
404
+ context: CanvasRenderingContext2D
405
+ ) {
406
+ const scaleRatio = config.devicePixelRatio;
407
+ canvas.setAttribute('width', (this.width * scaleRatio).toString());
408
+ canvas.setAttribute('height', (this.height * scaleRatio).toString());
409
+ context.scale(scaleRatio, scaleRatio);
410
+ }
411
+
412
+ /**
413
+ * Calculates canvas element offset relative to the document
414
+ * This method is also attached as "resize" event handler of window
415
+ */
416
+ calcOffset() {
417
+ return (this._offset = getElementOffset(this.lowerCanvasEl));
418
+ }
419
+
420
+ /**
421
+ * @private
422
+ */
423
+ protected _createCanvasElement() {
424
+ const element = createCanvasElement();
425
+ if (!element) {
426
+ throw new Error(CANVAS_INIT_ERROR);
427
+ }
428
+ if (typeof element.getContext === 'undefined') {
429
+ throw new Error(CANVAS_INIT_ERROR);
430
+ }
431
+ return element;
432
+ }
433
+
434
+ /**
435
+ * Creates a bottom canvas
436
+ * @private
437
+ * @param {HTMLElement} [canvasEl]
438
+ */
439
+ protected _createLowerCanvas(canvasEl: HTMLCanvasElement | string) {
440
+ // canvasEl === 'HTMLCanvasElement' does not work on jsdom/node
441
+ if (isHTMLCanvas(canvasEl)) {
442
+ this.lowerCanvasEl = canvasEl;
443
+ } else {
444
+ this.lowerCanvasEl =
445
+ (getDocument().getElementById(canvasEl) as HTMLCanvasElement) ||
446
+ this._createCanvasElement();
447
+ }
448
+ if (this.lowerCanvasEl.hasAttribute('data-fabric')) {
449
+ /* _DEV_MODE_START_ */
450
+ throw new Error(
451
+ 'fabric.js: trying to initialize a canvas that has already been initialized'
452
+ );
453
+ /* _DEV_MODE_END_ */
454
+ }
455
+ this.lowerCanvasEl.classList.add('lower-canvas');
456
+ this.lowerCanvasEl.setAttribute('data-fabric', 'main');
457
+ this.contextContainer = this.lowerCanvasEl.getContext('2d')!;
458
+ }
459
+
460
+ /**
461
+ * Returns canvas width (in px)
462
+ * @return {Number}
463
+ */
464
+ getWidth(): number {
465
+ return this.width;
466
+ }
467
+
468
+ /**
469
+ * Returns canvas height (in px)
470
+ * @return {Number}
471
+ */
472
+ getHeight(): number {
473
+ return this.height;
474
+ }
475
+
476
+ /**
477
+ * Sets width of this canvas instance
478
+ * @param {Number|String} value Value to set width to
479
+ * @param {Object} [options] Options object
480
+ * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions
481
+ * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions
482
+ * @deprecated will be removed in 7.0
483
+ */
484
+ setWidth(value: number, options: TCanvasSizeOptions) {
485
+ return this.setDimensions({ width: value }, options);
486
+ }
487
+
488
+ /**
489
+ * Sets height of this canvas instance
490
+ * @param {Number|String} value Value to set height to
491
+ * @param {Object} [options] Options object
492
+ * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions
493
+ * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions
494
+ * @deprecated will be removed in 7.0
495
+ */
496
+ setHeight(value: number, options: TCanvasSizeOptions) {
497
+ return this.setDimensions({ height: value }, options);
498
+ }
499
+
500
+ /**
501
+ * Internal use only
502
+ * @protected
503
+ */
504
+ protected _setDimensionsImpl(
505
+ dimensions: Partial<TSize>,
506
+ { cssOnly = false, backstoreOnly = false }: TCanvasSizeOptions = {}
507
+ ) {
508
+ Object.entries(dimensions).forEach(([prop, value]) => {
509
+ let cssValue = `${value}`;
510
+
511
+ if (!cssOnly) {
512
+ this._setBackstoreDimension(prop as keyof TSize, value);
513
+ cssValue += 'px';
514
+ this.hasLostContext = true;
515
+ }
516
+
517
+ if (!backstoreOnly) {
518
+ this._setCssDimension(prop as keyof TSize, cssValue);
519
+ }
520
+ });
521
+
522
+ this._isRetinaScaling() && this._initRetinaScaling();
523
+ this.calcOffset();
524
+ }
525
+
526
+ /**
527
+ * Sets dimensions (width, height) of this canvas instance. when options.cssOnly flag active you should also supply the unit of measure (px/%/em)
528
+ * @param {Object} dimensions Object with width/height properties
529
+ * @param {Number|String} [dimensions.width] Width of canvas element
530
+ * @param {Number|String} [dimensions.height] Height of canvas element
531
+ * @param {Object} [options] Options object
532
+ * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions
533
+ * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions
534
+ */
535
+ setDimensions(
536
+ dimensions: Partial<TSize>,
537
+ { cssOnly = false, backstoreOnly = false }: TCanvasSizeOptions = {}
538
+ ) {
539
+ this._setDimensionsImpl(dimensions, {
540
+ cssOnly,
541
+ backstoreOnly,
542
+ });
543
+ if (!cssOnly) {
544
+ this.requestRenderAll();
545
+ }
546
+ }
547
+
548
+ /**
549
+ * Helper for setting width/height
550
+ * @private
551
+ * @param {String} prop property (width|height)
552
+ * @param {Number} value value to set property to
553
+ * @todo subclass in canvas and handle upperCanvasEl there.
554
+ */
555
+ _setBackstoreDimension(prop: keyof TSize, value: number) {
556
+ this.lowerCanvasEl[prop] = value;
557
+ this[prop] = value;
558
+ }
559
+
560
+ /**
561
+ * Helper for setting css width/height
562
+ * @private
563
+ * @param {String} prop property (width|height)
564
+ * @param {String} value value to set property to
565
+ * @todo subclass in canvas and handle upperCanvasEl there.
566
+ */
567
+ _setCssDimension(prop: keyof TSize, value: string) {
568
+ this.lowerCanvasEl.style[prop] = value;
569
+ }
570
+
571
+ /**
572
+ * Returns canvas zoom level
573
+ * @return {Number}
574
+ */
575
+ getZoom() {
576
+ return this.viewportTransform[0];
577
+ }
578
+
579
+ /**
580
+ * Sets viewport transformation of this canvas instance
581
+ * @param {Array} vpt a Canvas 2D API transform matrix
582
+ */
583
+ setViewportTransform(vpt: TMat2D) {
584
+ const backgroundObject = this.backgroundImage,
585
+ overlayObject = this.overlayImage,
586
+ len = this._objects.length;
587
+
588
+ this.viewportTransform = vpt;
589
+ for (let i = 0; i < len; i++) {
590
+ const object = this._objects[i];
591
+ object.group || object.setCoords();
592
+ }
593
+ if (backgroundObject) {
594
+ backgroundObject.setCoords();
595
+ }
596
+ if (overlayObject) {
597
+ overlayObject.setCoords();
598
+ }
599
+ this.calcViewportBoundaries();
600
+ this.renderOnAddRemove && this.requestRenderAll();
601
+ }
602
+
603
+ /**
604
+ * Sets zoom level of this canvas instance, the zoom centered around point
605
+ * meaning that following zoom to point with the same point will have the visual
606
+ * effect of the zoom originating from that point. The point won't move.
607
+ * It has nothing to do with canvas center or visual center of the viewport.
608
+ * @param {Point} point to zoom with respect to
609
+ * @param {Number} value to set zoom to, less than 1 zooms out
610
+ */
611
+ zoomToPoint(point: Point, value: number) {
612
+ // TODO: just change the scale, preserve other transformations
613
+ const before = point,
614
+ vpt: TMat2D = [...this.viewportTransform];
615
+ const newPoint = transformPoint(point, invertTransform(vpt));
616
+ vpt[0] = value;
617
+ vpt[3] = value;
618
+ const after = transformPoint(newPoint, vpt);
619
+ vpt[4] += before.x - after.x;
620
+ vpt[5] += before.y - after.y;
621
+ this.setViewportTransform(vpt);
622
+ }
623
+
624
+ /**
625
+ * Sets zoom level of this canvas instance
626
+ * @param {Number} value to set zoom to, less than 1 zooms out
627
+ */
628
+ setZoom(value: number) {
629
+ this.zoomToPoint(new Point(0, 0), value);
630
+ }
631
+
632
+ /**
633
+ * Pan viewport so as to place point at top left corner of canvas
634
+ * @param {Point} point to move to
635
+ */
636
+ absolutePan(point: Point) {
637
+ const vpt: TMat2D = [...this.viewportTransform];
638
+ vpt[4] = -point.x;
639
+ vpt[5] = -point.y;
640
+ return this.setViewportTransform(vpt);
641
+ }
642
+
643
+ /**
644
+ * Pans viewpoint relatively
645
+ * @param {Point} point (position vector) to move by
646
+ */
647
+ relativePan(point: Point) {
648
+ return this.absolutePan(
649
+ new Point(
650
+ -point.x - this.viewportTransform[4],
651
+ -point.y - this.viewportTransform[5]
652
+ )
653
+ );
654
+ }
655
+
656
+ /**
657
+ * Returns &lt;canvas> element corresponding to this instance
658
+ * @return {HTMLCanvasElement}
659
+ */
660
+ getElement(): HTMLCanvasElement {
661
+ return this.lowerCanvasEl;
662
+ }
663
+
664
+ /**
665
+ * Clears specified context of canvas element
666
+ * @param {CanvasRenderingContext2D} ctx Context to clear
667
+ */
668
+ clearContext(ctx: CanvasRenderingContext2D) {
669
+ ctx.clearRect(0, 0, this.width, this.height);
670
+ }
671
+
672
+ /**
673
+ * Returns context of canvas where objects are drawn
674
+ * @return {CanvasRenderingContext2D}
675
+ */
676
+ getContext(): CanvasRenderingContext2D {
677
+ return this.contextContainer;
678
+ }
679
+
680
+ /**
681
+ * Clears all contexts (background, main, top) of an instance
682
+ */
683
+ clear() {
684
+ this.remove(...this.getObjects());
685
+ this.backgroundImage = null;
686
+ this.overlayImage = null;
687
+ this.backgroundColor = '';
688
+ this.overlayColor = '';
689
+ this.clearContext(this.contextContainer);
690
+ this.fire('canvas:cleared');
691
+ this.renderOnAddRemove && this.requestRenderAll();
692
+ }
693
+
694
+ /**
695
+ * Renders the canvas
696
+ */
697
+ renderAll() {
698
+ this.cancelRequestedRender();
699
+ if (this.destroyed) {
700
+ return;
701
+ }
702
+ this.renderCanvas(this.contextContainer, this._objects);
703
+ }
704
+
705
+ /**
706
+ * Function created to be instance bound at initialization
707
+ * used in requestAnimationFrame rendering
708
+ * Let the fabricJS call it. If you call it manually you could have more
709
+ * animationFrame stacking on to of each other
710
+ * for an imperative rendering, use canvas.renderAll
711
+ * @private
712
+ */
713
+ renderAndReset() {
714
+ this.nextRenderHandle = 0;
715
+ this.renderAll();
716
+ }
717
+
718
+ /**
719
+ * Append a renderAll request to next animation frame.
720
+ * unless one is already in progress, in that case nothing is done
721
+ * a boolean flag will avoid appending more.
722
+ */
723
+ requestRenderAll() {
724
+ if (!this.nextRenderHandle && !this.disposed && !this.destroyed) {
725
+ this.nextRenderHandle = requestAnimFrame(() => this.renderAndReset());
726
+ }
727
+ }
728
+
729
+ /**
730
+ * Calculate the position of the 4 corner of canvas with current viewportTransform.
731
+ * helps to determinate when an object is in the current rendering viewport using
732
+ * object absolute coordinates ( aCoords )
733
+ * @return {Object} points.tl
734
+ * @chainable
735
+ */
736
+ calcViewportBoundaries(): TCornerPoint {
737
+ const width = this.width,
738
+ height = this.height,
739
+ iVpt = invertTransform(this.viewportTransform),
740
+ a = transformPoint({ x: 0, y: 0 }, iVpt),
741
+ b = transformPoint({ x: width, y: height }, iVpt),
742
+ // we don't support vpt flipping
743
+ // but the code is robust enough to mostly work with flipping
744
+ min = a.min(b),
745
+ max = a.max(b);
746
+ return (this.vptCoords = {
747
+ tl: min,
748
+ tr: new Point(max.x, min.y),
749
+ bl: new Point(min.x, max.y),
750
+ br: max,
751
+ });
752
+ }
753
+
754
+ cancelRequestedRender() {
755
+ if (this.nextRenderHandle) {
756
+ cancelAnimFrame(this.nextRenderHandle);
757
+ this.nextRenderHandle = 0;
758
+ }
759
+ }
760
+
761
+ drawControls(ctx: CanvasRenderingContext2D) {
762
+ // Static canvas has no controls
763
+ }
764
+
765
+ /**
766
+ * Renders background, objects, overlay and controls.
767
+ * @param {CanvasRenderingContext2D} ctx
768
+ * @param {Array} objects to render
769
+ */
770
+ renderCanvas(ctx: CanvasRenderingContext2D, objects: FabricObject[]) {
771
+ if (this.destroyed) {
772
+ return;
773
+ }
774
+
775
+ const v = this.viewportTransform,
776
+ path = this.clipPath;
777
+ this.calcViewportBoundaries();
778
+ this.clearContext(ctx);
779
+ ctx.imageSmoothingEnabled = this.imageSmoothingEnabled;
780
+ // @ts-ignore node-canvas stuff
781
+ ctx.patternQuality = 'best';
782
+ this.fire('before:render', { ctx });
783
+ this._renderBackground(ctx);
784
+
785
+ ctx.save();
786
+ //apply viewport transform once for all rendering process
787
+ ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);
788
+ this._renderObjects(ctx, objects);
789
+ ctx.restore();
790
+ if (!this.controlsAboveOverlay) {
791
+ this.drawControls(ctx);
792
+ }
793
+ if (path) {
794
+ path._set('canvas', this);
795
+ // needed to setup a couple of variables
796
+ path.shouldCache();
797
+ path._transformDone = true;
798
+ path.renderCache({ forClipping: true });
799
+ this.drawClipPathOnCanvas(ctx, path as TCachedFabricObject);
800
+ }
801
+ this._renderOverlay(ctx);
802
+ if (this.controlsAboveOverlay) {
803
+ this.drawControls(ctx);
804
+ }
805
+ this.fire('after:render', { ctx });
806
+
807
+ if (this.__cleanupTask) {
808
+ this.__cleanupTask();
809
+ this.__cleanupTask = undefined;
810
+ }
811
+ }
812
+
813
+ /**
814
+ * Paint the cached clipPath on the lowerCanvasEl
815
+ * @param {CanvasRenderingContext2D} ctx Context to render on
816
+ */
817
+ drawClipPathOnCanvas(
818
+ ctx: CanvasRenderingContext2D,
819
+ clipPath: TCachedFabricObject
820
+ ) {
821
+ const v = this.viewportTransform;
822
+ ctx.save();
823
+ ctx.transform(...v);
824
+ // DEBUG: uncomment this line, comment the following
825
+ // ctx.globalAlpha = 0.4;
826
+ ctx.globalCompositeOperation = 'destination-in';
827
+ clipPath.transform(ctx);
828
+ ctx.scale(1 / clipPath.zoomX, 1 / clipPath.zoomY);
829
+ ctx.drawImage(
830
+ clipPath._cacheCanvas,
831
+ -clipPath.cacheTranslationX,
832
+ -clipPath.cacheTranslationY
833
+ );
834
+ ctx.restore();
835
+ }
836
+
837
+ /**
838
+ * @private
839
+ * @param {CanvasRenderingContext2D} ctx Context to render on
840
+ * @param {Array} objects to render
841
+ */
842
+ _renderObjects(ctx: CanvasRenderingContext2D, objects: FabricObject[]) {
843
+ for (let i = 0, len = objects.length; i < len; ++i) {
844
+ objects[i] && objects[i].render(ctx);
845
+ }
846
+ }
847
+
848
+ /**
849
+ * @private
850
+ * @param {CanvasRenderingContext2D} ctx Context to render on
851
+ * @param {string} property 'background' or 'overlay'
852
+ */
853
+ _renderBackgroundOrOverlay(
854
+ ctx: CanvasRenderingContext2D,
855
+ property: 'background' | 'overlay'
856
+ ) {
857
+ const fill = this[`${property}Color`],
858
+ object = this[`${property}Image`],
859
+ v = this.viewportTransform,
860
+ needsVpt = this[`${property}Vpt`];
861
+ if (!fill && !object) {
862
+ return;
863
+ }
864
+ const isAFiller = isFiller(fill);
865
+ if (fill) {
866
+ ctx.save();
867
+ ctx.beginPath();
868
+ ctx.moveTo(0, 0);
869
+ ctx.lineTo(this.width, 0);
870
+ ctx.lineTo(this.width, this.height);
871
+ ctx.lineTo(0, this.height);
872
+ ctx.closePath();
873
+ ctx.fillStyle = isAFiller ? fill.toLive(ctx /* this */)! : fill;
874
+ if (needsVpt) {
875
+ ctx.transform(...v);
876
+ }
877
+ if (isAFiller) {
878
+ ctx.transform(1, 0, 0, 1, fill.offsetX || 0, fill.offsetY || 0);
879
+ const m = ((fill as Gradient<'linear'>).gradientTransform ||
880
+ (fill as Pattern).patternTransform) as TMat2D;
881
+ m && ctx.transform(...m);
882
+ }
883
+ ctx.fill();
884
+ ctx.restore();
885
+ }
886
+ if (object) {
887
+ ctx.save();
888
+ if (needsVpt) {
889
+ ctx.transform(...v);
890
+ }
891
+ object.render(ctx);
892
+ ctx.restore();
893
+ }
894
+ }
895
+
896
+ /**
897
+ * @private
898
+ * @param {CanvasRenderingContext2D} ctx Context to render on
899
+ */
900
+ _renderBackground(ctx: CanvasRenderingContext2D) {
901
+ this._renderBackgroundOrOverlay(ctx, 'background');
902
+ }
903
+
904
+ /**
905
+ * @private
906
+ * @param {CanvasRenderingContext2D} ctx Context to render on
907
+ */
908
+ _renderOverlay(ctx: CanvasRenderingContext2D) {
909
+ this._renderBackgroundOrOverlay(ctx, 'overlay');
910
+ }
911
+
912
+ /**
913
+ * Returns coordinates of a center of canvas.
914
+ * Returned value is an object with top and left properties
915
+ * @return {Object} object with "top" and "left" number values
916
+ * @deprecated migrate to `getCenterPoint`
917
+ */
918
+ getCenter() {
919
+ return {
920
+ top: this.height / 2,
921
+ left: this.width / 2,
922
+ };
923
+ }
924
+
925
+ /**
926
+ * Returns coordinates of a center of canvas.
927
+ * @return {Point}
928
+ */
929
+ getCenterPoint() {
930
+ return new Point(this.width / 2, this.height / 2);
931
+ }
932
+
933
+ /**
934
+ * Centers object horizontally in the canvas
935
+ */
936
+ centerObjectH(object: FabricObject) {
937
+ return this._centerObject(
938
+ object,
939
+ new Point(this.getCenterPoint().x, object.getCenterPoint().y)
940
+ );
941
+ }
942
+
943
+ /**
944
+ * Centers object vertically in the canvas
945
+ * @param {FabricObject} object Object to center vertically
946
+ */
947
+ centerObjectV(object: FabricObject) {
948
+ return this._centerObject(
949
+ object,
950
+ new Point(object.getCenterPoint().x, this.getCenterPoint().y)
951
+ );
952
+ }
953
+
954
+ /**
955
+ * Centers object vertically and horizontally in the canvas
956
+ * @param {FabricObject} object Object to center vertically and horizontally
957
+ */
958
+ centerObject(object: FabricObject) {
959
+ return this._centerObject(object, this.getCenterPoint());
960
+ }
961
+
962
+ /**
963
+ * Centers object vertically and horizontally in the viewport
964
+ * @param {FabricObject} object Object to center vertically and horizontally
965
+ */
966
+ viewportCenterObject(object: FabricObject) {
967
+ return this._centerObject(object, this.getVpCenter());
968
+ }
969
+
970
+ /**
971
+ * Centers object horizontally in the viewport, object.top is unchanged
972
+ * @param {FabricObject} object Object to center vertically and horizontally
973
+ */
974
+ viewportCenterObjectH(object: FabricObject) {
975
+ return this._centerObject(
976
+ object,
977
+ new Point(this.getVpCenter().x, object.getCenterPoint().y)
978
+ );
979
+ }
980
+
981
+ /**
982
+ * Centers object Vertically in the viewport, object.top is unchanged
983
+ * @param {FabricObject} object Object to center vertically and horizontally
984
+ */
985
+ viewportCenterObjectV(object: FabricObject) {
986
+ return this._centerObject(
987
+ object,
988
+ new Point(object.getCenterPoint().x, this.getVpCenter().y)
989
+ );
990
+ }
991
+
992
+ /**
993
+ * Calculate the point in canvas that correspond to the center of actual viewport.
994
+ * @return {Point} vpCenter, viewport center
995
+ */
996
+ getVpCenter(): Point {
997
+ return transformPoint(
998
+ this.getCenterPoint(),
999
+ invertTransform(this.viewportTransform)
1000
+ );
1001
+ }
1002
+
1003
+ /**
1004
+ * @private
1005
+ * @param {FabricObject} object Object to center
1006
+ * @param {Point} center Center point
1007
+ */
1008
+ _centerObject(object: FabricObject, center: Point) {
1009
+ object.setXY(center, 'center', 'center');
1010
+ object.setCoords();
1011
+ this.renderOnAddRemove && this.requestRenderAll();
1012
+ }
1013
+
1014
+ /**
1015
+ * Returns dataless JSON representation of canvas
1016
+ * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
1017
+ * @return {String} json string
1018
+ */
1019
+ toDatalessJSON(propertiesToInclude?: string[]) {
1020
+ return this.toDatalessObject(propertiesToInclude);
1021
+ }
1022
+
1023
+ /**
1024
+ * Returns object representation of canvas
1025
+ * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
1026
+ * @return {Object} object representation of an instance
1027
+ */
1028
+ toObject(propertiesToInclude?: string[]) {
1029
+ return this._toObjectMethod('toObject', propertiesToInclude);
1030
+ }
1031
+
1032
+ /**
1033
+ * Returns Object representation of canvas
1034
+ * this alias is provided because if you call JSON.stringify on an instance,
1035
+ * the toJSON object will be invoked if it exists.
1036
+ * Having a toJSON method means you can do JSON.stringify(myCanvas)
1037
+ * @return {Object} JSON compatible object
1038
+ * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}
1039
+ * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo}
1040
+ * @example <caption>JSON without additional properties</caption>
1041
+ * var json = canvas.toJSON();
1042
+ * @example <caption>JSON with additional properties included</caption>
1043
+ * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY']);
1044
+ * @example <caption>JSON without default values</caption>
1045
+ * var json = canvas.toJSON();
1046
+ */
1047
+ toJSON() {
1048
+ return this.toObject();
1049
+ }
1050
+
1051
+ /**
1052
+ * Returns dataless object representation of canvas
1053
+ * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
1054
+ * @return {Object} object representation of an instance
1055
+ */
1056
+ toDatalessObject(propertiesToInclude?: string[]) {
1057
+ return this._toObjectMethod('toDatalessObject', propertiesToInclude);
1058
+ }
1059
+
1060
+ /**
1061
+ * @private
1062
+ */
1063
+ _toObjectMethod(
1064
+ methodName: TValidToObjectMethod,
1065
+ propertiesToInclude?: string[]
1066
+ ) {
1067
+ const clipPath = this.clipPath;
1068
+ const clipPathData =
1069
+ clipPath && !clipPath.excludeFromExport
1070
+ ? this._toObject(clipPath, methodName, propertiesToInclude)
1071
+ : null;
1072
+ return {
1073
+ version: VERSION,
1074
+ ...pick(this, propertiesToInclude as (keyof this)[]),
1075
+ objects: this._objects
1076
+ .filter((object) => !object.excludeFromExport)
1077
+ .map((instance) =>
1078
+ this._toObject(instance, methodName, propertiesToInclude)
1079
+ ),
1080
+ ...this.__serializeBgOverlay(methodName, propertiesToInclude),
1081
+ ...(clipPathData ? { clipPath: clipPathData } : null),
1082
+ };
1083
+ }
1084
+
1085
+ /**
1086
+ * @private
1087
+ */
1088
+ _toObject(
1089
+ instance: FabricObject,
1090
+ methodName: TValidToObjectMethod,
1091
+ propertiesToInclude?: string[]
1092
+ ) {
1093
+ let originalValue;
1094
+
1095
+ if (!this.includeDefaultValues) {
1096
+ originalValue = instance.includeDefaultValues;
1097
+ instance.includeDefaultValues = false;
1098
+ }
1099
+
1100
+ const object = instance[methodName](propertiesToInclude);
1101
+ if (!this.includeDefaultValues) {
1102
+ instance.includeDefaultValues = !!originalValue;
1103
+ }
1104
+ return object;
1105
+ }
1106
+
1107
+ /**
1108
+ * @private
1109
+ */
1110
+ __serializeBgOverlay(
1111
+ methodName: TValidToObjectMethod,
1112
+ propertiesToInclude?: string[]
1113
+ ) {
1114
+ const data: any = {},
1115
+ bgImage = this.backgroundImage,
1116
+ overlayImage = this.overlayImage,
1117
+ bgColor = this.backgroundColor,
1118
+ overlayColor = this.overlayColor;
1119
+
1120
+ if (isFiller(bgColor)) {
1121
+ if (!bgColor.excludeFromExport) {
1122
+ data.background = bgColor.toObject(propertiesToInclude);
1123
+ }
1124
+ } else if (bgColor) {
1125
+ data.background = bgColor;
1126
+ }
1127
+
1128
+ if (isFiller(overlayColor)) {
1129
+ if (!overlayColor.excludeFromExport) {
1130
+ data.overlay = overlayColor.toObject(propertiesToInclude);
1131
+ }
1132
+ } else if (overlayColor) {
1133
+ data.overlay = overlayColor;
1134
+ }
1135
+
1136
+ if (bgImage && !bgImage.excludeFromExport) {
1137
+ data.backgroundImage = this._toObject(
1138
+ bgImage,
1139
+ methodName,
1140
+ propertiesToInclude
1141
+ );
1142
+ }
1143
+ if (overlayImage && !overlayImage.excludeFromExport) {
1144
+ data.overlayImage = this._toObject(
1145
+ overlayImage,
1146
+ methodName,
1147
+ propertiesToInclude
1148
+ );
1149
+ }
1150
+
1151
+ return data;
1152
+ }
1153
+
1154
+ /* _TO_SVG_START_ */
1155
+ /**
1156
+ * When true, getSvgTransform() will apply the StaticCanvas.viewportTransform to the SVG transformation. When true,
1157
+ * a zoomed canvas will then produce zoomed SVG output.
1158
+ * @type Boolean
1159
+ * @default
1160
+ */
1161
+ declare svgViewportTransformation: boolean;
1162
+
1163
+ /**
1164
+ * Returns SVG representation of canvas
1165
+ * @function
1166
+ * @param {Object} [options] Options object for SVG output
1167
+ * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included
1168
+ * @param {Object} [options.viewBox] SVG viewbox object
1169
+ * @param {Number} [options.viewBox.x] x-coordinate of viewbox
1170
+ * @param {Number} [options.viewBox.y] y-coordinate of viewbox
1171
+ * @param {Number} [options.viewBox.width] Width of viewbox
1172
+ * @param {Number} [options.viewBox.height] Height of viewbox
1173
+ * @param {String} [options.encoding=UTF-8] Encoding of SVG output
1174
+ * @param {String} [options.width] desired width of svg with or without units
1175
+ * @param {String} [options.height] desired height of svg with or without units
1176
+ * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation.
1177
+ * @return {String} SVG string
1178
+ * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}
1179
+ * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo}
1180
+ * @example <caption>Normal SVG output</caption>
1181
+ * var svg = canvas.toSVG();
1182
+ * @example <caption>SVG output without preamble (without &lt;?xml ../>)</caption>
1183
+ * var svg = canvas.toSVG({suppressPreamble: true});
1184
+ * @example <caption>SVG output with viewBox attribute</caption>
1185
+ * var svg = canvas.toSVG({
1186
+ * viewBox: {
1187
+ * x: 100,
1188
+ * y: 100,
1189
+ * width: 200,
1190
+ * height: 300
1191
+ * }
1192
+ * });
1193
+ * @example <caption>SVG output with different encoding (default: UTF-8)</caption>
1194
+ * var svg = canvas.toSVG({encoding: 'ISO-8859-1'});
1195
+ * @example <caption>Modify SVG output with reviver function</caption>
1196
+ * var svg = canvas.toSVG(null, function(svg) {
1197
+ * return svg.replace('stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; ', '');
1198
+ * });
1199
+ */
1200
+ toSVG(options: TSVGExportOptions = {}, reviver: TSVGReviver) {
1201
+ options.reviver = reviver;
1202
+ const markup: string[] = [];
1203
+
1204
+ this._setSVGPreamble(markup, options);
1205
+ this._setSVGHeader(markup, options);
1206
+ if (this.clipPath) {
1207
+ markup.push(`<g clip-path="url(#${this.clipPath.clipPathId})" >\n`);
1208
+ }
1209
+ this._setSVGBgOverlayColor(markup, 'background');
1210
+ this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);
1211
+ this._setSVGObjects(markup, reviver);
1212
+ if (this.clipPath) {
1213
+ markup.push('</g>\n');
1214
+ }
1215
+ this._setSVGBgOverlayColor(markup, 'overlay');
1216
+ this._setSVGBgOverlayImage(markup, 'overlayImage', reviver);
1217
+
1218
+ markup.push('</svg>');
1219
+
1220
+ return markup.join('');
1221
+ }
1222
+
1223
+ /**
1224
+ * @private
1225
+ */
1226
+ _setSVGPreamble(markup: string[], options: TSVGExportOptions): void {
1227
+ if (options.suppressPreamble) {
1228
+ return;
1229
+ }
1230
+ markup.push(
1231
+ '<?xml version="1.0" encoding="',
1232
+ options.encoding || 'UTF-8',
1233
+ '" standalone="no" ?>\n',
1234
+ '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" ',
1235
+ '"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n'
1236
+ );
1237
+ }
1238
+
1239
+ /**
1240
+ * @private
1241
+ */
1242
+ _setSVGHeader(markup: string[], options: TSVGExportOptions): void {
1243
+ const width = options.width || `${this.width}`,
1244
+ height = options.height || `${this.height}`,
1245
+ NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS,
1246
+ optViewBox = options.viewBox;
1247
+ let viewBox: string;
1248
+ if (optViewBox) {
1249
+ viewBox = `viewBox="${optViewBox.x} ${optViewBox.y} ${optViewBox.width} ${optViewBox.height}" `;
1250
+ } else if (this.svgViewportTransformation) {
1251
+ const vpt = this.viewportTransform;
1252
+ viewBox = `viewBox="${toFixed(
1253
+ -vpt[4] / vpt[0],
1254
+ NUM_FRACTION_DIGITS
1255
+ )} ${toFixed(-vpt[5] / vpt[3], NUM_FRACTION_DIGITS)} ${toFixed(
1256
+ this.width / vpt[0],
1257
+ NUM_FRACTION_DIGITS
1258
+ )} ${toFixed(this.height / vpt[3], NUM_FRACTION_DIGITS)}" `;
1259
+ } else {
1260
+ viewBox = `viewBox="0 0 ${this.width} ${this.height}" `;
1261
+ }
1262
+
1263
+ markup.push(
1264
+ '<svg ',
1265
+ 'xmlns="http://www.w3.org/2000/svg" ',
1266
+ 'xmlns:xlink="http://www.w3.org/1999/xlink" ',
1267
+ 'version="1.1" ',
1268
+ 'width="',
1269
+ width,
1270
+ '" ',
1271
+ 'height="',
1272
+ height,
1273
+ '" ',
1274
+ viewBox,
1275
+ 'xml:space="preserve">\n',
1276
+ '<desc>Created with Fabric.js ',
1277
+ VERSION,
1278
+ '</desc>\n',
1279
+ '<defs>\n',
1280
+ this.createSVGFontFacesMarkup(),
1281
+ this.createSVGRefElementsMarkup(),
1282
+ this.createSVGClipPathMarkup(options),
1283
+ '</defs>\n'
1284
+ );
1285
+ }
1286
+
1287
+ createSVGClipPathMarkup(options: TSVGExportOptions): string {
1288
+ const clipPath = this.clipPath;
1289
+ if (clipPath) {
1290
+ clipPath.clipPathId = `CLIPPATH_${uid()}`;
1291
+ return (
1292
+ '<clipPath id="' +
1293
+ clipPath.clipPathId +
1294
+ '" >\n' +
1295
+ this.clipPath.toClipPathSVG(options.reviver) +
1296
+ '</clipPath>\n'
1297
+ );
1298
+ }
1299
+ return '';
1300
+ }
1301
+
1302
+ /**
1303
+ * Creates markup containing SVG referenced elements like patterns, gradients etc.
1304
+ * @return {String}
1305
+ */
1306
+ createSVGRefElementsMarkup(): string {
1307
+ return (['background', 'overlay'] as const)
1308
+ .map((prop) => {
1309
+ const fill = this[`${prop}Color`];
1310
+ if (isFiller(fill)) {
1311
+ const shouldTransform = this[`${prop}Vpt`],
1312
+ vpt = this.viewportTransform,
1313
+ object = {
1314
+ width: this.width / (shouldTransform ? vpt[0] : 1),
1315
+ height: this.height / (shouldTransform ? vpt[3] : 1),
1316
+ };
1317
+ return fill.toSVG(object as Rect, {
1318
+ additionalTransform: shouldTransform ? matrixToSVG(vpt) : '',
1319
+ });
1320
+ }
1321
+ })
1322
+ .join('');
1323
+ }
1324
+
1325
+ /**
1326
+ * Creates markup containing SVG font faces,
1327
+ * font URLs for font faces must be collected by developers
1328
+ * and are not extracted from the DOM by fabricjs
1329
+ * @param {Array} objects Array of fabric objects
1330
+ * @return {String}
1331
+ */
1332
+ createSVGFontFacesMarkup(): string {
1333
+ const objects: FabricObject[] = [],
1334
+ fontList: Record<string, boolean> = {},
1335
+ fontPaths = config.fontPaths;
1336
+
1337
+ this._objects.forEach(function add(object) {
1338
+ objects.push(object);
1339
+ if (isCollection(object)) {
1340
+ object._objects.forEach(add);
1341
+ }
1342
+ });
1343
+
1344
+ objects.forEach((obj) => {
1345
+ if (!isTextObject(obj)) {
1346
+ return;
1347
+ }
1348
+ let fontFamily = obj.fontFamily;
1349
+ if (fontList[fontFamily] || !fontPaths[fontFamily]) {
1350
+ return;
1351
+ }
1352
+ fontList[fontFamily] = true;
1353
+ if (!obj.styles) {
1354
+ return;
1355
+ }
1356
+ Object.values(obj.styles).forEach((styleRow) => {
1357
+ Object.values(styleRow).forEach((textCharStyle) => {
1358
+ fontFamily = textCharStyle.fontFamily;
1359
+ if (!fontList[fontFamily] && fontPaths[fontFamily]) {
1360
+ fontList[fontFamily] = true;
1361
+ }
1362
+ });
1363
+ });
1364
+ });
1365
+
1366
+ const fontListMarkup = Object.keys(fontList)
1367
+ .map(
1368
+ (fontFamily) =>
1369
+ `\t\t@font-face {\n\t\t\tfont-family: '${fontFamily}';\n\t\t\tsrc: url('${fontPaths[fontFamily]}');\n\t\t}\n`
1370
+ )
1371
+ .join('');
1372
+
1373
+ if (fontListMarkup) {
1374
+ return `\t<style type="text/css"><![CDATA[\n${fontListMarkup}]]></style>\n`;
1375
+ }
1376
+ return '';
1377
+ }
1378
+
1379
+ /**
1380
+ * @private
1381
+ */
1382
+ _setSVGObjects(markup: string[], reviver: TSVGReviver) {
1383
+ this.forEachObject((fabricObject) => {
1384
+ if (fabricObject.excludeFromExport) {
1385
+ return;
1386
+ }
1387
+ this._setSVGObject(markup, fabricObject, reviver);
1388
+ });
1389
+ }
1390
+
1391
+ /**
1392
+ * This is its own function because the Canvas ( non static ) requires extra code here
1393
+ * @private
1394
+ */
1395
+ _setSVGObject(
1396
+ markup: string[],
1397
+ instance: FabricObject,
1398
+ reviver: TSVGReviver
1399
+ ) {
1400
+ markup.push(instance.toSVG(reviver));
1401
+ }
1402
+
1403
+ /**
1404
+ * @private
1405
+ */
1406
+ _setSVGBgOverlayImage(
1407
+ markup: string[],
1408
+ property: 'overlayImage' | 'backgroundImage',
1409
+ reviver: TSVGReviver
1410
+ ) {
1411
+ const bgOrOverlay = this[property];
1412
+ if (bgOrOverlay && !bgOrOverlay.excludeFromExport && bgOrOverlay.toSVG) {
1413
+ markup.push(bgOrOverlay.toSVG(reviver));
1414
+ }
1415
+ }
1416
+
1417
+ /**
1418
+ * @TODO this seems to handle patterns but fail at gradients.
1419
+ * @private
1420
+ */
1421
+ _setSVGBgOverlayColor(markup: string[], property: 'background' | 'overlay') {
1422
+ const filler = this[`${property}Color`];
1423
+ if (!filler) {
1424
+ return;
1425
+ }
1426
+ if (isFiller(filler)) {
1427
+ const repeat = (filler as Pattern).repeat || '',
1428
+ finalWidth = this.width,
1429
+ finalHeight = this.height,
1430
+ shouldInvert = this[`${property}Vpt`],
1431
+ additionalTransform = shouldInvert
1432
+ ? matrixToSVG(invertTransform(this.viewportTransform))
1433
+ : '';
1434
+ markup.push(
1435
+ `<rect transform="${additionalTransform} translate(${finalWidth / 2},${
1436
+ finalHeight / 2
1437
+ })" x="${filler.offsetX - finalWidth / 2}" y="${
1438
+ filler.offsetY - finalHeight / 2
1439
+ }" width="${
1440
+ (repeat === 'repeat-y' || repeat === 'no-repeat') && isPattern(filler)
1441
+ ? filler.source.width
1442
+ : finalWidth
1443
+ }" height="${
1444
+ (repeat === 'repeat-x' || repeat === 'no-repeat') && isPattern(filler)
1445
+ ? filler.source.height
1446
+ : finalHeight
1447
+ }" fill="url(#SVGID_${filler.id})"></rect>\n`
1448
+ );
1449
+ } else {
1450
+ markup.push(
1451
+ '<rect x="0" y="0" width="100%" height="100%" ',
1452
+ 'fill="',
1453
+ filler,
1454
+ '"',
1455
+ '></rect>\n'
1456
+ );
1457
+ }
1458
+ }
1459
+ /* _TO_SVG_END_ */
1460
+
1461
+ /**
1462
+ * Populates canvas with data from the specified JSON.
1463
+ * JSON format must conform to the one of {@link fabric.Canvas#toJSON}
1464
+ *
1465
+ * **IMPORTANT**: It is recommended to abort loading tasks before calling this method to prevent race conditions and unnecessary networking
1466
+ *
1467
+ * @param {String|Object} json JSON string or object
1468
+ * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.
1469
+ * @param {Object} [options] options
1470
+ * @param {AbortSignal} [options.signal] see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal
1471
+ * @return {Promise<Canvas | StaticCanvas>} instance
1472
+ * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#deserialization}
1473
+ * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo}
1474
+ * @example <caption>loadFromJSON</caption>
1475
+ * canvas.loadFromJSON(json).then((canvas) => canvas.requestRenderAll());
1476
+ * @example <caption>loadFromJSON with reviver</caption>
1477
+ * canvas.loadFromJSON(json, function(o, object) {
1478
+ * // `o` = json object
1479
+ * // `object` = fabric.Object instance
1480
+ * // ... do some stuff ...
1481
+ * }).then((canvas) => {
1482
+ * ... canvas is restored, add your code.
1483
+ * });
1484
+ *
1485
+ */
1486
+ loadFromJSON(
1487
+ json: string | Record<string, any>,
1488
+ reviver?: EnlivenObjectOptions['reviver'],
1489
+ { signal }: TCanvasHydrationOption = {}
1490
+ ): Promise<this> {
1491
+ if (!json) {
1492
+ return Promise.reject(new Error('fabric.js: `json` is undefined'));
1493
+ }
1494
+
1495
+ // parse json if it wasn't already
1496
+ const serialized = typeof json === 'string' ? JSON.parse(json) : json;
1497
+ const {
1498
+ objects = [],
1499
+ backgroundImage,
1500
+ background,
1501
+ overlayImage,
1502
+ overlay,
1503
+ clipPath,
1504
+ } = serialized;
1505
+ const renderOnAddRemove = this.renderOnAddRemove;
1506
+ this.renderOnAddRemove = false;
1507
+
1508
+ return Promise.all([
1509
+ enlivenObjects(objects, {
1510
+ reviver,
1511
+ signal,
1512
+ }),
1513
+ enlivenObjectEnlivables(
1514
+ {
1515
+ backgroundImage,
1516
+ backgroundColor: background,
1517
+ overlayImage,
1518
+ overlayColor: overlay,
1519
+ clipPath,
1520
+ },
1521
+ { signal }
1522
+ ),
1523
+ ]).then(([enlived, enlivedMap]) => {
1524
+ this.clear();
1525
+ this.add(...enlived);
1526
+ this.set(serialized);
1527
+ this.set(enlivedMap);
1528
+ this.renderOnAddRemove = renderOnAddRemove;
1529
+ return this;
1530
+ });
1531
+ }
1532
+
1533
+ /**
1534
+ * Clones canvas instance
1535
+ * @param {string[]} [properties] Array of properties to include in the cloned canvas and children
1536
+ */
1537
+ clone(properties: string[]) {
1538
+ const data = this.toObject(properties);
1539
+ const canvas = this.cloneWithoutData();
1540
+ return canvas.loadFromJSON(data);
1541
+ }
1542
+
1543
+ /**
1544
+ * Clones canvas instance without cloning existing data.
1545
+ * This essentially copies canvas dimensions since loadFromJSON does not affect canvas size.
1546
+ */
1547
+ cloneWithoutData() {
1548
+ const el = createCanvasElement();
1549
+ el.width = this.width;
1550
+ el.height = this.height;
1551
+ return new (this.constructor as Constructor<this>)(el);
1552
+ }
1553
+
1554
+ /**
1555
+ * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately
1556
+ * @param {Object} [options] Options object
1557
+ * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png"
1558
+ * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.
1559
+ * @param {Number} [options.multiplier=1] Multiplier to scale by, to have consistent
1560
+ * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14
1561
+ * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14
1562
+ * @param {Number} [options.width] Cropping width. Introduced in v1.2.14
1563
+ * @param {Number} [options.height] Cropping height. Introduced in v1.2.14
1564
+ * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 2.0.0
1565
+ * @param {(object: fabric.Object) => boolean} [options.filter] Function to filter objects.
1566
+ * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format
1567
+ * @see {@link https://jsfiddle.net/xsjua1rd/ demo}
1568
+ * @example <caption>Generate jpeg dataURL with lower quality</caption>
1569
+ * var dataURL = canvas.toDataURL({
1570
+ * format: 'jpeg',
1571
+ * quality: 0.8
1572
+ * });
1573
+ * @example <caption>Generate cropped png dataURL (clipping of canvas)</caption>
1574
+ * var dataURL = canvas.toDataURL({
1575
+ * format: 'png',
1576
+ * left: 100,
1577
+ * top: 100,
1578
+ * width: 200,
1579
+ * height: 200
1580
+ * });
1581
+ * @example <caption>Generate double scaled png dataURL</caption>
1582
+ * var dataURL = canvas.toDataURL({
1583
+ * format: 'png',
1584
+ * multiplier: 2
1585
+ * });
1586
+ * @example <caption>Generate dataURL with objects that overlap a specified object</caption>
1587
+ * var myObject;
1588
+ * var dataURL = canvas.toDataURL({
1589
+ * filter: (object) => object.isContainedWithinObject(myObject) || object.intersectsWithObject(myObject)
1590
+ * });
1591
+ */
1592
+ toDataURL(options = {} as TDataUrlOptions): string {
1593
+ const {
1594
+ format = ImageFormat.png,
1595
+ quality = 1,
1596
+ multiplier = 1,
1597
+ enableRetinaScaling = false,
1598
+ } = options;
1599
+ const finalMultiplier =
1600
+ multiplier * (enableRetinaScaling ? this.getRetinaScaling() : 1);
1601
+
1602
+ return toDataURL(
1603
+ this.toCanvasElement(finalMultiplier, options),
1604
+ format,
1605
+ quality
1606
+ );
1607
+ }
1608
+
1609
+ /**
1610
+ * Create a new HTMLCanvas element painted with the current canvas content.
1611
+ * No need to resize the actual one or repaint it.
1612
+ * Will transfer object ownership to a new canvas, paint it, and set everything back.
1613
+ * This is an intermediary step used to get to a dataUrl but also it is useful to
1614
+ * create quick image copies of a canvas without passing for the dataUrl string
1615
+ * @param {Number} [multiplier] a zoom factor.
1616
+ * @param {Object} [options] Cropping informations
1617
+ * @param {Number} [options.left] Cropping left offset.
1618
+ * @param {Number} [options.top] Cropping top offset.
1619
+ * @param {Number} [options.width] Cropping width.
1620
+ * @param {Number} [options.height] Cropping height.
1621
+ * @param {(object: fabric.Object) => boolean} [options.filter] Function to filter objects.
1622
+ */
1623
+ toCanvasElement(
1624
+ multiplier = 1,
1625
+ { width, height, left, top, filter } = {} as TToCanvasElementOptions
1626
+ ): HTMLCanvasElement {
1627
+ const scaledWidth = (width || this.width) * multiplier,
1628
+ scaledHeight = (height || this.height) * multiplier,
1629
+ zoom = this.getZoom(),
1630
+ originalWidth = this.width,
1631
+ originalHeight = this.height,
1632
+ newZoom = zoom * multiplier,
1633
+ vp = this.viewportTransform,
1634
+ translateX = (vp[4] - (left || 0)) * multiplier,
1635
+ translateY = (vp[5] - (top || 0)) * multiplier,
1636
+ newVp = [newZoom, 0, 0, newZoom, translateX, translateY] as TMat2D,
1637
+ originalRetina = this.enableRetinaScaling,
1638
+ canvasEl = createCanvasElement(),
1639
+ objectsToRender = filter
1640
+ ? this._objects.filter((obj) => filter(obj))
1641
+ : this._objects;
1642
+ canvasEl.width = scaledWidth;
1643
+ canvasEl.height = scaledHeight;
1644
+ this.enableRetinaScaling = false;
1645
+ this.viewportTransform = newVp;
1646
+ this.width = scaledWidth;
1647
+ this.height = scaledHeight;
1648
+ this.calcViewportBoundaries();
1649
+ this.renderCanvas(canvasEl.getContext('2d')!, objectsToRender);
1650
+ this.viewportTransform = vp;
1651
+ this.width = originalWidth;
1652
+ this.height = originalHeight;
1653
+ this.calcViewportBoundaries();
1654
+ this.enableRetinaScaling = originalRetina;
1655
+ return canvasEl;
1656
+ }
1657
+
1658
+ /**
1659
+ * Waits until rendering has settled to destroy the canvas
1660
+ * @returns {Promise<boolean>} a promise resolving to `true` once the canvas has been destroyed or to `false` if the canvas has was already destroyed
1661
+ * @throws if aborted by a consequent call
1662
+ */
1663
+ dispose() {
1664
+ this.disposed = true;
1665
+ return new Promise<boolean>((resolve, reject) => {
1666
+ const task = () => {
1667
+ this.destroy();
1668
+ resolve(true);
1669
+ };
1670
+ task.kill = reject;
1671
+ if (this.__cleanupTask) {
1672
+ this.__cleanupTask.kill('aborted');
1673
+ }
1674
+
1675
+ if (this.destroyed) {
1676
+ resolve(false);
1677
+ } else if (this.nextRenderHandle) {
1678
+ this.__cleanupTask = task;
1679
+ } else {
1680
+ task();
1681
+ }
1682
+ });
1683
+ }
1684
+
1685
+ /**
1686
+ * Clears the canvas element, disposes objects and frees resources
1687
+ *
1688
+ * **CAUTION**:
1689
+ *
1690
+ * This method is **UNSAFE**.
1691
+ * You may encounter a race condition using it if there's a requested render.
1692
+ * Call this method only if you are sure rendering has settled.
1693
+ * Consider using {@link dispose} as it is **SAFE**
1694
+ *
1695
+ * @private
1696
+ */
1697
+ destroy() {
1698
+ this.destroyed = true;
1699
+ this.cancelRequestedRender();
1700
+ this.forEachObject((object) => object.dispose());
1701
+ this._objects = [];
1702
+ if (this.backgroundImage) {
1703
+ this.backgroundImage.dispose();
1704
+ }
1705
+ this.backgroundImage = null;
1706
+ if (this.overlayImage) {
1707
+ this.overlayImage.dispose();
1708
+ }
1709
+ this.overlayImage = null;
1710
+ // @ts-expect-error disposing
1711
+ this.contextContainer = null;
1712
+ const canvasElement = this.lowerCanvasEl!;
1713
+ (this as TDestroyedCanvas<StaticCanvas>).lowerCanvasEl = undefined;
1714
+ // restore canvas style and attributes
1715
+ canvasElement.classList.remove('lower-canvas');
1716
+ canvasElement.removeAttribute('data-fabric');
1717
+ // restore canvas size to original size in case retina scaling was applied
1718
+ canvasElement.setAttribute('width', `${this.width}`);
1719
+ canvasElement.setAttribute('height', `${this.height}`);
1720
+ canvasElement.style.cssText = this._originalCanvasStyle || '';
1721
+ this._originalCanvasStyle = undefined;
1722
+ getEnv().dispose(canvasElement);
1723
+ }
1724
+
1725
+ /**
1726
+ * Returns a string representation of an instance
1727
+ * @return {String} string representation of an instance
1728
+ */
1729
+ toString() {
1730
+ return `#<Canvas (${this.complexity()}): { objects: ${
1731
+ this._objects.length
1732
+ } }>`;
1733
+ }
1734
+ }