fabric 7.0.0 → 7.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 (323) hide show
  1. package/.husky/pre-commit +1 -0
  2. package/CHANGELOG.md +21 -0
  3. package/dist/extensions/cropping_controls/croppingControls.d.ts +16 -0
  4. package/dist/extensions/cropping_controls/croppingControls.d.ts.map +1 -0
  5. package/dist/extensions/cropping_controls/croppingHandlers.d.ts +39 -0
  6. package/dist/extensions/cropping_controls/croppingHandlers.d.ts.map +1 -0
  7. package/dist/extensions/cropping_controls/enterCropMode.d.ts +7 -0
  8. package/dist/extensions/cropping_controls/enterCropMode.d.ts.map +1 -0
  9. package/dist/extensions/cropping_controls/renderCornerControl.d.ts +14 -0
  10. package/dist/extensions/cropping_controls/renderCornerControl.d.ts.map +1 -0
  11. package/dist/extensions/index.d.ts +3 -0
  12. package/dist/extensions/index.d.ts.map +1 -1
  13. package/dist/fabric.d.ts +1 -0
  14. package/dist/fabric.d.ts.map +1 -1
  15. package/dist/index.js +628 -537
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.min.js +1 -1
  18. package/dist/index.min.js.map +1 -1
  19. package/dist/index.min.mjs +1 -1
  20. package/dist/index.min.mjs.map +1 -1
  21. package/dist/index.mjs +628 -537
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/index.node.cjs +628 -537
  24. package/dist/index.node.cjs.map +1 -1
  25. package/dist/index.node.mjs +628 -537
  26. package/dist/index.node.mjs.map +1 -1
  27. package/dist/package.json.min.mjs +1 -1
  28. package/dist/package.json.mjs +1 -1
  29. package/dist/src/EventTypeDefs.d.ts +5 -0
  30. package/dist/src/EventTypeDefs.d.ts.map +1 -1
  31. package/dist/src/Pattern/Pattern.d.ts.map +1 -1
  32. package/dist/src/Pattern/Pattern.min.mjs +1 -1
  33. package/dist/src/Pattern/Pattern.min.mjs.map +1 -1
  34. package/dist/src/Pattern/Pattern.mjs +2 -1
  35. package/dist/src/Pattern/Pattern.mjs.map +1 -1
  36. package/dist/src/Shadow.d.ts +1 -1
  37. package/dist/src/Shadow.d.ts.map +1 -1
  38. package/dist/src/Shadow.min.mjs +1 -1
  39. package/dist/src/Shadow.min.mjs.map +1 -1
  40. package/dist/src/Shadow.mjs +5 -4
  41. package/dist/src/Shadow.mjs.map +1 -1
  42. package/dist/src/canvas/CanvasOptions.d.ts.map +1 -1
  43. package/dist/src/canvas/CanvasOptions.min.mjs.map +1 -1
  44. package/dist/src/canvas/CanvasOptions.mjs.map +1 -1
  45. package/dist/src/canvas/SelectableCanvas.d.ts +2 -0
  46. package/dist/src/canvas/SelectableCanvas.d.ts.map +1 -1
  47. package/dist/src/canvas/SelectableCanvas.min.mjs +1 -1
  48. package/dist/src/canvas/SelectableCanvas.min.mjs.map +1 -1
  49. package/dist/src/canvas/SelectableCanvas.mjs +33 -13
  50. package/dist/src/canvas/SelectableCanvas.mjs.map +1 -1
  51. package/dist/src/canvas/StaticCanvas.d.ts.map +1 -1
  52. package/dist/src/canvas/StaticCanvas.min.mjs +1 -1
  53. package/dist/src/canvas/StaticCanvas.min.mjs.map +1 -1
  54. package/dist/src/canvas/StaticCanvas.mjs +3 -1
  55. package/dist/src/canvas/StaticCanvas.mjs.map +1 -1
  56. package/dist/src/canvas/StaticCanvasOptions.d.ts.map +1 -1
  57. package/dist/src/canvas/StaticCanvasOptions.min.mjs.map +1 -1
  58. package/dist/src/canvas/StaticCanvasOptions.mjs.map +1 -1
  59. package/dist/src/constants.d.ts +1 -0
  60. package/dist/src/constants.d.ts.map +1 -1
  61. package/dist/src/constants.min.mjs.map +1 -1
  62. package/dist/src/constants.mjs.map +1 -1
  63. package/dist/src/controls/Control.d.ts +22 -1
  64. package/dist/src/controls/Control.d.ts.map +1 -1
  65. package/dist/src/controls/Control.min.mjs +1 -1
  66. package/dist/src/controls/Control.min.mjs.map +1 -1
  67. package/dist/src/controls/Control.mjs +45 -1
  68. package/dist/src/controls/Control.mjs.map +1 -1
  69. package/dist/src/controls/changeWidth.d.ts +22 -0
  70. package/dist/src/controls/changeWidth.d.ts.map +1 -1
  71. package/dist/src/controls/changeWidth.min.mjs +1 -1
  72. package/dist/src/controls/changeWidth.min.mjs.map +1 -1
  73. package/dist/src/controls/changeWidth.mjs +46 -18
  74. package/dist/src/controls/changeWidth.mjs.map +1 -1
  75. package/dist/src/controls/controlRendering.d.ts.map +1 -1
  76. package/dist/src/controls/controlRendering.min.mjs +1 -1
  77. package/dist/src/controls/controlRendering.min.mjs.map +1 -1
  78. package/dist/src/controls/controlRendering.mjs +18 -34
  79. package/dist/src/controls/controlRendering.mjs.map +1 -1
  80. package/dist/src/controls/index.d.ts +2 -1
  81. package/dist/src/controls/index.d.ts.map +1 -1
  82. package/dist/src/controls/index.min.mjs +1 -1
  83. package/dist/src/controls/index.mjs +1 -1
  84. package/dist/src/gradient/Gradient.d.ts.map +1 -1
  85. package/dist/src/gradient/Gradient.min.mjs +1 -1
  86. package/dist/src/gradient/Gradient.min.mjs.map +1 -1
  87. package/dist/src/gradient/Gradient.mjs +19 -6
  88. package/dist/src/gradient/Gradient.mjs.map +1 -1
  89. package/dist/src/shapes/Circle.d.ts.map +1 -1
  90. package/dist/src/shapes/Circle.min.mjs +1 -1
  91. package/dist/src/shapes/Circle.min.mjs.map +1 -1
  92. package/dist/src/shapes/Circle.mjs +10 -7
  93. package/dist/src/shapes/Circle.mjs.map +1 -1
  94. package/dist/src/shapes/Ellipse.d.ts.map +1 -1
  95. package/dist/src/shapes/Ellipse.min.mjs +1 -1
  96. package/dist/src/shapes/Ellipse.min.mjs.map +1 -1
  97. package/dist/src/shapes/Ellipse.mjs +2 -1
  98. package/dist/src/shapes/Ellipse.mjs.map +1 -1
  99. package/dist/src/shapes/Group.d.ts.map +1 -1
  100. package/dist/src/shapes/Group.min.mjs +1 -1
  101. package/dist/src/shapes/Group.min.mjs.map +1 -1
  102. package/dist/src/shapes/Group.mjs +2 -1
  103. package/dist/src/shapes/Group.mjs.map +1 -1
  104. package/dist/src/shapes/IText/IText.d.ts.map +1 -1
  105. package/dist/src/shapes/IText/IText.min.mjs.map +1 -1
  106. package/dist/src/shapes/IText/IText.mjs.map +1 -1
  107. package/dist/src/shapes/Image.d.ts +1 -1
  108. package/dist/src/shapes/Image.d.ts.map +1 -1
  109. package/dist/src/shapes/Image.min.mjs +1 -1
  110. package/dist/src/shapes/Image.min.mjs.map +1 -1
  111. package/dist/src/shapes/Image.mjs +4 -3
  112. package/dist/src/shapes/Image.mjs.map +1 -1
  113. package/dist/src/shapes/Line.d.ts.map +1 -1
  114. package/dist/src/shapes/Line.min.mjs +1 -1
  115. package/dist/src/shapes/Line.min.mjs.map +1 -1
  116. package/dist/src/shapes/Line.mjs +6 -10
  117. package/dist/src/shapes/Line.mjs.map +1 -1
  118. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.d.ts.map +1 -1
  119. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.min.mjs +1 -1
  120. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.min.mjs.map +1 -1
  121. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.mjs +5 -4
  122. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.mjs.map +1 -1
  123. package/dist/src/shapes/Object/InteractiveObject.d.ts.map +1 -1
  124. package/dist/src/shapes/Object/InteractiveObject.min.mjs.map +1 -1
  125. package/dist/src/shapes/Object/InteractiveObject.mjs.map +1 -1
  126. package/dist/src/shapes/Object/Object.d.ts.map +1 -1
  127. package/dist/src/shapes/Object/Object.min.mjs +1 -1
  128. package/dist/src/shapes/Object/Object.min.mjs.map +1 -1
  129. package/dist/src/shapes/Object/Object.mjs +3 -0
  130. package/dist/src/shapes/Object/Object.mjs.map +1 -1
  131. package/dist/src/shapes/Object/ObjectGeometry.min.mjs +1 -1
  132. package/dist/src/shapes/Object/ObjectGeometry.min.mjs.map +1 -1
  133. package/dist/src/shapes/Object/ObjectGeometry.mjs +1 -1
  134. package/dist/src/shapes/Object/ObjectGeometry.mjs.map +1 -1
  135. package/dist/src/shapes/Object/types/FabricObjectProps.d.ts.map +1 -1
  136. package/dist/src/shapes/Object/types/ObjectProps.d.ts.map +1 -1
  137. package/dist/src/shapes/Path.d.ts.map +1 -1
  138. package/dist/src/shapes/Path.min.mjs.map +1 -1
  139. package/dist/src/shapes/Path.mjs +1 -2
  140. package/dist/src/shapes/Path.mjs.map +1 -1
  141. package/dist/src/shapes/Polyline.d.ts.map +1 -1
  142. package/dist/src/shapes/Polyline.min.mjs +1 -1
  143. package/dist/src/shapes/Polyline.min.mjs.map +1 -1
  144. package/dist/src/shapes/Polyline.mjs +10 -6
  145. package/dist/src/shapes/Polyline.mjs.map +1 -1
  146. package/dist/src/shapes/Rect.d.ts.map +1 -1
  147. package/dist/src/shapes/Rect.min.mjs +1 -1
  148. package/dist/src/shapes/Rect.min.mjs.map +1 -1
  149. package/dist/src/shapes/Rect.mjs +2 -1
  150. package/dist/src/shapes/Rect.mjs.map +1 -1
  151. package/dist/src/shapes/Text/StyledText.d.ts.map +1 -1
  152. package/dist/src/shapes/Text/StyledText.min.mjs.map +1 -1
  153. package/dist/src/shapes/Text/StyledText.mjs +0 -3
  154. package/dist/src/shapes/Text/StyledText.mjs.map +1 -1
  155. package/dist/src/shapes/Text/Text.d.ts.map +1 -1
  156. package/dist/src/shapes/Text/Text.min.mjs.map +1 -1
  157. package/dist/src/shapes/Text/Text.mjs.map +1 -1
  158. package/dist/src/shapes/Text/TextSVGExportMixin.d.ts.map +1 -1
  159. package/dist/src/shapes/Text/TextSVGExportMixin.min.mjs +1 -1
  160. package/dist/src/shapes/Text/TextSVGExportMixin.min.mjs.map +1 -1
  161. package/dist/src/shapes/Text/TextSVGExportMixin.mjs +5 -6
  162. package/dist/src/shapes/Text/TextSVGExportMixin.mjs.map +1 -1
  163. package/dist/src/shapes/Textbox.d.ts.map +1 -1
  164. package/dist/src/shapes/Textbox.min.mjs.map +1 -1
  165. package/dist/src/shapes/Textbox.mjs.map +1 -1
  166. package/dist/src/shapes/Triangle.d.ts.map +1 -1
  167. package/dist/src/shapes/Triangle.min.mjs.map +1 -1
  168. package/dist/src/shapes/Triangle.mjs.map +1 -1
  169. package/dist/src/util/lang_string.d.ts +1 -1
  170. package/dist/src/util/lang_string.d.ts.map +1 -1
  171. package/dist/src/util/lang_string.min.mjs +1 -1
  172. package/dist/src/util/lang_string.min.mjs.map +1 -1
  173. package/dist/src/util/lang_string.mjs +1 -1
  174. package/dist/src/util/lang_string.mjs.map +1 -1
  175. package/dist/src/util/misc/svgParsing.d.ts.map +1 -1
  176. package/dist/src/util/misc/svgParsing.min.mjs +1 -1
  177. package/dist/src/util/misc/svgParsing.min.mjs.map +1 -1
  178. package/dist/src/util/misc/svgParsing.mjs +2 -1
  179. package/dist/src/util/misc/svgParsing.mjs.map +1 -1
  180. package/dist-extensions/cropping_controls/croppingControls.mjs +140 -0
  181. package/dist-extensions/cropping_controls/croppingControls.mjs.map +1 -0
  182. package/dist-extensions/cropping_controls/croppingHandlers.mjs +228 -0
  183. package/dist-extensions/cropping_controls/croppingHandlers.mjs.map +1 -0
  184. package/dist-extensions/cropping_controls/enterCropMode.mjs +38 -0
  185. package/dist-extensions/cropping_controls/enterCropMode.mjs.map +1 -0
  186. package/dist-extensions/cropping_controls/renderCornerControl.mjs +45 -0
  187. package/dist-extensions/cropping_controls/renderCornerControl.mjs.map +1 -0
  188. package/dist-extensions/extensions/cropping_controls/croppingControls.d.ts +16 -0
  189. package/dist-extensions/extensions/cropping_controls/croppingControls.d.ts.map +1 -0
  190. package/dist-extensions/extensions/cropping_controls/croppingHandlers.d.ts +39 -0
  191. package/dist-extensions/extensions/cropping_controls/croppingHandlers.d.ts.map +1 -0
  192. package/dist-extensions/extensions/cropping_controls/enterCropMode.d.ts +7 -0
  193. package/dist-extensions/extensions/cropping_controls/enterCropMode.d.ts.map +1 -0
  194. package/dist-extensions/extensions/cropping_controls/renderCornerControl.d.ts +14 -0
  195. package/dist-extensions/extensions/cropping_controls/renderCornerControl.d.ts.map +1 -0
  196. package/dist-extensions/extensions/index.d.ts +3 -0
  197. package/dist-extensions/extensions/index.d.ts.map +1 -1
  198. package/dist-extensions/fabric-extensions.min.js +1 -1
  199. package/dist-extensions/fabric-extensions.min.js.map +1 -1
  200. package/dist-extensions/fabric.d.ts +1 -0
  201. package/dist-extensions/fabric.d.ts.map +1 -1
  202. package/dist-extensions/index.mjs +3 -0
  203. package/dist-extensions/index.mjs.map +1 -1
  204. package/dist-extensions/src/EventTypeDefs.d.ts +5 -0
  205. package/dist-extensions/src/EventTypeDefs.d.ts.map +1 -1
  206. package/dist-extensions/src/Pattern/Pattern.d.ts.map +1 -1
  207. package/dist-extensions/src/Shadow.d.ts +1 -1
  208. package/dist-extensions/src/Shadow.d.ts.map +1 -1
  209. package/dist-extensions/src/canvas/CanvasOptions.d.ts.map +1 -1
  210. package/dist-extensions/src/canvas/SelectableCanvas.d.ts +2 -0
  211. package/dist-extensions/src/canvas/SelectableCanvas.d.ts.map +1 -1
  212. package/dist-extensions/src/canvas/StaticCanvas.d.ts.map +1 -1
  213. package/dist-extensions/src/canvas/StaticCanvasOptions.d.ts.map +1 -1
  214. package/dist-extensions/src/constants.d.ts +1 -0
  215. package/dist-extensions/src/constants.d.ts.map +1 -1
  216. package/dist-extensions/src/controls/Control.d.ts +22 -1
  217. package/dist-extensions/src/controls/Control.d.ts.map +1 -1
  218. package/dist-extensions/src/controls/changeWidth.d.ts +22 -0
  219. package/dist-extensions/src/controls/changeWidth.d.ts.map +1 -1
  220. package/dist-extensions/src/controls/controlRendering.d.ts.map +1 -1
  221. package/dist-extensions/src/controls/index.d.ts +2 -1
  222. package/dist-extensions/src/controls/index.d.ts.map +1 -1
  223. package/dist-extensions/src/gradient/Gradient.d.ts.map +1 -1
  224. package/dist-extensions/src/shapes/Circle.d.ts.map +1 -1
  225. package/dist-extensions/src/shapes/Ellipse.d.ts.map +1 -1
  226. package/dist-extensions/src/shapes/Group.d.ts.map +1 -1
  227. package/dist-extensions/src/shapes/IText/IText.d.ts.map +1 -1
  228. package/dist-extensions/src/shapes/Image.d.ts.map +1 -1
  229. package/dist-extensions/src/shapes/Line.d.ts.map +1 -1
  230. package/dist-extensions/src/shapes/Object/FabricObjectSVGExportMixin.d.ts.map +1 -1
  231. package/dist-extensions/src/shapes/Object/InteractiveObject.d.ts.map +1 -1
  232. package/dist-extensions/src/shapes/Object/Object.d.ts.map +1 -1
  233. package/dist-extensions/src/shapes/Object/types/FabricObjectProps.d.ts.map +1 -1
  234. package/dist-extensions/src/shapes/Object/types/ObjectProps.d.ts.map +1 -1
  235. package/dist-extensions/src/shapes/Path.d.ts +1 -1
  236. package/dist-extensions/src/shapes/Path.d.ts.map +1 -1
  237. package/dist-extensions/src/shapes/Polyline.d.ts.map +1 -1
  238. package/dist-extensions/src/shapes/Rect.d.ts.map +1 -1
  239. package/dist-extensions/src/shapes/Text/StyledText.d.ts.map +1 -1
  240. package/dist-extensions/src/shapes/Text/Text.d.ts.map +1 -1
  241. package/dist-extensions/src/shapes/Text/TextSVGExportMixin.d.ts.map +1 -1
  242. package/dist-extensions/src/shapes/Textbox.d.ts.map +1 -1
  243. package/dist-extensions/src/shapes/Triangle.d.ts.map +1 -1
  244. package/dist-extensions/src/util/lang_string.d.ts +1 -1
  245. package/dist-extensions/src/util/lang_string.d.ts.map +1 -1
  246. package/dist-extensions/src/util/misc/svgParsing.d.ts.map +1 -1
  247. package/eslint.config.mjs +2 -0
  248. package/extensions/cropping_controls/croppingControls.spec.ts +115 -0
  249. package/extensions/cropping_controls/croppingControls.ts +150 -0
  250. package/extensions/cropping_controls/croppingHandlers.spec.ts +579 -0
  251. package/extensions/cropping_controls/croppingHandlers.ts +285 -0
  252. package/extensions/cropping_controls/enterCropMode.ts +30 -0
  253. package/extensions/cropping_controls/renderCornerControl.ts +53 -0
  254. package/extensions/index.ts +9 -0
  255. package/fabric.ts +1 -0
  256. package/package.json +17 -8
  257. package/src/ClassRegistry.spec.ts +18 -19
  258. package/src/EventTypeDefs.ts +15 -11
  259. package/src/Pattern/Pattern.spec.ts +12 -0
  260. package/src/Pattern/Pattern.ts +3 -2
  261. package/src/Shadow.ts +9 -8
  262. package/src/brushes/PencilBrush.spec.ts +11 -11
  263. package/src/canvas/Canvas-dispose.spec.ts +8 -7
  264. package/src/canvas/Canvas.spec.ts +27 -29
  265. package/src/canvas/CanvasOptions.ts +2 -1
  266. package/src/canvas/SelectableCanvas.ts +38 -15
  267. package/src/canvas/StaticCanvas.spec.ts +20 -0
  268. package/src/canvas/StaticCanvas.ts +7 -4
  269. package/src/canvas/StaticCanvasOptions.ts +1 -3
  270. package/src/constants.ts +1 -0
  271. package/src/controls/Control.spec.ts +102 -0
  272. package/src/controls/Control.ts +71 -2
  273. package/src/controls/changeHeight.spec.ts +147 -0
  274. package/src/controls/changeWidth.ts +68 -35
  275. package/src/controls/controlRendering.ts +20 -48
  276. package/src/controls/index.ts +7 -1
  277. package/src/gradient/Gradient.spec.ts +101 -46
  278. package/src/gradient/Gradient.ts +27 -14
  279. package/src/shapes/Circle.spec.ts +10 -39
  280. package/src/shapes/Circle.ts +11 -11
  281. package/src/shapes/Ellipse.spec.ts +8 -37
  282. package/src/shapes/Ellipse.ts +7 -7
  283. package/src/shapes/Group.ts +3 -3
  284. package/src/shapes/IText/IText-click-behavior.spec.ts +36 -49
  285. package/src/shapes/IText/IText.ts +5 -6
  286. package/src/shapes/IText/ITextKeyBehavior.test.ts +0 -1
  287. package/src/shapes/IText/__snapshots__/ITextBehavior.test.ts.snap +6 -6
  288. package/src/shapes/Image.spec.ts +17 -33
  289. package/src/shapes/Image.ts +15 -11
  290. package/src/shapes/Line.spec.ts +4 -30
  291. package/src/shapes/Line.ts +11 -16
  292. package/src/shapes/Object/FabricObjectSVGExportMixin.ts +11 -4
  293. package/src/shapes/Object/InteractiveObject.ts +4 -4
  294. package/src/shapes/Object/Object.ts +6 -5
  295. package/src/shapes/Object/ObjectGeometry.spec.ts +15 -0
  296. package/src/shapes/Object/ObjectGeometry.ts +1 -1
  297. package/src/shapes/Object/objectSvgExport.spec.ts +112 -0
  298. package/src/shapes/Object/types/FabricObjectProps.ts +1 -4
  299. package/src/shapes/Object/types/ObjectProps.ts +1 -3
  300. package/src/shapes/Path.spec.ts +4 -27
  301. package/src/shapes/Path.ts +2 -4
  302. package/src/shapes/Polygon.spec.ts +4 -31
  303. package/src/shapes/Polyline.spec.ts +4 -31
  304. package/src/shapes/Polyline.ts +11 -12
  305. package/src/shapes/Rect.spec.ts +25 -33
  306. package/src/shapes/Rect.ts +7 -7
  307. package/src/shapes/Text/StyledText.ts +0 -3
  308. package/src/shapes/Text/Text.spec.ts +3 -32
  309. package/src/shapes/Text/Text.ts +5 -6
  310. package/src/shapes/Text/TextSVGExportMixin.spec.ts +9 -0
  311. package/src/shapes/Text/TextSVGExportMixin.ts +14 -16
  312. package/src/shapes/Text/__snapshots__/Text.spec.ts.snap +1 -1
  313. package/src/shapes/Text/__snapshots__/TextSVGExportMixin.spec.ts.snap +1 -1
  314. package/src/shapes/Textbox.spec.ts +5 -5
  315. package/src/shapes/Textbox.ts +6 -5
  316. package/src/shapes/Triangle.ts +4 -4
  317. package/src/shapes/__snapshots__/Image.spec.ts.snap +4 -4
  318. package/src/shapes/__snapshots__/Textbox.spec.ts.snap +5 -5
  319. package/src/util/lang_string.ts +3 -2
  320. package/src/util/misc/svgParsing.ts +2 -1
  321. package/tsconfig.spec.json +1 -0
  322. package/vitest.config.ts +12 -2
  323. package/vitest.extend.ts +6 -2
@@ -1 +1 @@
1
- {"version":3,"file":"TextSVGExportMixin.min.mjs","sources":["../../../../src/shapes/Text/TextSVGExportMixin.ts"],"sourcesContent":["import { config } from '../../config';\nimport type { TSVGReviver } from '../../typedefs';\nimport { escapeXml } from '../../util/lang_string';\nimport { colorPropToSVG, createSVGRect } from '../../util/misc/svgParsing';\nimport { hasStyleChanged } from '../../util/misc/textStyles';\nimport { toFixed } from '../../util/misc/toFixed';\nimport { FabricObjectSVGExportMixin } from '../Object/FabricObjectSVGExportMixin';\nimport { type TextStyleDeclaration } from './StyledText';\nimport { JUSTIFY } from '../Text/constants';\nimport type { FabricText, GraphemeBBox } from './Text';\nimport { STROKE, FILL } from '../../constants';\nimport { createRotateMatrix } from '../../util/misc/matrix';\nimport { radiansToDegrees } from '../../util/misc/radiansDegreesConversion';\nimport { Point } from '../../Point';\nimport { matrixToSVG } from '../../util/misc/svgExport';\n\nconst multipleSpacesRegex = / +/g;\nconst dblQuoteRegex = /\"/g;\n\nfunction createSVGInlineRect(\n color: string,\n left: number,\n top: number,\n width: number,\n height: number,\n) {\n return `\\t\\t${createSVGRect(color, { left, top, width, height })}\\n`;\n}\n\nexport class TextSVGExportMixin extends FabricObjectSVGExportMixin {\n _toSVG(this: TextSVGExportMixin & FabricText): string[] {\n const offsets = this._getSVGLeftTopOffsets(),\n textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);\n return this._wrapSVGTextAndBg(textAndBg);\n }\n\n toSVG(this: TextSVGExportMixin & FabricText, reviver?: TSVGReviver): string {\n const textSvg = this._createBaseSVGMarkup(this._toSVG(), {\n reviver,\n noStyle: true,\n withShadow: true,\n }),\n path = this.path;\n if (path) {\n return (\n textSvg +\n path._createBaseSVGMarkup(path._toSVG(), {\n reviver,\n withShadow: true,\n additionalTransform: matrixToSVG(this.calcOwnMatrix()),\n })\n );\n }\n return textSvg;\n }\n\n private _getSVGLeftTopOffsets(this: TextSVGExportMixin & FabricText) {\n return {\n textLeft: -this.width / 2,\n textTop: -this.height / 2,\n lineTop: this.getHeightOfLine(0),\n };\n }\n\n private _wrapSVGTextAndBg(\n this: TextSVGExportMixin & FabricText,\n {\n textBgRects,\n textSpans,\n }: {\n textSpans: string[];\n textBgRects: string[];\n },\n ) {\n const noShadow = true,\n textDecoration = this.getSvgTextDecoration(this);\n return [\n textBgRects.join(''),\n '\\t\\t<text xml:space=\"preserve\" ',\n `font-family=\"${this.fontFamily.replace(dblQuoteRegex, \"'\")}\" `,\n `font-size=\"${this.fontSize}\" `,\n this.fontStyle ? `font-style=\"${this.fontStyle}\" ` : '',\n this.fontWeight ? `font-weight=\"${this.fontWeight}\" ` : '',\n textDecoration ? `text-decoration=\"${textDecoration}\" ` : '',\n this.direction === 'rtl' ? `direction=\"${this.direction}\" ` : '',\n 'style=\"',\n this.getSvgStyles(noShadow),\n '\"',\n this.addPaintOrder(),\n ' >',\n textSpans.join(''),\n '</text>\\n',\n ];\n }\n\n /**\n * @private\n * @param {Number} textTopOffset Text top offset\n * @param {Number} textLeftOffset Text left offset\n * @return {Object}\n */\n private _getSVGTextAndBg(\n this: TextSVGExportMixin & FabricText,\n textTopOffset: number,\n textLeftOffset: number,\n ) {\n const textSpans: string[] = [],\n textBgRects: string[] = [];\n let height = textTopOffset,\n lineOffset;\n\n // bounding-box background\n this.backgroundColor &&\n textBgRects.push(\n ...createSVGInlineRect(\n this.backgroundColor,\n -this.width / 2,\n -this.height / 2,\n this.width,\n this.height,\n ),\n );\n\n // text and text-background\n for (let i = 0, len = this._textLines.length; i < len; i++) {\n lineOffset = this._getLineLeftOffset(i);\n if (this.direction === 'rtl') {\n lineOffset += this.width;\n }\n if (this.textBackgroundColor || this.styleHas('textBackgroundColor', i)) {\n this._setSVGTextLineBg(\n textBgRects,\n i,\n textLeftOffset + lineOffset,\n height,\n );\n }\n this._setSVGTextLineText(\n textSpans,\n i,\n textLeftOffset + lineOffset,\n height,\n );\n height += this.getHeightOfLine(i);\n }\n\n return {\n textSpans,\n textBgRects,\n };\n }\n\n private _createTextCharSpan(\n this: TextSVGExportMixin & FabricText,\n char: string,\n styleDecl: TextStyleDeclaration,\n left: number,\n top: number,\n charBox: GraphemeBBox,\n ) {\n const numFractionDigit = config.NUM_FRACTION_DIGITS;\n const styleProps = this.getSvgSpanStyles(\n styleDecl,\n char !== char.trim() || !!char.match(multipleSpacesRegex),\n ),\n fillStyles = styleProps ? `style=\"${styleProps}\"` : '',\n dy = styleDecl.deltaY,\n dySpan = dy ? ` dy=\"${toFixed(dy, numFractionDigit)}\" ` : '',\n { angle, renderLeft, renderTop, width } = charBox;\n let angleAttr = '';\n if (renderLeft !== undefined) {\n const wBy2 = width / 2;\n angle &&\n (angleAttr = ` rotate=\"${toFixed(radiansToDegrees(angle), numFractionDigit)}\"`);\n const m = createRotateMatrix({ angle: radiansToDegrees(angle!) });\n m[4] = renderLeft!;\n m[5] = renderTop!;\n const renderPoint = new Point(-wBy2, 0).transform(m);\n left = renderPoint.x;\n top = renderPoint.y;\n }\n\n return `<tspan x=\"${toFixed(left, numFractionDigit)}\" y=\"${toFixed(\n top,\n numFractionDigit,\n )}\" ${dySpan}${angleAttr}${fillStyles}>${escapeXml(char)}</tspan>`;\n }\n\n private _setSVGTextLineText(\n this: TextSVGExportMixin & FabricText,\n textSpans: string[],\n lineIndex: number,\n textLeftOffset: number,\n textTopOffset: number,\n ) {\n const lineHeight = this.getHeightOfLine(lineIndex),\n isJustify = this.textAlign.includes(JUSTIFY),\n line = this._textLines[lineIndex];\n let actualStyle,\n nextStyle,\n charsToRender = '',\n charBox,\n style,\n boxWidth = 0,\n timeToRender;\n\n textTopOffset +=\n (lineHeight * (1 - this._fontSizeFraction)) / this.lineHeight;\n for (let i = 0, len = line.length - 1; i <= len; i++) {\n timeToRender = i === len || this.charSpacing || this.path;\n charsToRender += line[i];\n charBox = this.__charBounds[lineIndex][i];\n if (boxWidth === 0) {\n textLeftOffset += charBox.kernedWidth - charBox.width;\n boxWidth += charBox.width;\n } else {\n boxWidth += charBox.kernedWidth;\n }\n if (isJustify && !timeToRender) {\n if (this._reSpaceAndTab.test(line[i])) {\n timeToRender = true;\n }\n }\n if (!timeToRender) {\n // if we have charSpacing or a path, we render char by char\n actualStyle =\n actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n timeToRender = hasStyleChanged(actualStyle, nextStyle, true);\n }\n if (timeToRender) {\n style = this._getStyleDeclaration(lineIndex, i);\n textSpans.push(\n this._createTextCharSpan(\n charsToRender,\n style,\n textLeftOffset,\n textTopOffset,\n charBox,\n ),\n );\n charsToRender = '';\n actualStyle = nextStyle;\n if (this.direction === 'rtl') {\n textLeftOffset -= boxWidth;\n } else {\n textLeftOffset += boxWidth;\n }\n boxWidth = 0;\n }\n }\n }\n\n private _setSVGTextLineBg(\n this: TextSVGExportMixin & FabricText,\n textBgRects: (string | number)[],\n i: number,\n leftOffset: number,\n textTopOffset: number,\n ) {\n const line = this._textLines[i],\n heightOfLine = this.getHeightOfLine(i) / this.lineHeight;\n let boxWidth = 0,\n boxStart = 0,\n currentColor,\n lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n for (let j = 0; j < line.length; j++) {\n const { left, width, kernedWidth } = this.__charBounds[i][j];\n currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n if (currentColor !== lastColor) {\n lastColor &&\n textBgRects.push(\n ...createSVGInlineRect(\n lastColor,\n leftOffset + boxStart,\n textTopOffset,\n boxWidth,\n heightOfLine,\n ),\n );\n boxStart = left;\n boxWidth = width;\n lastColor = currentColor;\n } else {\n boxWidth += kernedWidth;\n }\n }\n currentColor &&\n textBgRects.push(\n ...createSVGInlineRect(\n lastColor,\n leftOffset + boxStart,\n textTopOffset,\n boxWidth,\n heightOfLine,\n ),\n );\n }\n\n /**\n * Returns styles-string for svg-export\n * @param {Boolean} skipShadow a boolean to skip shadow filter output\n * @return {String}\n */\n getSvgStyles(this: TextSVGExportMixin & FabricText, skipShadow?: boolean) {\n return `${super.getSvgStyles(skipShadow)} text-decoration-thickness: ${toFixed((this.textDecorationThickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%; white-space: pre;`;\n }\n\n /**\n * Returns styles-string for svg-export\n * @param {Object} style the object from which to retrieve style properties\n * @param {Boolean} useWhiteSpace a boolean to include an additional attribute in the style.\n * @return {String}\n */\n getSvgSpanStyles(\n this: TextSVGExportMixin & FabricText,\n style: TextStyleDeclaration,\n useWhiteSpace?: boolean,\n ) {\n const {\n fontFamily,\n strokeWidth,\n stroke,\n fill,\n fontSize,\n fontStyle,\n fontWeight,\n deltaY,\n textDecorationThickness,\n linethrough,\n overline,\n underline,\n } = style;\n\n const textDecoration = this.getSvgTextDecoration({\n underline: underline ?? this.underline,\n overline: overline ?? this.overline,\n linethrough: linethrough ?? this.linethrough,\n });\n const thickness = textDecorationThickness || this.textDecorationThickness;\n return [\n stroke ? colorPropToSVG(STROKE, stroke) : '',\n strokeWidth ? `stroke-width: ${strokeWidth}; ` : '',\n fontFamily\n ? `font-family: ${\n !fontFamily.includes(\"'\") && !fontFamily.includes('\"')\n ? `'${fontFamily}'`\n : fontFamily\n }; `\n : '',\n fontSize ? `font-size: ${fontSize}px; ` : '',\n fontStyle ? `font-style: ${fontStyle}; ` : '',\n fontWeight ? `font-weight: ${fontWeight}; ` : '',\n textDecoration\n ? `text-decoration: ${textDecoration}; text-decoration-thickness: ${toFixed((thickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%; `\n : '',\n fill ? colorPropToSVG(FILL, fill) : '',\n deltaY ? `baseline-shift: ${-deltaY}; ` : '',\n useWhiteSpace ? 'white-space: pre; ' : '',\n ].join('');\n }\n\n /**\n * Returns text-decoration property for svg-export\n * @param {Object} style the object from which to retrieve style properties\n * @return {String}\n */\n getSvgTextDecoration(\n this: TextSVGExportMixin & FabricText,\n style: TextStyleDeclaration,\n ) {\n return (['overline', 'underline', 'line-through'] as const)\n .filter(\n (decoration) =>\n style[\n decoration.replace('-', '') as\n | 'overline'\n | 'underline'\n | 'linethrough'\n ],\n )\n .join(' ');\n }\n}\n"],"names":["multipleSpacesRegex","dblQuoteRegex","createSVGInlineRect","color","left","top","width","height","createSVGRect","TextSVGExportMixin","FabricObjectSVGExportMixin","_toSVG","offsets","this","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","toSVG","reviver","textSvg","_createBaseSVGMarkup","noStyle","withShadow","path","additionalTransform","matrixToSVG","calcOwnMatrix","lineTop","getHeightOfLine","_ref","textBgRects","textSpans","textDecoration","getSvgTextDecoration","join","fontFamily","replace","fontSize","fontStyle","fontWeight","direction","getSvgStyles","addPaintOrder","textTopOffset","textLeftOffset","lineOffset","backgroundColor","push","i","len","_textLines","length","_getLineLeftOffset","textBackgroundColor","styleHas","_setSVGTextLineBg","_setSVGTextLineText","_createTextCharSpan","char","styleDecl","charBox","numFractionDigit","config","NUM_FRACTION_DIGITS","styleProps","getSvgSpanStyles","trim","match","fillStyles","dy","deltaY","dySpan","toFixed","angle","renderLeft","renderTop","angleAttr","undefined","wBy2","radiansToDegrees","m","createRotateMatrix","renderPoint","Point","transform","x","y","escapeXml","lineIndex","lineHeight","isJustify","textAlign","includes","JUSTIFY","line","actualStyle","nextStyle","style","timeToRender","charsToRender","boxWidth","_fontSizeFraction","charSpacing","__charBounds","kernedWidth","_reSpaceAndTab","test","getCompleteStyleDeclaration","hasStyleChanged","_getStyleDeclaration","leftOffset","heightOfLine","currentColor","boxStart","lastColor","getValueOfPropertyAt","j","skipShadow","super","textDecorationThickness","getObjectScaling","useWhiteSpace","strokeWidth","stroke","fill","linethrough","overline","underline","thickness","colorPropToSVG","STROKE","FILL","filter","decoration"],"mappings":"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"}
1
+ {"version":3,"file":"TextSVGExportMixin.min.mjs","sources":["../../../../src/shapes/Text/TextSVGExportMixin.ts"],"sourcesContent":["import { config } from '../../config';\nimport type { TSVGReviver } from '../../typedefs';\nimport { escapeXml } from '../../util/lang_string';\nimport { colorPropToSVG, createSVGRect } from '../../util/misc/svgParsing';\nimport { hasStyleChanged } from '../../util/misc/textStyles';\nimport { toFixed } from '../../util/misc/toFixed';\nimport { FabricObjectSVGExportMixin } from '../Object/FabricObjectSVGExportMixin';\nimport { type TextStyleDeclaration } from './StyledText';\nimport { JUSTIFY } from '../Text/constants';\nimport type { FabricText, GraphemeBBox } from './Text';\nimport { STROKE, FILL } from '../../constants';\nimport { createRotateMatrix } from '../../util/misc/matrix';\nimport { radiansToDegrees } from '../../util/misc/radiansDegreesConversion';\nimport { Point } from '../../Point';\nimport { matrixToSVG } from '../../util/misc/svgExport';\n\nconst multipleSpacesRegex = / +/g;\nconst dblQuoteRegex = /\"/g;\n\nfunction createSVGInlineRect(\n color: string,\n left: number,\n top: number,\n width: number,\n height: number,\n) {\n return `\\t\\t${createSVGRect(color, { left, top, width, height })}\\n`;\n}\n\nexport class TextSVGExportMixin extends FabricObjectSVGExportMixin {\n _toSVG(this: TextSVGExportMixin & FabricText): string[] {\n const offsets = this._getSVGLeftTopOffsets(),\n textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);\n return this._wrapSVGTextAndBg(textAndBg);\n }\n\n toSVG(this: TextSVGExportMixin & FabricText, reviver?: TSVGReviver): string {\n const textSvg = this._createBaseSVGMarkup(this._toSVG(), {\n reviver,\n noStyle: true,\n withShadow: true,\n }),\n path = this.path;\n if (path) {\n return (\n textSvg +\n path._createBaseSVGMarkup(path._toSVG(), {\n reviver,\n withShadow: true,\n additionalTransform: matrixToSVG(this.calcOwnMatrix()),\n })\n );\n }\n return textSvg;\n }\n\n private _getSVGLeftTopOffsets(this: TextSVGExportMixin & FabricText) {\n return {\n textLeft: -this.width / 2,\n textTop: -this.height / 2,\n lineTop: this.getHeightOfLine(0),\n };\n }\n\n private _wrapSVGTextAndBg(\n this: TextSVGExportMixin & FabricText,\n {\n textBgRects,\n textSpans,\n }: {\n textSpans: string[];\n textBgRects: string[];\n },\n ) {\n const noShadow = true,\n textDecoration = this.getSvgTextDecoration(this);\n return [\n textBgRects.join(''),\n '\\t\\t<text xml:space=\"preserve\" ',\n `font-family=\"${escapeXml(this.fontFamily.replace(dblQuoteRegex, \"'\"))}\" `,\n `font-size=\"${escapeXml(this.fontSize)}\" `,\n this.fontStyle ? `font-style=\"${escapeXml(this.fontStyle)}\" ` : '',\n this.fontWeight ? `font-weight=\"${escapeXml(this.fontWeight)}\" ` : '',\n textDecoration ? `text-decoration=\"${textDecoration}\" ` : '',\n this.direction === 'rtl' ? `direction=\"rtl\" ` : '',\n 'style=\"',\n this.getSvgStyles(noShadow),\n '\"',\n this.addPaintOrder(),\n ' >',\n textSpans.join(''),\n '</text>\\n',\n ];\n }\n\n /**\n * @private\n * @param {Number} textTopOffset Text top offset\n * @param {Number} textLeftOffset Text left offset\n * @return {Object}\n */\n private _getSVGTextAndBg(\n this: TextSVGExportMixin & FabricText,\n textTopOffset: number,\n textLeftOffset: number,\n ) {\n const textSpans: string[] = [],\n textBgRects: string[] = [];\n let height = textTopOffset,\n lineOffset;\n\n // bounding-box background\n this.backgroundColor &&\n textBgRects.push(\n createSVGInlineRect(\n this.backgroundColor,\n -this.width / 2,\n -this.height / 2,\n this.width,\n this.height,\n ),\n );\n\n // text and text-background\n for (let i = 0, len = this._textLines.length; i < len; i++) {\n lineOffset = this._getLineLeftOffset(i);\n if (this.direction === 'rtl') {\n lineOffset += this.width;\n }\n if (this.textBackgroundColor || this.styleHas('textBackgroundColor', i)) {\n this._setSVGTextLineBg(\n textBgRects,\n i,\n textLeftOffset + lineOffset,\n height,\n );\n }\n this._setSVGTextLineText(\n textSpans,\n i,\n textLeftOffset + lineOffset,\n height,\n );\n height += this.getHeightOfLine(i);\n }\n\n return {\n textSpans,\n textBgRects,\n };\n }\n\n private _createTextCharSpan(\n this: TextSVGExportMixin & FabricText,\n char: string,\n styleDecl: TextStyleDeclaration,\n left: number,\n top: number,\n charBox: GraphemeBBox,\n ) {\n const numFractionDigit = config.NUM_FRACTION_DIGITS;\n const styleProps = this.getSvgSpanStyles(\n styleDecl,\n char !== char.trim() || !!char.match(multipleSpacesRegex),\n ),\n fillStyles = styleProps ? `style=\"${styleProps}\"` : '',\n dy = styleDecl.deltaY,\n dySpan = dy ? ` dy=\"${toFixed(dy, numFractionDigit)}\" ` : '',\n { angle, renderLeft, renderTop, width } = charBox;\n let angleAttr = '';\n if (renderLeft !== undefined) {\n const wBy2 = width / 2;\n angle &&\n (angleAttr = ` rotate=\"${toFixed(radiansToDegrees(angle), numFractionDigit)}\"`);\n const m = createRotateMatrix({ angle: radiansToDegrees(angle!) });\n m[4] = renderLeft!;\n m[5] = renderTop!;\n const renderPoint = new Point(-wBy2, 0).transform(m);\n left = renderPoint.x;\n top = renderPoint.y;\n }\n\n return `<tspan x=\"${toFixed(left, numFractionDigit)}\" y=\"${toFixed(\n top,\n numFractionDigit,\n )}\" ${dySpan}${angleAttr}${fillStyles}>${escapeXml(char)}</tspan>`;\n }\n\n private _setSVGTextLineText(\n this: TextSVGExportMixin & FabricText,\n textSpans: string[],\n lineIndex: number,\n textLeftOffset: number,\n textTopOffset: number,\n ) {\n const lineHeight = this.getHeightOfLine(lineIndex),\n isJustify = this.textAlign.includes(JUSTIFY),\n line = this._textLines[lineIndex];\n let actualStyle,\n nextStyle,\n charsToRender = '',\n charBox,\n style,\n boxWidth = 0,\n timeToRender;\n\n textTopOffset +=\n (lineHeight * (1 - this._fontSizeFraction)) / this.lineHeight;\n for (let i = 0, len = line.length - 1; i <= len; i++) {\n timeToRender = i === len || this.charSpacing || this.path;\n charsToRender += line[i];\n charBox = this.__charBounds[lineIndex][i];\n if (boxWidth === 0) {\n textLeftOffset += charBox.kernedWidth - charBox.width;\n boxWidth += charBox.width;\n } else {\n boxWidth += charBox.kernedWidth;\n }\n if (isJustify && !timeToRender) {\n if (this._reSpaceAndTab.test(line[i])) {\n timeToRender = true;\n }\n }\n if (!timeToRender) {\n // if we have charSpacing or a path, we render char by char\n actualStyle =\n actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n timeToRender = hasStyleChanged(actualStyle, nextStyle, true);\n }\n if (timeToRender) {\n style = this._getStyleDeclaration(lineIndex, i);\n textSpans.push(\n this._createTextCharSpan(\n charsToRender,\n style,\n textLeftOffset,\n textTopOffset,\n charBox,\n ),\n );\n charsToRender = '';\n actualStyle = nextStyle;\n if (this.direction === 'rtl') {\n textLeftOffset -= boxWidth;\n } else {\n textLeftOffset += boxWidth;\n }\n boxWidth = 0;\n }\n }\n }\n\n private _setSVGTextLineBg(\n this: TextSVGExportMixin & FabricText,\n textBgRects: (string | number)[],\n i: number,\n leftOffset: number,\n textTopOffset: number,\n ) {\n const line = this._textLines[i],\n heightOfLine = this.getHeightOfLine(i) / this.lineHeight;\n let boxWidth = 0,\n boxStart = 0,\n currentColor,\n lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n for (let j = 0; j < line.length; j++) {\n const { left, width, kernedWidth } = this.__charBounds[i][j];\n currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n if (currentColor !== lastColor) {\n lastColor &&\n textBgRects.push(\n createSVGInlineRect(\n lastColor,\n leftOffset + boxStart,\n textTopOffset,\n boxWidth,\n heightOfLine,\n ),\n );\n boxStart = left;\n boxWidth = width;\n lastColor = currentColor;\n } else {\n boxWidth += kernedWidth;\n }\n }\n currentColor &&\n textBgRects.push(\n createSVGInlineRect(\n lastColor,\n leftOffset + boxStart,\n textTopOffset,\n boxWidth,\n heightOfLine,\n ),\n );\n }\n\n /**\n * Returns styles-string for svg-export\n * @param {Boolean} skipShadow a boolean to skip shadow filter output\n * @return {String}\n */\n getSvgStyles(this: TextSVGExportMixin & FabricText, skipShadow?: boolean) {\n return `${super.getSvgStyles(skipShadow)} text-decoration-thickness: ${toFixed((this.textDecorationThickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%; white-space: pre;`;\n }\n\n /**\n * Returns styles-string for svg-export\n * @param {Object} style the object from which to retrieve style properties\n * @param {Boolean} useWhiteSpace a boolean to include an additional attribute in the style.\n * @return {String}\n */\n getSvgSpanStyles(\n this: TextSVGExportMixin & FabricText,\n style: TextStyleDeclaration,\n useWhiteSpace?: boolean,\n ) {\n const {\n fontFamily,\n strokeWidth,\n stroke,\n fill,\n fontSize,\n fontStyle,\n fontWeight,\n textDecorationThickness,\n linethrough,\n overline,\n underline,\n } = style;\n\n const textDecoration = this.getSvgTextDecoration({\n underline: underline ?? this.underline,\n overline: overline ?? this.overline,\n linethrough: linethrough ?? this.linethrough,\n });\n const thickness = textDecorationThickness || this.textDecorationThickness;\n return [\n stroke ? colorPropToSVG(STROKE, stroke) : '',\n strokeWidth ? `stroke-width: ${escapeXml(strokeWidth)}; ` : '',\n fontFamily\n ? `font-family: ${\n !fontFamily.includes(\"'\") && !fontFamily.includes('\"')\n ? `'${escapeXml(fontFamily)}'`\n : escapeXml(fontFamily)\n }; `\n : '',\n fontSize ? `font-size: ${escapeXml(fontSize)}px; ` : '',\n fontStyle ? `font-style: ${escapeXml(fontStyle)}; ` : '',\n fontWeight ? `font-weight: ${escapeXml(fontWeight)}; ` : '',\n textDecoration\n ? `text-decoration: ${textDecoration}; text-decoration-thickness: ${toFixed((thickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%; `\n : '',\n fill ? colorPropToSVG(FILL, fill) : '',\n useWhiteSpace ? 'white-space: pre; ' : '',\n ].join('');\n }\n\n /**\n * Returns text-decoration property for svg-export\n * @param {Object} style the object from which to retrieve style properties\n * @return {String}\n */\n getSvgTextDecoration(\n this: TextSVGExportMixin & FabricText,\n style: TextStyleDeclaration,\n ) {\n return (['overline', 'underline', 'line-through'] as const)\n .filter(\n (decoration) =>\n style[\n decoration.replace('-', '') as\n | 'overline'\n | 'underline'\n | 'linethrough'\n ],\n )\n .join(' ');\n }\n}\n"],"names":["multipleSpacesRegex","dblQuoteRegex","createSVGInlineRect","color","left","top","width","height","createSVGRect","TextSVGExportMixin","FabricObjectSVGExportMixin","_toSVG","offsets","this","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","toSVG","reviver","textSvg","_createBaseSVGMarkup","noStyle","withShadow","path","additionalTransform","matrixToSVG","calcOwnMatrix","lineTop","getHeightOfLine","_ref","textBgRects","textSpans","textDecoration","getSvgTextDecoration","join","escapeXml","fontFamily","replace","fontSize","fontStyle","fontWeight","direction","getSvgStyles","addPaintOrder","textTopOffset","textLeftOffset","lineOffset","backgroundColor","push","i","len","_textLines","length","_getLineLeftOffset","textBackgroundColor","styleHas","_setSVGTextLineBg","_setSVGTextLineText","_createTextCharSpan","char","styleDecl","charBox","numFractionDigit","config","NUM_FRACTION_DIGITS","styleProps","getSvgSpanStyles","trim","match","fillStyles","dy","deltaY","dySpan","toFixed","angle","renderLeft","renderTop","angleAttr","undefined","wBy2","radiansToDegrees","m","createRotateMatrix","renderPoint","Point","transform","x","y","lineIndex","lineHeight","isJustify","textAlign","includes","JUSTIFY","line","actualStyle","nextStyle","style","timeToRender","charsToRender","boxWidth","_fontSizeFraction","charSpacing","__charBounds","kernedWidth","_reSpaceAndTab","test","getCompleteStyleDeclaration","hasStyleChanged","_getStyleDeclaration","leftOffset","heightOfLine","currentColor","boxStart","lastColor","getValueOfPropertyAt","j","skipShadow","super","textDecorationThickness","getObjectScaling","useWhiteSpace","strokeWidth","stroke","fill","linethrough","overline","underline","thickness","colorPropToSVG","STROKE","FILL","filter","decoration"],"mappings":"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"}
@@ -57,7 +57,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
57
57
  } = _ref;
58
58
  const noShadow = true,
59
59
  textDecoration = this.getSvgTextDecoration(this);
60
- return [textBgRects.join(''), '\t\t<text xml:space="preserve" ', `font-family="${this.fontFamily.replace(dblQuoteRegex, "'")}" `, `font-size="${this.fontSize}" `, this.fontStyle ? `font-style="${this.fontStyle}" ` : '', this.fontWeight ? `font-weight="${this.fontWeight}" ` : '', textDecoration ? `text-decoration="${textDecoration}" ` : '', this.direction === 'rtl' ? `direction="${this.direction}" ` : '', 'style="', this.getSvgStyles(noShadow), '"', this.addPaintOrder(), ' >', textSpans.join(''), '</text>\n'];
60
+ return [textBgRects.join(''), '\t\t<text xml:space="preserve" ', `font-family="${escapeXml(this.fontFamily.replace(dblQuoteRegex, "'"))}" `, `font-size="${escapeXml(this.fontSize)}" `, this.fontStyle ? `font-style="${escapeXml(this.fontStyle)}" ` : '', this.fontWeight ? `font-weight="${escapeXml(this.fontWeight)}" ` : '', textDecoration ? `text-decoration="${textDecoration}" ` : '', this.direction === 'rtl' ? `direction="rtl" ` : '', 'style="', this.getSvgStyles(noShadow), '"', this.addPaintOrder(), ' >', textSpans.join(''), '</text>\n'];
61
61
  }
62
62
 
63
63
  /**
@@ -73,7 +73,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
73
73
  lineOffset;
74
74
 
75
75
  // bounding-box background
76
- this.backgroundColor && textBgRects.push(...createSVGInlineRect(this.backgroundColor, -this.width / 2, -this.height / 2, this.width, this.height));
76
+ this.backgroundColor && textBgRects.push(createSVGInlineRect(this.backgroundColor, -this.width / 2, -this.height / 2, this.width, this.height));
77
77
 
78
78
  // text and text-background
79
79
  for (let i = 0, len = this._textLines.length; i < len; i++) {
@@ -181,7 +181,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
181
181
  } = this.__charBounds[i][j];
182
182
  currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');
183
183
  if (currentColor !== lastColor) {
184
- lastColor && textBgRects.push(...createSVGInlineRect(lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine));
184
+ lastColor && textBgRects.push(createSVGInlineRect(lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine));
185
185
  boxStart = left;
186
186
  boxWidth = width;
187
187
  lastColor = currentColor;
@@ -189,7 +189,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
189
189
  boxWidth += kernedWidth;
190
190
  }
191
191
  }
192
- currentColor && textBgRects.push(...createSVGInlineRect(lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine));
192
+ currentColor && textBgRects.push(createSVGInlineRect(lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine));
193
193
  }
194
194
 
195
195
  /**
@@ -216,7 +216,6 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
216
216
  fontSize,
217
217
  fontStyle,
218
218
  fontWeight,
219
- deltaY,
220
219
  textDecorationThickness,
221
220
  linethrough,
222
221
  overline,
@@ -228,7 +227,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
228
227
  linethrough: linethrough !== null && linethrough !== void 0 ? linethrough : this.linethrough
229
228
  });
230
229
  const thickness = textDecorationThickness || this.textDecorationThickness;
231
- return [stroke ? colorPropToSVG(STROKE, stroke) : '', strokeWidth ? `stroke-width: ${strokeWidth}; ` : '', fontFamily ? `font-family: ${!fontFamily.includes("'") && !fontFamily.includes('"') ? `'${fontFamily}'` : fontFamily}; ` : '', fontSize ? `font-size: ${fontSize}px; ` : '', fontStyle ? `font-style: ${fontStyle}; ` : '', fontWeight ? `font-weight: ${fontWeight}; ` : '', textDecoration ? `text-decoration: ${textDecoration}; text-decoration-thickness: ${toFixed(thickness * this.getObjectScaling().y / 10, config.NUM_FRACTION_DIGITS)}%; ` : '', fill ? colorPropToSVG(FILL, fill) : '', deltaY ? `baseline-shift: ${-deltaY}; ` : '', useWhiteSpace ? 'white-space: pre; ' : ''].join('');
230
+ return [stroke ? colorPropToSVG(STROKE, stroke) : '', strokeWidth ? `stroke-width: ${escapeXml(strokeWidth)}; ` : '', fontFamily ? `font-family: ${!fontFamily.includes("'") && !fontFamily.includes('"') ? `'${escapeXml(fontFamily)}'` : escapeXml(fontFamily)}; ` : '', fontSize ? `font-size: ${escapeXml(fontSize)}px; ` : '', fontStyle ? `font-style: ${escapeXml(fontStyle)}; ` : '', fontWeight ? `font-weight: ${escapeXml(fontWeight)}; ` : '', textDecoration ? `text-decoration: ${textDecoration}; text-decoration-thickness: ${toFixed(thickness * this.getObjectScaling().y / 10, config.NUM_FRACTION_DIGITS)}%; ` : '', fill ? colorPropToSVG(FILL, fill) : '', useWhiteSpace ? 'white-space: pre; ' : ''].join('');
232
231
  }
233
232
 
234
233
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"TextSVGExportMixin.mjs","sources":["../../../../src/shapes/Text/TextSVGExportMixin.ts"],"sourcesContent":["import { config } from '../../config';\nimport type { TSVGReviver } from '../../typedefs';\nimport { escapeXml } from '../../util/lang_string';\nimport { colorPropToSVG, createSVGRect } from '../../util/misc/svgParsing';\nimport { hasStyleChanged } from '../../util/misc/textStyles';\nimport { toFixed } from '../../util/misc/toFixed';\nimport { FabricObjectSVGExportMixin } from '../Object/FabricObjectSVGExportMixin';\nimport { type TextStyleDeclaration } from './StyledText';\nimport { JUSTIFY } from '../Text/constants';\nimport type { FabricText, GraphemeBBox } from './Text';\nimport { STROKE, FILL } from '../../constants';\nimport { createRotateMatrix } from '../../util/misc/matrix';\nimport { radiansToDegrees } from '../../util/misc/radiansDegreesConversion';\nimport { Point } from '../../Point';\nimport { matrixToSVG } from '../../util/misc/svgExport';\n\nconst multipleSpacesRegex = / +/g;\nconst dblQuoteRegex = /\"/g;\n\nfunction createSVGInlineRect(\n color: string,\n left: number,\n top: number,\n width: number,\n height: number,\n) {\n return `\\t\\t${createSVGRect(color, { left, top, width, height })}\\n`;\n}\n\nexport class TextSVGExportMixin extends FabricObjectSVGExportMixin {\n _toSVG(this: TextSVGExportMixin & FabricText): string[] {\n const offsets = this._getSVGLeftTopOffsets(),\n textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);\n return this._wrapSVGTextAndBg(textAndBg);\n }\n\n toSVG(this: TextSVGExportMixin & FabricText, reviver?: TSVGReviver): string {\n const textSvg = this._createBaseSVGMarkup(this._toSVG(), {\n reviver,\n noStyle: true,\n withShadow: true,\n }),\n path = this.path;\n if (path) {\n return (\n textSvg +\n path._createBaseSVGMarkup(path._toSVG(), {\n reviver,\n withShadow: true,\n additionalTransform: matrixToSVG(this.calcOwnMatrix()),\n })\n );\n }\n return textSvg;\n }\n\n private _getSVGLeftTopOffsets(this: TextSVGExportMixin & FabricText) {\n return {\n textLeft: -this.width / 2,\n textTop: -this.height / 2,\n lineTop: this.getHeightOfLine(0),\n };\n }\n\n private _wrapSVGTextAndBg(\n this: TextSVGExportMixin & FabricText,\n {\n textBgRects,\n textSpans,\n }: {\n textSpans: string[];\n textBgRects: string[];\n },\n ) {\n const noShadow = true,\n textDecoration = this.getSvgTextDecoration(this);\n return [\n textBgRects.join(''),\n '\\t\\t<text xml:space=\"preserve\" ',\n `font-family=\"${this.fontFamily.replace(dblQuoteRegex, \"'\")}\" `,\n `font-size=\"${this.fontSize}\" `,\n this.fontStyle ? `font-style=\"${this.fontStyle}\" ` : '',\n this.fontWeight ? `font-weight=\"${this.fontWeight}\" ` : '',\n textDecoration ? `text-decoration=\"${textDecoration}\" ` : '',\n this.direction === 'rtl' ? `direction=\"${this.direction}\" ` : '',\n 'style=\"',\n this.getSvgStyles(noShadow),\n '\"',\n this.addPaintOrder(),\n ' >',\n textSpans.join(''),\n '</text>\\n',\n ];\n }\n\n /**\n * @private\n * @param {Number} textTopOffset Text top offset\n * @param {Number} textLeftOffset Text left offset\n * @return {Object}\n */\n private _getSVGTextAndBg(\n this: TextSVGExportMixin & FabricText,\n textTopOffset: number,\n textLeftOffset: number,\n ) {\n const textSpans: string[] = [],\n textBgRects: string[] = [];\n let height = textTopOffset,\n lineOffset;\n\n // bounding-box background\n this.backgroundColor &&\n textBgRects.push(\n ...createSVGInlineRect(\n this.backgroundColor,\n -this.width / 2,\n -this.height / 2,\n this.width,\n this.height,\n ),\n );\n\n // text and text-background\n for (let i = 0, len = this._textLines.length; i < len; i++) {\n lineOffset = this._getLineLeftOffset(i);\n if (this.direction === 'rtl') {\n lineOffset += this.width;\n }\n if (this.textBackgroundColor || this.styleHas('textBackgroundColor', i)) {\n this._setSVGTextLineBg(\n textBgRects,\n i,\n textLeftOffset + lineOffset,\n height,\n );\n }\n this._setSVGTextLineText(\n textSpans,\n i,\n textLeftOffset + lineOffset,\n height,\n );\n height += this.getHeightOfLine(i);\n }\n\n return {\n textSpans,\n textBgRects,\n };\n }\n\n private _createTextCharSpan(\n this: TextSVGExportMixin & FabricText,\n char: string,\n styleDecl: TextStyleDeclaration,\n left: number,\n top: number,\n charBox: GraphemeBBox,\n ) {\n const numFractionDigit = config.NUM_FRACTION_DIGITS;\n const styleProps = this.getSvgSpanStyles(\n styleDecl,\n char !== char.trim() || !!char.match(multipleSpacesRegex),\n ),\n fillStyles = styleProps ? `style=\"${styleProps}\"` : '',\n dy = styleDecl.deltaY,\n dySpan = dy ? ` dy=\"${toFixed(dy, numFractionDigit)}\" ` : '',\n { angle, renderLeft, renderTop, width } = charBox;\n let angleAttr = '';\n if (renderLeft !== undefined) {\n const wBy2 = width / 2;\n angle &&\n (angleAttr = ` rotate=\"${toFixed(radiansToDegrees(angle), numFractionDigit)}\"`);\n const m = createRotateMatrix({ angle: radiansToDegrees(angle!) });\n m[4] = renderLeft!;\n m[5] = renderTop!;\n const renderPoint = new Point(-wBy2, 0).transform(m);\n left = renderPoint.x;\n top = renderPoint.y;\n }\n\n return `<tspan x=\"${toFixed(left, numFractionDigit)}\" y=\"${toFixed(\n top,\n numFractionDigit,\n )}\" ${dySpan}${angleAttr}${fillStyles}>${escapeXml(char)}</tspan>`;\n }\n\n private _setSVGTextLineText(\n this: TextSVGExportMixin & FabricText,\n textSpans: string[],\n lineIndex: number,\n textLeftOffset: number,\n textTopOffset: number,\n ) {\n const lineHeight = this.getHeightOfLine(lineIndex),\n isJustify = this.textAlign.includes(JUSTIFY),\n line = this._textLines[lineIndex];\n let actualStyle,\n nextStyle,\n charsToRender = '',\n charBox,\n style,\n boxWidth = 0,\n timeToRender;\n\n textTopOffset +=\n (lineHeight * (1 - this._fontSizeFraction)) / this.lineHeight;\n for (let i = 0, len = line.length - 1; i <= len; i++) {\n timeToRender = i === len || this.charSpacing || this.path;\n charsToRender += line[i];\n charBox = this.__charBounds[lineIndex][i];\n if (boxWidth === 0) {\n textLeftOffset += charBox.kernedWidth - charBox.width;\n boxWidth += charBox.width;\n } else {\n boxWidth += charBox.kernedWidth;\n }\n if (isJustify && !timeToRender) {\n if (this._reSpaceAndTab.test(line[i])) {\n timeToRender = true;\n }\n }\n if (!timeToRender) {\n // if we have charSpacing or a path, we render char by char\n actualStyle =\n actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n timeToRender = hasStyleChanged(actualStyle, nextStyle, true);\n }\n if (timeToRender) {\n style = this._getStyleDeclaration(lineIndex, i);\n textSpans.push(\n this._createTextCharSpan(\n charsToRender,\n style,\n textLeftOffset,\n textTopOffset,\n charBox,\n ),\n );\n charsToRender = '';\n actualStyle = nextStyle;\n if (this.direction === 'rtl') {\n textLeftOffset -= boxWidth;\n } else {\n textLeftOffset += boxWidth;\n }\n boxWidth = 0;\n }\n }\n }\n\n private _setSVGTextLineBg(\n this: TextSVGExportMixin & FabricText,\n textBgRects: (string | number)[],\n i: number,\n leftOffset: number,\n textTopOffset: number,\n ) {\n const line = this._textLines[i],\n heightOfLine = this.getHeightOfLine(i) / this.lineHeight;\n let boxWidth = 0,\n boxStart = 0,\n currentColor,\n lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n for (let j = 0; j < line.length; j++) {\n const { left, width, kernedWidth } = this.__charBounds[i][j];\n currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n if (currentColor !== lastColor) {\n lastColor &&\n textBgRects.push(\n ...createSVGInlineRect(\n lastColor,\n leftOffset + boxStart,\n textTopOffset,\n boxWidth,\n heightOfLine,\n ),\n );\n boxStart = left;\n boxWidth = width;\n lastColor = currentColor;\n } else {\n boxWidth += kernedWidth;\n }\n }\n currentColor &&\n textBgRects.push(\n ...createSVGInlineRect(\n lastColor,\n leftOffset + boxStart,\n textTopOffset,\n boxWidth,\n heightOfLine,\n ),\n );\n }\n\n /**\n * Returns styles-string for svg-export\n * @param {Boolean} skipShadow a boolean to skip shadow filter output\n * @return {String}\n */\n getSvgStyles(this: TextSVGExportMixin & FabricText, skipShadow?: boolean) {\n return `${super.getSvgStyles(skipShadow)} text-decoration-thickness: ${toFixed((this.textDecorationThickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%; white-space: pre;`;\n }\n\n /**\n * Returns styles-string for svg-export\n * @param {Object} style the object from which to retrieve style properties\n * @param {Boolean} useWhiteSpace a boolean to include an additional attribute in the style.\n * @return {String}\n */\n getSvgSpanStyles(\n this: TextSVGExportMixin & FabricText,\n style: TextStyleDeclaration,\n useWhiteSpace?: boolean,\n ) {\n const {\n fontFamily,\n strokeWidth,\n stroke,\n fill,\n fontSize,\n fontStyle,\n fontWeight,\n deltaY,\n textDecorationThickness,\n linethrough,\n overline,\n underline,\n } = style;\n\n const textDecoration = this.getSvgTextDecoration({\n underline: underline ?? this.underline,\n overline: overline ?? this.overline,\n linethrough: linethrough ?? this.linethrough,\n });\n const thickness = textDecorationThickness || this.textDecorationThickness;\n return [\n stroke ? colorPropToSVG(STROKE, stroke) : '',\n strokeWidth ? `stroke-width: ${strokeWidth}; ` : '',\n fontFamily\n ? `font-family: ${\n !fontFamily.includes(\"'\") && !fontFamily.includes('\"')\n ? `'${fontFamily}'`\n : fontFamily\n }; `\n : '',\n fontSize ? `font-size: ${fontSize}px; ` : '',\n fontStyle ? `font-style: ${fontStyle}; ` : '',\n fontWeight ? `font-weight: ${fontWeight}; ` : '',\n textDecoration\n ? `text-decoration: ${textDecoration}; text-decoration-thickness: ${toFixed((thickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%; `\n : '',\n fill ? colorPropToSVG(FILL, fill) : '',\n deltaY ? `baseline-shift: ${-deltaY}; ` : '',\n useWhiteSpace ? 'white-space: pre; ' : '',\n ].join('');\n }\n\n /**\n * Returns text-decoration property for svg-export\n * @param {Object} style the object from which to retrieve style properties\n * @return {String}\n */\n getSvgTextDecoration(\n this: TextSVGExportMixin & FabricText,\n style: TextStyleDeclaration,\n ) {\n return (['overline', 'underline', 'line-through'] as const)\n .filter(\n (decoration) =>\n style[\n decoration.replace('-', '') as\n | 'overline'\n | 'underline'\n | 'linethrough'\n ],\n )\n .join(' ');\n }\n}\n"],"names":["multipleSpacesRegex","dblQuoteRegex","createSVGInlineRect","color","left","top","width","height","createSVGRect","TextSVGExportMixin","FabricObjectSVGExportMixin","_toSVG","offsets","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","toSVG","reviver","textSvg","_createBaseSVGMarkup","noStyle","withShadow","path","additionalTransform","matrixToSVG","calcOwnMatrix","lineTop","getHeightOfLine","_ref","textBgRects","textSpans","noShadow","textDecoration","getSvgTextDecoration","join","fontFamily","replace","fontSize","fontStyle","fontWeight","direction","getSvgStyles","addPaintOrder","textTopOffset","textLeftOffset","lineOffset","backgroundColor","push","i","len","_textLines","length","_getLineLeftOffset","textBackgroundColor","styleHas","_setSVGTextLineBg","_setSVGTextLineText","_createTextCharSpan","char","styleDecl","charBox","numFractionDigit","config","NUM_FRACTION_DIGITS","styleProps","getSvgSpanStyles","trim","match","fillStyles","dy","deltaY","dySpan","toFixed","angle","renderLeft","renderTop","angleAttr","undefined","wBy2","radiansToDegrees","m","createRotateMatrix","renderPoint","Point","transform","x","y","escapeXml","lineIndex","lineHeight","isJustify","textAlign","includes","JUSTIFY","line","actualStyle","nextStyle","charsToRender","style","boxWidth","timeToRender","_fontSizeFraction","charSpacing","__charBounds","kernedWidth","_reSpaceAndTab","test","getCompleteStyleDeclaration","hasStyleChanged","_getStyleDeclaration","leftOffset","heightOfLine","boxStart","currentColor","lastColor","getValueOfPropertyAt","j","skipShadow","textDecorationThickness","getObjectScaling","useWhiteSpace","strokeWidth","stroke","fill","linethrough","overline","underline","thickness","colorPropToSVG","STROKE","FILL","filter","decoration"],"mappings":"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"}
1
+ {"version":3,"file":"TextSVGExportMixin.mjs","sources":["../../../../src/shapes/Text/TextSVGExportMixin.ts"],"sourcesContent":["import { config } from '../../config';\nimport type { TSVGReviver } from '../../typedefs';\nimport { escapeXml } from '../../util/lang_string';\nimport { colorPropToSVG, createSVGRect } from '../../util/misc/svgParsing';\nimport { hasStyleChanged } from '../../util/misc/textStyles';\nimport { toFixed } from '../../util/misc/toFixed';\nimport { FabricObjectSVGExportMixin } from '../Object/FabricObjectSVGExportMixin';\nimport { type TextStyleDeclaration } from './StyledText';\nimport { JUSTIFY } from '../Text/constants';\nimport type { FabricText, GraphemeBBox } from './Text';\nimport { STROKE, FILL } from '../../constants';\nimport { createRotateMatrix } from '../../util/misc/matrix';\nimport { radiansToDegrees } from '../../util/misc/radiansDegreesConversion';\nimport { Point } from '../../Point';\nimport { matrixToSVG } from '../../util/misc/svgExport';\n\nconst multipleSpacesRegex = / +/g;\nconst dblQuoteRegex = /\"/g;\n\nfunction createSVGInlineRect(\n color: string,\n left: number,\n top: number,\n width: number,\n height: number,\n) {\n return `\\t\\t${createSVGRect(color, { left, top, width, height })}\\n`;\n}\n\nexport class TextSVGExportMixin extends FabricObjectSVGExportMixin {\n _toSVG(this: TextSVGExportMixin & FabricText): string[] {\n const offsets = this._getSVGLeftTopOffsets(),\n textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);\n return this._wrapSVGTextAndBg(textAndBg);\n }\n\n toSVG(this: TextSVGExportMixin & FabricText, reviver?: TSVGReviver): string {\n const textSvg = this._createBaseSVGMarkup(this._toSVG(), {\n reviver,\n noStyle: true,\n withShadow: true,\n }),\n path = this.path;\n if (path) {\n return (\n textSvg +\n path._createBaseSVGMarkup(path._toSVG(), {\n reviver,\n withShadow: true,\n additionalTransform: matrixToSVG(this.calcOwnMatrix()),\n })\n );\n }\n return textSvg;\n }\n\n private _getSVGLeftTopOffsets(this: TextSVGExportMixin & FabricText) {\n return {\n textLeft: -this.width / 2,\n textTop: -this.height / 2,\n lineTop: this.getHeightOfLine(0),\n };\n }\n\n private _wrapSVGTextAndBg(\n this: TextSVGExportMixin & FabricText,\n {\n textBgRects,\n textSpans,\n }: {\n textSpans: string[];\n textBgRects: string[];\n },\n ) {\n const noShadow = true,\n textDecoration = this.getSvgTextDecoration(this);\n return [\n textBgRects.join(''),\n '\\t\\t<text xml:space=\"preserve\" ',\n `font-family=\"${escapeXml(this.fontFamily.replace(dblQuoteRegex, \"'\"))}\" `,\n `font-size=\"${escapeXml(this.fontSize)}\" `,\n this.fontStyle ? `font-style=\"${escapeXml(this.fontStyle)}\" ` : '',\n this.fontWeight ? `font-weight=\"${escapeXml(this.fontWeight)}\" ` : '',\n textDecoration ? `text-decoration=\"${textDecoration}\" ` : '',\n this.direction === 'rtl' ? `direction=\"rtl\" ` : '',\n 'style=\"',\n this.getSvgStyles(noShadow),\n '\"',\n this.addPaintOrder(),\n ' >',\n textSpans.join(''),\n '</text>\\n',\n ];\n }\n\n /**\n * @private\n * @param {Number} textTopOffset Text top offset\n * @param {Number} textLeftOffset Text left offset\n * @return {Object}\n */\n private _getSVGTextAndBg(\n this: TextSVGExportMixin & FabricText,\n textTopOffset: number,\n textLeftOffset: number,\n ) {\n const textSpans: string[] = [],\n textBgRects: string[] = [];\n let height = textTopOffset,\n lineOffset;\n\n // bounding-box background\n this.backgroundColor &&\n textBgRects.push(\n createSVGInlineRect(\n this.backgroundColor,\n -this.width / 2,\n -this.height / 2,\n this.width,\n this.height,\n ),\n );\n\n // text and text-background\n for (let i = 0, len = this._textLines.length; i < len; i++) {\n lineOffset = this._getLineLeftOffset(i);\n if (this.direction === 'rtl') {\n lineOffset += this.width;\n }\n if (this.textBackgroundColor || this.styleHas('textBackgroundColor', i)) {\n this._setSVGTextLineBg(\n textBgRects,\n i,\n textLeftOffset + lineOffset,\n height,\n );\n }\n this._setSVGTextLineText(\n textSpans,\n i,\n textLeftOffset + lineOffset,\n height,\n );\n height += this.getHeightOfLine(i);\n }\n\n return {\n textSpans,\n textBgRects,\n };\n }\n\n private _createTextCharSpan(\n this: TextSVGExportMixin & FabricText,\n char: string,\n styleDecl: TextStyleDeclaration,\n left: number,\n top: number,\n charBox: GraphemeBBox,\n ) {\n const numFractionDigit = config.NUM_FRACTION_DIGITS;\n const styleProps = this.getSvgSpanStyles(\n styleDecl,\n char !== char.trim() || !!char.match(multipleSpacesRegex),\n ),\n fillStyles = styleProps ? `style=\"${styleProps}\"` : '',\n dy = styleDecl.deltaY,\n dySpan = dy ? ` dy=\"${toFixed(dy, numFractionDigit)}\" ` : '',\n { angle, renderLeft, renderTop, width } = charBox;\n let angleAttr = '';\n if (renderLeft !== undefined) {\n const wBy2 = width / 2;\n angle &&\n (angleAttr = ` rotate=\"${toFixed(radiansToDegrees(angle), numFractionDigit)}\"`);\n const m = createRotateMatrix({ angle: radiansToDegrees(angle!) });\n m[4] = renderLeft!;\n m[5] = renderTop!;\n const renderPoint = new Point(-wBy2, 0).transform(m);\n left = renderPoint.x;\n top = renderPoint.y;\n }\n\n return `<tspan x=\"${toFixed(left, numFractionDigit)}\" y=\"${toFixed(\n top,\n numFractionDigit,\n )}\" ${dySpan}${angleAttr}${fillStyles}>${escapeXml(char)}</tspan>`;\n }\n\n private _setSVGTextLineText(\n this: TextSVGExportMixin & FabricText,\n textSpans: string[],\n lineIndex: number,\n textLeftOffset: number,\n textTopOffset: number,\n ) {\n const lineHeight = this.getHeightOfLine(lineIndex),\n isJustify = this.textAlign.includes(JUSTIFY),\n line = this._textLines[lineIndex];\n let actualStyle,\n nextStyle,\n charsToRender = '',\n charBox,\n style,\n boxWidth = 0,\n timeToRender;\n\n textTopOffset +=\n (lineHeight * (1 - this._fontSizeFraction)) / this.lineHeight;\n for (let i = 0, len = line.length - 1; i <= len; i++) {\n timeToRender = i === len || this.charSpacing || this.path;\n charsToRender += line[i];\n charBox = this.__charBounds[lineIndex][i];\n if (boxWidth === 0) {\n textLeftOffset += charBox.kernedWidth - charBox.width;\n boxWidth += charBox.width;\n } else {\n boxWidth += charBox.kernedWidth;\n }\n if (isJustify && !timeToRender) {\n if (this._reSpaceAndTab.test(line[i])) {\n timeToRender = true;\n }\n }\n if (!timeToRender) {\n // if we have charSpacing or a path, we render char by char\n actualStyle =\n actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n timeToRender = hasStyleChanged(actualStyle, nextStyle, true);\n }\n if (timeToRender) {\n style = this._getStyleDeclaration(lineIndex, i);\n textSpans.push(\n this._createTextCharSpan(\n charsToRender,\n style,\n textLeftOffset,\n textTopOffset,\n charBox,\n ),\n );\n charsToRender = '';\n actualStyle = nextStyle;\n if (this.direction === 'rtl') {\n textLeftOffset -= boxWidth;\n } else {\n textLeftOffset += boxWidth;\n }\n boxWidth = 0;\n }\n }\n }\n\n private _setSVGTextLineBg(\n this: TextSVGExportMixin & FabricText,\n textBgRects: (string | number)[],\n i: number,\n leftOffset: number,\n textTopOffset: number,\n ) {\n const line = this._textLines[i],\n heightOfLine = this.getHeightOfLine(i) / this.lineHeight;\n let boxWidth = 0,\n boxStart = 0,\n currentColor,\n lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n for (let j = 0; j < line.length; j++) {\n const { left, width, kernedWidth } = this.__charBounds[i][j];\n currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n if (currentColor !== lastColor) {\n lastColor &&\n textBgRects.push(\n createSVGInlineRect(\n lastColor,\n leftOffset + boxStart,\n textTopOffset,\n boxWidth,\n heightOfLine,\n ),\n );\n boxStart = left;\n boxWidth = width;\n lastColor = currentColor;\n } else {\n boxWidth += kernedWidth;\n }\n }\n currentColor &&\n textBgRects.push(\n createSVGInlineRect(\n lastColor,\n leftOffset + boxStart,\n textTopOffset,\n boxWidth,\n heightOfLine,\n ),\n );\n }\n\n /**\n * Returns styles-string for svg-export\n * @param {Boolean} skipShadow a boolean to skip shadow filter output\n * @return {String}\n */\n getSvgStyles(this: TextSVGExportMixin & FabricText, skipShadow?: boolean) {\n return `${super.getSvgStyles(skipShadow)} text-decoration-thickness: ${toFixed((this.textDecorationThickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%; white-space: pre;`;\n }\n\n /**\n * Returns styles-string for svg-export\n * @param {Object} style the object from which to retrieve style properties\n * @param {Boolean} useWhiteSpace a boolean to include an additional attribute in the style.\n * @return {String}\n */\n getSvgSpanStyles(\n this: TextSVGExportMixin & FabricText,\n style: TextStyleDeclaration,\n useWhiteSpace?: boolean,\n ) {\n const {\n fontFamily,\n strokeWidth,\n stroke,\n fill,\n fontSize,\n fontStyle,\n fontWeight,\n textDecorationThickness,\n linethrough,\n overline,\n underline,\n } = style;\n\n const textDecoration = this.getSvgTextDecoration({\n underline: underline ?? this.underline,\n overline: overline ?? this.overline,\n linethrough: linethrough ?? this.linethrough,\n });\n const thickness = textDecorationThickness || this.textDecorationThickness;\n return [\n stroke ? colorPropToSVG(STROKE, stroke) : '',\n strokeWidth ? `stroke-width: ${escapeXml(strokeWidth)}; ` : '',\n fontFamily\n ? `font-family: ${\n !fontFamily.includes(\"'\") && !fontFamily.includes('\"')\n ? `'${escapeXml(fontFamily)}'`\n : escapeXml(fontFamily)\n }; `\n : '',\n fontSize ? `font-size: ${escapeXml(fontSize)}px; ` : '',\n fontStyle ? `font-style: ${escapeXml(fontStyle)}; ` : '',\n fontWeight ? `font-weight: ${escapeXml(fontWeight)}; ` : '',\n textDecoration\n ? `text-decoration: ${textDecoration}; text-decoration-thickness: ${toFixed((thickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%; `\n : '',\n fill ? colorPropToSVG(FILL, fill) : '',\n useWhiteSpace ? 'white-space: pre; ' : '',\n ].join('');\n }\n\n /**\n * Returns text-decoration property for svg-export\n * @param {Object} style the object from which to retrieve style properties\n * @return {String}\n */\n getSvgTextDecoration(\n this: TextSVGExportMixin & FabricText,\n style: TextStyleDeclaration,\n ) {\n return (['overline', 'underline', 'line-through'] as const)\n .filter(\n (decoration) =>\n style[\n decoration.replace('-', '') as\n | 'overline'\n | 'underline'\n | 'linethrough'\n ],\n )\n .join(' ');\n }\n}\n"],"names":["multipleSpacesRegex","dblQuoteRegex","createSVGInlineRect","color","left","top","width","height","createSVGRect","TextSVGExportMixin","FabricObjectSVGExportMixin","_toSVG","offsets","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","toSVG","reviver","textSvg","_createBaseSVGMarkup","noStyle","withShadow","path","additionalTransform","matrixToSVG","calcOwnMatrix","lineTop","getHeightOfLine","_ref","textBgRects","textSpans","noShadow","textDecoration","getSvgTextDecoration","join","escapeXml","fontFamily","replace","fontSize","fontStyle","fontWeight","direction","getSvgStyles","addPaintOrder","textTopOffset","textLeftOffset","lineOffset","backgroundColor","push","i","len","_textLines","length","_getLineLeftOffset","textBackgroundColor","styleHas","_setSVGTextLineBg","_setSVGTextLineText","_createTextCharSpan","char","styleDecl","charBox","numFractionDigit","config","NUM_FRACTION_DIGITS","styleProps","getSvgSpanStyles","trim","match","fillStyles","dy","deltaY","dySpan","toFixed","angle","renderLeft","renderTop","angleAttr","undefined","wBy2","radiansToDegrees","m","createRotateMatrix","renderPoint","Point","transform","x","y","lineIndex","lineHeight","isJustify","textAlign","includes","JUSTIFY","line","actualStyle","nextStyle","charsToRender","style","boxWidth","timeToRender","_fontSizeFraction","charSpacing","__charBounds","kernedWidth","_reSpaceAndTab","test","getCompleteStyleDeclaration","hasStyleChanged","_getStyleDeclaration","leftOffset","heightOfLine","boxStart","currentColor","lastColor","getValueOfPropertyAt","j","skipShadow","textDecorationThickness","getObjectScaling","useWhiteSpace","strokeWidth","stroke","fill","linethrough","overline","underline","thickness","colorPropToSVG","STROKE","FILL","filter","decoration"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Textbox.d.ts","sourceRoot":"","sources":["../../../src/shapes/Textbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Textbox.d.ts","sourceRoot":"","sources":["../../../src/shapes/Textbox.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Textbox.min.mjs","sources":["../../../src/shapes/Textbox.ts"],"sourcesContent":["import type { TClassProperties, TOptions } from '../typedefs';\nimport { IText } from './IText/IText';\nimport { classRegistry } from '../ClassRegistry';\nimport { createTextboxDefaultControls } from '../controls/commonControls';\nimport { JUSTIFY } from './Text/constants';\nimport type { TextStyleDeclaration } from './Text/StyledText';\nimport type { SerializedITextProps, ITextProps } from './IText/IText';\nimport type { ITextEvents } from './IText/ITextBehavior';\nimport type { TextLinesInfo } from './Text/Text';\nimport type { Control } from '../controls/Control';\n\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\n// regexes, list of properties that are not suppose to change by instances, magic consts.\n// this will be a separated effort\nexport const textboxDefaultValues: Partial<TClassProperties<Textbox>> = {\n minWidth: 20,\n dynamicMinWidth: 2,\n lockScalingFlip: true,\n noScaleCache: false,\n _wordJoiners: /[ \\t\\r]/,\n splitByGrapheme: false,\n};\n\nexport type GraphemeData = {\n wordsData: {\n word: string[];\n width: number;\n }[][];\n largestWordWidth: number;\n};\n\nexport type StyleMap = Record<string, { line: number; offset: number }>;\n\n// @TODO this is not complete\ninterface UniqueTextboxProps {\n minWidth: number;\n splitByGrapheme: boolean;\n dynamicMinWidth: number;\n _wordJoiners: RegExp;\n}\n\nexport interface SerializedTextboxProps\n extends SerializedITextProps,\n Pick<UniqueTextboxProps, 'minWidth' | 'splitByGrapheme'> {}\n\nexport interface TextboxProps extends ITextProps, UniqueTextboxProps {}\n\n/**\n * Textbox class, based on IText, allows the user to resize the text rectangle\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\n * user can only change width. Height is adjusted automatically based on the\n * wrapping of lines.\n */\nexport class Textbox<\n Props extends TOptions<TextboxProps> = Partial<TextboxProps>,\n SProps extends SerializedTextboxProps = SerializedTextboxProps,\n EventSpec extends ITextEvents = ITextEvents,\n >\n extends IText<Props, SProps, EventSpec>\n implements UniqueTextboxProps\n{\n /**\n * Minimum width of textbox, in pixels.\n * @type Number\n */\n declare minWidth: number;\n\n /**\n * Minimum calculated width of a textbox, in pixels.\n * fixed to 2 so that an empty textbox cannot go to 0\n * and is still selectable without text.\n * @type Number\n */\n declare dynamicMinWidth: number;\n\n /**\n * Use this boolean property in order to split strings that have no white space concept.\n * this is a cheap way to help with chinese/japanese\n * @type Boolean\n * @since 2.6.0\n */\n declare splitByGrapheme: boolean;\n\n declare _wordJoiners: RegExp;\n\n declare _styleMap: StyleMap;\n\n declare isWrapping: boolean;\n\n static type = 'Textbox';\n\n static textLayoutProperties = [...IText.textLayoutProperties, 'width'];\n\n static ownDefaults = textboxDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Textbox.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n */\n constructor(text: string, options?: Props) {\n super(text, { ...Textbox.ownDefaults, ...options } as Props);\n }\n\n /**\n * Creates the default control object.\n * If you prefer to have on instance of controls shared among all objects\n * make this function return an empty object and add controls to the ownDefaults object\n */\n static createControls(): { controls: Record<string, Control> } {\n return { controls: createTextboxDefaultControls() };\n }\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @private\n * @override\n */\n initDimensions() {\n if (!this.initialized) {\n return;\n }\n this.isEditing && this.initDelayedCursor();\n this._clearCache();\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n // wrap lines\n this._styleMap = this._generateStyleMap(this._splitText());\n // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n if (this.dynamicMinWidth > this.width) {\n this._set('width', this.dynamicMinWidth);\n }\n if (this.textAlign.includes(JUSTIFY)) {\n // once text is measured we need to make space fatter to make justified text.\n this.enlargeSpaces();\n }\n // clear cache and re-calculate height\n this.height = this.calcTextHeight();\n }\n\n /**\n * Generate an object that translates the style object so that it is\n * broken up by visual lines (new lines and automatic wrapping).\n * The original text styles object is broken up by actual lines (new lines only),\n * which is only sufficient for Text / IText\n * @private\n */\n _generateStyleMap(textInfo: TextLinesInfo): StyleMap {\n let realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0;\n const map: StyleMap = {};\n\n for (let i = 0; i < textInfo.graphemeLines.length; i++) {\n if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n } else if (\n !this.splitByGrapheme &&\n this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\n i > 0\n ) {\n // this case deals with space's that are removed from end of lines when wrapping\n realLineCharCount++;\n charCount++;\n }\n\n map[i] = { line: realLineCount, offset: realLineCharCount };\n\n charCount += textInfo.graphemeLines[i].length;\n realLineCharCount += textInfo.graphemeLines[i].length;\n }\n\n return map;\n }\n\n /**\n * Returns true if object has a style property or has it on a specified line\n * @param {Number} lineIndex\n * @return {Boolean}\n */\n styleHas(property: keyof TextStyleDeclaration, lineIndex: number): boolean {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (map) {\n lineIndex = map.line;\n }\n }\n return super.styleHas(property, lineIndex);\n }\n\n /**\n * Returns true if object has no styling or no styling in a line\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\n * @return {Boolean}\n */\n isEmptyStyles(lineIndex: number): boolean {\n if (!this.styles) {\n return true;\n }\n let offset = 0,\n nextLineIndex = lineIndex + 1,\n nextOffset: number,\n shouldLimit = false;\n const map = this._styleMap[lineIndex],\n mapNextLine = this._styleMap[lineIndex + 1];\n if (map) {\n lineIndex = map.line;\n offset = map.offset;\n }\n if (mapNextLine) {\n nextLineIndex = mapNextLine.line;\n shouldLimit = nextLineIndex === lineIndex;\n nextOffset = mapNextLine.offset;\n }\n const obj =\n typeof lineIndex === 'undefined'\n ? this.styles\n : { line: this.styles[lineIndex] };\n for (const p1 in obj) {\n for (const p2 in obj[p1]) {\n const p2Number = parseInt(p2, 10);\n if (p2Number >= offset && (!shouldLimit || p2Number < nextOffset!)) {\n for (const p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n }\n return true;\n }\n\n /**\n * @protected\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined\n */\n _getStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n ): TextStyleDeclaration {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (!map) {\n return {};\n }\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n return super._getStyleDeclaration(lineIndex, charIndex);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n protected _setStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n style: object,\n ) {\n const map = this._styleMap[lineIndex];\n super._setStyleDeclaration(map.line, map.offset + charIndex, style);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n protected _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\n const map = this._styleMap[lineIndex];\n super._deleteStyleDeclaration(map.line, map.offset + charIndex);\n }\n\n /**\n * probably broken need a fix\n * Returns the real style line that correspond to the wrapped lineIndex line\n * Used just to verify if the line does exist or not.\n * @param {Number} lineIndex\n * @returns {Boolean} if the line exists or not\n * @private\n */\n protected _getLineStyle(lineIndex: number): boolean {\n const map = this._styleMap[lineIndex];\n return !!this.styles[map.line];\n }\n\n /**\n * Set the line style to an empty object so that is initialized\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n protected _setLineStyle(lineIndex: number) {\n const map = this._styleMap[lineIndex];\n super._setLineStyle(map.line);\n }\n\n /**\n * Wraps text using the 'width' property of Textbox. First this function\n * splits text on newlines, so we preserve newlines entered by the user.\n * Then it wraps each line using the width of the Textbox by calling\n * _wrapLine().\n * @param {Array} lines The string array of text that is split into lines\n * @param {Number} desiredWidth width you want to wrap to\n * @returns {Array} Array of lines\n */\n _wrapText(lines: string[], desiredWidth: number): string[][] {\n this.isWrapping = true;\n // extract all thewords and the widths to optimally wrap lines.\n const data = this.getGraphemeDataForRender(lines);\n const wrapped: string[][] = [];\n for (let i = 0; i < data.wordsData.length; i++) {\n wrapped.push(...this._wrapLine(i, desiredWidth, data));\n }\n this.isWrapping = false;\n return wrapped;\n }\n\n /**\n * For each line of text terminated by an hard line stop,\n * measure each word width and extract the largest word from all.\n * The returned words here are the one that at the end will be rendered.\n * @param {string[]} lines the lines we need to measure\n *\n */\n getGraphemeDataForRender(lines: string[]): GraphemeData {\n const splitByGrapheme = this.splitByGrapheme,\n infix = splitByGrapheme ? '' : ' ';\n\n let largestWordWidth = 0;\n\n const data = lines.map((line, lineIndex) => {\n let offset = 0;\n const wordsOrGraphemes = splitByGrapheme\n ? this.graphemeSplit(line)\n : this.wordSplit(line);\n\n if (wordsOrGraphemes.length === 0) {\n return [{ word: [], width: 0 }];\n }\n\n return wordsOrGraphemes.map((word: string) => {\n // if using splitByGrapheme words are already in graphemes.\n const graphemeArray = splitByGrapheme\n ? [word]\n : this.graphemeSplit(word);\n const width = this._measureWord(graphemeArray, lineIndex, offset);\n largestWordWidth = Math.max(width, largestWordWidth);\n offset += graphemeArray.length + infix.length;\n return { word: graphemeArray, width };\n });\n });\n\n return {\n wordsData: data,\n largestWordWidth,\n };\n }\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n * It gets called when charBounds are not available yet.\n * Override if necessary\n * Use with {@link Textbox#wordSplit}\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n */\n _measureWord(word: string[], lineIndex: number, charOffset = 0): number {\n let width = 0,\n prevGrapheme;\n const skipLeft = true;\n for (let i = 0, len = word.length; i < len; i++) {\n const box = this._getGraphemeBox(\n word[i],\n lineIndex,\n i + charOffset,\n prevGrapheme,\n skipLeft,\n );\n width += box.kernedWidth;\n prevGrapheme = word[i];\n }\n return width;\n }\n\n /**\n * Override this method to customize word splitting\n * Use with {@link Textbox#_measureWord}\n * @param {string} value\n * @returns {string[]} array of words\n */\n wordSplit(value: string): string[] {\n return value.split(this._wordJoiners);\n }\n\n /**\n * Wraps a line of text using the width of the Textbox as desiredWidth\n * and leveraging the known width o words from GraphemeData\n * @private\n * @param {Number} lineIndex\n * @param {Number} desiredWidth width you want to wrap the line to\n * @param {GraphemeData} graphemeData an object containing all the lines' words width.\n * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine(\n lineIndex: number,\n desiredWidth: number,\n { largestWordWidth, wordsData }: GraphemeData,\n reservedSpace = 0,\n ): string[][] {\n const additionalSpace = this._getWidthOfCharSpacing(),\n splitByGrapheme = this.splitByGrapheme,\n graphemeLines = [],\n infix = splitByGrapheme ? '' : ' ';\n\n let lineWidth = 0,\n line: string[] = [],\n // spaces in different languages?\n offset = 0,\n infixWidth = 0,\n lineJustStarted = true;\n\n desiredWidth -= reservedSpace;\n\n const maxWidth = Math.max(\n desiredWidth,\n largestWordWidth,\n this.dynamicMinWidth,\n );\n // layout words\n const data = wordsData[lineIndex];\n offset = 0;\n let i;\n for (i = 0; i < data.length; i++) {\n const { word, width: wordWidth } = data[i];\n offset += word.length;\n\n lineWidth += infixWidth + wordWidth - additionalSpace;\n if (lineWidth > maxWidth && !lineJustStarted) {\n graphemeLines.push(line);\n line = [];\n lineWidth = wordWidth;\n lineJustStarted = true;\n } else {\n lineWidth += additionalSpace;\n }\n\n if (!lineJustStarted && !splitByGrapheme) {\n line.push(infix);\n }\n line = line.concat(word);\n\n infixWidth = splitByGrapheme\n ? 0\n : this._measureWord([infix], lineIndex, offset);\n offset++;\n lineJustStarted = false;\n }\n\n i && graphemeLines.push(line);\n\n // TODO: this code is probably not necessary anymore.\n // it can be moved out of this function since largestWordWidth is now\n // known in advance\n if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n }\n return graphemeLines;\n }\n\n /**\n * Detect if the text line is ended with an hard break\n * text and itext do not have wrapping, return false\n * @param {Number} lineIndex text to split\n * @return {Boolean}\n */\n isEndOfWrapping(lineIndex: number): boolean {\n if (!this._styleMap[lineIndex + 1]) {\n // is last line, return true;\n return true;\n }\n if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n // this is last line before a line break, return true;\n return true;\n }\n return false;\n }\n\n /**\n * Detect if a line has a linebreak and so we need to account for it when moving\n * and counting style.\n * This is important only for splitByGrapheme at the end of wrapping.\n * If we are not wrapping the offset is always 1\n * @return Number\n */\n missingNewlineOffset(lineIndex: number, skipWrapping?: boolean): 0 | 1 {\n if (this.splitByGrapheme && !skipWrapping) {\n return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n }\n return 1;\n }\n\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly every time it is called.\n * @param {String} text text to split\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines(text: string) {\n const newText = super._splitTextIntoLines(text),\n graphemeLines = this._wrapText(newText.lines, this.width),\n lines = new Array(graphemeLines.length);\n for (let i = 0; i < graphemeLines.length; i++) {\n lines[i] = graphemeLines[i].join('');\n }\n newText.lines = lines;\n newText.graphemeLines = graphemeLines;\n return newText;\n }\n\n getMinWidth() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\n }\n\n _removeExtraneousStyles() {\n const linesToKeep = new Map();\n for (const prop in this._styleMap) {\n const propNumber = parseInt(prop, 10);\n if (this._textLines[propNumber]) {\n const lineIndex = this._styleMap[prop].line;\n linesToKeep.set(`${lineIndex}`, true);\n }\n }\n for (const prop in this.styles) {\n if (!linesToKeep.has(prop)) {\n delete this.styles[prop];\n }\n }\n }\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return super.toObject<T, K>([\n 'minWidth',\n 'splitByGrapheme',\n ...propertiesToInclude,\n ] as K[]);\n }\n}\n\nclassRegistry.setClass(Textbox);\n"],"names":["textboxDefaultValues","minWidth","dynamicMinWidth","lockScalingFlip","noScaleCache","_wordJoiners","splitByGrapheme","Textbox","IText","getDefaults","super","ownDefaults","constructor","text","options","createControls","controls","createTextboxDefaultControls","initDimensions","this","initialized","isEditing","initDelayedCursor","_clearCache","_styleMap","_generateStyleMap","_splitText","width","_set","textAlign","includes","JUSTIFY","enlargeSpaces","height","calcTextHeight","textInfo","realLineCount","realLineCharCount","charCount","map","i","graphemeLines","length","graphemeText","_reSpaceAndTab","test","line","offset","styleHas","property","lineIndex","isWrapping","isEmptyStyles","styles","nextOffset","nextLineIndex","shouldLimit","mapNextLine","obj","p1","p2","p2Number","parseInt","p3","_getStyleDeclaration","charIndex","_setStyleDeclaration","style","_deleteStyleDeclaration","_getLineStyle","_setLineStyle","_wrapText","lines","desiredWidth","data","getGraphemeDataForRender","wrapped","wordsData","push","_wrapLine","infix","largestWordWidth","wordsOrGraphemes","graphemeSplit","wordSplit","word","graphemeArray","_measureWord","Math","max","prevGrapheme","charOffset","arguments","undefined","len","_getGraphemeBox","kernedWidth","value","split","_ref","reservedSpace","additionalSpace","_getWidthOfCharSpacing","lineWidth","infixWidth","lineJustStarted","maxWidth","wordWidth","concat","isEndOfWrapping","missingNewlineOffset","skipWrapping","_splitTextIntoLines","newText","Array","join","getMinWidth","_removeExtraneousStyles","linesToKeep","Map","prop","propNumber","_textLines","set","has","toObject","propertiesToInclude","_defineProperty","textLayoutProperties","classRegistry","setClass"],"mappings":"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"}
1
+ {"version":3,"file":"Textbox.min.mjs","sources":["../../../src/shapes/Textbox.ts"],"sourcesContent":["import type { TClassProperties, TOptions } from '../typedefs';\nimport { IText } from './IText/IText';\nimport { classRegistry } from '../ClassRegistry';\nimport { createTextboxDefaultControls } from '../controls/commonControls';\nimport { JUSTIFY } from './Text/constants';\nimport type { TextStyleDeclaration } from './Text/StyledText';\nimport type { SerializedITextProps, ITextProps } from './IText/IText';\nimport type { ITextEvents } from './IText/ITextBehavior';\nimport type { TextLinesInfo } from './Text/Text';\nimport type { Control } from '../controls/Control';\n\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\n// regexes, list of properties that are not suppose to change by instances, magic consts.\n// this will be a separated effort\nexport const textboxDefaultValues: Partial<TClassProperties<Textbox>> = {\n minWidth: 20,\n dynamicMinWidth: 2,\n lockScalingFlip: true,\n noScaleCache: false,\n _wordJoiners: /[ \\t\\r]/,\n splitByGrapheme: false,\n};\n\nexport type GraphemeData = {\n wordsData: {\n word: string[];\n width: number;\n }[][];\n largestWordWidth: number;\n};\n\nexport type StyleMap = Record<string, { line: number; offset: number }>;\n\n// @TODO this is not complete\ninterface UniqueTextboxProps {\n minWidth: number;\n splitByGrapheme: boolean;\n dynamicMinWidth: number;\n _wordJoiners: RegExp;\n}\n\nexport interface SerializedTextboxProps\n extends\n SerializedITextProps,\n Pick<UniqueTextboxProps, 'minWidth' | 'splitByGrapheme'> {}\n\nexport interface TextboxProps extends ITextProps, UniqueTextboxProps {}\n\n/**\n * Textbox class, based on IText, allows the user to resize the text rectangle\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\n * user can only change width. Height is adjusted automatically based on the\n * wrapping of lines.\n */\nexport class Textbox<\n Props extends TOptions<TextboxProps> = Partial<TextboxProps>,\n SProps extends SerializedTextboxProps = SerializedTextboxProps,\n EventSpec extends ITextEvents = ITextEvents,\n>\n extends IText<Props, SProps, EventSpec>\n implements UniqueTextboxProps\n{\n /**\n * Minimum width of textbox, in pixels.\n * @type Number\n */\n declare minWidth: number;\n\n /**\n * Minimum calculated width of a textbox, in pixels.\n * fixed to 2 so that an empty textbox cannot go to 0\n * and is still selectable without text.\n * @type Number\n */\n declare dynamicMinWidth: number;\n\n /**\n * Use this boolean property in order to split strings that have no white space concept.\n * this is a cheap way to help with chinese/japanese\n * @type Boolean\n * @since 2.6.0\n */\n declare splitByGrapheme: boolean;\n\n declare _wordJoiners: RegExp;\n\n declare _styleMap: StyleMap;\n\n declare isWrapping: boolean;\n\n static type = 'Textbox';\n\n static textLayoutProperties = [...IText.textLayoutProperties, 'width'];\n\n static ownDefaults = textboxDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Textbox.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n */\n constructor(text: string, options?: Props) {\n super(text, { ...Textbox.ownDefaults, ...options } as Props);\n }\n\n /**\n * Creates the default control object.\n * If you prefer to have on instance of controls shared among all objects\n * make this function return an empty object and add controls to the ownDefaults object\n */\n static createControls(): { controls: Record<string, Control> } {\n return { controls: createTextboxDefaultControls() };\n }\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @private\n * @override\n */\n initDimensions() {\n if (!this.initialized) {\n return;\n }\n this.isEditing && this.initDelayedCursor();\n this._clearCache();\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n // wrap lines\n this._styleMap = this._generateStyleMap(this._splitText());\n // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n if (this.dynamicMinWidth > this.width) {\n this._set('width', this.dynamicMinWidth);\n }\n if (this.textAlign.includes(JUSTIFY)) {\n // once text is measured we need to make space fatter to make justified text.\n this.enlargeSpaces();\n }\n // clear cache and re-calculate height\n this.height = this.calcTextHeight();\n }\n\n /**\n * Generate an object that translates the style object so that it is\n * broken up by visual lines (new lines and automatic wrapping).\n * The original text styles object is broken up by actual lines (new lines only),\n * which is only sufficient for Text / IText\n * @private\n */\n _generateStyleMap(textInfo: TextLinesInfo): StyleMap {\n let realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0;\n const map: StyleMap = {};\n\n for (let i = 0; i < textInfo.graphemeLines.length; i++) {\n if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n } else if (\n !this.splitByGrapheme &&\n this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\n i > 0\n ) {\n // this case deals with space's that are removed from end of lines when wrapping\n realLineCharCount++;\n charCount++;\n }\n\n map[i] = { line: realLineCount, offset: realLineCharCount };\n\n charCount += textInfo.graphemeLines[i].length;\n realLineCharCount += textInfo.graphemeLines[i].length;\n }\n\n return map;\n }\n\n /**\n * Returns true if object has a style property or has it on a specified line\n * @param {Number} lineIndex\n * @return {Boolean}\n */\n styleHas(property: keyof TextStyleDeclaration, lineIndex: number): boolean {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (map) {\n lineIndex = map.line;\n }\n }\n return super.styleHas(property, lineIndex);\n }\n\n /**\n * Returns true if object has no styling or no styling in a line\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\n * @return {Boolean}\n */\n isEmptyStyles(lineIndex: number): boolean {\n if (!this.styles) {\n return true;\n }\n let offset = 0,\n nextLineIndex = lineIndex + 1,\n nextOffset: number,\n shouldLimit = false;\n const map = this._styleMap[lineIndex],\n mapNextLine = this._styleMap[lineIndex + 1];\n if (map) {\n lineIndex = map.line;\n offset = map.offset;\n }\n if (mapNextLine) {\n nextLineIndex = mapNextLine.line;\n shouldLimit = nextLineIndex === lineIndex;\n nextOffset = mapNextLine.offset;\n }\n const obj =\n typeof lineIndex === 'undefined'\n ? this.styles\n : { line: this.styles[lineIndex] };\n for (const p1 in obj) {\n for (const p2 in obj[p1]) {\n const p2Number = parseInt(p2, 10);\n if (p2Number >= offset && (!shouldLimit || p2Number < nextOffset!)) {\n for (const p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n }\n return true;\n }\n\n /**\n * @protected\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined\n */\n _getStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n ): TextStyleDeclaration {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (!map) {\n return {};\n }\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n return super._getStyleDeclaration(lineIndex, charIndex);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n protected _setStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n style: object,\n ) {\n const map = this._styleMap[lineIndex];\n super._setStyleDeclaration(map.line, map.offset + charIndex, style);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n protected _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\n const map = this._styleMap[lineIndex];\n super._deleteStyleDeclaration(map.line, map.offset + charIndex);\n }\n\n /**\n * probably broken need a fix\n * Returns the real style line that correspond to the wrapped lineIndex line\n * Used just to verify if the line does exist or not.\n * @param {Number} lineIndex\n * @returns {Boolean} if the line exists or not\n * @private\n */\n protected _getLineStyle(lineIndex: number): boolean {\n const map = this._styleMap[lineIndex];\n return !!this.styles[map.line];\n }\n\n /**\n * Set the line style to an empty object so that is initialized\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n protected _setLineStyle(lineIndex: number) {\n const map = this._styleMap[lineIndex];\n super._setLineStyle(map.line);\n }\n\n /**\n * Wraps text using the 'width' property of Textbox. First this function\n * splits text on newlines, so we preserve newlines entered by the user.\n * Then it wraps each line using the width of the Textbox by calling\n * _wrapLine().\n * @param {Array} lines The string array of text that is split into lines\n * @param {Number} desiredWidth width you want to wrap to\n * @returns {Array} Array of lines\n */\n _wrapText(lines: string[], desiredWidth: number): string[][] {\n this.isWrapping = true;\n // extract all thewords and the widths to optimally wrap lines.\n const data = this.getGraphemeDataForRender(lines);\n const wrapped: string[][] = [];\n for (let i = 0; i < data.wordsData.length; i++) {\n wrapped.push(...this._wrapLine(i, desiredWidth, data));\n }\n this.isWrapping = false;\n return wrapped;\n }\n\n /**\n * For each line of text terminated by an hard line stop,\n * measure each word width and extract the largest word from all.\n * The returned words here are the one that at the end will be rendered.\n * @param {string[]} lines the lines we need to measure\n *\n */\n getGraphemeDataForRender(lines: string[]): GraphemeData {\n const splitByGrapheme = this.splitByGrapheme,\n infix = splitByGrapheme ? '' : ' ';\n\n let largestWordWidth = 0;\n\n const data = lines.map((line, lineIndex) => {\n let offset = 0;\n const wordsOrGraphemes = splitByGrapheme\n ? this.graphemeSplit(line)\n : this.wordSplit(line);\n\n if (wordsOrGraphemes.length === 0) {\n return [{ word: [], width: 0 }];\n }\n\n return wordsOrGraphemes.map((word: string) => {\n // if using splitByGrapheme words are already in graphemes.\n const graphemeArray = splitByGrapheme\n ? [word]\n : this.graphemeSplit(word);\n const width = this._measureWord(graphemeArray, lineIndex, offset);\n largestWordWidth = Math.max(width, largestWordWidth);\n offset += graphemeArray.length + infix.length;\n return { word: graphemeArray, width };\n });\n });\n\n return {\n wordsData: data,\n largestWordWidth,\n };\n }\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n * It gets called when charBounds are not available yet.\n * Override if necessary\n * Use with {@link Textbox#wordSplit}\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n */\n _measureWord(word: string[], lineIndex: number, charOffset = 0): number {\n let width = 0,\n prevGrapheme;\n const skipLeft = true;\n for (let i = 0, len = word.length; i < len; i++) {\n const box = this._getGraphemeBox(\n word[i],\n lineIndex,\n i + charOffset,\n prevGrapheme,\n skipLeft,\n );\n width += box.kernedWidth;\n prevGrapheme = word[i];\n }\n return width;\n }\n\n /**\n * Override this method to customize word splitting\n * Use with {@link Textbox#_measureWord}\n * @param {string} value\n * @returns {string[]} array of words\n */\n wordSplit(value: string): string[] {\n return value.split(this._wordJoiners);\n }\n\n /**\n * Wraps a line of text using the width of the Textbox as desiredWidth\n * and leveraging the known width o words from GraphemeData\n * @private\n * @param {Number} lineIndex\n * @param {Number} desiredWidth width you want to wrap the line to\n * @param {GraphemeData} graphemeData an object containing all the lines' words width.\n * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine(\n lineIndex: number,\n desiredWidth: number,\n { largestWordWidth, wordsData }: GraphemeData,\n reservedSpace = 0,\n ): string[][] {\n const additionalSpace = this._getWidthOfCharSpacing(),\n splitByGrapheme = this.splitByGrapheme,\n graphemeLines = [],\n infix = splitByGrapheme ? '' : ' ';\n\n let lineWidth = 0,\n line: string[] = [],\n // spaces in different languages?\n offset = 0,\n infixWidth = 0,\n lineJustStarted = true;\n\n desiredWidth -= reservedSpace;\n\n const maxWidth = Math.max(\n desiredWidth,\n largestWordWidth,\n this.dynamicMinWidth,\n );\n // layout words\n const data = wordsData[lineIndex];\n offset = 0;\n let i;\n for (i = 0; i < data.length; i++) {\n const { word, width: wordWidth } = data[i];\n offset += word.length;\n\n lineWidth += infixWidth + wordWidth - additionalSpace;\n if (lineWidth > maxWidth && !lineJustStarted) {\n graphemeLines.push(line);\n line = [];\n lineWidth = wordWidth;\n lineJustStarted = true;\n } else {\n lineWidth += additionalSpace;\n }\n\n if (!lineJustStarted && !splitByGrapheme) {\n line.push(infix);\n }\n line = line.concat(word);\n\n infixWidth = splitByGrapheme\n ? 0\n : this._measureWord([infix], lineIndex, offset);\n offset++;\n lineJustStarted = false;\n }\n\n i && graphemeLines.push(line);\n\n // TODO: this code is probably not necessary anymore.\n // it can be moved out of this function since largestWordWidth is now\n // known in advance\n if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n }\n return graphemeLines;\n }\n\n /**\n * Detect if the text line is ended with an hard break\n * text and itext do not have wrapping, return false\n * @param {Number} lineIndex text to split\n * @return {Boolean}\n */\n isEndOfWrapping(lineIndex: number): boolean {\n if (!this._styleMap[lineIndex + 1]) {\n // is last line, return true;\n return true;\n }\n if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n // this is last line before a line break, return true;\n return true;\n }\n return false;\n }\n\n /**\n * Detect if a line has a linebreak and so we need to account for it when moving\n * and counting style.\n * This is important only for splitByGrapheme at the end of wrapping.\n * If we are not wrapping the offset is always 1\n * @return Number\n */\n missingNewlineOffset(lineIndex: number, skipWrapping?: boolean): 0 | 1 {\n if (this.splitByGrapheme && !skipWrapping) {\n return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n }\n return 1;\n }\n\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly every time it is called.\n * @param {String} text text to split\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines(text: string) {\n const newText = super._splitTextIntoLines(text),\n graphemeLines = this._wrapText(newText.lines, this.width),\n lines = new Array(graphemeLines.length);\n for (let i = 0; i < graphemeLines.length; i++) {\n lines[i] = graphemeLines[i].join('');\n }\n newText.lines = lines;\n newText.graphemeLines = graphemeLines;\n return newText;\n }\n\n getMinWidth() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\n }\n\n _removeExtraneousStyles() {\n const linesToKeep = new Map();\n for (const prop in this._styleMap) {\n const propNumber = parseInt(prop, 10);\n if (this._textLines[propNumber]) {\n const lineIndex = this._styleMap[prop].line;\n linesToKeep.set(`${lineIndex}`, true);\n }\n }\n for (const prop in this.styles) {\n if (!linesToKeep.has(prop)) {\n delete this.styles[prop];\n }\n }\n }\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return super.toObject<T, K>([\n 'minWidth',\n 'splitByGrapheme',\n ...propertiesToInclude,\n ] as K[]);\n }\n}\n\nclassRegistry.setClass(Textbox);\n"],"names":["textboxDefaultValues","minWidth","dynamicMinWidth","lockScalingFlip","noScaleCache","_wordJoiners","splitByGrapheme","Textbox","IText","getDefaults","super","ownDefaults","constructor","text","options","createControls","controls","createTextboxDefaultControls","initDimensions","this","initialized","isEditing","initDelayedCursor","_clearCache","_styleMap","_generateStyleMap","_splitText","width","_set","textAlign","includes","JUSTIFY","enlargeSpaces","height","calcTextHeight","textInfo","realLineCount","realLineCharCount","charCount","map","i","graphemeLines","length","graphemeText","_reSpaceAndTab","test","line","offset","styleHas","property","lineIndex","isWrapping","isEmptyStyles","styles","nextOffset","nextLineIndex","shouldLimit","mapNextLine","obj","p1","p2","p2Number","parseInt","p3","_getStyleDeclaration","charIndex","_setStyleDeclaration","style","_deleteStyleDeclaration","_getLineStyle","_setLineStyle","_wrapText","lines","desiredWidth","data","getGraphemeDataForRender","wrapped","wordsData","push","_wrapLine","infix","largestWordWidth","wordsOrGraphemes","graphemeSplit","wordSplit","word","graphemeArray","_measureWord","Math","max","prevGrapheme","charOffset","arguments","undefined","len","_getGraphemeBox","kernedWidth","value","split","_ref","reservedSpace","additionalSpace","_getWidthOfCharSpacing","lineWidth","infixWidth","lineJustStarted","maxWidth","wordWidth","concat","isEndOfWrapping","missingNewlineOffset","skipWrapping","_splitTextIntoLines","newText","Array","join","getMinWidth","_removeExtraneousStyles","linesToKeep","Map","prop","propNumber","_textLines","set","has","toObject","propertiesToInclude","_defineProperty","textLayoutProperties","classRegistry","setClass"],"mappings":"8TAcO,MAAMA,EAA2D,CACtEC,SAAU,GACVC,gBAAiB,EACjBC,iBAAiB,EACjBC,cAAc,EACdC,aAAc,UACdC,iBAAiB,GAkCZ,MAAMC,UAKHC,EAqCR,kBAAOC,GACL,MAAO,IACFC,MAAMD,iBACNF,EAAQI,YAEf,CAOAC,WAAAA,CAAYC,EAAcC,GACxBJ,MAAMG,EAAM,IAAKN,EAAQI,eAAgBG,GAC3C,CAOA,qBAAOC,GACL,MAAO,CAAEC,SAAUC,IACrB,CAQAC,cAAAA,GACOC,KAAKC,cAGVD,KAAKE,WAAaF,KAAKG,oBACvBH,KAAKI,cAELJ,KAAKjB,gBAAkB,EAEvBiB,KAAKK,UAAYL,KAAKM,kBAAkBN,KAAKO,cAEzCP,KAAKjB,gBAAkBiB,KAAKQ,OAC9BR,KAAKS,KAAK,QAAST,KAAKjB,iBAEtBiB,KAAKU,UAAUC,SAASC,IAE1BZ,KAAKa,gBAGPb,KAAKc,OAASd,KAAKe,iBACrB,CASAT,iBAAAA,CAAkBU,GAChB,IAAIC,EAAgB,EAClBC,EAAoB,EACpBC,EAAY,EACd,MAAMC,EAAgB,CAAA,EAEtB,IAAK,IAAIC,EAAI,EAAGA,EAAIL,EAASM,cAAcC,OAAQF,IACR,OAArCL,EAASQ,aAAaL,IAAuBE,EAAI,GACnDH,EAAoB,EACpBC,IACAF,MAECjB,KAAKb,iBACNa,KAAKyB,eAAeC,KAAKV,EAASQ,aAAaL,KAC/CE,EAAI,IAGJH,IACAC,KAGFC,EAAIC,GAAK,CAAEM,KAAMV,EAAeW,OAAQV,GAExCC,GAAaH,EAASM,cAAcD,GAAGE,OACvCL,GAAqBF,EAASM,cAAcD,GAAGE,OAGjD,OAAOH,CACT,CAOAS,QAAAA,CAASC,EAAsCC,GAC7C,GAAI/B,KAAKK,YAAcL,KAAKgC,WAAY,CACtC,MAAMZ,EAAMpB,KAAKK,UAAU0B,GACvBX,IACFW,EAAYX,EAAIO,KAEpB,CACA,OAAOpC,MAAMsC,SAASC,EAAUC,EAClC,CAOAE,aAAAA,CAAcF,GACZ,IAAK/B,KAAKkC,OACR,OAAO,EAET,IAEEC,EAFEP,EAAS,EACXQ,EAAgBL,EAAY,EAE5BM,GAAc,EAChB,MAAMjB,EAAMpB,KAAKK,UAAU0B,GACzBO,EAActC,KAAKK,UAAU0B,EAAY,GACvCX,IACFW,EAAYX,EAAIO,KAChBC,EAASR,EAAIQ,QAEXU,IACFF,EAAgBE,EAAYX,KAC5BU,EAAcD,IAAkBL,EAChCI,EAAaG,EAAYV,QAE3B,MAAMW,OACiB,IAAdR,EACH/B,KAAKkC,OACL,CAAEP,KAAM3B,KAAKkC,OAAOH,IAC1B,IAAK,MAAMS,KAAMD,EACf,IAAK,MAAME,KAAMF,EAAIC,GAAK,CACxB,MAAME,EAAWC,SAASF,EAAI,IAC9B,GAAIC,GAAYd,KAAYS,GAAeK,EAAWP,GACpD,IAAK,MAAMS,KAAML,EAAIC,GAAIC,GACvB,OAAO,CAGb,CAEF,OAAO,CACT,CAQAI,oBAAAA,CACEd,EACAe,GAEA,GAAI9C,KAAKK,YAAcL,KAAKgC,WAAY,CACtC,MAAMZ,EAAMpB,KAAKK,UAAU0B,GAC3B,IAAKX,EACH,MAAO,CAAA,EAETW,EAAYX,EAAIO,KAChBmB,EAAY1B,EAAIQ,OAASkB,CAC3B,CACA,OAAOvD,MAAMsD,qBAAqBd,EAAWe,EAC/C,CAQUC,oBAAAA,CACRhB,EACAe,EACAE,GAEA,MAAM5B,EAAMpB,KAAKK,UAAU0B,GAC3BxC,MAAMwD,qBAAqB3B,EAAIO,KAAMP,EAAIQ,OAASkB,EAAWE,EAC/D,CAOUC,uBAAAA,CAAwBlB,EAAmBe,GACnD,MAAM1B,EAAMpB,KAAKK,UAAU0B,GAC3BxC,MAAM0D,wBAAwB7B,EAAIO,KAAMP,EAAIQ,OAASkB,EACvD,CAUUI,aAAAA,CAAcnB,GACtB,MAAMX,EAAMpB,KAAKK,UAAU0B,GAC3B,QAAS/B,KAAKkC,OAAOd,EAAIO,KAC3B,CAQUwB,aAAAA,CAAcpB,GACtB,MAAMX,EAAMpB,KAAKK,UAAU0B,GAC3BxC,MAAM4D,cAAc/B,EAAIO,KAC1B,CAWAyB,SAAAA,CAAUC,EAAiBC,GACzBtD,KAAKgC,YAAa,EAElB,MAAMuB,EAAOvD,KAAKwD,yBAAyBH,GACrCI,EAAsB,GAC5B,IAAK,IAAIpC,EAAI,EAAGA,EAAIkC,EAAKG,UAAUnC,OAAQF,IACzCoC,EAAQE,QAAQ3D,KAAK4D,UAAUvC,EAAGiC,EAAcC,IAGlD,OADAvD,KAAKgC,YAAa,EACXyB,CACT,CASAD,wBAAAA,CAAyBH,GACvB,MAAMlE,EAAkBa,KAAKb,gBAC3B0E,EAAQ1E,EAAkB,GAAK,IAEjC,IAAI2E,EAAmB,EAwBvB,MAAO,CACLJ,UAvBWL,EAAMjC,IAAI,CAACO,EAAMI,KAC5B,IAAIH,EAAS,EACb,MAAMmC,EAAmB5E,EACrBa,KAAKgE,cAAcrC,GACnB3B,KAAKiE,UAAUtC,GAEnB,OAAgC,IAA5BoC,EAAiBxC,OACZ,CAAC,CAAE2C,KAAM,GAAI1D,MAAO,IAGtBuD,EAAiB3C,IAAK8C,IAE3B,MAAMC,EAAgBhF,EAClB,CAAC+E,GACDlE,KAAKgE,cAAcE,GACjB1D,EAAQR,KAAKoE,aAAaD,EAAepC,EAAWH,GAG1D,OAFAkC,EAAmBO,KAAKC,IAAI9D,EAAOsD,GACnClC,GAAUuC,EAAc5C,OAASsC,EAAMtC,OAChC,CAAE2C,KAAMC,EAAe3D,aAMhCsD,mBAEJ,CAcAM,YAAAA,CAAaF,EAAgBnC,GAA2C,IAEpEwC,EAF4CC,EAAUC,UAAAlD,OAAA,QAAAmD,IAAAD,UAAA,GAAAA,UAAA,GAAG,EACvDjE,EAAQ,EAGZ,IAAK,IAAIa,EAAI,EAAGsD,EAAMT,EAAK3C,OAAQF,EAAIsD,EAAKtD,IAAK,CAQ/Cb,GAPYR,KAAK4E,gBACfV,EAAK7C,GACLU,EACAV,EAAImD,EACJD,EANa,MASFM,YACbN,EAAeL,EAAK7C,EACtB,CACA,OAAOb,CACT,CAQAyD,SAAAA,CAAUa,GACR,OAAOA,EAAMC,MAAM/E,KAAKd,aAC1B,CAaA0E,SAAAA,CACE7B,EACAuB,EAAoB0B,GAGR,IAFZlB,iBAAEA,EAAgBJ,UAAEA,GAAyBsB,EAC7CC,EAAaR,UAAAlD,OAAA,QAAAmD,IAAAD,UAAA,GAAAA,UAAA,GAAG,EAEhB,MAAMS,EAAkBlF,KAAKmF,yBAC3BhG,EAAkBa,KAAKb,gBACvBmC,EAAgB,GAChBuC,EAAQ1E,EAAkB,GAAK,IAEjC,IAAIiG,EAAY,EACdzD,EAAiB,GAEjBC,EAAS,EACTyD,EAAa,EACbC,GAAkB,EAEpBhC,GAAgB2B,EAEhB,MAAMM,EAAWlB,KAAKC,IACpBhB,EACAQ,EACA9D,KAAKjB,iBAGDwE,EAAOG,EAAU3B,GAEvB,IAAIV,EACJ,IAFAO,EAAS,EAEJP,EAAI,EAAGA,EAAIkC,EAAKhC,OAAQF,IAAK,CAChC,MAAM6C,KAAEA,EAAM1D,MAAOgF,GAAcjC,EAAKlC,GACxCO,GAAUsC,EAAK3C,OAEf6D,GAAaC,EAAaG,EAAYN,EAClCE,EAAYG,IAAaD,GAC3BhE,EAAcqC,KAAKhC,GACnBA,EAAO,GACPyD,EAAYI,EACZF,GAAkB,GAElBF,GAAaF,EAGVI,GAAoBnG,GACvBwC,EAAKgC,KAAKE,GAEZlC,EAAOA,EAAK8D,OAAOvB,GAEnBmB,EAAalG,EACT,EACAa,KAAKoE,aAAa,CAACP,GAAQ9B,EAAWH,GAC1CA,IACA0D,GAAkB,CACpB,CAUA,OARAjE,GAAKC,EAAcqC,KAAKhC,GAKpBmC,EAAmBmB,EAAgBjF,KAAKjB,kBAC1CiB,KAAKjB,gBAAkB+E,EAAmBoB,EAAkBD,GAEvD3D,CACT,CAQAoE,eAAAA,CAAgB3D,GACd,OAAK/B,KAAKK,UAAU0B,EAAY,IAI5B/B,KAAKK,UAAU0B,EAAY,GAAGJ,OAAS3B,KAAKK,UAAU0B,GAAWJ,IAKvE,CASAgE,oBAAAA,CAAqB5D,EAAmB6D,GACtC,OAAI5F,KAAKb,kBAAoByG,EACpB5F,KAAK0F,gBAAgB3D,GAAa,EAAI,EAExC,CACT,CASA8D,mBAAAA,CAAoBnG,GAClB,MAAMoG,EAAUvG,MAAMsG,oBAAoBnG,GACxC4B,EAAgBtB,KAAKoD,UAAU0C,EAAQzC,MAAOrD,KAAKQ,OACnD6C,EAAQ,IAAI0C,MAAMzE,EAAcC,QAClC,IAAK,IAAIF,EAAI,EAAGA,EAAIC,EAAcC,OAAQF,IACxCgC,EAAMhC,GAAKC,EAAcD,GAAG2E,KAAK,IAInC,OAFAF,EAAQzC,MAAQA,EAChByC,EAAQxE,cAAgBA,EACjBwE,CACT,CAEAG,WAAAA,GACE,OAAO5B,KAAKC,IAAItE,KAAKlB,SAAUkB,KAAKjB,gBACtC,CAEAmH,uBAAAA,GACE,MAAMC,EAAc,IAAIC,IACxB,IAAK,MAAMC,KAAQrG,KAAKK,UAAW,CACjC,MAAMiG,EAAa3D,SAAS0D,EAAM,IAClC,GAAIrG,KAAKuG,WAAWD,GAAa,CAC/B,MAAMvE,EAAY/B,KAAKK,UAAUgG,GAAM1E,KACvCwE,EAAYK,IAAI,GAAGzE,KAAa,EAClC,CACF,CACA,IAAK,MAAMsE,KAAQrG,KAAKkC,OACjBiE,EAAYM,IAAIJ,WACZrG,KAAKkC,OAAOmE,EAGzB,CAOAK,QAAAA,GAGsD,IAApDC,EAAwBlC,UAAAlD,OAAA,QAAAmD,IAAAD,UAAA,GAAAA,UAAA,GAAG,GAC3B,OAAOlF,MAAMmH,SAAe,CAC1B,WACA,qBACGC,GAEP,EApfAC,EAtBWxH,EAAO,OAoCJ,WAASwH,EApCZxH,EAAO,uBAsCY,IAAIC,EAAMwH,qBAAsB,UAAQD,EAtC3DxH,EAAO,cAwCGP,GAqevBiI,EAAcC,SAAS3H"}
@@ -1 +1 @@
1
- {"version":3,"file":"Textbox.mjs","sources":["../../../src/shapes/Textbox.ts"],"sourcesContent":["import type { TClassProperties, TOptions } from '../typedefs';\nimport { IText } from './IText/IText';\nimport { classRegistry } from '../ClassRegistry';\nimport { createTextboxDefaultControls } from '../controls/commonControls';\nimport { JUSTIFY } from './Text/constants';\nimport type { TextStyleDeclaration } from './Text/StyledText';\nimport type { SerializedITextProps, ITextProps } from './IText/IText';\nimport type { ITextEvents } from './IText/ITextBehavior';\nimport type { TextLinesInfo } from './Text/Text';\nimport type { Control } from '../controls/Control';\n\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\n// regexes, list of properties that are not suppose to change by instances, magic consts.\n// this will be a separated effort\nexport const textboxDefaultValues: Partial<TClassProperties<Textbox>> = {\n minWidth: 20,\n dynamicMinWidth: 2,\n lockScalingFlip: true,\n noScaleCache: false,\n _wordJoiners: /[ \\t\\r]/,\n splitByGrapheme: false,\n};\n\nexport type GraphemeData = {\n wordsData: {\n word: string[];\n width: number;\n }[][];\n largestWordWidth: number;\n};\n\nexport type StyleMap = Record<string, { line: number; offset: number }>;\n\n// @TODO this is not complete\ninterface UniqueTextboxProps {\n minWidth: number;\n splitByGrapheme: boolean;\n dynamicMinWidth: number;\n _wordJoiners: RegExp;\n}\n\nexport interface SerializedTextboxProps\n extends SerializedITextProps,\n Pick<UniqueTextboxProps, 'minWidth' | 'splitByGrapheme'> {}\n\nexport interface TextboxProps extends ITextProps, UniqueTextboxProps {}\n\n/**\n * Textbox class, based on IText, allows the user to resize the text rectangle\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\n * user can only change width. Height is adjusted automatically based on the\n * wrapping of lines.\n */\nexport class Textbox<\n Props extends TOptions<TextboxProps> = Partial<TextboxProps>,\n SProps extends SerializedTextboxProps = SerializedTextboxProps,\n EventSpec extends ITextEvents = ITextEvents,\n >\n extends IText<Props, SProps, EventSpec>\n implements UniqueTextboxProps\n{\n /**\n * Minimum width of textbox, in pixels.\n * @type Number\n */\n declare minWidth: number;\n\n /**\n * Minimum calculated width of a textbox, in pixels.\n * fixed to 2 so that an empty textbox cannot go to 0\n * and is still selectable without text.\n * @type Number\n */\n declare dynamicMinWidth: number;\n\n /**\n * Use this boolean property in order to split strings that have no white space concept.\n * this is a cheap way to help with chinese/japanese\n * @type Boolean\n * @since 2.6.0\n */\n declare splitByGrapheme: boolean;\n\n declare _wordJoiners: RegExp;\n\n declare _styleMap: StyleMap;\n\n declare isWrapping: boolean;\n\n static type = 'Textbox';\n\n static textLayoutProperties = [...IText.textLayoutProperties, 'width'];\n\n static ownDefaults = textboxDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Textbox.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n */\n constructor(text: string, options?: Props) {\n super(text, { ...Textbox.ownDefaults, ...options } as Props);\n }\n\n /**\n * Creates the default control object.\n * If you prefer to have on instance of controls shared among all objects\n * make this function return an empty object and add controls to the ownDefaults object\n */\n static createControls(): { controls: Record<string, Control> } {\n return { controls: createTextboxDefaultControls() };\n }\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @private\n * @override\n */\n initDimensions() {\n if (!this.initialized) {\n return;\n }\n this.isEditing && this.initDelayedCursor();\n this._clearCache();\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n // wrap lines\n this._styleMap = this._generateStyleMap(this._splitText());\n // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n if (this.dynamicMinWidth > this.width) {\n this._set('width', this.dynamicMinWidth);\n }\n if (this.textAlign.includes(JUSTIFY)) {\n // once text is measured we need to make space fatter to make justified text.\n this.enlargeSpaces();\n }\n // clear cache and re-calculate height\n this.height = this.calcTextHeight();\n }\n\n /**\n * Generate an object that translates the style object so that it is\n * broken up by visual lines (new lines and automatic wrapping).\n * The original text styles object is broken up by actual lines (new lines only),\n * which is only sufficient for Text / IText\n * @private\n */\n _generateStyleMap(textInfo: TextLinesInfo): StyleMap {\n let realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0;\n const map: StyleMap = {};\n\n for (let i = 0; i < textInfo.graphemeLines.length; i++) {\n if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n } else if (\n !this.splitByGrapheme &&\n this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\n i > 0\n ) {\n // this case deals with space's that are removed from end of lines when wrapping\n realLineCharCount++;\n charCount++;\n }\n\n map[i] = { line: realLineCount, offset: realLineCharCount };\n\n charCount += textInfo.graphemeLines[i].length;\n realLineCharCount += textInfo.graphemeLines[i].length;\n }\n\n return map;\n }\n\n /**\n * Returns true if object has a style property or has it on a specified line\n * @param {Number} lineIndex\n * @return {Boolean}\n */\n styleHas(property: keyof TextStyleDeclaration, lineIndex: number): boolean {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (map) {\n lineIndex = map.line;\n }\n }\n return super.styleHas(property, lineIndex);\n }\n\n /**\n * Returns true if object has no styling or no styling in a line\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\n * @return {Boolean}\n */\n isEmptyStyles(lineIndex: number): boolean {\n if (!this.styles) {\n return true;\n }\n let offset = 0,\n nextLineIndex = lineIndex + 1,\n nextOffset: number,\n shouldLimit = false;\n const map = this._styleMap[lineIndex],\n mapNextLine = this._styleMap[lineIndex + 1];\n if (map) {\n lineIndex = map.line;\n offset = map.offset;\n }\n if (mapNextLine) {\n nextLineIndex = mapNextLine.line;\n shouldLimit = nextLineIndex === lineIndex;\n nextOffset = mapNextLine.offset;\n }\n const obj =\n typeof lineIndex === 'undefined'\n ? this.styles\n : { line: this.styles[lineIndex] };\n for (const p1 in obj) {\n for (const p2 in obj[p1]) {\n const p2Number = parseInt(p2, 10);\n if (p2Number >= offset && (!shouldLimit || p2Number < nextOffset!)) {\n for (const p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n }\n return true;\n }\n\n /**\n * @protected\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined\n */\n _getStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n ): TextStyleDeclaration {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (!map) {\n return {};\n }\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n return super._getStyleDeclaration(lineIndex, charIndex);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n protected _setStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n style: object,\n ) {\n const map = this._styleMap[lineIndex];\n super._setStyleDeclaration(map.line, map.offset + charIndex, style);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n protected _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\n const map = this._styleMap[lineIndex];\n super._deleteStyleDeclaration(map.line, map.offset + charIndex);\n }\n\n /**\n * probably broken need a fix\n * Returns the real style line that correspond to the wrapped lineIndex line\n * Used just to verify if the line does exist or not.\n * @param {Number} lineIndex\n * @returns {Boolean} if the line exists or not\n * @private\n */\n protected _getLineStyle(lineIndex: number): boolean {\n const map = this._styleMap[lineIndex];\n return !!this.styles[map.line];\n }\n\n /**\n * Set the line style to an empty object so that is initialized\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n protected _setLineStyle(lineIndex: number) {\n const map = this._styleMap[lineIndex];\n super._setLineStyle(map.line);\n }\n\n /**\n * Wraps text using the 'width' property of Textbox. First this function\n * splits text on newlines, so we preserve newlines entered by the user.\n * Then it wraps each line using the width of the Textbox by calling\n * _wrapLine().\n * @param {Array} lines The string array of text that is split into lines\n * @param {Number} desiredWidth width you want to wrap to\n * @returns {Array} Array of lines\n */\n _wrapText(lines: string[], desiredWidth: number): string[][] {\n this.isWrapping = true;\n // extract all thewords and the widths to optimally wrap lines.\n const data = this.getGraphemeDataForRender(lines);\n const wrapped: string[][] = [];\n for (let i = 0; i < data.wordsData.length; i++) {\n wrapped.push(...this._wrapLine(i, desiredWidth, data));\n }\n this.isWrapping = false;\n return wrapped;\n }\n\n /**\n * For each line of text terminated by an hard line stop,\n * measure each word width and extract the largest word from all.\n * The returned words here are the one that at the end will be rendered.\n * @param {string[]} lines the lines we need to measure\n *\n */\n getGraphemeDataForRender(lines: string[]): GraphemeData {\n const splitByGrapheme = this.splitByGrapheme,\n infix = splitByGrapheme ? '' : ' ';\n\n let largestWordWidth = 0;\n\n const data = lines.map((line, lineIndex) => {\n let offset = 0;\n const wordsOrGraphemes = splitByGrapheme\n ? this.graphemeSplit(line)\n : this.wordSplit(line);\n\n if (wordsOrGraphemes.length === 0) {\n return [{ word: [], width: 0 }];\n }\n\n return wordsOrGraphemes.map((word: string) => {\n // if using splitByGrapheme words are already in graphemes.\n const graphemeArray = splitByGrapheme\n ? [word]\n : this.graphemeSplit(word);\n const width = this._measureWord(graphemeArray, lineIndex, offset);\n largestWordWidth = Math.max(width, largestWordWidth);\n offset += graphemeArray.length + infix.length;\n return { word: graphemeArray, width };\n });\n });\n\n return {\n wordsData: data,\n largestWordWidth,\n };\n }\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n * It gets called when charBounds are not available yet.\n * Override if necessary\n * Use with {@link Textbox#wordSplit}\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n */\n _measureWord(word: string[], lineIndex: number, charOffset = 0): number {\n let width = 0,\n prevGrapheme;\n const skipLeft = true;\n for (let i = 0, len = word.length; i < len; i++) {\n const box = this._getGraphemeBox(\n word[i],\n lineIndex,\n i + charOffset,\n prevGrapheme,\n skipLeft,\n );\n width += box.kernedWidth;\n prevGrapheme = word[i];\n }\n return width;\n }\n\n /**\n * Override this method to customize word splitting\n * Use with {@link Textbox#_measureWord}\n * @param {string} value\n * @returns {string[]} array of words\n */\n wordSplit(value: string): string[] {\n return value.split(this._wordJoiners);\n }\n\n /**\n * Wraps a line of text using the width of the Textbox as desiredWidth\n * and leveraging the known width o words from GraphemeData\n * @private\n * @param {Number} lineIndex\n * @param {Number} desiredWidth width you want to wrap the line to\n * @param {GraphemeData} graphemeData an object containing all the lines' words width.\n * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine(\n lineIndex: number,\n desiredWidth: number,\n { largestWordWidth, wordsData }: GraphemeData,\n reservedSpace = 0,\n ): string[][] {\n const additionalSpace = this._getWidthOfCharSpacing(),\n splitByGrapheme = this.splitByGrapheme,\n graphemeLines = [],\n infix = splitByGrapheme ? '' : ' ';\n\n let lineWidth = 0,\n line: string[] = [],\n // spaces in different languages?\n offset = 0,\n infixWidth = 0,\n lineJustStarted = true;\n\n desiredWidth -= reservedSpace;\n\n const maxWidth = Math.max(\n desiredWidth,\n largestWordWidth,\n this.dynamicMinWidth,\n );\n // layout words\n const data = wordsData[lineIndex];\n offset = 0;\n let i;\n for (i = 0; i < data.length; i++) {\n const { word, width: wordWidth } = data[i];\n offset += word.length;\n\n lineWidth += infixWidth + wordWidth - additionalSpace;\n if (lineWidth > maxWidth && !lineJustStarted) {\n graphemeLines.push(line);\n line = [];\n lineWidth = wordWidth;\n lineJustStarted = true;\n } else {\n lineWidth += additionalSpace;\n }\n\n if (!lineJustStarted && !splitByGrapheme) {\n line.push(infix);\n }\n line = line.concat(word);\n\n infixWidth = splitByGrapheme\n ? 0\n : this._measureWord([infix], lineIndex, offset);\n offset++;\n lineJustStarted = false;\n }\n\n i && graphemeLines.push(line);\n\n // TODO: this code is probably not necessary anymore.\n // it can be moved out of this function since largestWordWidth is now\n // known in advance\n if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n }\n return graphemeLines;\n }\n\n /**\n * Detect if the text line is ended with an hard break\n * text and itext do not have wrapping, return false\n * @param {Number} lineIndex text to split\n * @return {Boolean}\n */\n isEndOfWrapping(lineIndex: number): boolean {\n if (!this._styleMap[lineIndex + 1]) {\n // is last line, return true;\n return true;\n }\n if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n // this is last line before a line break, return true;\n return true;\n }\n return false;\n }\n\n /**\n * Detect if a line has a linebreak and so we need to account for it when moving\n * and counting style.\n * This is important only for splitByGrapheme at the end of wrapping.\n * If we are not wrapping the offset is always 1\n * @return Number\n */\n missingNewlineOffset(lineIndex: number, skipWrapping?: boolean): 0 | 1 {\n if (this.splitByGrapheme && !skipWrapping) {\n return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n }\n return 1;\n }\n\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly every time it is called.\n * @param {String} text text to split\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines(text: string) {\n const newText = super._splitTextIntoLines(text),\n graphemeLines = this._wrapText(newText.lines, this.width),\n lines = new Array(graphemeLines.length);\n for (let i = 0; i < graphemeLines.length; i++) {\n lines[i] = graphemeLines[i].join('');\n }\n newText.lines = lines;\n newText.graphemeLines = graphemeLines;\n return newText;\n }\n\n getMinWidth() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\n }\n\n _removeExtraneousStyles() {\n const linesToKeep = new Map();\n for (const prop in this._styleMap) {\n const propNumber = parseInt(prop, 10);\n if (this._textLines[propNumber]) {\n const lineIndex = this._styleMap[prop].line;\n linesToKeep.set(`${lineIndex}`, true);\n }\n }\n for (const prop in this.styles) {\n if (!linesToKeep.has(prop)) {\n delete this.styles[prop];\n }\n }\n }\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return super.toObject<T, K>([\n 'minWidth',\n 'splitByGrapheme',\n ...propertiesToInclude,\n ] as K[]);\n }\n}\n\nclassRegistry.setClass(Textbox);\n"],"names":["textboxDefaultValues","minWidth","dynamicMinWidth","lockScalingFlip","noScaleCache","_wordJoiners","splitByGrapheme","Textbox","IText","getDefaults","ownDefaults","constructor","text","options","createControls","controls","createTextboxDefaultControls","initDimensions","initialized","isEditing","initDelayedCursor","_clearCache","_styleMap","_generateStyleMap","_splitText","width","_set","textAlign","includes","JUSTIFY","enlargeSpaces","height","calcTextHeight","textInfo","realLineCount","realLineCharCount","charCount","map","i","graphemeLines","length","graphemeText","_reSpaceAndTab","test","line","offset","styleHas","property","lineIndex","isWrapping","isEmptyStyles","styles","nextLineIndex","nextOffset","shouldLimit","mapNextLine","obj","p1","p2","p2Number","parseInt","p3","_getStyleDeclaration","charIndex","_setStyleDeclaration","style","_deleteStyleDeclaration","_getLineStyle","_setLineStyle","_wrapText","lines","desiredWidth","data","getGraphemeDataForRender","wrapped","wordsData","push","_wrapLine","infix","largestWordWidth","wordsOrGraphemes","graphemeSplit","wordSplit","word","graphemeArray","_measureWord","Math","max","charOffset","arguments","undefined","prevGrapheme","skipLeft","len","box","_getGraphemeBox","kernedWidth","value","split","_ref","reservedSpace","additionalSpace","_getWidthOfCharSpacing","lineWidth","infixWidth","lineJustStarted","maxWidth","wordWidth","concat","isEndOfWrapping","missingNewlineOffset","skipWrapping","_splitTextIntoLines","newText","Array","join","getMinWidth","_removeExtraneousStyles","linesToKeep","Map","prop","propNumber","_textLines","set","has","toObject","propertiesToInclude","_defineProperty","textLayoutProperties","classRegistry","setClass"],"mappings":"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"}
1
+ {"version":3,"file":"Textbox.mjs","sources":["../../../src/shapes/Textbox.ts"],"sourcesContent":["import type { TClassProperties, TOptions } from '../typedefs';\nimport { IText } from './IText/IText';\nimport { classRegistry } from '../ClassRegistry';\nimport { createTextboxDefaultControls } from '../controls/commonControls';\nimport { JUSTIFY } from './Text/constants';\nimport type { TextStyleDeclaration } from './Text/StyledText';\nimport type { SerializedITextProps, ITextProps } from './IText/IText';\nimport type { ITextEvents } from './IText/ITextBehavior';\nimport type { TextLinesInfo } from './Text/Text';\nimport type { Control } from '../controls/Control';\n\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\n// regexes, list of properties that are not suppose to change by instances, magic consts.\n// this will be a separated effort\nexport const textboxDefaultValues: Partial<TClassProperties<Textbox>> = {\n minWidth: 20,\n dynamicMinWidth: 2,\n lockScalingFlip: true,\n noScaleCache: false,\n _wordJoiners: /[ \\t\\r]/,\n splitByGrapheme: false,\n};\n\nexport type GraphemeData = {\n wordsData: {\n word: string[];\n width: number;\n }[][];\n largestWordWidth: number;\n};\n\nexport type StyleMap = Record<string, { line: number; offset: number }>;\n\n// @TODO this is not complete\ninterface UniqueTextboxProps {\n minWidth: number;\n splitByGrapheme: boolean;\n dynamicMinWidth: number;\n _wordJoiners: RegExp;\n}\n\nexport interface SerializedTextboxProps\n extends\n SerializedITextProps,\n Pick<UniqueTextboxProps, 'minWidth' | 'splitByGrapheme'> {}\n\nexport interface TextboxProps extends ITextProps, UniqueTextboxProps {}\n\n/**\n * Textbox class, based on IText, allows the user to resize the text rectangle\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\n * user can only change width. Height is adjusted automatically based on the\n * wrapping of lines.\n */\nexport class Textbox<\n Props extends TOptions<TextboxProps> = Partial<TextboxProps>,\n SProps extends SerializedTextboxProps = SerializedTextboxProps,\n EventSpec extends ITextEvents = ITextEvents,\n>\n extends IText<Props, SProps, EventSpec>\n implements UniqueTextboxProps\n{\n /**\n * Minimum width of textbox, in pixels.\n * @type Number\n */\n declare minWidth: number;\n\n /**\n * Minimum calculated width of a textbox, in pixels.\n * fixed to 2 so that an empty textbox cannot go to 0\n * and is still selectable without text.\n * @type Number\n */\n declare dynamicMinWidth: number;\n\n /**\n * Use this boolean property in order to split strings that have no white space concept.\n * this is a cheap way to help with chinese/japanese\n * @type Boolean\n * @since 2.6.0\n */\n declare splitByGrapheme: boolean;\n\n declare _wordJoiners: RegExp;\n\n declare _styleMap: StyleMap;\n\n declare isWrapping: boolean;\n\n static type = 'Textbox';\n\n static textLayoutProperties = [...IText.textLayoutProperties, 'width'];\n\n static ownDefaults = textboxDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Textbox.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n */\n constructor(text: string, options?: Props) {\n super(text, { ...Textbox.ownDefaults, ...options } as Props);\n }\n\n /**\n * Creates the default control object.\n * If you prefer to have on instance of controls shared among all objects\n * make this function return an empty object and add controls to the ownDefaults object\n */\n static createControls(): { controls: Record<string, Control> } {\n return { controls: createTextboxDefaultControls() };\n }\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @private\n * @override\n */\n initDimensions() {\n if (!this.initialized) {\n return;\n }\n this.isEditing && this.initDelayedCursor();\n this._clearCache();\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n // wrap lines\n this._styleMap = this._generateStyleMap(this._splitText());\n // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n if (this.dynamicMinWidth > this.width) {\n this._set('width', this.dynamicMinWidth);\n }\n if (this.textAlign.includes(JUSTIFY)) {\n // once text is measured we need to make space fatter to make justified text.\n this.enlargeSpaces();\n }\n // clear cache and re-calculate height\n this.height = this.calcTextHeight();\n }\n\n /**\n * Generate an object that translates the style object so that it is\n * broken up by visual lines (new lines and automatic wrapping).\n * The original text styles object is broken up by actual lines (new lines only),\n * which is only sufficient for Text / IText\n * @private\n */\n _generateStyleMap(textInfo: TextLinesInfo): StyleMap {\n let realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0;\n const map: StyleMap = {};\n\n for (let i = 0; i < textInfo.graphemeLines.length; i++) {\n if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n } else if (\n !this.splitByGrapheme &&\n this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\n i > 0\n ) {\n // this case deals with space's that are removed from end of lines when wrapping\n realLineCharCount++;\n charCount++;\n }\n\n map[i] = { line: realLineCount, offset: realLineCharCount };\n\n charCount += textInfo.graphemeLines[i].length;\n realLineCharCount += textInfo.graphemeLines[i].length;\n }\n\n return map;\n }\n\n /**\n * Returns true if object has a style property or has it on a specified line\n * @param {Number} lineIndex\n * @return {Boolean}\n */\n styleHas(property: keyof TextStyleDeclaration, lineIndex: number): boolean {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (map) {\n lineIndex = map.line;\n }\n }\n return super.styleHas(property, lineIndex);\n }\n\n /**\n * Returns true if object has no styling or no styling in a line\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\n * @return {Boolean}\n */\n isEmptyStyles(lineIndex: number): boolean {\n if (!this.styles) {\n return true;\n }\n let offset = 0,\n nextLineIndex = lineIndex + 1,\n nextOffset: number,\n shouldLimit = false;\n const map = this._styleMap[lineIndex],\n mapNextLine = this._styleMap[lineIndex + 1];\n if (map) {\n lineIndex = map.line;\n offset = map.offset;\n }\n if (mapNextLine) {\n nextLineIndex = mapNextLine.line;\n shouldLimit = nextLineIndex === lineIndex;\n nextOffset = mapNextLine.offset;\n }\n const obj =\n typeof lineIndex === 'undefined'\n ? this.styles\n : { line: this.styles[lineIndex] };\n for (const p1 in obj) {\n for (const p2 in obj[p1]) {\n const p2Number = parseInt(p2, 10);\n if (p2Number >= offset && (!shouldLimit || p2Number < nextOffset!)) {\n for (const p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n }\n return true;\n }\n\n /**\n * @protected\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined\n */\n _getStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n ): TextStyleDeclaration {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (!map) {\n return {};\n }\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n return super._getStyleDeclaration(lineIndex, charIndex);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n protected _setStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n style: object,\n ) {\n const map = this._styleMap[lineIndex];\n super._setStyleDeclaration(map.line, map.offset + charIndex, style);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n protected _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\n const map = this._styleMap[lineIndex];\n super._deleteStyleDeclaration(map.line, map.offset + charIndex);\n }\n\n /**\n * probably broken need a fix\n * Returns the real style line that correspond to the wrapped lineIndex line\n * Used just to verify if the line does exist or not.\n * @param {Number} lineIndex\n * @returns {Boolean} if the line exists or not\n * @private\n */\n protected _getLineStyle(lineIndex: number): boolean {\n const map = this._styleMap[lineIndex];\n return !!this.styles[map.line];\n }\n\n /**\n * Set the line style to an empty object so that is initialized\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n protected _setLineStyle(lineIndex: number) {\n const map = this._styleMap[lineIndex];\n super._setLineStyle(map.line);\n }\n\n /**\n * Wraps text using the 'width' property of Textbox. First this function\n * splits text on newlines, so we preserve newlines entered by the user.\n * Then it wraps each line using the width of the Textbox by calling\n * _wrapLine().\n * @param {Array} lines The string array of text that is split into lines\n * @param {Number} desiredWidth width you want to wrap to\n * @returns {Array} Array of lines\n */\n _wrapText(lines: string[], desiredWidth: number): string[][] {\n this.isWrapping = true;\n // extract all thewords and the widths to optimally wrap lines.\n const data = this.getGraphemeDataForRender(lines);\n const wrapped: string[][] = [];\n for (let i = 0; i < data.wordsData.length; i++) {\n wrapped.push(...this._wrapLine(i, desiredWidth, data));\n }\n this.isWrapping = false;\n return wrapped;\n }\n\n /**\n * For each line of text terminated by an hard line stop,\n * measure each word width and extract the largest word from all.\n * The returned words here are the one that at the end will be rendered.\n * @param {string[]} lines the lines we need to measure\n *\n */\n getGraphemeDataForRender(lines: string[]): GraphemeData {\n const splitByGrapheme = this.splitByGrapheme,\n infix = splitByGrapheme ? '' : ' ';\n\n let largestWordWidth = 0;\n\n const data = lines.map((line, lineIndex) => {\n let offset = 0;\n const wordsOrGraphemes = splitByGrapheme\n ? this.graphemeSplit(line)\n : this.wordSplit(line);\n\n if (wordsOrGraphemes.length === 0) {\n return [{ word: [], width: 0 }];\n }\n\n return wordsOrGraphemes.map((word: string) => {\n // if using splitByGrapheme words are already in graphemes.\n const graphemeArray = splitByGrapheme\n ? [word]\n : this.graphemeSplit(word);\n const width = this._measureWord(graphemeArray, lineIndex, offset);\n largestWordWidth = Math.max(width, largestWordWidth);\n offset += graphemeArray.length + infix.length;\n return { word: graphemeArray, width };\n });\n });\n\n return {\n wordsData: data,\n largestWordWidth,\n };\n }\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n * It gets called when charBounds are not available yet.\n * Override if necessary\n * Use with {@link Textbox#wordSplit}\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n */\n _measureWord(word: string[], lineIndex: number, charOffset = 0): number {\n let width = 0,\n prevGrapheme;\n const skipLeft = true;\n for (let i = 0, len = word.length; i < len; i++) {\n const box = this._getGraphemeBox(\n word[i],\n lineIndex,\n i + charOffset,\n prevGrapheme,\n skipLeft,\n );\n width += box.kernedWidth;\n prevGrapheme = word[i];\n }\n return width;\n }\n\n /**\n * Override this method to customize word splitting\n * Use with {@link Textbox#_measureWord}\n * @param {string} value\n * @returns {string[]} array of words\n */\n wordSplit(value: string): string[] {\n return value.split(this._wordJoiners);\n }\n\n /**\n * Wraps a line of text using the width of the Textbox as desiredWidth\n * and leveraging the known width o words from GraphemeData\n * @private\n * @param {Number} lineIndex\n * @param {Number} desiredWidth width you want to wrap the line to\n * @param {GraphemeData} graphemeData an object containing all the lines' words width.\n * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine(\n lineIndex: number,\n desiredWidth: number,\n { largestWordWidth, wordsData }: GraphemeData,\n reservedSpace = 0,\n ): string[][] {\n const additionalSpace = this._getWidthOfCharSpacing(),\n splitByGrapheme = this.splitByGrapheme,\n graphemeLines = [],\n infix = splitByGrapheme ? '' : ' ';\n\n let lineWidth = 0,\n line: string[] = [],\n // spaces in different languages?\n offset = 0,\n infixWidth = 0,\n lineJustStarted = true;\n\n desiredWidth -= reservedSpace;\n\n const maxWidth = Math.max(\n desiredWidth,\n largestWordWidth,\n this.dynamicMinWidth,\n );\n // layout words\n const data = wordsData[lineIndex];\n offset = 0;\n let i;\n for (i = 0; i < data.length; i++) {\n const { word, width: wordWidth } = data[i];\n offset += word.length;\n\n lineWidth += infixWidth + wordWidth - additionalSpace;\n if (lineWidth > maxWidth && !lineJustStarted) {\n graphemeLines.push(line);\n line = [];\n lineWidth = wordWidth;\n lineJustStarted = true;\n } else {\n lineWidth += additionalSpace;\n }\n\n if (!lineJustStarted && !splitByGrapheme) {\n line.push(infix);\n }\n line = line.concat(word);\n\n infixWidth = splitByGrapheme\n ? 0\n : this._measureWord([infix], lineIndex, offset);\n offset++;\n lineJustStarted = false;\n }\n\n i && graphemeLines.push(line);\n\n // TODO: this code is probably not necessary anymore.\n // it can be moved out of this function since largestWordWidth is now\n // known in advance\n if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n }\n return graphemeLines;\n }\n\n /**\n * Detect if the text line is ended with an hard break\n * text and itext do not have wrapping, return false\n * @param {Number} lineIndex text to split\n * @return {Boolean}\n */\n isEndOfWrapping(lineIndex: number): boolean {\n if (!this._styleMap[lineIndex + 1]) {\n // is last line, return true;\n return true;\n }\n if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n // this is last line before a line break, return true;\n return true;\n }\n return false;\n }\n\n /**\n * Detect if a line has a linebreak and so we need to account for it when moving\n * and counting style.\n * This is important only for splitByGrapheme at the end of wrapping.\n * If we are not wrapping the offset is always 1\n * @return Number\n */\n missingNewlineOffset(lineIndex: number, skipWrapping?: boolean): 0 | 1 {\n if (this.splitByGrapheme && !skipWrapping) {\n return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n }\n return 1;\n }\n\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly every time it is called.\n * @param {String} text text to split\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines(text: string) {\n const newText = super._splitTextIntoLines(text),\n graphemeLines = this._wrapText(newText.lines, this.width),\n lines = new Array(graphemeLines.length);\n for (let i = 0; i < graphemeLines.length; i++) {\n lines[i] = graphemeLines[i].join('');\n }\n newText.lines = lines;\n newText.graphemeLines = graphemeLines;\n return newText;\n }\n\n getMinWidth() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\n }\n\n _removeExtraneousStyles() {\n const linesToKeep = new Map();\n for (const prop in this._styleMap) {\n const propNumber = parseInt(prop, 10);\n if (this._textLines[propNumber]) {\n const lineIndex = this._styleMap[prop].line;\n linesToKeep.set(`${lineIndex}`, true);\n }\n }\n for (const prop in this.styles) {\n if (!linesToKeep.has(prop)) {\n delete this.styles[prop];\n }\n }\n }\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return super.toObject<T, K>([\n 'minWidth',\n 'splitByGrapheme',\n ...propertiesToInclude,\n ] as K[]);\n }\n}\n\nclassRegistry.setClass(Textbox);\n"],"names":["textboxDefaultValues","minWidth","dynamicMinWidth","lockScalingFlip","noScaleCache","_wordJoiners","splitByGrapheme","Textbox","IText","getDefaults","ownDefaults","constructor","text","options","createControls","controls","createTextboxDefaultControls","initDimensions","initialized","isEditing","initDelayedCursor","_clearCache","_styleMap","_generateStyleMap","_splitText","width","_set","textAlign","includes","JUSTIFY","enlargeSpaces","height","calcTextHeight","textInfo","realLineCount","realLineCharCount","charCount","map","i","graphemeLines","length","graphemeText","_reSpaceAndTab","test","line","offset","styleHas","property","lineIndex","isWrapping","isEmptyStyles","styles","nextLineIndex","nextOffset","shouldLimit","mapNextLine","obj","p1","p2","p2Number","parseInt","p3","_getStyleDeclaration","charIndex","_setStyleDeclaration","style","_deleteStyleDeclaration","_getLineStyle","_setLineStyle","_wrapText","lines","desiredWidth","data","getGraphemeDataForRender","wrapped","wordsData","push","_wrapLine","infix","largestWordWidth","wordsOrGraphemes","graphemeSplit","wordSplit","word","graphemeArray","_measureWord","Math","max","charOffset","arguments","undefined","prevGrapheme","skipLeft","len","box","_getGraphemeBox","kernedWidth","value","split","_ref","reservedSpace","additionalSpace","_getWidthOfCharSpacing","lineWidth","infixWidth","lineJustStarted","maxWidth","wordWidth","concat","isEndOfWrapping","missingNewlineOffset","skipWrapping","_splitTextIntoLines","newText","Array","join","getMinWidth","_removeExtraneousStyles","linesToKeep","Map","prop","propNumber","_textLines","set","has","toObject","propertiesToInclude","_defineProperty","textLayoutProperties","classRegistry","setClass"],"mappings":";;;;;;AAWA;AACA;AACA;AACO,MAAMA,oBAAwD,GAAG;AACtEC,EAAAA,QAAQ,EAAE,EAAE;AACZC,EAAAA,eAAe,EAAE,CAAC;AAClBC,EAAAA,eAAe,EAAE,IAAI;AACrBC,EAAAA,YAAY,EAAE,KAAK;AACnBC,EAAAA,YAAY,EAAE,SAAS;AACvBC,EAAAA,eAAe,EAAE;AACnB;;AAYA;;AAeA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,OAAO,SAKVC,KAAK,CAEf;EAmCE,OAAOC,WAAWA,GAAwB;IACxC,OAAO;AACL,MAAA,GAAG,KAAK,CAACA,WAAW,EAAE;AACtB,MAAA,GAAGF,OAAO,CAACG;KACZ;AACH,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACEC,EAAAA,WAAWA,CAACC,IAAY,EAAEC,OAAe,EAAE;IACzC,KAAK,CAACD,IAAI,EAAE;MAAE,GAAGL,OAAO,CAACG,WAAW;MAAE,GAAGG;AAAQ,KAAU,CAAC;AAC9D,EAAA;;AAEA;AACF;AACA;AACA;AACA;EACE,OAAOC,cAAcA,GAA0C;IAC7D,OAAO;MAAEC,QAAQ,EAAEC,4BAA4B;KAAI;AACrD,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACEC,EAAAA,cAAcA,GAAG;AACf,IAAA,IAAI,CAAC,IAAI,CAACC,WAAW,EAAE;AACrB,MAAA;AACF,IAAA;AACA,IAAA,IAAI,CAACC,SAAS,IAAI,IAAI,CAACC,iBAAiB,EAAE;IAC1C,IAAI,CAACC,WAAW,EAAE;AAClB;IACA,IAAI,CAACnB,eAAe,GAAG,CAAC;AACxB;AACA,IAAA,IAAI,CAACoB,SAAS,GAAG,IAAI,CAACC,iBAAiB,CAAC,IAAI,CAACC,UAAU,EAAE,CAAC;AAC1D;AACA,IAAA,IAAI,IAAI,CAACtB,eAAe,GAAG,IAAI,CAACuB,KAAK,EAAE;MACrC,IAAI,CAACC,IAAI,CAAC,OAAO,EAAE,IAAI,CAACxB,eAAe,CAAC;AAC1C,IAAA;IACA,IAAI,IAAI,CAACyB,SAAS,CAACC,QAAQ,CAACC,OAAO,CAAC,EAAE;AACpC;MACA,IAAI,CAACC,aAAa,EAAE;AACtB,IAAA;AACA;AACA,IAAA,IAAI,CAACC,MAAM,GAAG,IAAI,CAACC,cAAc,EAAE;AACrC,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACA;EACET,iBAAiBA,CAACU,QAAuB,EAAY;IACnD,IAAIC,aAAa,GAAG,CAAC;AACnBC,MAAAA,iBAAiB,GAAG,CAAC;AACrBC,MAAAA,SAAS,GAAG,CAAC;IACf,MAAMC,GAAa,GAAG,EAAE;AAExB,IAAA,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGL,QAAQ,CAACM,aAAa,CAACC,MAAM,EAAEF,CAAC,EAAE,EAAE;AACtD,MAAA,IAAIL,QAAQ,CAACQ,YAAY,CAACL,SAAS,CAAC,KAAK,IAAI,IAAIE,CAAC,GAAG,CAAC,EAAE;AACtDH,QAAAA,iBAAiB,GAAG,CAAC;AACrBC,QAAAA,SAAS,EAAE;AACXF,QAAAA,aAAa,EAAE;MACjB,CAAC,MAAM,IACL,CAAC,IAAI,CAAC5B,eAAe,IACrB,IAAI,CAACoC,cAAc,CAACC,IAAI,CAACV,QAAQ,CAACQ,YAAY,CAACL,SAAS,CAAC,CAAC,IAC1DE,CAAC,GAAG,CAAC,EACL;AACA;AACAH,QAAAA,iBAAiB,EAAE;AACnBC,QAAAA,SAAS,EAAE;AACb,MAAA;MAEAC,GAAG,CAACC,CAAC,CAAC,GAAG;AAAEM,QAAAA,IAAI,EAAEV,aAAa;AAAEW,QAAAA,MAAM,EAAEV;OAAmB;MAE3DC,SAAS,IAAIH,QAAQ,CAACM,aAAa,CAACD,CAAC,CAAC,CAACE,MAAM;MAC7CL,iBAAiB,IAAIF,QAAQ,CAACM,aAAa,CAACD,CAAC,CAAC,CAACE,MAAM;AACvD,IAAA;AAEA,IAAA,OAAOH,GAAG;AACZ,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACES,EAAAA,QAAQA,CAACC,QAAoC,EAAEC,SAAiB,EAAW;IACzE,IAAI,IAAI,CAAC1B,SAAS,IAAI,CAAC,IAAI,CAAC2B,UAAU,EAAE;AACtC,MAAA,MAAMZ,GAAG,GAAG,IAAI,CAACf,SAAS,CAAC0B,SAAS,CAAC;AACrC,MAAA,IAAIX,GAAG,EAAE;QACPW,SAAS,GAAGX,GAAG,CAACO,IAAI;AACtB,MAAA;AACF,IAAA;AACA,IAAA,OAAO,KAAK,CAACE,QAAQ,CAACC,QAAQ,EAAEC,SAAS,CAAC;AAC5C,EAAA;;AAEA;AACF;AACA;AACA;AACA;EACEE,aAAaA,CAACF,SAAiB,EAAW;AACxC,IAAA,IAAI,CAAC,IAAI,CAACG,MAAM,EAAE;AAChB,MAAA,OAAO,IAAI;AACb,IAAA;IACA,IAAIN,MAAM,GAAG,CAAC;MACZO,aAAa,GAAGJ,SAAS,GAAG,CAAC;MAC7BK,UAAkB;AAClBC,MAAAA,WAAW,GAAG,KAAK;AACrB,IAAA,MAAMjB,GAAG,GAAG,IAAI,CAACf,SAAS,CAAC0B,SAAS,CAAC;MACnCO,WAAW,GAAG,IAAI,CAACjC,SAAS,CAAC0B,SAAS,GAAG,CAAC,CAAC;AAC7C,IAAA,IAAIX,GAAG,EAAE;MACPW,SAAS,GAAGX,GAAG,CAACO,IAAI;MACpBC,MAAM,GAAGR,GAAG,CAACQ,MAAM;AACrB,IAAA;AACA,IAAA,IAAIU,WAAW,EAAE;MACfH,aAAa,GAAGG,WAAW,CAACX,IAAI;MAChCU,WAAW,GAAGF,aAAa,KAAKJ,SAAS;MACzCK,UAAU,GAAGE,WAAW,CAACV,MAAM;AACjC,IAAA;IACA,MAAMW,GAAG,GACP,OAAOR,SAAS,KAAK,WAAW,GAC5B,IAAI,CAACG,MAAM,GACX;AAAEP,MAAAA,IAAI,EAAE,IAAI,CAACO,MAAM,CAACH,SAAS;KAAG;AACtC,IAAA,KAAK,MAAMS,EAAE,IAAID,GAAG,EAAE;AACpB,MAAA,KAAK,MAAME,EAAE,IAAIF,GAAG,CAACC,EAAE,CAAC,EAAE;AACxB,QAAA,MAAME,QAAQ,GAAGC,QAAQ,CAACF,EAAE,EAAE,EAAE,CAAC;QACjC,IAAIC,QAAQ,IAAId,MAAM,KAAK,CAACS,WAAW,IAAIK,QAAQ,GAAGN,UAAW,CAAC,EAAE;UAClE,KAAK,MAAMQ,EAAE,IAAIL,GAAG,CAACC,EAAE,CAAC,CAACC,EAAE,CAAC,EAAE;AAC5B,YAAA,OAAO,KAAK;AACd,UAAA;AACF,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA,OAAO,IAAI;AACb,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACEI,EAAAA,oBAAoBA,CAClBd,SAAiB,EACjBe,SAAiB,EACK;IACtB,IAAI,IAAI,CAACzC,SAAS,IAAI,CAAC,IAAI,CAAC2B,UAAU,EAAE;AACtC,MAAA,MAAMZ,GAAG,GAAG,IAAI,CAACf,SAAS,CAAC0B,SAAS,CAAC;MACrC,IAAI,CAACX,GAAG,EAAE;AACR,QAAA,OAAO,EAAE;AACX,MAAA;MACAW,SAAS,GAAGX,GAAG,CAACO,IAAI;AACpBmB,MAAAA,SAAS,GAAG1B,GAAG,CAACQ,MAAM,GAAGkB,SAAS;AACpC,IAAA;AACA,IAAA,OAAO,KAAK,CAACD,oBAAoB,CAACd,SAAS,EAAEe,SAAS,CAAC;AACzD,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACYC,EAAAA,oBAAoBA,CAC5BhB,SAAiB,EACjBe,SAAiB,EACjBE,KAAa,EACb;AACA,IAAA,MAAM5B,GAAG,GAAG,IAAI,CAACf,SAAS,CAAC0B,SAAS,CAAC;AACrC,IAAA,KAAK,CAACgB,oBAAoB,CAAC3B,GAAG,CAACO,IAAI,EAAEP,GAAG,CAACQ,MAAM,GAAGkB,SAAS,EAAEE,KAAK,CAAC;AACrE,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACYC,EAAAA,uBAAuBA,CAAClB,SAAiB,EAAEe,SAAiB,EAAE;AACtE,IAAA,MAAM1B,GAAG,GAAG,IAAI,CAACf,SAAS,CAAC0B,SAAS,CAAC;AACrC,IAAA,KAAK,CAACkB,uBAAuB,CAAC7B,GAAG,CAACO,IAAI,EAAEP,GAAG,CAACQ,MAAM,GAAGkB,SAAS,CAAC;AACjE,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACYI,aAAaA,CAACnB,SAAiB,EAAW;AAClD,IAAA,MAAMX,GAAG,GAAG,IAAI,CAACf,SAAS,CAAC0B,SAAS,CAAC;IACrC,OAAO,CAAC,CAAC,IAAI,CAACG,MAAM,CAACd,GAAG,CAACO,IAAI,CAAC;AAChC,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;EACYwB,aAAaA,CAACpB,SAAiB,EAAE;AACzC,IAAA,MAAMX,GAAG,GAAG,IAAI,CAACf,SAAS,CAAC0B,SAAS,CAAC;AACrC,IAAA,KAAK,CAACoB,aAAa,CAAC/B,GAAG,CAACO,IAAI,CAAC;AAC/B,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACEyB,EAAAA,SAASA,CAACC,KAAe,EAAEC,YAAoB,EAAc;IAC3D,IAAI,CAACtB,UAAU,GAAG,IAAI;AACtB;AACA,IAAA,MAAMuB,IAAI,GAAG,IAAI,CAACC,wBAAwB,CAACH,KAAK,CAAC;IACjD,MAAMI,OAAmB,GAAG,EAAE;AAC9B,IAAA,KAAK,IAAIpC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGkC,IAAI,CAACG,SAAS,CAACnC,MAAM,EAAEF,CAAC,EAAE,EAAE;AAC9CoC,MAAAA,OAAO,CAACE,IAAI,CAAC,GAAG,IAAI,CAACC,SAAS,CAACvC,CAAC,EAAEiC,YAAY,EAAEC,IAAI,CAAC,CAAC;AACxD,IAAA;IACA,IAAI,CAACvB,UAAU,GAAG,KAAK;AACvB,IAAA,OAAOyB,OAAO;AAChB,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACA;EACED,wBAAwBA,CAACH,KAAe,EAAgB;AACtD,IAAA,MAAMhE,eAAe,GAAG,IAAI,CAACA,eAAe;AAC1CwE,MAAAA,KAAK,GAAGxE,eAAe,GAAG,EAAE,GAAG,GAAG;IAEpC,IAAIyE,gBAAgB,GAAG,CAAC;IAExB,MAAMP,IAAI,GAAGF,KAAK,CAACjC,GAAG,CAAC,CAACO,IAAI,EAAEI,SAAS,KAAK;MAC1C,IAAIH,MAAM,GAAG,CAAC;AACd,MAAA,MAAMmC,gBAAgB,GAAG1E,eAAe,GACpC,IAAI,CAAC2E,aAAa,CAACrC,IAAI,CAAC,GACxB,IAAI,CAACsC,SAAS,CAACtC,IAAI,CAAC;AAExB,MAAA,IAAIoC,gBAAgB,CAACxC,MAAM,KAAK,CAAC,EAAE;AACjC,QAAA,OAAO,CAAC;AAAE2C,UAAAA,IAAI,EAAE,EAAE;AAAE1D,UAAAA,KAAK,EAAE;AAAE,SAAC,CAAC;AACjC,MAAA;AAEA,MAAA,OAAOuD,gBAAgB,CAAC3C,GAAG,CAAE8C,IAAY,IAAK;AAC5C;AACA,QAAA,MAAMC,aAAa,GAAG9E,eAAe,GACjC,CAAC6E,IAAI,CAAC,GACN,IAAI,CAACF,aAAa,CAACE,IAAI,CAAC;QAC5B,MAAM1D,KAAK,GAAG,IAAI,CAAC4D,YAAY,CAACD,aAAa,EAAEpC,SAAS,EAAEH,MAAM,CAAC;QACjEkC,gBAAgB,GAAGO,IAAI,CAACC,GAAG,CAAC9D,KAAK,EAAEsD,gBAAgB,CAAC;AACpDlC,QAAAA,MAAM,IAAIuC,aAAa,CAAC5C,MAAM,GAAGsC,KAAK,CAACtC,MAAM;QAC7C,OAAO;AAAE2C,UAAAA,IAAI,EAAEC,aAAa;AAAE3D,UAAAA;SAAO;AACvC,MAAA,CAAC,CAAC;AACJ,IAAA,CAAC,CAAC;IAEF,OAAO;AACLkD,MAAAA,SAAS,EAAEH,IAAI;AACfO,MAAAA;KACD;AACH,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACEM,EAAAA,YAAYA,CAACF,IAAc,EAAEnC,SAAiB,EAA0B;AAAA,IAAA,IAAxBwC,UAAU,GAAAC,SAAA,CAAAjD,MAAA,GAAA,CAAA,IAAAiD,SAAA,CAAA,CAAA,CAAA,KAAAC,SAAA,GAAAD,SAAA,CAAA,CAAA,CAAA,GAAG,CAAC;IAC5D,IAAIhE,KAAK,GAAG,CAAC;MACXkE,YAAY;IACd,MAAMC,QAAQ,GAAG,IAAI;AACrB,IAAA,KAAK,IAAItD,CAAC,GAAG,CAAC,EAAEuD,GAAG,GAAGV,IAAI,CAAC3C,MAAM,EAAEF,CAAC,GAAGuD,GAAG,EAAEvD,CAAC,EAAE,EAAE;MAC/C,MAAMwD,GAAG,GAAG,IAAI,CAACC,eAAe,CAC9BZ,IAAI,CAAC7C,CAAC,CAAC,EACPU,SAAS,EACTV,CAAC,GAAGkD,UAAU,EACdG,YAAY,EACZC,QACF,CAAC;MACDnE,KAAK,IAAIqE,GAAG,CAACE,WAAW;AACxBL,MAAAA,YAAY,GAAGR,IAAI,CAAC7C,CAAC,CAAC;AACxB,IAAA;AACA,IAAA,OAAOb,KAAK;AACd,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;EACEyD,SAASA,CAACe,KAAa,EAAY;AACjC,IAAA,OAAOA,KAAK,CAACC,KAAK,CAAC,IAAI,CAAC7F,YAAY,CAAC;AACvC,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACEwE,EAAAA,SAASA,CACP7B,SAAiB,EACjBuB,YAAoB,EAAA4B,IAAA,EAGR;IAAA,IAFZ;MAAEpB,gBAAgB;AAAEJ,MAAAA;AAAwB,KAAC,GAAAwB,IAAA;AAAA,IAAA,IAC7CC,aAAa,GAAAX,SAAA,CAAAjD,MAAA,GAAA,CAAA,IAAAiD,SAAA,CAAA,CAAA,CAAA,KAAAC,SAAA,GAAAD,SAAA,CAAA,CAAA,CAAA,GAAG,CAAC;AAEjB,IAAA,MAAMY,eAAe,GAAG,IAAI,CAACC,sBAAsB,EAAE;MACnDhG,eAAe,GAAG,IAAI,CAACA,eAAe;AACtCiC,MAAAA,aAAa,GAAG,EAAE;AAClBuC,MAAAA,KAAK,GAAGxE,eAAe,GAAG,EAAE,GAAG,GAAG;IAEpC,IAAIiG,SAAS,GAAG,CAAC;AACf3D,MAAAA,IAAc,GAAG,EAAE;AACnB;AACAC,MAAAA,MAAM,GAAG,CAAC;AACV2D,MAAAA,UAAU,GAAG,CAAC;AACdC,MAAAA,eAAe,GAAG,IAAI;AAExBlC,IAAAA,YAAY,IAAI6B,aAAa;AAE7B,IAAA,MAAMM,QAAQ,GAAGpB,IAAI,CAACC,GAAG,CACvBhB,YAAY,EACZQ,gBAAgB,EAChB,IAAI,CAAC7E,eACP,CAAC;AACD;AACA,IAAA,MAAMsE,IAAI,GAAGG,SAAS,CAAC3B,SAAS,CAAC;AACjCH,IAAAA,MAAM,GAAG,CAAC;AACV,IAAA,IAAIP,CAAC;AACL,IAAA,KAAKA,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGkC,IAAI,CAAChC,MAAM,EAAEF,CAAC,EAAE,EAAE;MAChC,MAAM;QAAE6C,IAAI;AAAE1D,QAAAA,KAAK,EAAEkF;AAAU,OAAC,GAAGnC,IAAI,CAAClC,CAAC,CAAC;MAC1CO,MAAM,IAAIsC,IAAI,CAAC3C,MAAM;AAErB+D,MAAAA,SAAS,IAAIC,UAAU,GAAGG,SAAS,GAAGN,eAAe;AACrD,MAAA,IAAIE,SAAS,GAAGG,QAAQ,IAAI,CAACD,eAAe,EAAE;AAC5ClE,QAAAA,aAAa,CAACqC,IAAI,CAAChC,IAAI,CAAC;AACxBA,QAAAA,IAAI,GAAG,EAAE;AACT2D,QAAAA,SAAS,GAAGI,SAAS;AACrBF,QAAAA,eAAe,GAAG,IAAI;AACxB,MAAA,CAAC,MAAM;AACLF,QAAAA,SAAS,IAAIF,eAAe;AAC9B,MAAA;AAEA,MAAA,IAAI,CAACI,eAAe,IAAI,CAACnG,eAAe,EAAE;AACxCsC,QAAAA,IAAI,CAACgC,IAAI,CAACE,KAAK,CAAC;AAClB,MAAA;AACAlC,MAAAA,IAAI,GAAGA,IAAI,CAACgE,MAAM,CAACzB,IAAI,CAAC;AAExBqB,MAAAA,UAAU,GAAGlG,eAAe,GACxB,CAAC,GACD,IAAI,CAAC+E,YAAY,CAAC,CAACP,KAAK,CAAC,EAAE9B,SAAS,EAAEH,MAAM,CAAC;AACjDA,MAAAA,MAAM,EAAE;AACR4D,MAAAA,eAAe,GAAG,KAAK;AACzB,IAAA;AAEAnE,IAAAA,CAAC,IAAIC,aAAa,CAACqC,IAAI,CAAChC,IAAI,CAAC;;AAE7B;AACA;AACA;AACA,IAAA,IAAImC,gBAAgB,GAAGqB,aAAa,GAAG,IAAI,CAAClG,eAAe,EAAE;AAC3D,MAAA,IAAI,CAACA,eAAe,GAAG6E,gBAAgB,GAAGsB,eAAe,GAAGD,aAAa;AAC3E,IAAA;AACA,IAAA,OAAO7D,aAAa;AACtB,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;EACEsE,eAAeA,CAAC7D,SAAiB,EAAW;IAC1C,IAAI,CAAC,IAAI,CAAC1B,SAAS,CAAC0B,SAAS,GAAG,CAAC,CAAC,EAAE;AAClC;AACA,MAAA,OAAO,IAAI;AACb,IAAA;AACA,IAAA,IAAI,IAAI,CAAC1B,SAAS,CAAC0B,SAAS,GAAG,CAAC,CAAC,CAACJ,IAAI,KAAK,IAAI,CAACtB,SAAS,CAAC0B,SAAS,CAAC,CAACJ,IAAI,EAAE;AACzE;AACA,MAAA,OAAO,IAAI;AACb,IAAA;AACA,IAAA,OAAO,KAAK;AACd,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACEkE,EAAAA,oBAAoBA,CAAC9D,SAAiB,EAAE+D,YAAsB,EAAS;AACrE,IAAA,IAAI,IAAI,CAACzG,eAAe,IAAI,CAACyG,YAAY,EAAE;MACzC,OAAO,IAAI,CAACF,eAAe,CAAC7D,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC;AAChD,IAAA;AACA,IAAA,OAAO,CAAC;AACV,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACA;EACEgE,mBAAmBA,CAACpG,IAAY,EAAE;AAChC,IAAA,MAAMqG,OAAO,GAAG,KAAK,CAACD,mBAAmB,CAACpG,IAAI,CAAC;AAC7C2B,MAAAA,aAAa,GAAG,IAAI,CAAC8B,SAAS,CAAC4C,OAAO,CAAC3C,KAAK,EAAE,IAAI,CAAC7C,KAAK,CAAC;AACzD6C,MAAAA,KAAK,GAAG,IAAI4C,KAAK,CAAC3E,aAAa,CAACC,MAAM,CAAC;AACzC,IAAA,KAAK,IAAIF,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGC,aAAa,CAACC,MAAM,EAAEF,CAAC,EAAE,EAAE;AAC7CgC,MAAAA,KAAK,CAAChC,CAAC,CAAC,GAAGC,aAAa,CAACD,CAAC,CAAC,CAAC6E,IAAI,CAAC,EAAE,CAAC;AACtC,IAAA;IACAF,OAAO,CAAC3C,KAAK,GAAGA,KAAK;IACrB2C,OAAO,CAAC1E,aAAa,GAAGA,aAAa;AACrC,IAAA,OAAO0E,OAAO;AAChB,EAAA;AAEAG,EAAAA,WAAWA,GAAG;IACZ,OAAO9B,IAAI,CAACC,GAAG,CAAC,IAAI,CAACtF,QAAQ,EAAE,IAAI,CAACC,eAAe,CAAC;AACtD,EAAA;AAEAmH,EAAAA,uBAAuBA,GAAG;AACxB,IAAA,MAAMC,WAAW,GAAG,IAAIC,GAAG,EAAE;AAC7B,IAAA,KAAK,MAAMC,IAAI,IAAI,IAAI,CAAClG,SAAS,EAAE;AACjC,MAAA,MAAMmG,UAAU,GAAG7D,QAAQ,CAAC4D,IAAI,EAAE,EAAE,CAAC;AACrC,MAAA,IAAI,IAAI,CAACE,UAAU,CAACD,UAAU,CAAC,EAAE;QAC/B,MAAMzE,SAAS,GAAG,IAAI,CAAC1B,SAAS,CAACkG,IAAI,CAAC,CAAC5E,IAAI;QAC3C0E,WAAW,CAACK,GAAG,CAAC,CAAA,EAAG3E,SAAS,CAAA,CAAE,EAAE,IAAI,CAAC;AACvC,MAAA;AACF,IAAA;AACA,IAAA,KAAK,MAAMwE,IAAI,IAAI,IAAI,CAACrE,MAAM,EAAE;AAC9B,MAAA,IAAI,CAACmE,WAAW,CAACM,GAAG,CAACJ,IAAI,CAAC,EAAE;AAC1B,QAAA,OAAO,IAAI,CAACrE,MAAM,CAACqE,IAAI,CAAC;AAC1B,MAAA;AACF,IAAA;AACF,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACEK,EAAAA,QAAQA,GAG8C;AAAA,IAAA,IAApDC,mBAAwB,GAAArC,SAAA,CAAAjD,MAAA,GAAA,CAAA,IAAAiD,SAAA,CAAA,CAAA,CAAA,KAAAC,SAAA,GAAAD,SAAA,CAAA,CAAA,CAAA,GAAG,EAAE;AAC7B,IAAA,OAAO,KAAK,CAACoC,QAAQ,CAAO,CAC1B,UAAU,EACV,iBAAiB,EACjB,GAAGC,mBAAmB,CAChB,CAAC;AACX,EAAA;AACF;AAngBE;AACF;AACA;AACA;AAGE;AACF;AACA;AACA;AACA;AACA;AAGE;AACF;AACA;AACA;AACA;AACA;AALEC,eAAA,CAtBWxH,OAAO,EAAA,MAAA,EAoCJ,SAAS,CAAA;AAAAwH,eAAA,CApCZxH,OAAO,EAAA,sBAAA,EAsCY,CAAC,GAAGC,KAAK,CAACwH,oBAAoB,EAAE,OAAO,CAAC,CAAA;AAAAD,eAAA,CAtC3DxH,OAAO,EAAA,aAAA,EAwCGP,oBAAoB,CAAA;AAqe3CiI,aAAa,CAACC,QAAQ,CAAC3H,OAAO,CAAC;;;;"}