@nasser-sw/fabric 7.0.1-beta8 → 7.0.1-beta9

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 (138) hide show
  1. package/debug/konva-master/CHANGELOG.md +1475 -0
  2. package/debug/konva-master/LICENSE +22 -0
  3. package/debug/konva-master/README.md +209 -0
  4. package/debug/konva-master/gulpfile.mjs +110 -0
  5. package/debug/konva-master/package.json +139 -0
  6. package/debug/konva-master/release.sh +62 -0
  7. package/debug/konva-master/resources/doc-includes/ContainerParams.txt +6 -0
  8. package/debug/konva-master/resources/doc-includes/NodeParams.txt +20 -0
  9. package/debug/konva-master/resources/doc-includes/ShapeParams.txt +53 -0
  10. package/debug/konva-master/resources/jsdoc.conf.json +28 -0
  11. package/debug/konva-master/rollup.config.mjs +32 -0
  12. package/debug/konva-master/src/Animation.ts +237 -0
  13. package/debug/konva-master/src/BezierFunctions.ts +826 -0
  14. package/debug/konva-master/src/Canvas.ts +230 -0
  15. package/debug/konva-master/src/Container.ts +649 -0
  16. package/debug/konva-master/src/Context.ts +1017 -0
  17. package/debug/konva-master/src/Core.ts +5 -0
  18. package/debug/konva-master/src/DragAndDrop.ts +173 -0
  19. package/debug/konva-master/src/Factory.ts +246 -0
  20. package/debug/konva-master/src/FastLayer.ts +29 -0
  21. package/debug/konva-master/src/Global.ts +210 -0
  22. package/debug/konva-master/src/Group.ts +31 -0
  23. package/debug/konva-master/src/Layer.ts +546 -0
  24. package/debug/konva-master/src/Node.ts +3477 -0
  25. package/debug/konva-master/src/PointerEvents.ts +67 -0
  26. package/debug/konva-master/src/Shape.ts +2081 -0
  27. package/debug/konva-master/src/Stage.ts +1000 -0
  28. package/debug/konva-master/src/Tween.ts +811 -0
  29. package/debug/konva-master/src/Util.ts +1123 -0
  30. package/debug/konva-master/src/Validators.ts +210 -0
  31. package/debug/konva-master/src/_CoreInternals.ts +85 -0
  32. package/debug/konva-master/src/_FullInternals.ts +171 -0
  33. package/debug/konva-master/src/canvas-backend.ts +36 -0
  34. package/debug/konva-master/src/filters/Blur.ts +388 -0
  35. package/debug/konva-master/src/filters/Brighten.ts +48 -0
  36. package/debug/konva-master/src/filters/Brightness.ts +30 -0
  37. package/debug/konva-master/src/filters/Contrast.ts +75 -0
  38. package/debug/konva-master/src/filters/Emboss.ts +207 -0
  39. package/debug/konva-master/src/filters/Enhance.ts +154 -0
  40. package/debug/konva-master/src/filters/Grayscale.ts +25 -0
  41. package/debug/konva-master/src/filters/HSL.ts +108 -0
  42. package/debug/konva-master/src/filters/HSV.ts +106 -0
  43. package/debug/konva-master/src/filters/Invert.ts +23 -0
  44. package/debug/konva-master/src/filters/Kaleidoscope.ts +274 -0
  45. package/debug/konva-master/src/filters/Mask.ts +220 -0
  46. package/debug/konva-master/src/filters/Noise.ts +44 -0
  47. package/debug/konva-master/src/filters/Pixelate.ts +107 -0
  48. package/debug/konva-master/src/filters/Posterize.ts +46 -0
  49. package/debug/konva-master/src/filters/RGB.ts +82 -0
  50. package/debug/konva-master/src/filters/RGBA.ts +103 -0
  51. package/debug/konva-master/src/filters/Sepia.ts +27 -0
  52. package/debug/konva-master/src/filters/Solarize.ts +29 -0
  53. package/debug/konva-master/src/filters/Threshold.ts +44 -0
  54. package/debug/konva-master/src/index.ts +3 -0
  55. package/debug/konva-master/src/shapes/Arc.ts +176 -0
  56. package/debug/konva-master/src/shapes/Arrow.ts +231 -0
  57. package/debug/konva-master/src/shapes/Circle.ts +76 -0
  58. package/debug/konva-master/src/shapes/Ellipse.ts +121 -0
  59. package/debug/konva-master/src/shapes/Image.ts +319 -0
  60. package/debug/konva-master/src/shapes/Label.ts +386 -0
  61. package/debug/konva-master/src/shapes/Line.ts +364 -0
  62. package/debug/konva-master/src/shapes/Path.ts +1013 -0
  63. package/debug/konva-master/src/shapes/Rect.ts +79 -0
  64. package/debug/konva-master/src/shapes/RegularPolygon.ts +167 -0
  65. package/debug/konva-master/src/shapes/Ring.ts +94 -0
  66. package/debug/konva-master/src/shapes/Sprite.ts +370 -0
  67. package/debug/konva-master/src/shapes/Star.ts +125 -0
  68. package/debug/konva-master/src/shapes/Text.ts +1065 -0
  69. package/debug/konva-master/src/shapes/TextPath.ts +583 -0
  70. package/debug/konva-master/src/shapes/Transformer.ts +1889 -0
  71. package/debug/konva-master/src/shapes/Wedge.ts +129 -0
  72. package/debug/konva-master/src/skia-backend.ts +35 -0
  73. package/debug/konva-master/src/types.ts +84 -0
  74. package/debug/konva-master/tsconfig.json +31 -0
  75. package/debug/konva-master/tsconfig.test.json +7 -0
  76. package/dist/index.js +915 -23
  77. package/dist/index.js.map +1 -1
  78. package/dist/index.min.js +1 -1
  79. package/dist/index.min.js.map +1 -1
  80. package/dist/index.min.mjs +1 -1
  81. package/dist/index.min.mjs.map +1 -1
  82. package/dist/index.mjs +915 -23
  83. package/dist/index.mjs.map +1 -1
  84. package/dist/index.node.cjs +915 -23
  85. package/dist/index.node.cjs.map +1 -1
  86. package/dist/index.node.mjs +915 -23
  87. package/dist/index.node.mjs.map +1 -1
  88. package/dist/package.json.min.mjs +1 -1
  89. package/dist/package.json.mjs +1 -1
  90. package/dist/src/shapes/Text/Text.d.ts +19 -0
  91. package/dist/src/shapes/Text/Text.d.ts.map +1 -1
  92. package/dist/src/shapes/Text/Text.min.mjs +1 -1
  93. package/dist/src/shapes/Text/Text.min.mjs.map +1 -1
  94. package/dist/src/shapes/Text/Text.mjs +238 -4
  95. package/dist/src/shapes/Text/Text.mjs.map +1 -1
  96. package/dist/src/shapes/Textbox.d.ts +38 -1
  97. package/dist/src/shapes/Textbox.d.ts.map +1 -1
  98. package/dist/src/shapes/Textbox.min.mjs +1 -1
  99. package/dist/src/shapes/Textbox.min.mjs.map +1 -1
  100. package/dist/src/shapes/Textbox.mjs +497 -15
  101. package/dist/src/shapes/Textbox.mjs.map +1 -1
  102. package/dist/src/text/examples/arabicTextExample.d.ts +60 -0
  103. package/dist/src/text/examples/arabicTextExample.d.ts.map +1 -0
  104. package/dist/src/text/measure.d.ts +9 -0
  105. package/dist/src/text/measure.d.ts.map +1 -1
  106. package/dist/src/text/measure.min.mjs +1 -1
  107. package/dist/src/text/measure.min.mjs.map +1 -1
  108. package/dist/src/text/measure.mjs +175 -4
  109. package/dist/src/text/measure.mjs.map +1 -1
  110. package/dist/src/text/overlayEditor.d.ts.map +1 -1
  111. package/dist/src/text/overlayEditor.min.mjs +1 -1
  112. package/dist/src/text/overlayEditor.min.mjs.map +1 -1
  113. package/dist/src/text/overlayEditor.mjs +7 -0
  114. package/dist/src/text/overlayEditor.mjs.map +1 -1
  115. package/dist/src/text/scriptUtils.d.ts +142 -0
  116. package/dist/src/text/scriptUtils.d.ts.map +1 -0
  117. package/dist/src/text/scriptUtils.min.mjs +2 -0
  118. package/dist/src/text/scriptUtils.min.mjs.map +1 -0
  119. package/dist/src/text/scriptUtils.mjs +212 -0
  120. package/dist/src/text/scriptUtils.mjs.map +1 -0
  121. package/dist-extensions/src/shapes/Text/Text.d.ts +19 -0
  122. package/dist-extensions/src/shapes/Text/Text.d.ts.map +1 -1
  123. package/dist-extensions/src/shapes/Textbox.d.ts +38 -1
  124. package/dist-extensions/src/shapes/Textbox.d.ts.map +1 -1
  125. package/dist-extensions/src/text/measure.d.ts +9 -0
  126. package/dist-extensions/src/text/measure.d.ts.map +1 -1
  127. package/dist-extensions/src/text/overlayEditor.d.ts.map +1 -1
  128. package/dist-extensions/src/text/scriptUtils.d.ts +142 -0
  129. package/dist-extensions/src/text/scriptUtils.d.ts.map +1 -0
  130. package/fabric-test-editor.html +2401 -46
  131. package/fonts/STV Bold.ttf +0 -0
  132. package/fonts/STV Light.ttf +0 -0
  133. package/fonts/STV Regular.ttf +0 -0
  134. package/package.json +1 -1
  135. package/src/shapes/Text/Text.ts +238 -5
  136. package/src/shapes/Textbox.ts +521 -11
  137. package/src/text/measure.ts +200 -50
  138. package/src/text/overlayEditor.ts +7 -0
@@ -1 +1 @@
1
- {"version":3,"file":"Textbox.mjs","sources":["../../../src/shapes/Textbox.ts"],"sourcesContent":["import type { TClassProperties, TOptions } from '../typedefs';\r\nimport { IText } from './IText/IText';\r\nimport { classRegistry } from '../ClassRegistry';\r\nimport { createTextboxDefaultControls } from '../controls/commonControls';\r\nimport { JUSTIFY, JUSTIFY_CENTER } from './Text/constants';\r\nimport type { TextStyleDeclaration } from './Text/StyledText';\r\nimport type { SerializedITextProps, ITextProps } from './IText/IText';\r\nimport type { ITextEvents } from './IText/ITextBehavior';\r\nimport type { TextLinesInfo } from './Text/Text';\r\nimport type { Control } from '../controls/Control';\r\nimport { layoutText } from '../text/layout';\r\n\r\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\r\n// regexes, list of properties that are not suppose to change by instances, magic consts.\r\n// this will be a separated effort\r\nexport const textboxDefaultValues: Partial<TClassProperties<Textbox>> = {\r\n minWidth: 20,\r\n dynamicMinWidth: 2,\r\n lockScalingFlip: true,\r\n noScaleCache: false,\r\n _wordJoiners: /[ \\t\\r]/,\r\n splitByGrapheme: false,\r\n};\r\n\r\nexport type GraphemeData = {\r\n wordsData: {\r\n word: string[];\r\n width: number;\r\n }[][];\r\n largestWordWidth: number;\r\n};\r\n\r\nexport type StyleMap = Record<string, { line: number; offset: number }>;\r\n\r\n// @TODO this is not complete\r\ninterface UniqueTextboxProps {\r\n minWidth: number;\r\n splitByGrapheme: boolean;\r\n dynamicMinWidth: number;\r\n _wordJoiners: RegExp;\r\n}\r\n\r\nexport interface SerializedTextboxProps\r\n extends SerializedITextProps,\r\n Pick<UniqueTextboxProps, 'minWidth' | 'splitByGrapheme'> {}\r\n\r\nexport interface TextboxProps extends ITextProps, UniqueTextboxProps {}\r\n\r\n/**\r\n * Textbox class, based on IText, allows the user to resize the text rectangle\r\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\r\n * user can only change width. Height is adjusted automatically based on the\r\n * wrapping of lines.\r\n */\r\nexport class Textbox<\r\n Props extends TOptions<TextboxProps> = Partial<TextboxProps>,\r\n SProps extends SerializedTextboxProps = SerializedTextboxProps,\r\n EventSpec extends ITextEvents = ITextEvents,\r\n >\r\n extends IText<Props, SProps, EventSpec>\r\n implements UniqueTextboxProps\r\n{\r\n /**\r\n * Minimum width of textbox, in pixels.\r\n * @type Number\r\n */\r\n declare minWidth: number;\r\n\r\n /**\r\n * Minimum calculated width of a textbox, in pixels.\r\n * fixed to 2 so that an empty textbox cannot go to 0\r\n * and is still selectable without text.\r\n * @type Number\r\n */\r\n declare dynamicMinWidth: number;\r\n\r\n /**\r\n * Use this boolean property in order to split strings that have no white space concept.\r\n * this is a cheap way to help with chinese/japanese\r\n * @type Boolean\r\n * @since 2.6.0\r\n */\r\n declare splitByGrapheme: boolean;\r\n\r\n declare _wordJoiners: RegExp;\r\n\r\n declare _styleMap: StyleMap;\r\n\r\n declare isWrapping: boolean;\r\n\r\n static type = 'Textbox';\r\n\r\n static textLayoutProperties = [...IText.textLayoutProperties, 'width'];\r\n\r\n static ownDefaults = textboxDefaultValues;\r\n\r\n static getDefaults(): Record<string, any> {\r\n return {\r\n ...super.getDefaults(),\r\n ...Textbox.ownDefaults,\r\n };\r\n }\r\n\r\n /**\r\n * Constructor\r\n * @param {String} text Text string\r\n * @param {Object} [options] Options object\r\n */\r\n constructor(text: string, options?: Props) {\r\n super(text, { ...Textbox.ownDefaults, ...options } as Props);\r\n this.initializeEventListeners();\r\n }\r\n\r\n /**\r\n * Creates the default control object.\r\n * If you prefer to have on instance of controls shared among all objects\r\n * make this function return an empty object and add controls to the ownDefaults object\r\n */\r\n static createControls(): { controls: Record<string, Control> } {\r\n return { controls: createTextboxDefaultControls() };\r\n }\r\n\r\n /**\r\n * Unlike superclass's version of this function, Textbox does not update\r\n * its width.\r\n * @private\r\n * @override\r\n */\r\n initDimensions() {\r\n if (!this.initialized) {\r\n return;\r\n }\r\n \r\n // Use advanced layout if enabled\r\n if (this.enableAdvancedLayout) {\r\n return this.initDimensionsAdvanced();\r\n }\r\n \r\n this.isEditing && this.initDelayedCursor();\r\n this._clearCache();\r\n // clear dynamicMinWidth as it will be different after we re-wrap line\r\n this.dynamicMinWidth = 0;\r\n // wrap lines\r\n this._styleMap = this._generateStyleMap(this._splitText());\r\n // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\r\n if (this.dynamicMinWidth > this.width) {\r\n this._set('width', this.dynamicMinWidth);\r\n }\r\n if (this.textAlign.includes(JUSTIFY)) {\r\n // once text is measured we need to make space fatter to make justified text.\r\n this.enlargeSpaces();\r\n }\r\n // clear cache and re-calculate height\r\n this.height = this.calcTextHeight();\r\n }\r\n\r\n /**\r\n * Advanced dimensions calculation using new layout engine\r\n * @private\r\n */\r\n initDimensionsAdvanced() {\r\n if (!this.initialized) {\r\n return;\r\n }\r\n \r\n this.isEditing && this.initDelayedCursor();\r\n this._clearCache();\r\n this.dynamicMinWidth = 0;\r\n \r\n // Use new layout engine\r\n const layout = layoutText({\r\n text: this.text,\r\n width: this.width,\r\n height: this.height,\r\n wrap: this.wrap || 'word',\r\n align: (this as any)._mapTextAlignToAlign(this.textAlign),\r\n ellipsis: this.ellipsis || false,\r\n fontSize: this.fontSize,\r\n lineHeight: this.lineHeight,\r\n letterSpacing: this.letterSpacing || 0,\r\n charSpacing: this.charSpacing,\r\n direction: this.direction === 'inherit' ? 'ltr' : this.direction,\r\n fontFamily: this.fontFamily,\r\n fontStyle: this.fontStyle,\r\n fontWeight: this.fontWeight,\r\n verticalAlign: this.verticalAlign || 'top',\r\n });\r\n \r\n // Update dynamic minimum width based on layout\r\n if (layout.lines.length > 0) {\r\n const maxLineWidth = Math.max(...layout.lines.map(line => line.width));\r\n this.dynamicMinWidth = Math.max(this.minWidth, maxLineWidth);\r\n }\r\n \r\n // Adjust width if needed (preserving Textbox behavior)\r\n if (this.dynamicMinWidth > this.width) {\r\n this._set('width', this.dynamicMinWidth);\r\n // Re-layout with new width\r\n const newLayout = layoutText({\r\n ...(this as any)._getAdvancedLayoutOptions(),\r\n width: this.width,\r\n });\r\n this.height = newLayout.totalHeight;\r\n (this as any)._convertLayoutToLegacyFormat(newLayout);\r\n } else {\r\n this.height = layout.totalHeight;\r\n (this as any)._convertLayoutToLegacyFormat(layout);\r\n }\r\n \r\n // Generate style map for compatibility\r\n this._styleMap = this._generateStyleMapFromLayout(layout);\r\n this.dirty = true;\r\n }\r\n\r\n /**\r\n * Generate style map from new layout format\r\n * @private\r\n */\r\n _generateStyleMapFromLayout(layout: any): StyleMap {\r\n const map: StyleMap = {};\r\n let realLineCount = 0;\r\n let charCount = 0;\r\n\r\n layout.lines.forEach((line: any, i: number) => {\r\n if (line.text.includes('\\n') && i > 0) {\r\n realLineCount++;\r\n }\r\n \r\n map[i] = { line: realLineCount, offset: 0 };\r\n charCount += line.graphemes.length;\r\n \r\n if (i < layout.lines.length - 1) {\r\n charCount += 1; // newline character\r\n }\r\n });\r\n\r\n return map;\r\n }\r\n\r\n /**\r\n * Generate an object that translates the style object so that it is\r\n * broken up by visual lines (new lines and automatic wrapping).\r\n * The original text styles object is broken up by actual lines (new lines only),\r\n * which is only sufficient for Text / IText\r\n * @private\r\n */\r\n _generateStyleMap(textInfo: TextLinesInfo): StyleMap {\r\n let realLineCount = 0,\r\n realLineCharCount = 0,\r\n charCount = 0;\r\n const map: StyleMap = {};\r\n\r\n for (let i = 0; i < textInfo.graphemeLines.length; i++) {\r\n if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\r\n realLineCharCount = 0;\r\n charCount++;\r\n realLineCount++;\r\n } else if (\r\n !this.splitByGrapheme &&\r\n this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\r\n i > 0\r\n ) {\r\n // this case deals with space's that are removed from end of lines when wrapping\r\n realLineCharCount++;\r\n charCount++;\r\n }\r\n\r\n map[i] = { line: realLineCount, offset: realLineCharCount };\r\n\r\n charCount += textInfo.graphemeLines[i].length;\r\n realLineCharCount += textInfo.graphemeLines[i].length;\r\n }\r\n\r\n return map;\r\n }\r\n\r\n /**\r\n * Returns true if object has a style property or has it on a specified line\r\n * @param {Number} lineIndex\r\n * @return {Boolean}\r\n */\r\n styleHas(property: keyof TextStyleDeclaration, lineIndex: number): boolean {\r\n if (this._styleMap && !this.isWrapping) {\r\n const map = this._styleMap[lineIndex];\r\n if (map) {\r\n lineIndex = map.line;\r\n }\r\n }\r\n return super.styleHas(property, lineIndex);\r\n }\r\n\r\n /**\r\n * Returns true if object has no styling or no styling in a line\r\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\r\n * @return {Boolean}\r\n */\r\n isEmptyStyles(lineIndex: number): boolean {\r\n if (!this.styles) {\r\n return true;\r\n }\r\n let offset = 0,\r\n nextLineIndex = lineIndex + 1,\r\n nextOffset: number,\r\n shouldLimit = false;\r\n const map = this._styleMap[lineIndex],\r\n mapNextLine = this._styleMap[lineIndex + 1];\r\n if (map) {\r\n lineIndex = map.line;\r\n offset = map.offset;\r\n }\r\n if (mapNextLine) {\r\n nextLineIndex = mapNextLine.line;\r\n shouldLimit = nextLineIndex === lineIndex;\r\n nextOffset = mapNextLine.offset;\r\n }\r\n const obj =\r\n typeof lineIndex === 'undefined'\r\n ? this.styles\r\n : { line: this.styles[lineIndex] };\r\n for (const p1 in obj) {\r\n for (const p2 in obj[p1]) {\r\n const p2Number = parseInt(p2, 10);\r\n if (p2Number >= offset && (!shouldLimit || p2Number < nextOffset!)) {\r\n for (const p3 in obj[p1][p2]) {\r\n return false;\r\n }\r\n }\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * @protected\r\n * @param {Number} lineIndex\r\n * @param {Number} charIndex\r\n * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined\r\n */\r\n _getStyleDeclaration(\r\n lineIndex: number,\r\n charIndex: number,\r\n ): TextStyleDeclaration {\r\n if (this._styleMap && !this.isWrapping) {\r\n const map = this._styleMap[lineIndex];\r\n if (!map) {\r\n return {};\r\n }\r\n lineIndex = map.line;\r\n charIndex = map.offset + charIndex;\r\n }\r\n return super._getStyleDeclaration(lineIndex, charIndex);\r\n }\r\n\r\n /**\r\n * @param {Number} lineIndex\r\n * @param {Number} charIndex\r\n * @param {Object} style\r\n * @private\r\n */\r\n protected _setStyleDeclaration(\r\n lineIndex: number,\r\n charIndex: number,\r\n style: object,\r\n ) {\r\n const map = this._styleMap[lineIndex];\r\n super._setStyleDeclaration(map.line, map.offset + charIndex, style);\r\n }\r\n\r\n /**\r\n * @param {Number} lineIndex\r\n * @param {Number} charIndex\r\n * @private\r\n */\r\n protected _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\r\n const map = this._styleMap[lineIndex];\r\n super._deleteStyleDeclaration(map.line, map.offset + charIndex);\r\n }\r\n\r\n /**\r\n * probably broken need a fix\r\n * Returns the real style line that correspond to the wrapped lineIndex line\r\n * Used just to verify if the line does exist or not.\r\n * @param {Number} lineIndex\r\n * @returns {Boolean} if the line exists or not\r\n * @private\r\n */\r\n protected _getLineStyle(lineIndex: number): boolean {\r\n const map = this._styleMap[lineIndex];\r\n return !!this.styles[map.line];\r\n }\r\n\r\n /**\r\n * Set the line style to an empty object so that is initialized\r\n * @param {Number} lineIndex\r\n * @param {Object} style\r\n * @private\r\n */\r\n protected _setLineStyle(lineIndex: number) {\r\n const map = this._styleMap[lineIndex];\r\n super._setLineStyle(map.line);\r\n }\r\n\r\n /**\r\n * Wraps text using the 'width' property of Textbox. First this function\r\n * splits text on newlines, so we preserve newlines entered by the user.\r\n * Then it wraps each line using the width of the Textbox by calling\r\n * _wrapLine().\r\n * @param {Array} lines The string array of text that is split into lines\r\n * @param {Number} desiredWidth width you want to wrap to\r\n * @returns {Array} Array of lines\r\n */\r\n _wrapText(lines: string[], desiredWidth: number): string[][] {\r\n this.isWrapping = true;\r\n // extract all thewords and the widths to optimally wrap lines.\r\n const data = this.getGraphemeDataForRender(lines);\r\n const wrapped: string[][] = [];\r\n for (let i = 0; i < data.wordsData.length; i++) {\r\n wrapped.push(...this._wrapLine(i, desiredWidth, data));\r\n }\r\n this.isWrapping = false;\r\n return wrapped;\r\n }\r\n\r\n /**\r\n * For each line of text terminated by an hard line stop,\r\n * measure each word width and extract the largest word from all.\r\n * The returned words here are the one that at the end will be rendered.\r\n * @param {string[]} lines the lines we need to measure\r\n *\r\n */\r\n getGraphemeDataForRender(lines: string[]): GraphemeData {\r\n const splitByGrapheme = this.splitByGrapheme,\r\n infix = splitByGrapheme ? '' : ' ';\r\n\r\n let largestWordWidth = 0;\r\n\r\n const data = lines.map((line, lineIndex) => {\r\n let offset = 0;\r\n const wordsOrGraphemes = splitByGrapheme\r\n ? this.graphemeSplit(line)\r\n : this.wordSplit(line);\r\n\r\n if (wordsOrGraphemes.length === 0) {\r\n return [{ word: [], width: 0 }];\r\n }\r\n\r\n return wordsOrGraphemes.map((word: string) => {\r\n // if using splitByGrapheme words are already in graphemes.\r\n const graphemeArray = splitByGrapheme\r\n ? [word]\r\n : this.graphemeSplit(word);\r\n const width = this._measureWord(graphemeArray, lineIndex, offset);\r\n largestWordWidth = Math.max(width, largestWordWidth);\r\n offset += graphemeArray.length + infix.length;\r\n return { word: graphemeArray, width };\r\n });\r\n });\r\n\r\n return {\r\n wordsData: data,\r\n largestWordWidth,\r\n };\r\n }\r\n\r\n /**\r\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\r\n * It gets called when charBounds are not available yet.\r\n * Override if necessary\r\n * Use with {@link Textbox#wordSplit}\r\n *\r\n * @param {CanvasRenderingContext2D} ctx\r\n * @param {String} text\r\n * @param {number} lineIndex\r\n * @param {number} charOffset\r\n * @returns {number}\r\n */\r\n _measureWord(word: string[], lineIndex: number, charOffset = 0): number {\r\n let width = 0,\r\n prevGrapheme;\r\n const skipLeft = true;\r\n for (let i = 0, len = word.length; i < len; i++) {\r\n const box = this._getGraphemeBox(\r\n word[i],\r\n lineIndex,\r\n i + charOffset,\r\n prevGrapheme,\r\n skipLeft,\r\n );\r\n width += box.kernedWidth;\r\n prevGrapheme = word[i];\r\n }\r\n return width;\r\n }\r\n\r\n /**\r\n * Override this method to customize word splitting\r\n * Use with {@link Textbox#_measureWord}\r\n * @param {string} value\r\n * @returns {string[]} array of words\r\n */\r\n wordSplit(value: string): string[] {\r\n return value.split(this._wordJoiners);\r\n }\r\n\r\n /**\r\n * Wraps a line of text using the width of the Textbox as desiredWidth\r\n * and leveraging the known width o words from GraphemeData\r\n * @private\r\n * @param {Number} lineIndex\r\n * @param {Number} desiredWidth width you want to wrap the line to\r\n * @param {GraphemeData} graphemeData an object containing all the lines' words width.\r\n * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\r\n * @returns {Array} Array of line(s) into which the given text is wrapped\r\n * to.\r\n */\r\n _wrapLine(\r\n lineIndex: number,\r\n desiredWidth: number,\r\n { largestWordWidth, wordsData }: GraphemeData,\r\n reservedSpace = 0,\r\n ): string[][] {\r\n const additionalSpace = this._getWidthOfCharSpacing(),\r\n splitByGrapheme = this.splitByGrapheme,\r\n graphemeLines = [],\r\n infix = splitByGrapheme ? '' : ' ';\r\n\r\n let lineWidth = 0,\r\n line: string[] = [],\r\n // spaces in different languages?\r\n offset = 0,\r\n infixWidth = 0,\r\n lineJustStarted = true;\r\n\r\n desiredWidth -= reservedSpace;\r\n\r\n const maxWidth = Math.max(\r\n desiredWidth,\r\n largestWordWidth,\r\n this.dynamicMinWidth,\r\n );\r\n // layout words\r\n const data = wordsData[lineIndex];\r\n offset = 0;\r\n let i;\r\n for (i = 0; i < data.length; i++) {\r\n const { word, width: wordWidth } = data[i];\r\n offset += word.length;\r\n\r\n lineWidth += infixWidth + wordWidth - additionalSpace;\r\n if (lineWidth > maxWidth && !lineJustStarted) {\r\n graphemeLines.push(line);\r\n line = [];\r\n lineWidth = wordWidth;\r\n lineJustStarted = true;\r\n } else {\r\n lineWidth += additionalSpace;\r\n }\r\n\r\n if (!lineJustStarted && !splitByGrapheme) {\r\n line.push(infix);\r\n }\r\n line = line.concat(word);\r\n\r\n infixWidth = splitByGrapheme\r\n ? 0\r\n : this._measureWord([infix], lineIndex, offset);\r\n offset++;\r\n lineJustStarted = false;\r\n }\r\n\r\n i && graphemeLines.push(line);\r\n\r\n // TODO: this code is probably not necessary anymore.\r\n // it can be moved out of this function since largestWordWidth is now\r\n // known in advance\r\n if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\r\n this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\r\n }\r\n return graphemeLines;\r\n }\r\n\r\n /**\r\n * Detect if the text line is ended with an hard break\r\n * text and itext do not have wrapping, return false\r\n * @param {Number} lineIndex text to split\r\n * @return {Boolean}\r\n */\r\n isEndOfWrapping(lineIndex: number): boolean {\r\n if (!this._styleMap[lineIndex + 1]) {\r\n // is last line, return true;\r\n return true;\r\n }\r\n if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\r\n // this is last line before a line break, return true;\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Detect if a line has a linebreak and so we need to account for it when moving\r\n * and counting style.\r\n * This is important only for splitByGrapheme at the end of wrapping.\r\n * If we are not wrapping the offset is always 1\r\n * @return Number\r\n */\r\n missingNewlineOffset(lineIndex: number, skipWrapping?: boolean): 0 | 1 {\r\n if (this.splitByGrapheme && !skipWrapping) {\r\n return this.isEndOfWrapping(lineIndex) ? 1 : 0;\r\n }\r\n return 1;\r\n }\r\n\r\n /**\r\n * Gets lines of text to render in the Textbox. This function calculates\r\n * text wrapping on the fly every time it is called.\r\n * @param {String} text text to split\r\n * @returns {Array} Array of lines in the Textbox.\r\n * @override\r\n */\r\n _splitTextIntoLines(text: string) {\r\n const newText = super._splitTextIntoLines(text),\r\n graphemeLines = this._wrapText(newText.lines, this.width),\r\n lines = new Array(graphemeLines.length);\r\n for (let i = 0; i < graphemeLines.length; i++) {\r\n lines[i] = graphemeLines[i].join('');\r\n }\r\n newText.lines = lines;\r\n newText.graphemeLines = graphemeLines;\r\n return newText;\r\n }\r\n\r\n getMinWidth() {\r\n return Math.max(this.minWidth, this.dynamicMinWidth);\r\n }\r\n\r\n _removeExtraneousStyles() {\r\n const linesToKeep = new Map();\r\n for (const prop in this._styleMap) {\r\n const propNumber = parseInt(prop, 10);\r\n if (this._textLines[propNumber]) {\r\n const lineIndex = this._styleMap[prop].line;\r\n linesToKeep.set(`${lineIndex}`, true);\r\n }\r\n }\r\n for (const prop in this.styles) {\r\n if (!linesToKeep.has(prop)) {\r\n delete this.styles[prop];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Initialize event listeners for safety snap functionality\r\n * @private\r\n */\r\n private initializeEventListeners(): void {\r\n // Track which side is being used for resize to handle position compensation\r\n let resizeOrigin: 'left' | 'right' | null = null;\r\n \r\n // Detect resize origin during resizing\r\n this.on('resizing', (e: any) => {\r\n // Check transform origin to determine which side is being resized\r\n if (e.transform) {\r\n const { originX } = e.transform;\r\n // originX tells us which side is the anchor - opposite side is being dragged\r\n resizeOrigin = originX === 'right' ? 'left' : originX === 'left' ? 'right' : null;\r\n } else if (e.originX) {\r\n const { originX } = e;\r\n resizeOrigin = originX === 'right' ? 'left' : originX === 'left' ? 'right' : null;\r\n }\r\n });\r\n \r\n // Only trigger safety snap after resize is complete (not during)\r\n // Use 'modified' event which fires after user releases the mouse\r\n this.on('modified', () => {\r\n const currentResizeOrigin = resizeOrigin; // Capture the value before reset\r\n // Small delay to ensure text layout is updated\r\n setTimeout(() => this.safetySnapWidth(currentResizeOrigin), 10);\r\n resizeOrigin = null; // Reset after capturing\r\n });\r\n \r\n // Also listen to canvas-level modified event as backup\r\n this.canvas?.on('object:modified', (e) => {\r\n if (e.target === this) {\r\n const currentResizeOrigin = resizeOrigin; // Capture the value before reset\r\n setTimeout(() => this.safetySnapWidth(currentResizeOrigin), 10);\r\n resizeOrigin = null; // Reset after capturing\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Safety snap to prevent glyph clipping after manual resize.\r\n * Similar to Polotno - checks if any glyphs are too close to edges\r\n * and automatically expands width if needed.\r\n * @private\r\n * @param resizeOrigin - Which side was used for resizing ('left' or 'right')\r\n */\r\n private safetySnapWidth(resizeOrigin?: 'left' | 'right' | null): void {\r\n // For Textbox objects, we always want to check for clipping regardless of isWrapping flag\r\n if (!this._textLines || this.type.toLowerCase() !== 'textbox' || this._textLines.length === 0) {\r\n return;\r\n }\r\n \r\n const lineCount = this._textLines.length;\r\n if (lineCount === 0) return;\r\n\r\n // Check all lines, not just the last one\r\n let maxActualLineWidth = 0; // Actual measured width without buffers\r\n let maxRequiredWidth = 0; // Width including RTL buffer\r\n \r\n for (let i = 0; i < lineCount; i++) {\r\n const lineText = this._textLines[i].join(''); // Convert grapheme array to string\r\n const lineWidth = this.getLineWidth(i);\r\n maxActualLineWidth = Math.max(maxActualLineWidth, lineWidth);\r\n \r\n // RTL detection - regex for Arabic, Hebrew, and other RTL characters\r\n const rtlRegex = /[\\u0590-\\u05FF\\u0600-\\u06FF\\u0750-\\u077F\\uFB50-\\uFDFF\\uFE70-\\uFEFF]/;\r\n if (rtlRegex.test(lineText)) {\r\n // Add minimal RTL compensation buffer - just enough to prevent clipping\r\n const rtlBuffer = (this.fontSize || 16) * 0.15; // 15% of font size (much smaller)\r\n maxRequiredWidth = Math.max(maxRequiredWidth, lineWidth + rtlBuffer);\r\n } else {\r\n maxRequiredWidth = Math.max(maxRequiredWidth, lineWidth);\r\n }\r\n }\r\n\r\n // Safety margin - how close glyphs can get before we snap\r\n const safetyThreshold = 2; // px - very subtle trigger\r\n \r\n if (maxRequiredWidth > this.width - safetyThreshold) {\r\n // Set width to exactly what's needed + minimal safety margin\r\n const newWidth = maxRequiredWidth + 1; // Add just 1px safety margin\r\n \r\n // Store original position before width change\r\n const originalLeft = this.left;\r\n const originalTop = this.top;\r\n const widthIncrease = newWidth - this.width;\r\n \r\n // Change width \r\n this.set('width', newWidth);\r\n \r\n // Force text layout recalculation\r\n this.initDimensions();\r\n \r\n // Only compensate position when resizing from left handle\r\n // Right handle resize doesn't shift the text position\r\n if (resizeOrigin === 'left') {\r\n // When resizing from left, the expansion pushes text right\r\n // Compensate by moving the textbox left by the width increase\r\n this.set({\r\n 'left': originalLeft - widthIncrease,\r\n 'top': originalTop\r\n });\r\n }\r\n \r\n this.setCoords();\r\n \r\n // Also refresh the overlay editor if it exists\r\n if ((this as any).__overlayEditor) {\r\n setTimeout(() => {\r\n (this as any).__overlayEditor.refresh();\r\n }, 0);\r\n }\r\n \r\n this.canvas?.requestRenderAll();\r\n }\r\n }\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} object representation of an instance\r\n */\r\n toObject<\r\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\r\n K extends keyof T = never,\r\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\r\n return super.toObject<T, K>([\r\n 'minWidth',\r\n 'splitByGrapheme',\r\n ...propertiesToInclude,\r\n ] as K[]);\r\n }\r\n}\r\n\r\nclassRegistry.setClass(Textbox);\r\n"],"names":["textboxDefaultValues","minWidth","dynamicMinWidth","lockScalingFlip","noScaleCache","_wordJoiners","splitByGrapheme","Textbox","IText","getDefaults","ownDefaults","constructor","text","options","initializeEventListeners","createControls","controls","createTextboxDefaultControls","initDimensions","initialized","enableAdvancedLayout","initDimensionsAdvanced","isEditing","initDelayedCursor","_clearCache","_styleMap","_generateStyleMap","_splitText","width","_set","textAlign","includes","JUSTIFY","enlargeSpaces","height","calcTextHeight","layout","layoutText","wrap","align","_mapTextAlignToAlign","ellipsis","fontSize","lineHeight","letterSpacing","charSpacing","direction","fontFamily","fontStyle","fontWeight","verticalAlign","lines","length","maxLineWidth","Math","max","map","line","newLayout","_getAdvancedLayoutOptions","totalHeight","_convertLayoutToLegacyFormat","_generateStyleMapFromLayout","dirty","realLineCount","charCount","forEach","i","offset","graphemes","textInfo","realLineCharCount","graphemeLines","graphemeText","_reSpaceAndTab","test","styleHas","property","lineIndex","isWrapping","isEmptyStyles","styles","nextLineIndex","nextOffset","shouldLimit","mapNextLine","obj","p1","p2","p2Number","parseInt","p3","_getStyleDeclaration","charIndex","_setStyleDeclaration","style","_deleteStyleDeclaration","_getLineStyle","_setLineStyle","_wrapText","desiredWidth","data","getGraphemeDataForRender","wrapped","wordsData","push","_wrapLine","infix","largestWordWidth","wordsOrGraphemes","graphemeSplit","wordSplit","word","graphemeArray","_measureWord","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","_this$canvas","resizeOrigin","on","e","transform","originX","currentResizeOrigin","setTimeout","safetySnapWidth","canvas","target","type","toLowerCase","lineCount","maxRequiredWidth","lineText","getLineWidth","rtlRegex","rtlBuffer","safetyThreshold","_this$canvas2","newWidth","originalLeft","left","originalTop","top","widthIncrease","setCoords","__overlayEditor","refresh","requestRenderAll","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';\r\nimport { IText } from './IText/IText';\r\nimport { classRegistry } from '../ClassRegistry';\r\nimport { createTextboxDefaultControls } from '../controls/commonControls';\r\nimport { JUSTIFY, JUSTIFY_CENTER } from './Text/constants';\r\nimport type { TextStyleDeclaration } from './Text/StyledText';\r\nimport type { SerializedITextProps, ITextProps } from './IText/IText';\r\nimport type { ITextEvents } from './IText/ITextBehavior';\r\nimport type { TextLinesInfo } from './Text/Text';\r\nimport type { Control } from '../controls/Control';\r\nimport { fontLacksEnglishGlyphsCached } from '../text/measure';\r\nimport { layoutText } from '../text/layout';\r\n\r\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\r\n// regexes, list of properties that are not suppose to change by instances, magic consts.\r\n// this will be a separated effort\r\nexport const textboxDefaultValues: Partial<TClassProperties<Textbox>> = {\r\n minWidth: 20,\r\n dynamicMinWidth: 2,\r\n lockScalingFlip: true,\r\n noScaleCache: false,\r\n _wordJoiners: /[ \\t\\r]/,\r\n splitByGrapheme: false,\r\n};\r\n\r\nexport type GraphemeData = {\r\n wordsData: {\r\n word: string[];\r\n width: number;\r\n }[][];\r\n largestWordWidth: number;\r\n};\r\n\r\nexport type StyleMap = Record<string, { line: number; offset: number }>;\r\n\r\n// @TODO this is not complete\r\ninterface UniqueTextboxProps {\r\n minWidth: number;\r\n splitByGrapheme: boolean;\r\n dynamicMinWidth: number;\r\n _wordJoiners: RegExp;\r\n}\r\n\r\nexport interface SerializedTextboxProps\r\n extends SerializedITextProps,\r\n Pick<UniqueTextboxProps, 'minWidth' | 'splitByGrapheme'> {}\r\n\r\nexport interface TextboxProps extends ITextProps, UniqueTextboxProps {}\r\n\r\n/**\r\n * Textbox class, based on IText, allows the user to resize the text rectangle\r\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\r\n * user can only change width. Height is adjusted automatically based on the\r\n * wrapping of lines.\r\n */\r\nexport class Textbox<\r\n Props extends TOptions<TextboxProps> = Partial<TextboxProps>,\r\n SProps extends SerializedTextboxProps = SerializedTextboxProps,\r\n EventSpec extends ITextEvents = ITextEvents,\r\n >\r\n extends IText<Props, SProps, EventSpec>\r\n implements UniqueTextboxProps\r\n{\r\n /**\r\n * Minimum width of textbox, in pixels.\r\n * @type Number\r\n */\r\n declare minWidth: number;\r\n\r\n /**\r\n * Minimum calculated width of a textbox, in pixels.\r\n * fixed to 2 so that an empty textbox cannot go to 0\r\n * and is still selectable without text.\r\n * @type Number\r\n */\r\n declare dynamicMinWidth: number;\r\n\r\n /**\r\n * Use this boolean property in order to split strings that have no white space concept.\r\n * this is a cheap way to help with chinese/japanese\r\n * @type Boolean\r\n * @since 2.6.0\r\n */\r\n declare splitByGrapheme: boolean;\r\n\r\n declare _wordJoiners: RegExp;\r\n\r\n declare _styleMap: StyleMap;\r\n\r\n declare isWrapping: boolean;\r\n\r\n static type = 'Textbox';\r\n\r\n static textLayoutProperties = [...IText.textLayoutProperties, 'width'];\r\n\r\n static ownDefaults = textboxDefaultValues;\r\n\r\n static getDefaults(): Record<string, any> {\r\n return {\r\n ...super.getDefaults(),\r\n ...Textbox.ownDefaults,\r\n };\r\n }\r\n\r\n /**\r\n * Constructor\r\n * @param {String} text Text string\r\n * @param {Object} [options] Options object\r\n */\r\n constructor(text: string, options?: Props) {\r\n super(text, { ...Textbox.ownDefaults, ...options } as Props);\r\n this.initializeEventListeners();\r\n }\r\n\r\n /**\r\n * Creates the default control object.\r\n * If you prefer to have on instance of controls shared among all objects\r\n * make this function return an empty object and add controls to the ownDefaults object\r\n */\r\n static createControls(): { controls: Record<string, Control> } {\r\n return { controls: createTextboxDefaultControls() };\r\n }\r\n\r\n /**\r\n * Unlike superclass's version of this function, Textbox does not update\r\n * its width.\r\n * @private\r\n * @override\r\n */\r\n initDimensions() {\r\n if (!this.initialized) {\r\n this.initialized = true;\r\n }\r\n \r\n // Prevent rapid recalculations during moves\r\n if ((this as any)._usingBrowserWrapping) {\r\n const now = Date.now();\r\n const lastCall = (this as any)._lastInitDimensionsTime || 0;\r\n const isRapidCall = now - lastCall < 100;\r\n const isDuringLoading = (this as any)._jsonLoading || !(this as any)._browserWrapInitialized;\r\n \r\n if (isRapidCall && !isDuringLoading) {\r\n return;\r\n }\r\n (this as any)._lastInitDimensionsTime = now;\r\n }\r\n \r\n // Skip if nothing changed\r\n const currentState = `${this.text}|${this.width}|${this.fontSize}|${this.fontFamily}|${this.textAlign}`;\r\n if ((this as any)._lastDimensionState === currentState && this._textLines && this._textLines.length > 0) {\r\n return;\r\n }\r\n (this as any)._lastDimensionState = currentState;\r\n \r\n // Use advanced layout if enabled\r\n if (this.enableAdvancedLayout) {\r\n return this.initDimensionsAdvanced();\r\n }\r\n \r\n this.isEditing && this.initDelayedCursor();\r\n this._clearCache();\r\n // clear dynamicMinWidth as it will be different after we re-wrap line\r\n this.dynamicMinWidth = 0;\r\n // wrap lines\r\n const splitTextResult = this._splitText();\r\n this._styleMap = this._generateStyleMap(splitTextResult);\r\n \r\n // For browser wrapping, ensure _textLines is set from browser results\r\n if ((this as any)._usingBrowserWrapping && splitTextResult && splitTextResult.lines) {\r\n this._textLines = splitTextResult.lines.map(line => line.split(''));\r\n \r\n // Store justify measurements and browser height\r\n const justifyMeasurements = (splitTextResult as any).justifySpaceMeasurements;\r\n if (justifyMeasurements) {\r\n (this._styleMap as any).justifySpaceMeasurements = justifyMeasurements;\r\n }\r\n \r\n const actualHeight = (splitTextResult as any).actualBrowserHeight;\r\n if (actualHeight) {\r\n (this as any)._actualBrowserHeight = actualHeight;\r\n }\r\n }\r\n // Don't auto-resize width when using browser wrapping to prevent width increases during moves\r\n if (!((this as any)._usingBrowserWrapping) && this.dynamicMinWidth > this.width) {\r\n this._set('width', this.dynamicMinWidth);\r\n }\r\n \r\n // For browser wrapping fonts (like STV), ensure minimum width for new textboxes\r\n // since these fonts can't measure English characters properly\r\n if ((this as any)._usingBrowserWrapping && this.width < 50) {\r\n console.log(`🔤 BROWSER WRAP: Font ${this.fontFamily} has width ${this.width}px, setting to 300px for usability`);\r\n this.width = 300;\r\n }\r\n \r\n // Mark browser wrapping as initialized when complete\r\n if ((this as any)._usingBrowserWrapping) {\r\n (this as any)._browserWrapInitialized = true;\r\n }\r\n \r\n if (this.textAlign.includes(JUSTIFY)) {\r\n // For browser wrapping fonts, apply browser-calculated justify spaces\r\n if ((this as any)._usingBrowserWrapping) {\r\n console.log('🔤 BROWSER WRAP: Applying browser-calculated justify spaces');\r\n this._applyBrowserJustifySpaces();\r\n return;\r\n }\r\n \r\n // Don't apply justify alignment during drag operations to prevent snapping\r\n const now = Date.now();\r\n const lastDragTime = (this as any)._lastInitDimensionsTime || 0;\r\n const isDuringDrag = now - lastDragTime < 200; // 200ms window for drag detection\r\n \r\n if (isDuringDrag) {\r\n console.log('🔤 Skipping justify during drag operation to prevent snapping');\r\n return;\r\n }\r\n \r\n // For non-browser-wrapping fonts, use Fabric's justify system\r\n // once text is measured we need to make space fatter to make justified text.\r\n // Ensure __charBounds exists and fonts are ready before applying justify\r\n if (this.__charBounds && this.__charBounds.length > 0) {\r\n // Check if font is ready for accurate justify calculations\r\n const fontReady = this._isFontReady ? this._isFontReady() : true;\r\n if (fontReady) {\r\n this.enlargeSpaces();\r\n } else {\r\n console.warn('⚠️ Textbox: Font not ready for justify, deferring enlargeSpaces');\r\n // Defer justify calculation until font is ready\r\n this._scheduleJustifyAfterFontLoad();\r\n }\r\n } else {\r\n console.warn('⚠️ Textbox: __charBounds not ready for justify alignment, deferring enlargeSpaces');\r\n // Defer the justify calculation until the next frame\r\n setTimeout(() => {\r\n if (this.__charBounds && this.__charBounds.length > 0 && this.enlargeSpaces) {\r\n console.log('🔧 Applying deferred Textbox justify alignment');\r\n this.enlargeSpaces();\r\n this.canvas?.requestRenderAll();\r\n }\r\n }, 0);\r\n }\r\n }\r\n // Calculate height - use Fabric's calculation for proper text rendering space\r\n if ((this as any)._usingBrowserWrapping && this._textLines && this._textLines.length > 0) {\r\n const actualBrowserHeight = (this as any)._actualBrowserHeight;\r\n const oldHeight = this.height;\r\n // Use Fabric's height calculation since it knows how much space text rendering needs\r\n this.height = this.calcTextHeight();\r\n \r\n // Force canvas refresh and control update if height changed significantly\r\n if (Math.abs(this.height - oldHeight) > 1) {\r\n this.setCoords();\r\n this.canvas?.requestRenderAll();\r\n \r\n // DEBUG: Log exact positioning details\r\n console.log(`🎯 POSITIONING DEBUG:`);\r\n console.log(` Textbox height: ${this.height}px`);\r\n console.log(` Textbox top: ${this.top}px`);\r\n console.log(` Textbox left: ${this.left}px`);\r\n console.log(` Text lines: ${this._textLines?.length || 0}`);\r\n console.log(` Font size: ${this.fontSize}px`);\r\n console.log(` Line height: ${this.lineHeight || 1.16}`);\r\n console.log(` Calculated line height: ${this.fontSize * (this.lineHeight || 1.16)}px`);\r\n console.log(` _getTopOffset(): ${this._getTopOffset()}px`);\r\n console.log(` calcTextHeight(): ${this.calcTextHeight()}px`);\r\n console.log(` Browser height: ${actualBrowserHeight}px`);\r\n console.log(` Height difference: ${this.height - this.calcTextHeight()}px`);\r\n }\r\n } else {\r\n this.height = this.calcTextHeight();\r\n }\r\n }\r\n\r\n /**\r\n * Schedule justify calculation after font loads (Textbox-specific)\r\n * @private\r\n */\r\n _scheduleJustifyAfterFontLoad(): void {\r\n if (typeof document === 'undefined' || !('fonts' in document)) {\r\n return;\r\n }\r\n \r\n // Only schedule if not already waiting\r\n if ((this as any)._fontJustifyScheduled) {\r\n return;\r\n }\r\n (this as any)._fontJustifyScheduled = true;\r\n \r\n const fontSpec = `${this.fontSize}px ${this.fontFamily}`;\r\n document.fonts.load(fontSpec).then(() => {\r\n (this as any)._fontJustifyScheduled = false;\r\n console.log('🔧 Textbox: Font loaded, applying justify alignment');\r\n \r\n // Re-run initDimensions to ensure proper justify calculation\r\n this.initDimensions();\r\n this.canvas?.requestRenderAll();\r\n }).catch(() => {\r\n (this as any)._fontJustifyScheduled = false;\r\n console.warn('⚠️ Textbox: Font loading failed, justify may be incorrect');\r\n });\r\n }\r\n\r\n /**\r\n * Advanced dimensions calculation using new layout engine\r\n * @private\r\n */\r\n initDimensionsAdvanced() {\r\n if (!this.initialized) {\r\n return;\r\n }\r\n \r\n this.isEditing && this.initDelayedCursor();\r\n this._clearCache();\r\n this.dynamicMinWidth = 0;\r\n \r\n // Use new layout engine\r\n const layout = layoutText({\r\n text: this.text,\r\n width: this.width,\r\n height: this.height,\r\n wrap: this.wrap || 'word',\r\n align: (this as any)._mapTextAlignToAlign(this.textAlign),\r\n ellipsis: this.ellipsis || false,\r\n fontSize: this.fontSize,\r\n lineHeight: this.lineHeight,\r\n letterSpacing: this.letterSpacing || 0,\r\n charSpacing: this.charSpacing,\r\n direction: this.direction === 'inherit' ? 'ltr' : this.direction,\r\n fontFamily: this.fontFamily,\r\n fontStyle: this.fontStyle,\r\n fontWeight: this.fontWeight,\r\n verticalAlign: this.verticalAlign || 'top',\r\n });\r\n \r\n // Update dynamic minimum width based on layout\r\n if (layout.lines.length > 0) {\r\n const maxLineWidth = Math.max(...layout.lines.map(line => line.width));\r\n this.dynamicMinWidth = Math.max(this.minWidth, maxLineWidth);\r\n }\r\n \r\n // Adjust width if needed (preserving Textbox behavior)\r\n if (this.dynamicMinWidth > this.width) {\r\n this._set('width', this.dynamicMinWidth);\r\n // Re-layout with new width\r\n const newLayout = layoutText({\r\n ...(this as any)._getAdvancedLayoutOptions(),\r\n width: this.width,\r\n });\r\n this.height = newLayout.totalHeight;\r\n (this as any)._convertLayoutToLegacyFormat(newLayout);\r\n } else {\r\n this.height = layout.totalHeight;\r\n (this as any)._convertLayoutToLegacyFormat(layout);\r\n }\r\n \r\n // Generate style map for compatibility\r\n this._styleMap = this._generateStyleMapFromLayout(layout);\r\n this.dirty = true;\r\n }\r\n\r\n /**\r\n * Generate style map from new layout format\r\n * @private\r\n */\r\n _generateStyleMapFromLayout(layout: any): StyleMap {\r\n const map: StyleMap = {};\r\n let realLineCount = 0;\r\n let charCount = 0;\r\n\r\n layout.lines.forEach((line: any, i: number) => {\r\n if (line.text.includes('\\n') && i > 0) {\r\n realLineCount++;\r\n }\r\n \r\n map[i] = { line: realLineCount, offset: 0 };\r\n charCount += line.graphemes.length;\r\n \r\n if (i < layout.lines.length - 1) {\r\n charCount += 1; // newline character\r\n }\r\n });\r\n\r\n return map;\r\n }\r\n\r\n /**\r\n * Generate an object that translates the style object so that it is\r\n * broken up by visual lines (new lines and automatic wrapping).\r\n * The original text styles object is broken up by actual lines (new lines only),\r\n * which is only sufficient for Text / IText\r\n * @private\r\n */\r\n _generateStyleMap(textInfo: TextLinesInfo): StyleMap {\r\n let realLineCount = 0,\r\n realLineCharCount = 0,\r\n charCount = 0;\r\n const map: StyleMap = {};\r\n\r\n for (let i = 0; i < textInfo.graphemeLines.length; i++) {\r\n if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\r\n realLineCharCount = 0;\r\n charCount++;\r\n realLineCount++;\r\n } else if (\r\n !this.splitByGrapheme &&\r\n this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\r\n i > 0\r\n ) {\r\n // this case deals with space's that are removed from end of lines when wrapping\r\n realLineCharCount++;\r\n charCount++;\r\n }\r\n\r\n map[i] = { line: realLineCount, offset: realLineCharCount };\r\n\r\n charCount += textInfo.graphemeLines[i].length;\r\n realLineCharCount += textInfo.graphemeLines[i].length;\r\n }\r\n\r\n return map;\r\n }\r\n\r\n /**\r\n * Returns true if object has a style property or has it on a specified line\r\n * @param {Number} lineIndex\r\n * @return {Boolean}\r\n */\r\n styleHas(property: keyof TextStyleDeclaration, lineIndex: number): boolean {\r\n if (this._styleMap && !this.isWrapping) {\r\n const map = this._styleMap[lineIndex];\r\n if (map) {\r\n lineIndex = map.line;\r\n }\r\n }\r\n return super.styleHas(property, lineIndex);\r\n }\r\n\r\n /**\r\n * Returns true if object has no styling or no styling in a line\r\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\r\n * @return {Boolean}\r\n */\r\n isEmptyStyles(lineIndex: number): boolean {\r\n if (!this.styles) {\r\n return true;\r\n }\r\n let offset = 0,\r\n nextLineIndex = lineIndex + 1,\r\n nextOffset: number,\r\n shouldLimit = false;\r\n const map = this._styleMap[lineIndex],\r\n mapNextLine = this._styleMap[lineIndex + 1];\r\n if (map) {\r\n lineIndex = map.line;\r\n offset = map.offset;\r\n }\r\n if (mapNextLine) {\r\n nextLineIndex = mapNextLine.line;\r\n shouldLimit = nextLineIndex === lineIndex;\r\n nextOffset = mapNextLine.offset;\r\n }\r\n const obj =\r\n typeof lineIndex === 'undefined'\r\n ? this.styles\r\n : { line: this.styles[lineIndex] };\r\n for (const p1 in obj) {\r\n for (const p2 in obj[p1]) {\r\n const p2Number = parseInt(p2, 10);\r\n if (p2Number >= offset && (!shouldLimit || p2Number < nextOffset!)) {\r\n for (const p3 in obj[p1][p2]) {\r\n return false;\r\n }\r\n }\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * @protected\r\n * @param {Number} lineIndex\r\n * @param {Number} charIndex\r\n * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined\r\n */\r\n _getStyleDeclaration(\r\n lineIndex: number,\r\n charIndex: number,\r\n ): TextStyleDeclaration {\r\n if (this._styleMap && !this.isWrapping) {\r\n const map = this._styleMap[lineIndex];\r\n if (!map) {\r\n return {};\r\n }\r\n lineIndex = map.line;\r\n charIndex = map.offset + charIndex;\r\n }\r\n return super._getStyleDeclaration(lineIndex, charIndex);\r\n }\r\n\r\n /**\r\n * @param {Number} lineIndex\r\n * @param {Number} charIndex\r\n * @param {Object} style\r\n * @private\r\n */\r\n protected _setStyleDeclaration(\r\n lineIndex: number,\r\n charIndex: number,\r\n style: object,\r\n ) {\r\n const map = this._styleMap[lineIndex];\r\n super._setStyleDeclaration(map.line, map.offset + charIndex, style);\r\n }\r\n\r\n /**\r\n * @param {Number} lineIndex\r\n * @param {Number} charIndex\r\n * @private\r\n */\r\n protected _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\r\n const map = this._styleMap[lineIndex];\r\n super._deleteStyleDeclaration(map.line, map.offset + charIndex);\r\n }\r\n\r\n /**\r\n * probably broken need a fix\r\n * Returns the real style line that correspond to the wrapped lineIndex line\r\n * Used just to verify if the line does exist or not.\r\n * @param {Number} lineIndex\r\n * @returns {Boolean} if the line exists or not\r\n * @private\r\n */\r\n protected _getLineStyle(lineIndex: number): boolean {\r\n const map = this._styleMap[lineIndex];\r\n return !!this.styles[map.line];\r\n }\r\n\r\n /**\r\n * Set the line style to an empty object so that is initialized\r\n * @param {Number} lineIndex\r\n * @param {Object} style\r\n * @private\r\n */\r\n protected _setLineStyle(lineIndex: number) {\r\n const map = this._styleMap[lineIndex];\r\n super._setLineStyle(map.line);\r\n }\r\n\r\n /**\r\n * Wraps text using the 'width' property of Textbox. First this function\r\n * splits text on newlines, so we preserve newlines entered by the user.\r\n * Then it wraps each line using the width of the Textbox by calling\r\n * _wrapLine().\r\n * @param {Array} lines The string array of text that is split into lines\r\n * @param {Number} desiredWidth width you want to wrap to\r\n * @returns {Array} Array of lines\r\n */\r\n _wrapText(lines: string[], desiredWidth: number): string[][] {\r\n this.isWrapping = true;\r\n // extract all thewords and the widths to optimally wrap lines.\r\n const data = this.getGraphemeDataForRender(lines);\r\n const wrapped: string[][] = [];\r\n for (let i = 0; i < data.wordsData.length; i++) {\r\n wrapped.push(...this._wrapLine(i, desiredWidth, data));\r\n }\r\n this.isWrapping = false;\r\n return wrapped;\r\n }\r\n\r\n /**\r\n * For each line of text terminated by an hard line stop,\r\n * measure each word width and extract the largest word from all.\r\n * The returned words here are the one that at the end will be rendered.\r\n * @param {string[]} lines the lines we need to measure\r\n *\r\n */\r\n getGraphemeDataForRender(lines: string[]): GraphemeData {\r\n const splitByGrapheme = this.splitByGrapheme,\r\n infix = splitByGrapheme ? '' : ' ';\r\n\r\n let largestWordWidth = 0;\r\n\r\n const data = lines.map((line, lineIndex) => {\r\n let offset = 0;\r\n const wordsOrGraphemes = splitByGrapheme\r\n ? this.graphemeSplit(line)\r\n : this.wordSplit(line);\r\n\r\n if (wordsOrGraphemes.length === 0) {\r\n return [{ word: [], width: 0 }];\r\n }\r\n\r\n return wordsOrGraphemes.map((word: string) => {\r\n // if using splitByGrapheme words are already in graphemes.\r\n const graphemeArray = splitByGrapheme\r\n ? [word]\r\n : this.graphemeSplit(word);\r\n const width = this._measureWord(graphemeArray, lineIndex, offset);\r\n largestWordWidth = Math.max(width, largestWordWidth);\r\n offset += graphemeArray.length + infix.length;\r\n return { word: graphemeArray, width };\r\n });\r\n });\r\n\r\n return {\r\n wordsData: data,\r\n largestWordWidth,\r\n };\r\n }\r\n\r\n /**\r\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\r\n * It gets called when charBounds are not available yet.\r\n * Override if necessary\r\n * Use with {@link Textbox#wordSplit}\r\n *\r\n * @param {CanvasRenderingContext2D} ctx\r\n * @param {String} text\r\n * @param {number} lineIndex\r\n * @param {number} charOffset\r\n * @returns {number}\r\n */\r\n _measureWord(word: string[], lineIndex: number, charOffset = 0): number {\r\n let width = 0,\r\n prevGrapheme;\r\n const skipLeft = true;\r\n for (let i = 0, len = word.length; i < len; i++) {\r\n const box = this._getGraphemeBox(\r\n word[i],\r\n lineIndex,\r\n i + charOffset,\r\n prevGrapheme,\r\n skipLeft,\r\n );\r\n width += box.kernedWidth;\r\n prevGrapheme = word[i];\r\n }\r\n return width;\r\n }\r\n\r\n /**\r\n * Override this method to customize word splitting\r\n * Use with {@link Textbox#_measureWord}\r\n * @param {string} value\r\n * @returns {string[]} array of words\r\n */\r\n wordSplit(value: string): string[] {\r\n return value.split(this._wordJoiners);\r\n }\r\n\r\n /**\r\n * Wraps a line of text using the width of the Textbox as desiredWidth\r\n * and leveraging the known width o words from GraphemeData\r\n * @private\r\n * @param {Number} lineIndex\r\n * @param {Number} desiredWidth width you want to wrap the line to\r\n * @param {GraphemeData} graphemeData an object containing all the lines' words width.\r\n * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\r\n * @returns {Array} Array of line(s) into which the given text is wrapped\r\n * to.\r\n */\r\n _wrapLine(\r\n lineIndex: number,\r\n desiredWidth: number,\r\n { largestWordWidth, wordsData }: GraphemeData,\r\n reservedSpace = 0,\r\n ): string[][] {\r\n const additionalSpace = this._getWidthOfCharSpacing(),\r\n splitByGrapheme = this.splitByGrapheme,\r\n graphemeLines = [],\r\n infix = splitByGrapheme ? '' : ' ';\r\n\r\n let lineWidth = 0,\r\n line: string[] = [],\r\n // spaces in different languages?\r\n offset = 0,\r\n infixWidth = 0,\r\n lineJustStarted = true;\r\n\r\n desiredWidth -= reservedSpace;\r\n\r\n const maxWidth = Math.max(\r\n desiredWidth,\r\n largestWordWidth,\r\n this.dynamicMinWidth,\r\n );\r\n // layout words\r\n const data = wordsData[lineIndex];\r\n offset = 0;\r\n let i;\r\n for (i = 0; i < data.length; i++) {\r\n const { word, width: wordWidth } = data[i];\r\n offset += word.length;\r\n\r\n // Predictive wrapping: check if adding this word would exceed the width\r\n const potentialLineWidth = lineWidth + infixWidth + wordWidth - additionalSpace;\r\n // Use exact width to match overlay editor behavior\r\n const conservativeMaxWidth = maxWidth; // No artificial buffer\r\n \r\n // Debug logging for wrapping decisions\r\n const currentLineText = line.join('');\r\n console.log(`🔧 FABRIC WRAP CHECK: \"${data[i].word}\" -> potential: ${potentialLineWidth.toFixed(1)}px vs limit: ${conservativeMaxWidth.toFixed(1)}px`);\r\n \r\n if (potentialLineWidth > conservativeMaxWidth && !lineJustStarted) {\r\n // This word would exceed the width, wrap before adding it\r\n console.log(`🔧 FABRIC WRAP! Line: \"${currentLineText}\" (${lineWidth.toFixed(1)}px)`);\r\n graphemeLines.push(line);\r\n line = [];\r\n lineWidth = wordWidth; // Start new line with just this word\r\n lineJustStarted = true;\r\n } else {\r\n // Word fits, add it to current line\r\n lineWidth = potentialLineWidth + additionalSpace;\r\n }\r\n\r\n if (!lineJustStarted && !splitByGrapheme) {\r\n line.push(infix);\r\n }\r\n line = line.concat(word);\r\n \r\n // Debug: show current line after adding word\r\n console.log(`🔧 FABRIC AFTER ADD: Line now: \"${line.join('')}\" (${line.length} chars)`);\r\n \r\n\r\n infixWidth = splitByGrapheme\r\n ? 0\r\n : this._measureWord([infix], lineIndex, offset);\r\n offset++;\r\n lineJustStarted = false;\r\n }\r\n\r\n i && graphemeLines.push(line);\r\n\r\n // TODO: this code is probably not necessary anymore.\r\n // it can be moved out of this function since largestWordWidth is now\r\n // known in advance\r\n // Don't modify dynamicMinWidth when using browser wrapping to prevent width increases\r\n if (!((this as any)._usingBrowserWrapping) && largestWordWidth + reservedSpace > this.dynamicMinWidth) {\r\n console.log(`🔧 FABRIC updating dynamicMinWidth: ${this.dynamicMinWidth} -> ${largestWordWidth - additionalSpace + reservedSpace}`);\r\n this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\r\n } else if ((this as any)._usingBrowserWrapping) {\r\n console.log(`🔤 BROWSER WRAP: Skipping dynamicMinWidth update to prevent width increase`);\r\n }\r\n \r\n // Debug: show final wrapped lines\r\n console.log(`🔧 FABRIC FINAL LINES: ${graphemeLines.length} lines`);\r\n graphemeLines.forEach((line, i) => {\r\n console.log(` Line ${i + 1}: \"${line.join('')}\" (${line.length} chars)`);\r\n });\r\n \r\n return graphemeLines;\r\n }\r\n\r\n /**\r\n * Detect if the text line is ended with an hard break\r\n * text and itext do not have wrapping, return false\r\n * @param {Number} lineIndex text to split\r\n * @return {Boolean}\r\n */\r\n isEndOfWrapping(lineIndex: number): boolean {\r\n if (!this._styleMap[lineIndex + 1]) {\r\n // is last line, return true;\r\n return true;\r\n }\r\n if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\r\n // this is last line before a line break, return true;\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Detect if a line has a linebreak and so we need to account for it when moving\r\n * and counting style.\r\n * This is important only for splitByGrapheme at the end of wrapping.\r\n * If we are not wrapping the offset is always 1\r\n * @return Number\r\n */\r\n missingNewlineOffset(lineIndex: number, skipWrapping?: boolean): 0 | 1 {\r\n if (this.splitByGrapheme && !skipWrapping) {\r\n return this.isEndOfWrapping(lineIndex) ? 1 : 0;\r\n }\r\n return 1;\r\n }\r\n\r\n /**\r\n * Gets lines of text to render in the Textbox. This function calculates\r\n * text wrapping on the fly every time it is called.\r\n * @param {String} text text to split\r\n * @returns {Array} Array of lines in the Textbox.\r\n * @override\r\n */\r\n _splitTextIntoLines(text: string) {\r\n // Check if we need browser wrapping using smart font detection\r\n const needsBrowserWrapping = this.fontFamily && fontLacksEnglishGlyphsCached(this.fontFamily);\r\n \r\n if (needsBrowserWrapping) {\r\n // Cache key based on text content, width, font properties, AND text alignment\r\n const textHash = text.length + text.slice(0, 50); // Include text content in cache key\r\n const cacheKey = `${textHash}|${this.width}|${this.fontSize}|${this.fontFamily}|${this.textAlign}`;\r\n \r\n // Check if we have a cached result and nothing has changed\r\n if ((this as any)._browserWrapCache && (this as any)._browserWrapCache.key === cacheKey) {\r\n const cachedResult = (this as any)._browserWrapCache.result;\r\n \r\n // For justify alignment, ensure we have the measurements\r\n if (this.textAlign.includes('justify') && !(cachedResult as any).justifySpaceMeasurements) {\r\n // Fall through to recalculate\r\n } else {\r\n return cachedResult;\r\n }\r\n }\r\n \r\n const result = this._splitTextIntoLinesWithBrowser(text);\r\n \r\n // Cache the result\r\n (this as any)._browserWrapCache = { key: cacheKey, result };\r\n \r\n // Mark that we used browser wrapping to prevent dynamicMinWidth modifications\r\n (this as any)._usingBrowserWrapping = true;\r\n \r\n return result;\r\n }\r\n \r\n // Clear the browser wrapping flag when using regular wrapping\r\n (this as any)._usingBrowserWrapping = false;\r\n \r\n // Default Fabric wrapping for other fonts\r\n const newText = super._splitTextIntoLines(text),\r\n graphemeLines = this._wrapText(newText.lines, this.width),\r\n lines = new Array(graphemeLines.length);\r\n for (let i = 0; i < graphemeLines.length; i++) {\r\n lines[i] = graphemeLines[i].join('');\r\n }\r\n newText.lines = lines;\r\n newText.graphemeLines = graphemeLines;\r\n return newText;\r\n }\r\n\r\n /**\r\n * Use browser's native text wrapping for accurate handling of fonts without English glyphs\r\n * @private\r\n */\r\n _splitTextIntoLinesWithBrowser(text: string) {\r\n if (typeof document === 'undefined') {\r\n // Fallback to regular wrapping in Node.js\r\n return this._splitTextIntoLinesDefault(text);\r\n }\r\n\r\n // Create a hidden element that mimics the overlay editor\r\n const testElement = document.createElement('div');\r\n testElement.style.position = 'absolute';\r\n testElement.style.left = '-9999px';\r\n testElement.style.visibility = 'hidden';\r\n testElement.style.fontSize = `${this.fontSize}px`;\r\n testElement.style.fontFamily = `\"${this.fontFamily}\"`;\r\n testElement.style.fontWeight = String(this.fontWeight || 'normal');\r\n testElement.style.fontStyle = String(this.fontStyle || 'normal');\r\n testElement.style.lineHeight = String(this.lineHeight || 1.16);\r\n \r\n testElement.style.width = `${this.width}px`;\r\n \r\n testElement.style.direction = this.direction || 'ltr';\r\n testElement.style.whiteSpace = 'pre-wrap';\r\n testElement.style.wordBreak = 'normal';\r\n testElement.style.overflowWrap = 'break-word';\r\n \r\n // Set browser-native text alignment (including justify)\r\n if (this.textAlign.includes('justify')) {\r\n testElement.style.textAlign = 'justify';\r\n testElement.style.textAlignLast = 'auto'; // Let browser decide last line alignment\r\n } else {\r\n testElement.style.textAlign = this.textAlign;\r\n }\r\n \r\n testElement.textContent = text;\r\n\r\n document.body.appendChild(testElement);\r\n\r\n // Get the browser's natural line breaks\r\n const range = document.createRange();\r\n const lines: string[] = [];\r\n const graphemeLines: string[][] = [];\r\n\r\n try {\r\n // Simple approach: split by measuring character positions\r\n const textNode = testElement.firstChild;\r\n if (textNode && textNode.nodeType === Node.TEXT_NODE) {\r\n let currentLineStart = 0;\r\n const textLength = text.length;\r\n let previousBottom = 0;\r\n \r\n for (let i = 0; i <= textLength; i++) {\r\n range.setStart(textNode, currentLineStart);\r\n range.setEnd(textNode, i);\r\n const rect = range.getBoundingClientRect();\r\n \r\n if (i > currentLineStart && (rect.bottom > previousBottom + 5 || i === textLength)) {\r\n // New line detected or end of text\r\n const lineEnd = i === textLength ? i : i - 1;\r\n const lineText = text.substring(currentLineStart, lineEnd).trim();\r\n if (lineText) {\r\n lines.push(lineText);\r\n // Convert to graphemes for compatibility\r\n const graphemeLine = lineText.split('');\r\n graphemeLines.push(graphemeLine);\r\n }\r\n currentLineStart = lineEnd;\r\n previousBottom = rect.bottom;\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.warn('Browser wrapping failed, using fallback:', error);\r\n document.body.removeChild(testElement);\r\n return this._splitTextIntoLinesDefault(text);\r\n }\r\n\r\n // Extract actual browser height BEFORE removing element\r\n const actualBrowserHeight = testElement.scrollHeight;\r\n const offsetHeight = testElement.offsetHeight;\r\n const clientHeight = testElement.clientHeight;\r\n const boundingRect = testElement.getBoundingClientRect();\r\n \r\n console.log(`🔤 Browser element measurements:`);\r\n console.log(` scrollHeight: ${actualBrowserHeight}px (content + padding + hidden overflow)`);\r\n console.log(` offsetHeight: ${offsetHeight}px (content + padding + border)`);\r\n console.log(` clientHeight: ${clientHeight}px (content + padding, no border/scrollbar)`);\r\n console.log(` boundingRect.height: ${boundingRect.height}px (actual rendered height)`);\r\n console.log(` Font size: ${this.fontSize}px, Line height: ${this.lineHeight || 1.16}, Lines: ${lines.length}`);\r\n\r\n // For justify alignment, extract space measurements from browser BEFORE removing element\r\n let justifySpaceMeasurements = null;\r\n if (this.textAlign.includes('justify')) {\r\n justifySpaceMeasurements = this._extractJustifySpaceMeasurements(testElement, lines);\r\n }\r\n\r\n document.body.removeChild(testElement);\r\n\r\n console.log(`🔤 Browser wrapping result: ${lines.length} lines`);\r\n \r\n // Try different height measurements to find the most accurate\r\n let bestHeight = actualBrowserHeight;\r\n \r\n // If scrollHeight and offsetHeight differ significantly, investigate\r\n if (Math.abs(actualBrowserHeight - offsetHeight) > 2) {\r\n console.log(`🔤 Height discrepancy detected: scrollHeight=${actualBrowserHeight}px vs offsetHeight=${offsetHeight}px`);\r\n }\r\n \r\n // Consider using boundingRect height if it's larger (sometimes more accurate for visible content)\r\n if (boundingRect.height > bestHeight) {\r\n console.log(`🔤 Using boundingRect height (${boundingRect.height}px) instead of scrollHeight (${bestHeight}px)`);\r\n bestHeight = boundingRect.height;\r\n }\r\n \r\n // Font-specific height adjustments for accurate bounding box\r\n let adjustedHeight = bestHeight;\r\n \r\n // Fonts without English glyphs need additional height buffer due to different font metrics\r\n const lacksEnglishGlyphs = fontLacksEnglishGlyphsCached(this.fontFamily);\r\n if (lacksEnglishGlyphs) {\r\n const glyphBuffer = this.fontSize * 0.25; // 25% of font size for non-English fonts\r\n adjustedHeight = bestHeight + glyphBuffer;\r\n console.log(`🔤 Non-English font detected (${this.fontFamily}): Adding ${glyphBuffer}px buffer (${bestHeight}px + ${glyphBuffer}px = ${adjustedHeight}px)`);\r\n } else {\r\n console.log(`🔤 Standard font (${this.fontFamily}): Using browser height directly (${bestHeight}px)`);\r\n }\r\n \r\n return {\r\n _unwrappedLines: [text.split('')],\r\n lines: lines,\r\n graphemeText: text.split(''),\r\n graphemeLines: graphemeLines,\r\n justifySpaceMeasurements: justifySpaceMeasurements,\r\n actualBrowserHeight: adjustedHeight,\r\n };\r\n }\r\n\r\n\r\n\r\n\r\n /**\r\n * Extract justify space measurements from browser\r\n * @private\r\n */\r\n _extractJustifySpaceMeasurements(element: HTMLElement, lines: string[]) {\r\n console.log(`🔤 Extracting browser justify space measurements for ${lines.length} lines`);\r\n \r\n // For now, we'll use a simplified approach:\r\n // Apply uniform space expansion to match the line width\r\n const spaceWidths: number[][] = [];\r\n \r\n lines.forEach((line, lineIndex) => {\r\n const lineSpaces: number[] = [];\r\n const spaceCount = (line.match(/\\s/g) || []).length;\r\n \r\n if (spaceCount > 0 && lineIndex < lines.length - 1) { // Don't justify last line\r\n // Calculate how much space expansion is needed\r\n const normalSpaceWidth = 6.4; // Default space width for STV font\r\n const lineWidth = this.width;\r\n \r\n // Estimate natural line width\r\n const charCount = line.length - spaceCount;\r\n const avgCharWidth = 12; // Approximate for STV font\r\n const naturalWidth = charCount * avgCharWidth + spaceCount * normalSpaceWidth;\r\n \r\n // Calculate expanded space width\r\n const remainingSpace = lineWidth - (charCount * avgCharWidth);\r\n const expandedSpaceWidth = remainingSpace / spaceCount;\r\n \r\n console.log(`🔤 Line ${lineIndex}: ${spaceCount} spaces, natural: ${normalSpaceWidth}px -> justified: ${expandedSpaceWidth.toFixed(1)}px`);\r\n \r\n // Fill array with expanded space widths for this line\r\n for (let i = 0; i < spaceCount; i++) {\r\n lineSpaces.push(expandedSpaceWidth);\r\n }\r\n }\r\n \r\n spaceWidths.push(lineSpaces);\r\n });\r\n \r\n return spaceWidths;\r\n }\r\n\r\n /**\r\n * Apply browser-calculated justify space measurements\r\n * @private\r\n */\r\n _applyBrowserJustifySpaces() {\r\n if (!this._textLines || !this.__charBounds) {\r\n console.warn('🔤 BROWSER JUSTIFY: _textLines or __charBounds not ready');\r\n return;\r\n }\r\n\r\n // Get space measurements from browser wrapping result\r\n const styleMap = this._styleMap as any;\r\n if (!styleMap || !styleMap.justifySpaceMeasurements) {\r\n console.warn('🔤 BROWSER JUSTIFY: No justify space measurements available');\r\n return;\r\n }\r\n\r\n const spaceWidths = styleMap.justifySpaceMeasurements as number[][];\r\n console.log('🔤 BROWSER JUSTIFY: Applying space measurements to __charBounds');\r\n\r\n // Apply space widths to character bounds\r\n this._textLines.forEach((line, lineIndex) => {\r\n if (!this.__charBounds || !this.__charBounds[lineIndex] || !spaceWidths[lineIndex]) return;\r\n \r\n const lineBounds = this.__charBounds[lineIndex];\r\n const lineSpaceWidths = spaceWidths[lineIndex];\r\n let spaceIndex = 0;\r\n\r\n for (let charIndex = 0; charIndex < line.length; charIndex++) {\r\n if (/\\s/.test(line[charIndex]) && spaceIndex < lineSpaceWidths.length) {\r\n const expandedWidth = lineSpaceWidths[spaceIndex];\r\n if (lineBounds[charIndex]) {\r\n const oldWidth = lineBounds[charIndex].width;\r\n lineBounds[charIndex].width = expandedWidth;\r\n console.log(`🔤 Line ${lineIndex} space ${spaceIndex}: ${oldWidth.toFixed(1)}px -> ${expandedWidth.toFixed(1)}px`);\r\n }\r\n spaceIndex++;\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Fallback to default Fabric wrapping\r\n * @private\r\n */\r\n _splitTextIntoLinesDefault(text: string) {\r\n const newText = super._splitTextIntoLines(text),\r\n graphemeLines = this._wrapText(newText.lines, this.width),\r\n lines = new Array(graphemeLines.length);\r\n for (let i = 0; i < graphemeLines.length; i++) {\r\n lines[i] = graphemeLines[i].join('');\r\n }\r\n newText.lines = lines;\r\n newText.graphemeLines = graphemeLines;\r\n return newText;\r\n }\r\n\r\n getMinWidth() {\r\n return Math.max(this.minWidth, this.dynamicMinWidth);\r\n }\r\n\r\n _removeExtraneousStyles() {\r\n const linesToKeep = new Map();\r\n for (const prop in this._styleMap) {\r\n const propNumber = parseInt(prop, 10);\r\n if (this._textLines[propNumber]) {\r\n const lineIndex = this._styleMap[prop].line;\r\n linesToKeep.set(`${lineIndex}`, true);\r\n }\r\n }\r\n for (const prop in this.styles) {\r\n if (!linesToKeep.has(prop)) {\r\n delete this.styles[prop];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Initialize event listeners for safety snap functionality\r\n * @private\r\n */\r\n private initializeEventListeners(): void {\r\n // Track which side is being used for resize to handle position compensation\r\n let resizeOrigin: 'left' | 'right' | null = null;\r\n \r\n // Detect resize origin during resizing\r\n this.on('resizing', (e: any) => {\r\n // Check transform origin to determine which side is being resized\r\n if (e.transform) {\r\n const { originX } = e.transform;\r\n // originX tells us which side is the anchor - opposite side is being dragged\r\n resizeOrigin = originX === 'right' ? 'left' : originX === 'left' ? 'right' : null;\r\n } else if (e.originX) {\r\n const { originX } = e;\r\n resizeOrigin = originX === 'right' ? 'left' : originX === 'left' ? 'right' : null;\r\n }\r\n });\r\n \r\n // Only trigger safety snap after resize is complete (not during)\r\n // Use 'modified' event which fires after user releases the mouse\r\n this.on('modified', () => {\r\n const currentResizeOrigin = resizeOrigin; // Capture the value before reset\r\n // Small delay to ensure text layout is updated\r\n setTimeout(() => this.safetySnapWidth(currentResizeOrigin), 10);\r\n resizeOrigin = null; // Reset after capturing\r\n });\r\n \r\n // Also listen to canvas-level modified event as backup\r\n this.canvas?.on('object:modified', (e) => {\r\n if (e.target === this) {\r\n const currentResizeOrigin = resizeOrigin; // Capture the value before reset\r\n setTimeout(() => this.safetySnapWidth(currentResizeOrigin), 10);\r\n resizeOrigin = null; // Reset after capturing\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Safety snap to prevent glyph clipping after manual resize.\r\n * Similar to Polotno - checks if any glyphs are too close to edges\r\n * and automatically expands width if needed.\r\n * @private\r\n * @param resizeOrigin - Which side was used for resizing ('left' or 'right')\r\n */\r\n private safetySnapWidth(resizeOrigin?: 'left' | 'right' | null): void {\r\n // For Textbox objects, we always want to check for clipping regardless of isWrapping flag\r\n if (!this._textLines || this.type.toLowerCase() !== 'textbox' || this._textLines.length === 0) {\r\n return;\r\n }\r\n \r\n const lineCount = this._textLines.length;\r\n if (lineCount === 0) return;\r\n\r\n // Check all lines, not just the last one\r\n let maxActualLineWidth = 0; // Actual measured width without buffers\r\n let maxRequiredWidth = 0; // Width including RTL buffer\r\n \r\n for (let i = 0; i < lineCount; i++) {\r\n const lineText = this._textLines[i].join(''); // Convert grapheme array to string\r\n const lineWidth = this.getLineWidth(i);\r\n maxActualLineWidth = Math.max(maxActualLineWidth, lineWidth);\r\n \r\n // RTL detection - regex for Arabic, Hebrew, and other RTL characters\r\n const rtlRegex = /[\\u0590-\\u05FF\\u0600-\\u06FF\\u0750-\\u077F\\uFB50-\\uFDFF\\uFE70-\\uFEFF]/;\r\n if (rtlRegex.test(lineText)) {\r\n // Add minimal RTL compensation buffer - just enough to prevent clipping\r\n const rtlBuffer = (this.fontSize || 16) * 0.15; // 15% of font size (much smaller)\r\n maxRequiredWidth = Math.max(maxRequiredWidth, lineWidth + rtlBuffer);\r\n } else {\r\n maxRequiredWidth = Math.max(maxRequiredWidth, lineWidth);\r\n }\r\n }\r\n\r\n // Safety margin - how close glyphs can get before we snap\r\n const safetyThreshold = 2; // px - very subtle trigger\r\n \r\n if (maxRequiredWidth > this.width - safetyThreshold) {\r\n // Set width to exactly what's needed + minimal safety margin\r\n const newWidth = maxRequiredWidth + 1; // Add just 1px safety margin\r\n \r\n // Store original position before width change\r\n const originalLeft = this.left;\r\n const originalTop = this.top;\r\n const widthIncrease = newWidth - this.width;\r\n \r\n // Change width \r\n this.set('width', newWidth);\r\n \r\n // Force text layout recalculation\r\n this.initDimensions();\r\n \r\n // Only compensate position when resizing from left handle\r\n // Right handle resize doesn't shift the text position\r\n if (resizeOrigin === 'left') {\r\n // When resizing from left, the expansion pushes text right\r\n // Compensate by moving the textbox left by the width increase\r\n this.set({\r\n 'left': originalLeft - widthIncrease,\r\n 'top': originalTop\r\n });\r\n }\r\n \r\n this.setCoords();\r\n \r\n // Also refresh the overlay editor if it exists\r\n if ((this as any).__overlayEditor) {\r\n setTimeout(() => {\r\n (this as any).__overlayEditor.refresh();\r\n }, 0);\r\n }\r\n \r\n this.canvas?.requestRenderAll();\r\n }\r\n }\r\n\r\n /**\r\n * Force complete textbox re-initialization (useful after JSON loading)\r\n * Overrides Text version with Textbox-specific logic\r\n */\r\n forceTextReinitialization(): void {\r\n console.log('🔄 Force reinitializing Textbox object');\r\n \r\n // CRITICAL: Ensure textbox is marked as initialized\r\n this.initialized = true;\r\n \r\n // Clear all caches and force dirty state\r\n this._clearCache();\r\n this.dirty = true;\r\n this.dynamicMinWidth = 0;\r\n \r\n // Force isEditing false to ensure clean state\r\n this.isEditing = false;\r\n \r\n console.log(' → Set initialized=true, dirty=true, cleared caches');\r\n \r\n // Re-initialize dimensions (this will handle justify properly)\r\n this.initDimensions();\r\n \r\n // Double-check that justify was applied by checking space widths\r\n if (this.textAlign.includes('justify') && this.__charBounds) {\r\n setTimeout(() => {\r\n // Verify justify was applied by checking if space widths vary\r\n let hasVariableSpaces = false;\r\n this.__charBounds.forEach((lineBounds, i) => {\r\n if (lineBounds && this._textLines && this._textLines[i]) {\r\n const spaces = lineBounds.filter((bound, j) => /\\s/.test(this._textLines[i][j]));\r\n if (spaces.length > 1) {\r\n const firstSpaceWidth = spaces[0].width;\r\n hasVariableSpaces = spaces.some(space => Math.abs(space.width - firstSpaceWidth) > 0.1);\r\n }\r\n }\r\n });\r\n \r\n if (!hasVariableSpaces && this.__charBounds.length > 0) {\r\n console.warn(' ⚠️ Justify spaces still uniform - forcing enlargeSpaces again');\r\n if (this.enlargeSpaces) {\r\n this.enlargeSpaces();\r\n }\r\n } else {\r\n console.log(' ✅ Justify spaces properly expanded');\r\n }\r\n \r\n // Ensure height is recalculated - use browser height if available\r\n if ((this as any)._usingBrowserWrapping && (this as any)._actualBrowserHeight) {\r\n this.height = (this as any)._actualBrowserHeight;\r\n console.log(`🔤 JUSTIFY: Preserved browser height: ${this.height}px`);\r\n } else {\r\n this.height = this.calcTextHeight();\r\n console.log(`🔧 JUSTIFY: Used calcTextHeight: ${this.height}px`);\r\n }\r\n this.canvas?.requestRenderAll();\r\n }, 10);\r\n }\r\n }\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} object representation of an instance\r\n */\r\n toObject<\r\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\r\n K extends keyof T = never,\r\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\r\n return super.toObject<T, K>([\r\n 'minWidth',\r\n 'splitByGrapheme',\r\n ...propertiesToInclude,\r\n ] as K[]);\r\n }\r\n}\r\n\r\nclassRegistry.setClass(Textbox);\r\n"],"names":["textboxDefaultValues","minWidth","dynamicMinWidth","lockScalingFlip","noScaleCache","_wordJoiners","splitByGrapheme","Textbox","IText","getDefaults","ownDefaults","constructor","text","options","initializeEventListeners","createControls","controls","createTextboxDefaultControls","initDimensions","initialized","_usingBrowserWrapping","now","Date","lastCall","_lastInitDimensionsTime","isRapidCall","isDuringLoading","_jsonLoading","_browserWrapInitialized","currentState","width","fontSize","fontFamily","textAlign","_lastDimensionState","_textLines","length","enableAdvancedLayout","initDimensionsAdvanced","isEditing","initDelayedCursor","_clearCache","splitTextResult","_splitText","_styleMap","_generateStyleMap","lines","map","line","split","justifyMeasurements","justifySpaceMeasurements","actualHeight","actualBrowserHeight","_actualBrowserHeight","_set","console","log","includes","JUSTIFY","_applyBrowserJustifySpaces","lastDragTime","isDuringDrag","__charBounds","fontReady","_isFontReady","enlargeSpaces","warn","_scheduleJustifyAfterFontLoad","setTimeout","_this$canvas","canvas","requestRenderAll","oldHeight","height","calcTextHeight","Math","abs","_this$canvas2","_this$_textLines","setCoords","top","left","lineHeight","_getTopOffset","document","_fontJustifyScheduled","fontSpec","fonts","load","then","_this$canvas3","catch","layout","layoutText","wrap","align","_mapTextAlignToAlign","ellipsis","letterSpacing","charSpacing","direction","fontStyle","fontWeight","verticalAlign","maxLineWidth","max","newLayout","_getAdvancedLayoutOptions","totalHeight","_convertLayoutToLegacyFormat","_generateStyleMapFromLayout","dirty","realLineCount","charCount","forEach","i","offset","graphemes","textInfo","realLineCharCount","graphemeLines","graphemeText","_reSpaceAndTab","test","styleHas","property","lineIndex","isWrapping","isEmptyStyles","styles","nextLineIndex","nextOffset","shouldLimit","mapNextLine","obj","p1","p2","p2Number","parseInt","p3","_getStyleDeclaration","charIndex","_setStyleDeclaration","style","_deleteStyleDeclaration","_getLineStyle","_setLineStyle","_wrapText","desiredWidth","data","getGraphemeDataForRender","wrapped","wordsData","push","_wrapLine","infix","largestWordWidth","wordsOrGraphemes","graphemeSplit","wordSplit","word","graphemeArray","_measureWord","charOffset","arguments","undefined","prevGrapheme","skipLeft","len","box","_getGraphemeBox","kernedWidth","value","_ref","reservedSpace","additionalSpace","_getWidthOfCharSpacing","lineWidth","infixWidth","lineJustStarted","maxWidth","wordWidth","potentialLineWidth","conservativeMaxWidth","currentLineText","join","toFixed","concat","isEndOfWrapping","missingNewlineOffset","skipWrapping","_splitTextIntoLines","needsBrowserWrapping","fontLacksEnglishGlyphsCached","textHash","slice","cacheKey","_browserWrapCache","key","cachedResult","result","_splitTextIntoLinesWithBrowser","newText","Array","_splitTextIntoLinesDefault","testElement","createElement","position","visibility","String","whiteSpace","wordBreak","overflowWrap","textAlignLast","textContent","body","appendChild","range","createRange","textNode","firstChild","nodeType","Node","TEXT_NODE","currentLineStart","textLength","previousBottom","setStart","setEnd","rect","getBoundingClientRect","bottom","lineEnd","lineText","substring","trim","graphemeLine","error","removeChild","scrollHeight","offsetHeight","clientHeight","boundingRect","_extractJustifySpaceMeasurements","bestHeight","adjustedHeight","lacksEnglishGlyphs","glyphBuffer","_unwrappedLines","element","spaceWidths","lineSpaces","spaceCount","match","normalSpaceWidth","avgCharWidth","remainingSpace","expandedSpaceWidth","styleMap","lineBounds","lineSpaceWidths","spaceIndex","expandedWidth","oldWidth","getMinWidth","_removeExtraneousStyles","linesToKeep","Map","prop","propNumber","set","has","_this$canvas4","resizeOrigin","on","e","transform","originX","currentResizeOrigin","safetySnapWidth","target","type","toLowerCase","lineCount","maxRequiredWidth","getLineWidth","rtlRegex","rtlBuffer","safetyThreshold","_this$canvas5","newWidth","originalLeft","originalTop","widthIncrease","__overlayEditor","refresh","forceTextReinitialization","_this$canvas6","hasVariableSpaces","spaces","filter","bound","j","firstSpaceWidth","some","space","toObject","propertiesToInclude","_defineProperty","textLayoutProperties","classRegistry","setClass"],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Usage Example: Enhanced Arabic Text Support
3
+ *
4
+ * This example demonstrates how to use the improved text measurement system
5
+ * for better Arabic font support and bounding box calculations.
6
+ */
7
+ import { FabricText } from '../../shapes/Text/Text';
8
+ /**
9
+ * Example 1: Basic Arabic text with enhanced layout
10
+ */
11
+ declare function createArabicTextWithEnhancedLayout(): FabricText<{
12
+ fontFamily: string;
13
+ fontSize: number;
14
+ fill: string;
15
+ enableAdvancedLayout: true;
16
+ direction: "rtl";
17
+ textAlign: string;
18
+ letterSpacing: number;
19
+ lineHeight: number;
20
+ }, import("../../shapes/Text/Text").SerializedTextProps, import("../../EventTypeDefs").ObjectEvents>;
21
+ /**
22
+ * Example 2: Comparing legacy vs enhanced measurement
23
+ */
24
+ declare function compareMeasurementSystems(): {
25
+ legacy: FabricText<{
26
+ fontFamily: string;
27
+ fontSize: number;
28
+ enableAdvancedLayout: false;
29
+ }, import("../../shapes/Text/Text").SerializedTextProps, import("../../EventTypeDefs").ObjectEvents>;
30
+ enhanced: FabricText<{
31
+ fontFamily: string;
32
+ fontSize: number;
33
+ enableAdvancedLayout: true;
34
+ }, import("../../shapes/Text/Text").SerializedTextProps, import("../../EventTypeDefs").ObjectEvents>;
35
+ };
36
+ /**
37
+ * Example 3: Manual measurement of Arabic characters
38
+ */
39
+ declare function measureArabicCharacters(): void;
40
+ /**
41
+ * Example 4: Mixed script text (Arabic + English)
42
+ */
43
+ declare function createMixedScriptText(): FabricText<{
44
+ fontFamily: string;
45
+ fontSize: number;
46
+ fill: string;
47
+ enableAdvancedLayout: true;
48
+ direction: "ltr";
49
+ textAlign: string;
50
+ }, import("../../shapes/Text/Text").SerializedTextProps, import("../../EventTypeDefs").ObjectEvents>;
51
+ /**
52
+ * Example 5: Font metrics comparison across scripts
53
+ */
54
+ declare function compareFontMetricsAcrossScripts(): void;
55
+ /**
56
+ * Main function to run all examples
57
+ */
58
+ declare function runArabicTextExamples(): void;
59
+ export { runArabicTextExamples, createArabicTextWithEnhancedLayout, compareMeasurementSystems, measureArabicCharacters, createMixedScriptText, compareFontMetricsAcrossScripts, };
60
+ //# sourceMappingURL=arabicTextExample.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arabicTextExample.d.ts","sourceRoot":"","sources":["../../../../src/text/examples/arabicTextExample.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAKpD;;GAEG;AACH,iBAAS,kCAAkC;;;;;;;;;qGA2B1C;AAED;;GAEG;AACH,iBAAS,yBAAyB;;;;;;;;;;;EAmCjC;AAED;;GAEG;AACH,iBAAS,uBAAuB,SA6B/B;AAED;;GAEG;AACH,iBAAS,qBAAqB;;;;;;;qGAqB7B;AAED;;GAEG;AACH,iBAAS,+BAA+B,SA8BvC;AAED;;GAEG;AACH,iBAAS,qBAAqB,SAsB7B;AAGD,OAAO,EACL,qBAAqB,EACrB,kCAAkC,EAClC,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,+BAA+B,GAChC,CAAC"}
@@ -127,5 +127,14 @@ export declare function estimateTextWidth(text: string, options: MeasurementOpti
127
127
  * Check if font is loaded and ready for measurement
128
128
  */
129
129
  export declare function isFontReady(fontFamily: string): boolean;
130
+ /**
131
+ * Detect if a font lacks English glyph support
132
+ * These fonts should use browser-native measurement instead of Fabric's character-by-character measurement
133
+ */
134
+ export declare function fontLacksEnglishGlyphs(fontFamily: string): boolean;
135
+ /**
136
+ * Cached version of font glyph detection
137
+ */
138
+ export declare function fontLacksEnglishGlyphsCached(fontFamily: string): boolean;
130
139
  export {};
131
140
  //# sourceMappingURL=measure.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../../../src/text/measure.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../../../src/text/measure.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{defineProperty as t}from"../../_virtual/_rollupPluginBabelHelpers.min.mjs";import{createCanvasElementFor as e}from"../util/misc/dom.min.mjs";let s=null;function i(){if(!s){const t=e({width:0,height:0});s=t.getContext("2d")}return s}function n(t,e,s){const n=u.get(t,e);if(n)return n;const c=s||i();a(c,e);const o=c.measureText(t),r=h(e),l={width:o.width,height:r.lineHeight,ascent:r.ascent,descent:r.descent,baseline:r.ascent};return u.set(t,e,l),l}function c(t,e,s,c){const h=n(t,s,c);if(!e)return{...h,kernedWidth:h.width};const o=`${e}${t}`,r=g.get(o,s);if(r)return{...h,kernedWidth:r};const l=i();a(l,s);const u=l.measureText(e+t).width-n(e,s,l).width;return g.set(o,s,u),{...h,kernedWidth:u}}function h(t){var e,s,n,c;const h=o(t),r=d.get(h);if(r)return r;const l=i();a(l,t);const u=l.measureText("M"),g=t.fontSize,m=null!==(e=u.fontBoundingBoxAscent)&&void 0!==e?e:.91*g,f=null!==(s=u.fontBoundingBoxDescent)&&void 0!==s?s:.21*g,p={ascent:m,descent:f,lineHeight:g,baseline:"alphabetic",fontBoundingBoxAscent:m,fontBoundingBoxDescent:f,actualBoundingBoxAscent:null!==(n=u.actualBoundingBoxAscent)&&void 0!==n?n:.716*g,actualBoundingBoxDescent:null!==(c=u.actualBoundingBoxDescent)&&void 0!==c?c:0};return d.set(h,p),p}function a(t,e){const s=o(e);t.font=s,e.letterSpacing&&"letterSpacing"in t&&(t.letterSpacing=`${e.letterSpacing}px`),e.direction&&(t.direction=e.direction),t.textBaseline="alphabetic"}function o(t){const{fontStyle:e,fontWeight:s,fontSize:i,fontFamily:n}=t;return`${e} ${s} ${i}px ${!n.includes(" ")||n.includes('"')||n.includes("'")?n:`"${n}"`}`}class r{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1e3;t(this,"cache",new Map),t(this,"maxSize",void 0),t(this,"hits",0),t(this,"misses",0),this.maxSize=e}get(t){const e=this.cache.get(t);if(e)return e.timestamp=Date.now(),this.hits++,e.value;this.misses++}set(t,e){if(this.cache.size>=this.maxSize){const t=this.findOldestKey();t&&this.cache.delete(t)}this.cache.set(t,{value:e,timestamp:Date.now()})}findOldestKey(){let t,e=1/0;for(const[s,i]of this.cache.entries())i.timestamp<e&&(e=i.timestamp,t=s);return t}clear(){this.cache.clear(),this.hits=0,this.misses=0}getStats(){const t=this.hits+this.misses;return{size:this.cache.size,hitRate:t>0?this.hits/t:0,hits:this.hits,misses:this.misses}}}class l{constructor(){t(this,"cache",new r(1e3))}getCacheKey(t,e){return`${o(e)}|${t}|${e.letterSpacing||0}`}get(t,e){const s=this.getCacheKey(t,e);return this.cache.get(s)}set(t,e,s){const i=this.getCacheKey(t,e);this.cache.set(i,s)}clear(){this.cache.clear()}getStats(){return this.cache.getStats()}}const u=new l,g=new class{constructor(){t(this,"cache",new r(5e3))}getCacheKey(t,e){return`${o(e)}|${t}`}get(t,e){const s=this.getCacheKey(t,e);return this.cache.get(s)}set(t,e,s){const i=this.getCacheKey(t,e);this.cache.set(i,s)}clear(){this.cache.clear()}getStats(){return this.cache.getStats()}},d=new class{constructor(){t(this,"cache",new Map)}get(t){return this.cache.get(t)}set(t,e){this.cache.set(t,e)}clear(){this.cache.clear()}getStats(){return{size:this.cache.size}}};export{l as MeasurementCache,d as fontMetricsCache,h as getFontMetrics,g as kerningCache,n as measureGrapheme,c as measureGraphemeWithKerning,u as measurementCache};
1
+ import{defineProperty as t}from"../../_virtual/_rollupPluginBabelHelpers.min.mjs";import{createCanvasElementFor as e}from"../util/misc/dom.min.mjs";let n=null;function s(){if(!n){const t=e({width:0,height:0});n=t.getContext("2d")}return n}function i(t,e,n){const i=l.get(t,e);if(i)return i;const c=n||s();r(c,e);const h=c.measureText(t),o=a(e),u={width:h.width,height:o.lineHeight,ascent:o.ascent,descent:o.descent,baseline:o.ascent};return l.set(t,e,u),u}function c(t,e,n,c){const a=i(t,n,c);if(!e)return{...a,kernedWidth:a.width};const h=`${e}${t}`,o=d.get(h,n);if(o)return{...a,kernedWidth:o};const u=s();r(u,n);const l=u.measureText(e+t).width-i(e,n,u).width;return d.set(h,n,l),{...a,kernedWidth:l}}function a(t){var e,n,i,c;const a=h(t),o=f.get(a);if(o)return o;const u=s();r(u,t);const l=function(t){const e=s();if("undefined"!=typeof document&&"fonts"in document)try{if(!document.fonts.check(`16px ${t}`))return"M"}catch(t){return"M"}const n=[{char:"م",script:"Arabic"},{char:"א",script:"Hebrew"},{char:"अ",script:"Devanagari"},{char:"ا",script:"Urdu"},{char:"ک",script:"Persian"},{char:"த",script:"Tamil"},{char:"ก",script:"Thai"},{char:"М",script:"Cyrillic"},{char:"Ω",script:"Greek"},{char:"M",script:"Latin"}];e.font=`16px ${t}`;const i=e.measureText("M").width;for(const t of n){const n=e.measureText(t.char);if(n.width>0&&Math.abs(n.width-i)>.1)return t.char}return"M"}(t.fontFamily),d=u.measureText(l),g=t.fontSize,m=null!==(e=d.fontBoundingBoxAscent)&&void 0!==e?e:.91*g,p=null!==(n=d.fontBoundingBoxDescent)&&void 0!==n?n:.21*g,x={ascent:m,descent:p,lineHeight:g,baseline:"alphabetic",fontBoundingBoxAscent:m,fontBoundingBoxDescent:p,actualBoundingBoxAscent:null!==(i=d.actualBoundingBoxAscent)&&void 0!==i?i:.716*g,actualBoundingBoxDescent:null!==(c=d.actualBoundingBoxDescent)&&void 0!==c?c:0};return f.set(a,x),x}function r(t,e){const n=h(e);t.font=n,e.letterSpacing&&"letterSpacing"in t&&(t.letterSpacing=`${e.letterSpacing}px`),e.direction&&(t.direction=e.direction),t.textBaseline="alphabetic"}function h(t){const{fontStyle:e,fontWeight:n,fontSize:s,fontFamily:i}=t;return`${e} ${n} ${s}px ${!i.includes(" ")||i.includes('"')||i.includes("'")?i:`"${i}"`}`}class o{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1e3;t(this,"cache",new Map),t(this,"maxSize",void 0),t(this,"hits",0),t(this,"misses",0),this.maxSize=e}get(t){const e=this.cache.get(t);if(e)return e.timestamp=Date.now(),this.hits++,e.value;this.misses++}set(t,e){if(this.cache.size>=this.maxSize){const t=this.findOldestKey();t&&this.cache.delete(t)}this.cache.set(t,{value:e,timestamp:Date.now()})}findOldestKey(){let t,e=1/0;for(const[n,s]of this.cache.entries())s.timestamp<e&&(e=s.timestamp,t=n);return t}clear(){this.cache.clear(),this.hits=0,this.misses=0}getStats(){const t=this.hits+this.misses;return{size:this.cache.size,hitRate:t>0?this.hits/t:0,hits:this.hits,misses:this.misses}}}class u{constructor(){t(this,"cache",new o(1e3))}getCacheKey(t,e){return`${h(e)}|${t}|${e.letterSpacing||0}`}get(t,e){const n=this.getCacheKey(t,e);return this.cache.get(n)}set(t,e,n){const s=this.getCacheKey(t,e);this.cache.set(s,n)}clear(){this.cache.clear()}getStats(){return this.cache.getStats()}}const l=new u,d=new class{constructor(){t(this,"cache",new o(5e3))}getCacheKey(t,e){return`${h(e)}|${t}`}get(t,e){const n=this.getCacheKey(t,e);return this.cache.get(n)}set(t,e,n){const s=this.getCacheKey(t,e);this.cache.set(s,n)}clear(){this.cache.clear()}getStats(){return this.cache.getStats()}},f=new class{constructor(){t(this,"cache",new Map)}get(t){return this.cache.get(t)}set(t,e){this.cache.set(t,e)}clear(){this.cache.clear()}getStats(){return{size:this.cache.size}}};function g(){l.clear(),d.clear(),f.clear()}function m(t){if("undefined"==typeof document)return!1;const e=t.toLowerCase();if(["stv","arabic","naskh","thuluth","kufi","diwani","nastaliq","kufic","hijazi","madinah","makkah"].some(t=>e.includes(t)))return!0;const n=s();n.font=`16px ${t}`;const i=["A","B","C","a","b","c","M","W"],c=i.map(t=>n.measureText(t).width);n.font="16px Arial, sans-serif";const a=i.map(t=>n.measureText(t).width);let r=0;for(let t=0;t<i.length;t++)Math.abs(c[t]-a[t])<.5&&r++;return r>=.7*i.length}"undefined"!=typeof document&&"fonts"in document&&document.fonts.addEventListener("loadingdone",()=>{g()});const p=new Map;function x(t){if(p.has(t))return p.get(t);const e=m(t);return p.set(t,e),e}export{u as MeasurementCache,g as clearAllCaches,m as fontLacksEnglishGlyphs,x as fontLacksEnglishGlyphsCached,f as fontMetricsCache,a as getFontMetrics,d as kerningCache,i as measureGrapheme,c as measureGraphemeWithKerning,l as measurementCache};
2
2
  //# sourceMappingURL=measure.min.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"measure.min.mjs","sources":["../../../src/text/measure.ts"],"sourcesContent":["/**\r\n * Advanced Text Measurement System\r\n * \r\n * Provides precise text measurement with caching, font metrics,\r\n * and DPI awareness for optimal performance and accuracy.\r\n */\r\n\r\nimport { createCanvasElementFor } from '../util/misc/dom';\r\n\r\nexport interface MeasurementOptions {\r\n fontFamily: string;\r\n fontSize: number;\r\n fontStyle: string;\r\n fontWeight: string | number;\r\n letterSpacing?: number;\r\n direction?: 'ltr' | 'rtl';\r\n}\r\n\r\nexport interface GraphemeMeasurement {\r\n width: number;\r\n height: number;\r\n ascent: number;\r\n descent: number;\r\n baseline: number;\r\n}\r\n\r\nexport interface KerningMeasurement extends GraphemeMeasurement {\r\n kernedWidth: number; // width accounting for kerning with previous char\r\n}\r\n\r\nexport interface FontMetrics {\r\n ascent: number;\r\n descent: number;\r\n lineHeight: number;\r\n baseline: string;\r\n fontBoundingBoxAscent?: number;\r\n fontBoundingBoxDescent?: number;\r\n actualBoundingBoxAscent?: number;\r\n actualBoundingBoxDescent?: number;\r\n}\r\n\r\n// Global measurement context - reused for performance\r\nlet measurementContext: CanvasRenderingContext2D | null = null;\r\n\r\n/**\r\n * Get or create the shared measurement context\r\n */\r\nfunction getMeasurementContext(): CanvasRenderingContext2D {\r\n if (!measurementContext) {\r\n const canvas = createCanvasElementFor({\r\n width: 0,\r\n height: 0,\r\n });\r\n measurementContext = canvas.getContext('2d')!;\r\n }\r\n return measurementContext;\r\n}\r\n\r\n/**\r\n * Measure a single grapheme\r\n */\r\nexport function measureGrapheme(\r\n grapheme: string,\r\n options: MeasurementOptions,\r\n ctx?: CanvasRenderingContext2D\r\n): GraphemeMeasurement {\r\n // Check cache first\r\n const cached = measurementCache.get(grapheme, options);\r\n if (cached) {\r\n return cached;\r\n }\r\n\r\n // Use provided context or get global one\r\n const context = ctx || getMeasurementContext();\r\n \r\n // Set font properties\r\n applyFontStyle(context, options);\r\n \r\n // Measure the grapheme\r\n const metrics = context.measureText(grapheme);\r\n const fontMetrics = getFontMetrics(options);\r\n \r\n // Calculate comprehensive measurements\r\n const measurement: GraphemeMeasurement = {\r\n width: metrics.width,\r\n height: fontMetrics.lineHeight,\r\n ascent: fontMetrics.ascent,\r\n descent: fontMetrics.descent,\r\n baseline: fontMetrics.ascent,\r\n };\r\n \r\n // Cache the result\r\n measurementCache.set(grapheme, options, measurement);\r\n \r\n return measurement;\r\n}\r\n\r\n/**\r\n * Measure a grapheme with kerning relative to previous character\r\n */\r\nexport function measureGraphemeWithKerning(\r\n grapheme: string,\r\n previousGrapheme: string | undefined,\r\n options: MeasurementOptions,\r\n ctx?: CanvasRenderingContext2D\r\n): KerningMeasurement {\r\n // Get individual measurement\r\n const individual = measureGrapheme(grapheme, options, ctx);\r\n \r\n // If no previous character, kerning width equals regular width\r\n if (!previousGrapheme) {\r\n return {\r\n ...individual,\r\n kernedWidth: individual.width,\r\n };\r\n }\r\n \r\n // Check kerning cache\r\n const kerningPair = `${previousGrapheme}${grapheme}`;\r\n const cachedKerning = kerningCache.get(kerningPair, options);\r\n if (cachedKerning) {\r\n return {\r\n ...individual,\r\n kernedWidth: cachedKerning,\r\n };\r\n }\r\n \r\n // Use provided context or get global one\r\n const context = ctx || getMeasurementContext();\r\n applyFontStyle(context, options);\r\n \r\n // Measure the pair\r\n const pairWidth = context.measureText(previousGrapheme + grapheme).width;\r\n const previousWidth = measureGrapheme(previousGrapheme, options, context).width;\r\n const kernedWidth = pairWidth - previousWidth;\r\n \r\n // Cache kerning result\r\n kerningCache.set(kerningPair, options, kernedWidth);\r\n \r\n return {\r\n ...individual,\r\n kernedWidth,\r\n };\r\n}\r\n\r\n/**\r\n * Get font metrics for layout calculations\r\n */\r\nexport function getFontMetrics(options: MeasurementOptions): FontMetrics {\r\n const cacheKey = getFontDeclaration(options);\r\n const cached = fontMetricsCache.get(cacheKey);\r\n if (cached) {\r\n return cached;\r\n }\r\n \r\n const context = getMeasurementContext();\r\n applyFontStyle(context, options);\r\n \r\n // Use 'M' as sample character for metrics\r\n const metrics = context.measureText('M');\r\n const fontSize = options.fontSize;\r\n \r\n // Calculate metrics with fallbacks\r\n const fontBoundingBoxAscent = metrics.fontBoundingBoxAscent ?? fontSize * 0.91;\r\n const fontBoundingBoxDescent = metrics.fontBoundingBoxDescent ?? fontSize * 0.21;\r\n const actualBoundingBoxAscent = metrics.actualBoundingBoxAscent ?? fontSize * 0.716;\r\n const actualBoundingBoxDescent = metrics.actualBoundingBoxDescent ?? 0;\r\n \r\n const result: FontMetrics = {\r\n ascent: fontBoundingBoxAscent,\r\n descent: fontBoundingBoxDescent,\r\n lineHeight: fontSize,\r\n baseline: 'alphabetic',\r\n fontBoundingBoxAscent,\r\n fontBoundingBoxDescent,\r\n actualBoundingBoxAscent,\r\n actualBoundingBoxDescent,\r\n };\r\n \r\n fontMetricsCache.set(cacheKey, result);\r\n return result;\r\n}\r\n\r\n/**\r\n * Apply font styling to canvas context\r\n */\r\nfunction applyFontStyle(ctx: CanvasRenderingContext2D, options: MeasurementOptions): void {\r\n const fontDeclaration = getFontDeclaration(options);\r\n ctx.font = fontDeclaration;\r\n \r\n if (options.letterSpacing) {\r\n // Modern browsers support letterSpacing\r\n if ('letterSpacing' in ctx) {\r\n (ctx as any).letterSpacing = `${options.letterSpacing}px`;\r\n }\r\n }\r\n \r\n if (options.direction) {\r\n ctx.direction = options.direction;\r\n }\r\n \r\n ctx.textBaseline = 'alphabetic';\r\n}\r\n\r\n/**\r\n * Generate font declaration string\r\n */\r\nfunction getFontDeclaration(options: MeasurementOptions): string {\r\n const { fontStyle, fontWeight, fontSize, fontFamily } = options;\r\n \r\n // Normalize font family (add quotes if needed)\r\n const normalizedFamily = fontFamily.includes(' ') && \r\n !fontFamily.includes('\"') && \r\n !fontFamily.includes(\"'\")\r\n ? `\"${fontFamily}\"`\r\n : fontFamily;\r\n \r\n return `${fontStyle} ${fontWeight} ${fontSize}px ${normalizedFamily}`;\r\n}\r\n\r\n/**\r\n * LRU Cache implementation for measurements\r\n */\r\nclass LRUCache<T> {\r\n private cache = new Map<string, { value: T; timestamp: number }>();\r\n private maxSize: number;\r\n private hits = 0;\r\n private misses = 0;\r\n\r\n constructor(maxSize = 1000) {\r\n this.maxSize = maxSize;\r\n }\r\n\r\n get(key: string): T | undefined {\r\n const entry = this.cache.get(key);\r\n if (entry) {\r\n // Update timestamp for LRU\r\n entry.timestamp = Date.now();\r\n this.hits++;\r\n return entry.value;\r\n }\r\n this.misses++;\r\n return undefined;\r\n }\r\n\r\n set(key: string, value: T): void {\r\n // Remove oldest entries if at capacity\r\n if (this.cache.size >= this.maxSize) {\r\n const oldestKey = this.findOldestKey();\r\n if (oldestKey) {\r\n this.cache.delete(oldestKey);\r\n }\r\n }\r\n\r\n this.cache.set(key, {\r\n value,\r\n timestamp: Date.now(),\r\n });\r\n }\r\n\r\n private findOldestKey(): string | undefined {\r\n let oldestKey: string | undefined;\r\n let oldestTime = Infinity;\r\n\r\n for (const [key, entry] of this.cache.entries()) {\r\n if (entry.timestamp < oldestTime) {\r\n oldestTime = entry.timestamp;\r\n oldestKey = key;\r\n }\r\n }\r\n\r\n return oldestKey;\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n this.hits = 0;\r\n this.misses = 0;\r\n }\r\n\r\n getStats(): { size: number; hitRate: number; hits: number; misses: number } {\r\n const total = this.hits + this.misses;\r\n return {\r\n size: this.cache.size,\r\n hitRate: total > 0 ? this.hits / total : 0,\r\n hits: this.hits,\r\n misses: this.misses,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Advanced measurement cache with font-aware keys\r\n */\r\nexport class MeasurementCache {\r\n private cache = new LRUCache<GraphemeMeasurement>(1000);\r\n\r\n getCacheKey(grapheme: string, options: MeasurementOptions): string {\r\n const fontDecl = getFontDeclaration(options);\r\n const letterSpacing = options.letterSpacing || 0;\r\n return `${fontDecl}|${grapheme}|${letterSpacing}`;\r\n }\r\n\r\n get(grapheme: string, options: MeasurementOptions): GraphemeMeasurement | undefined {\r\n const key = this.getCacheKey(grapheme, options);\r\n return this.cache.get(key);\r\n }\r\n\r\n set(grapheme: string, options: MeasurementOptions, measurement: GraphemeMeasurement): void {\r\n const key = this.getCacheKey(grapheme, options);\r\n this.cache.set(key, measurement);\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n }\r\n\r\n getStats() {\r\n return this.cache.getStats();\r\n }\r\n}\r\n\r\n/**\r\n * Kerning cache for character pairs\r\n */\r\nclass KerningCache {\r\n private cache = new LRUCache<number>(5000); // More entries for pairs\r\n\r\n getCacheKey(pair: string, options: MeasurementOptions): string {\r\n const fontDecl = getFontDeclaration(options);\r\n return `${fontDecl}|${pair}`;\r\n }\r\n\r\n get(pair: string, options: MeasurementOptions): number | undefined {\r\n const key = this.getCacheKey(pair, options);\r\n return this.cache.get(key);\r\n }\r\n\r\n set(pair: string, options: MeasurementOptions, kerning: number): void {\r\n const key = this.getCacheKey(pair, options);\r\n this.cache.set(key, kerning);\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n }\r\n\r\n getStats() {\r\n return this.cache.getStats();\r\n }\r\n}\r\n\r\n/**\r\n * Font metrics cache\r\n */\r\nclass FontMetricsCache {\r\n private cache = new Map<string, FontMetrics>();\r\n\r\n get(fontDeclaration: string): FontMetrics | undefined {\r\n return this.cache.get(fontDeclaration);\r\n }\r\n\r\n set(fontDeclaration: string, metrics: FontMetrics): void {\r\n this.cache.set(fontDeclaration, metrics);\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n }\r\n\r\n getStats() {\r\n return {\r\n size: this.cache.size,\r\n };\r\n }\r\n}\r\n\r\n// Global cache instances\r\nexport const measurementCache = new MeasurementCache();\r\nexport const kerningCache = new KerningCache();\r\nexport const fontMetricsCache = new FontMetricsCache();\r\n\r\n/**\r\n * Clear all measurement caches\r\n */\r\nexport function clearAllCaches(): void {\r\n measurementCache.clear();\r\n kerningCache.clear();\r\n fontMetricsCache.clear();\r\n}\r\n\r\n/**\r\n * Get combined cache statistics\r\n */\r\nexport function getCacheStats() {\r\n return {\r\n measurement: measurementCache.getStats(),\r\n kerning: kerningCache.getStats(),\r\n fontMetrics: fontMetricsCache.getStats(),\r\n };\r\n}\r\n\r\n/**\r\n * Batch measure multiple graphemes efficiently\r\n */\r\nexport function batchMeasureGraphemes(\r\n graphemes: string[],\r\n options: MeasurementOptions,\r\n ctx?: CanvasRenderingContext2D\r\n): GraphemeMeasurement[] {\r\n const context = ctx || getMeasurementContext();\r\n applyFontStyle(context, options);\r\n \r\n // Separate cached and uncached measurements\r\n const results: GraphemeMeasurement[] = new Array(graphemes.length);\r\n const uncachedIndices: number[] = [];\r\n \r\n // Check cache for all graphemes\r\n graphemes.forEach((grapheme, index) => {\r\n const cached = measurementCache.get(grapheme, options);\r\n if (cached) {\r\n results[index] = cached;\r\n } else {\r\n uncachedIndices.push(index);\r\n }\r\n });\r\n \r\n // Measure uncached graphemes\r\n const fontMetrics = getFontMetrics(options);\r\n uncachedIndices.forEach(index => {\r\n const grapheme = graphemes[index];\r\n const metrics = context.measureText(grapheme);\r\n \r\n const measurement: GraphemeMeasurement = {\r\n width: metrics.width,\r\n height: fontMetrics.lineHeight,\r\n ascent: fontMetrics.ascent,\r\n descent: fontMetrics.descent,\r\n baseline: fontMetrics.ascent,\r\n };\r\n \r\n measurementCache.set(grapheme, options, measurement);\r\n results[index] = measurement;\r\n });\r\n \r\n return results;\r\n}\r\n\r\n/**\r\n * Estimate text width without full layout (for performance)\r\n */\r\nexport function estimateTextWidth(\r\n text: string,\r\n options: MeasurementOptions\r\n): number {\r\n // Use average character width for estimation\r\n const avgChar = 'n'; // Representative character\r\n const avgMeasurement = measureGrapheme(avgChar, options);\r\n const letterSpacing = options.letterSpacing || 0;\r\n \r\n return text.length * (avgMeasurement.width + letterSpacing);\r\n}\r\n\r\n/**\r\n * Check if font is loaded and ready for measurement\r\n */\r\nexport function isFontReady(fontFamily: string): boolean {\r\n if (typeof document === 'undefined') return true;\r\n \r\n if ('fonts' in document) {\r\n return document.fonts.check(`16px ${fontFamily}`);\r\n }\r\n \r\n // Fallback - assume font is ready\r\n return true;\r\n}"],"names":["measurementContext","getMeasurementContext","canvas","createCanvasElementFor","width","height","getContext","measureGrapheme","grapheme","options","ctx","cached","measurementCache","get","context","applyFontStyle","metrics","measureText","fontMetrics","getFontMetrics","measurement","lineHeight","ascent","descent","baseline","set","measureGraphemeWithKerning","previousGrapheme","individual","kernedWidth","kerningPair","cachedKerning","kerningCache","_metrics$fontBounding","_metrics$fontBounding2","_metrics$actualBoundi","_metrics$actualBoundi2","cacheKey","getFontDeclaration","fontMetricsCache","fontSize","fontBoundingBoxAscent","fontBoundingBoxDescent","result","actualBoundingBoxAscent","actualBoundingBoxDescent","fontDeclaration","font","letterSpacing","direction","textBaseline","fontStyle","fontWeight","fontFamily","includes","LRUCache","constructor","maxSize","arguments","length","undefined","_defineProperty","this","Map","key","entry","cache","timestamp","Date","now","hits","value","misses","size","oldestKey","findOldestKey","delete","oldestTime","Infinity","entries","clear","getStats","total","hitRate","MeasurementCache","getCacheKey","pair","kerning"],"mappings":"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"}
1
+ {"version":3,"file":"measure.min.mjs","sources":["../../../src/text/measure.ts"],"sourcesContent":["/**\r\n * Advanced Text Measurement System\r\n *\r\n * Provides precise text measurement with caching, font metrics,\r\n * and DPI awareness for optimal performance and accuracy.\r\n */\r\n\r\nimport { createCanvasElementFor } from '../util/misc/dom';\r\n\r\nexport interface MeasurementOptions {\r\n fontFamily: string;\r\n fontSize: number;\r\n fontStyle: string;\r\n fontWeight: string | number;\r\n letterSpacing?: number;\r\n direction?: 'ltr' | 'rtl';\r\n}\r\n\r\nexport interface GraphemeMeasurement {\r\n width: number;\r\n height: number;\r\n ascent: number;\r\n descent: number;\r\n baseline: number;\r\n}\r\n\r\nexport interface KerningMeasurement extends GraphemeMeasurement {\r\n kernedWidth: number; // width accounting for kerning with previous char\r\n}\r\n\r\nexport interface FontMetrics {\r\n ascent: number;\r\n descent: number;\r\n lineHeight: number;\r\n baseline: string;\r\n fontBoundingBoxAscent?: number;\r\n fontBoundingBoxDescent?: number;\r\n actualBoundingBoxAscent?: number;\r\n actualBoundingBoxDescent?: number;\r\n}\r\n\r\n// Global measurement context - reused for performance\r\nlet measurementContext: CanvasRenderingContext2D | null = null;\r\n\r\n/**\r\n * Get or create the shared measurement context\r\n */\r\nfunction getMeasurementContext(): CanvasRenderingContext2D {\r\n if (!measurementContext) {\r\n const canvas = createCanvasElementFor({\r\n width: 0,\r\n height: 0,\r\n });\r\n measurementContext = canvas.getContext('2d')!;\r\n }\r\n return measurementContext;\r\n}\r\n\r\n/**\r\n * Measure a single grapheme\r\n */\r\nexport function measureGrapheme(\r\n grapheme: string,\r\n options: MeasurementOptions,\r\n ctx?: CanvasRenderingContext2D,\r\n): GraphemeMeasurement {\r\n // Check cache first\r\n const cached = measurementCache.get(grapheme, options);\r\n if (cached) {\r\n return cached;\r\n }\r\n\r\n // Use provided context or get global one\r\n const context = ctx || getMeasurementContext();\r\n\r\n // Set font properties\r\n applyFontStyle(context, options);\r\n\r\n // Measure the grapheme\r\n const metrics = context.measureText(grapheme);\r\n const fontMetrics = getFontMetrics(options);\r\n\r\n // Calculate comprehensive measurements\r\n const measurement: GraphemeMeasurement = {\r\n width: metrics.width,\r\n height: fontMetrics.lineHeight,\r\n ascent: fontMetrics.ascent,\r\n descent: fontMetrics.descent,\r\n baseline: fontMetrics.ascent,\r\n };\r\n\r\n // Cache the result\r\n measurementCache.set(grapheme, options, measurement);\r\n\r\n return measurement;\r\n}\r\n\r\n/**\r\n * Measure a grapheme with kerning relative to previous character\r\n */\r\nexport function measureGraphemeWithKerning(\r\n grapheme: string,\r\n previousGrapheme: string | undefined,\r\n options: MeasurementOptions,\r\n ctx?: CanvasRenderingContext2D,\r\n): KerningMeasurement {\r\n // Get individual measurement\r\n const individual = measureGrapheme(grapheme, options, ctx);\r\n\r\n // If no previous character, kerning width equals regular width\r\n if (!previousGrapheme) {\r\n return {\r\n ...individual,\r\n kernedWidth: individual.width,\r\n };\r\n }\r\n\r\n // Check kerning cache\r\n const kerningPair = `${previousGrapheme}${grapheme}`;\r\n const cachedKerning = kerningCache.get(kerningPair, options);\r\n if (cachedKerning) {\r\n return {\r\n ...individual,\r\n kernedWidth: cachedKerning,\r\n };\r\n }\r\n\r\n // Use provided context or get global one\r\n const context = ctx || getMeasurementContext();\r\n applyFontStyle(context, options);\r\n\r\n // Measure the pair\r\n const pairWidth = context.measureText(previousGrapheme + grapheme).width;\r\n const previousWidth = measureGrapheme(\r\n previousGrapheme,\r\n options,\r\n context,\r\n ).width;\r\n const kernedWidth = pairWidth - previousWidth;\r\n\r\n // Cache kerning result\r\n kerningCache.set(kerningPair, options, kernedWidth);\r\n\r\n return {\r\n ...individual,\r\n kernedWidth,\r\n };\r\n}\r\n\r\n/**\r\n * Get a representative character for font metrics measurement\r\n * Uses canvas to test which scripts the font actually supports\r\n */\r\nfunction getRepresentativeCharacter(fontFamily: string): string {\r\n const context = getMeasurementContext();\r\n \r\n // Wait for font to be ready if possible\r\n if (typeof document !== 'undefined' && 'fonts' in document) {\r\n try {\r\n // Check if font is ready, if not, use fallback immediately\r\n if (!document.fonts.check(`16px ${fontFamily}`)) {\r\n return 'M'; // Use safe fallback while font loads\r\n }\r\n } catch (e) {\r\n // Font check failed, use fallback\r\n return 'M';\r\n }\r\n }\r\n \r\n // Test characters for different scripts\r\n const testChars = [\r\n { char: 'م', script: 'Arabic' }, // Arabic\r\n { char: 'א', script: 'Hebrew' }, // Hebrew \r\n { char: 'अ', script: 'Devanagari' }, // Hindi/Sanskrit\r\n { char: 'ا', script: 'Urdu' }, // Urdu\r\n { char: 'ک', script: 'Persian' }, // Persian\r\n { char: 'த', script: 'Tamil' }, // Tamil\r\n { char: 'ก', script: 'Thai' }, // Thai\r\n { char: 'М', script: 'Cyrillic' }, // Cyrillic\r\n { char: 'Ω', script: 'Greek' }, // Greek\r\n { char: 'M', script: 'Latin' } // Latin (fallback)\r\n ];\r\n \r\n // Set the font\r\n context.font = `16px ${fontFamily}`;\r\n \r\n // Test each character to see which ones render properly\r\n // Use a more robust width check to avoid false positives\r\n const fallbackWidth = context.measureText('M').width;\r\n \r\n for (const test of testChars) {\r\n const metrics = context.measureText(test.char);\r\n \r\n // Character is valid if it has width and isn't just a fallback glyph\r\n if (metrics.width > 0 && Math.abs(metrics.width - fallbackWidth) > 0.1) {\r\n return test.char;\r\n }\r\n }\r\n \r\n // Fallback to Latin 'M'\r\n return 'M';\r\n}\r\n\r\n/**\r\n * Get font metrics for layout calculations\r\n */\r\nexport function getFontMetrics(options: MeasurementOptions): FontMetrics {\r\n const cacheKey = getFontDeclaration(options);\r\n const cached = fontMetricsCache.get(cacheKey);\r\n if (cached) {\r\n return cached;\r\n }\r\n\r\n const context = getMeasurementContext();\r\n applyFontStyle(context, options);\r\n\r\n // Use representative character based on font's primary script\r\n const sample = getRepresentativeCharacter(options.fontFamily);\r\n const metrics = context.measureText(sample);\r\n const fontSize = options.fontSize;\r\n\r\n // Calculate metrics with fallbacks\r\n const fontBoundingBoxAscent =\r\n metrics.fontBoundingBoxAscent ?? fontSize * 0.91;\r\n const fontBoundingBoxDescent =\r\n metrics.fontBoundingBoxDescent ?? fontSize * 0.21;\r\n const actualBoundingBoxAscent =\r\n metrics.actualBoundingBoxAscent ?? fontSize * 0.716;\r\n const actualBoundingBoxDescent = metrics.actualBoundingBoxDescent ?? 0;\r\n\r\n const result: FontMetrics = {\r\n ascent: fontBoundingBoxAscent,\r\n descent: fontBoundingBoxDescent,\r\n lineHeight: fontSize,\r\n baseline: 'alphabetic',\r\n fontBoundingBoxAscent,\r\n fontBoundingBoxDescent,\r\n actualBoundingBoxAscent,\r\n actualBoundingBoxDescent,\r\n };\r\n\r\n fontMetricsCache.set(cacheKey, result);\r\n return result;\r\n}\r\n\r\n/**\r\n * Apply font styling to canvas context\r\n */\r\nfunction applyFontStyle(\r\n ctx: CanvasRenderingContext2D,\r\n options: MeasurementOptions,\r\n): void {\r\n const fontDeclaration = getFontDeclaration(options);\r\n ctx.font = fontDeclaration;\r\n\r\n if (options.letterSpacing) {\r\n // Modern browsers support letterSpacing\r\n if ('letterSpacing' in ctx) {\r\n (ctx as any).letterSpacing = `${options.letterSpacing}px`;\r\n }\r\n }\r\n\r\n if (options.direction) {\r\n ctx.direction = options.direction;\r\n }\r\n\r\n ctx.textBaseline = 'alphabetic';\r\n}\r\n\r\n/**\r\n * Generate font declaration string\r\n */\r\nfunction getFontDeclaration(options: MeasurementOptions): string {\r\n const { fontStyle, fontWeight, fontSize, fontFamily } = options;\r\n\r\n // Normalize font family (add quotes if needed)\r\n let normalizedFamily =\r\n fontFamily.includes(' ') &&\r\n !fontFamily.includes('\"') &&\r\n !fontFamily.includes(\"'\")\r\n ? `\"${fontFamily}\"`\r\n : fontFamily;\r\n\r\n // Note: Font fallbacks are handled in the rendering phase only\r\n // to avoid affecting measurement calculations for text wrapping\r\n\r\n return `${fontStyle} ${fontWeight} ${fontSize}px ${normalizedFamily}`;\r\n}\r\n\r\n/**\r\n * LRU Cache implementation for measurements\r\n */\r\nclass LRUCache<T> {\r\n private cache = new Map<string, { value: T; timestamp: number }>();\r\n private maxSize: number;\r\n private hits = 0;\r\n private misses = 0;\r\n\r\n constructor(maxSize = 1000) {\r\n this.maxSize = maxSize;\r\n }\r\n\r\n get(key: string): T | undefined {\r\n const entry = this.cache.get(key);\r\n if (entry) {\r\n // Update timestamp for LRU\r\n entry.timestamp = Date.now();\r\n this.hits++;\r\n return entry.value;\r\n }\r\n this.misses++;\r\n return undefined;\r\n }\r\n\r\n set(key: string, value: T): void {\r\n // Remove oldest entries if at capacity\r\n if (this.cache.size >= this.maxSize) {\r\n const oldestKey = this.findOldestKey();\r\n if (oldestKey) {\r\n this.cache.delete(oldestKey);\r\n }\r\n }\r\n\r\n this.cache.set(key, {\r\n value,\r\n timestamp: Date.now(),\r\n });\r\n }\r\n\r\n private findOldestKey(): string | undefined {\r\n let oldestKey: string | undefined;\r\n let oldestTime = Infinity;\r\n\r\n for (const [key, entry] of this.cache.entries()) {\r\n if (entry.timestamp < oldestTime) {\r\n oldestTime = entry.timestamp;\r\n oldestKey = key;\r\n }\r\n }\r\n\r\n return oldestKey;\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n this.hits = 0;\r\n this.misses = 0;\r\n }\r\n\r\n getStats(): { size: number; hitRate: number; hits: number; misses: number } {\r\n const total = this.hits + this.misses;\r\n return {\r\n size: this.cache.size,\r\n hitRate: total > 0 ? this.hits / total : 0,\r\n hits: this.hits,\r\n misses: this.misses,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Advanced measurement cache with font-aware keys\r\n */\r\nexport class MeasurementCache {\r\n private cache = new LRUCache<GraphemeMeasurement>(1000);\r\n\r\n getCacheKey(grapheme: string, options: MeasurementOptions): string {\r\n const fontDecl = getFontDeclaration(options);\r\n const letterSpacing = options.letterSpacing || 0;\r\n return `${fontDecl}|${grapheme}|${letterSpacing}`;\r\n }\r\n\r\n get(\r\n grapheme: string,\r\n options: MeasurementOptions,\r\n ): GraphemeMeasurement | undefined {\r\n const key = this.getCacheKey(grapheme, options);\r\n return this.cache.get(key);\r\n }\r\n\r\n set(\r\n grapheme: string,\r\n options: MeasurementOptions,\r\n measurement: GraphemeMeasurement,\r\n ): void {\r\n const key = this.getCacheKey(grapheme, options);\r\n this.cache.set(key, measurement);\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n }\r\n\r\n getStats() {\r\n return this.cache.getStats();\r\n }\r\n}\r\n\r\n/**\r\n * Kerning cache for character pairs\r\n */\r\nclass KerningCache {\r\n private cache = new LRUCache<number>(5000); // More entries for pairs\r\n\r\n getCacheKey(pair: string, options: MeasurementOptions): string {\r\n const fontDecl = getFontDeclaration(options);\r\n return `${fontDecl}|${pair}`;\r\n }\r\n\r\n get(pair: string, options: MeasurementOptions): number | undefined {\r\n const key = this.getCacheKey(pair, options);\r\n return this.cache.get(key);\r\n }\r\n\r\n set(pair: string, options: MeasurementOptions, kerning: number): void {\r\n const key = this.getCacheKey(pair, options);\r\n this.cache.set(key, kerning);\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n }\r\n\r\n getStats() {\r\n return this.cache.getStats();\r\n }\r\n}\r\n\r\n/**\r\n * Font metrics cache\r\n */\r\nclass FontMetricsCache {\r\n private cache = new Map<string, FontMetrics>();\r\n\r\n get(fontDeclaration: string): FontMetrics | undefined {\r\n return this.cache.get(fontDeclaration);\r\n }\r\n\r\n set(fontDeclaration: string, metrics: FontMetrics): void {\r\n this.cache.set(fontDeclaration, metrics);\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n }\r\n\r\n getStats() {\r\n return {\r\n size: this.cache.size,\r\n };\r\n }\r\n}\r\n\r\n// Global cache instances\r\nexport const measurementCache = new MeasurementCache();\r\nexport const kerningCache = new KerningCache();\r\nexport const fontMetricsCache = new FontMetricsCache();\r\n\r\n// Set up font loading listener to clear caches when fonts change\r\nif (typeof document !== 'undefined' && 'fonts' in document) {\r\n document.fonts.addEventListener('loadingdone', () => {\r\n // Clear all caches when fonts finish loading\r\n clearAllCaches();\r\n });\r\n}\r\n\r\n/**\r\n * Clear all measurement caches\r\n */\r\nexport function clearAllCaches(): void {\r\n measurementCache.clear();\r\n kerningCache.clear();\r\n fontMetricsCache.clear();\r\n}\r\n\r\n/**\r\n * Get combined cache statistics\r\n */\r\nexport function getCacheStats() {\r\n return {\r\n measurement: measurementCache.getStats(),\r\n kerning: kerningCache.getStats(),\r\n fontMetrics: fontMetricsCache.getStats(),\r\n };\r\n}\r\n\r\n/**\r\n * Batch measure multiple graphemes efficiently\r\n */\r\nexport function batchMeasureGraphemes(\r\n graphemes: string[],\r\n options: MeasurementOptions,\r\n ctx?: CanvasRenderingContext2D,\r\n): GraphemeMeasurement[] {\r\n const context = ctx || getMeasurementContext();\r\n applyFontStyle(context, options);\r\n\r\n // Separate cached and uncached measurements\r\n const results: GraphemeMeasurement[] = new Array(graphemes.length);\r\n const uncachedIndices: number[] = [];\r\n\r\n // Check cache for all graphemes\r\n graphemes.forEach((grapheme, index) => {\r\n const cached = measurementCache.get(grapheme, options);\r\n if (cached) {\r\n results[index] = cached;\r\n } else {\r\n uncachedIndices.push(index);\r\n }\r\n });\r\n\r\n // Measure uncached graphemes\r\n const fontMetrics = getFontMetrics(options);\r\n uncachedIndices.forEach((index) => {\r\n const grapheme = graphemes[index];\r\n const metrics = context.measureText(grapheme);\r\n\r\n const measurement: GraphemeMeasurement = {\r\n width: metrics.width,\r\n height: fontMetrics.lineHeight,\r\n ascent: fontMetrics.ascent,\r\n descent: fontMetrics.descent,\r\n baseline: fontMetrics.ascent,\r\n };\r\n\r\n measurementCache.set(grapheme, options, measurement);\r\n results[index] = measurement;\r\n });\r\n\r\n return results;\r\n}\r\n\r\n/**\r\n * Estimate text width without full layout (for performance)\r\n */\r\nexport function estimateTextWidth(\r\n text: string,\r\n options: MeasurementOptions,\r\n): number {\r\n // Use average character width for estimation\r\n const avgChar = 'n'; // Representative character\r\n const avgMeasurement = measureGrapheme(avgChar, options);\r\n const letterSpacing = options.letterSpacing || 0;\r\n\r\n return text.length * (avgMeasurement.width + letterSpacing);\r\n}\r\n\r\n/**\r\n * Check if font is loaded and ready for measurement\r\n */\r\nexport function isFontReady(fontFamily: string): boolean {\r\n if (typeof document === 'undefined') return true;\r\n\r\n if ('fonts' in document) {\r\n return document.fonts.check(`16px ${fontFamily}`);\r\n }\r\n\r\n // Fallback - assume font is ready\r\n return true;\r\n}\r\n\r\n/**\r\n * Detect if a font lacks English glyph support\r\n * These fonts should use browser-native measurement instead of Fabric's character-by-character measurement\r\n */\r\nexport function fontLacksEnglishGlyphs(fontFamily: string): boolean {\r\n if (typeof document === 'undefined') return false;\r\n \r\n // Known fonts that lack English glyphs\r\n const knownNonEnglishFonts = [\r\n 'stv', 'arabic', 'naskh', 'thuluth', 'kufi', 'diwani',\r\n 'nastaliq', 'kufic', 'hijazi', 'madinah', 'makkah'\r\n ];\r\n \r\n const lowerFontFamily = fontFamily.toLowerCase();\r\n \r\n // Check known list first\r\n if (knownNonEnglishFonts.some(font => lowerFontFamily.includes(font))) {\r\n return true;\r\n }\r\n \r\n // Dynamic glyph support detection\r\n const context = getMeasurementContext();\r\n context.font = `16px ${fontFamily}`;\r\n \r\n // Test English characters\r\n const englishChars = ['A', 'B', 'C', 'a', 'b', 'c', 'M', 'W'];\r\n const fallbackFont = 'Arial, sans-serif';\r\n \r\n // Measure with target font\r\n const targetWidths = englishChars.map(char => context.measureText(char).width);\r\n \r\n // Measure with fallback font\r\n context.font = `16px ${fallbackFont}`;\r\n const fallbackWidths = englishChars.map(char => context.measureText(char).width);\r\n \r\n // If most measurements are identical, the font likely doesn't have English glyphs\r\n let identicalCount = 0;\r\n for (let i = 0; i < englishChars.length; i++) {\r\n if (Math.abs(targetWidths[i] - fallbackWidths[i]) < 0.5) {\r\n identicalCount++;\r\n }\r\n }\r\n \r\n const lacksSupportThreshold = englishChars.length * 0.7; // 70% identical = lacks support\r\n const lacksSupport = identicalCount >= lacksSupportThreshold;\r\n \r\n \r\n return lacksSupport;\r\n}\r\n\r\n// Cache for font glyph detection results\r\nconst fontGlyphCache = new Map<string, boolean>();\r\n\r\n/**\r\n * Cached version of font glyph detection\r\n */\r\nexport function fontLacksEnglishGlyphsCached(fontFamily: string): boolean {\r\n if (fontGlyphCache.has(fontFamily)) {\r\n return fontGlyphCache.get(fontFamily)!;\r\n }\r\n \r\n const result = fontLacksEnglishGlyphs(fontFamily);\r\n fontGlyphCache.set(fontFamily, result);\r\n return result;\r\n}\r\n"],"names":["measurementContext","getMeasurementContext","canvas","createCanvasElementFor","width","height","getContext","measureGrapheme","grapheme","options","ctx","cached","measurementCache","get","context","applyFontStyle","metrics","measureText","fontMetrics","getFontMetrics","measurement","lineHeight","ascent","descent","baseline","set","measureGraphemeWithKerning","previousGrapheme","individual","kernedWidth","kerningPair","cachedKerning","kerningCache","_metrics$fontBounding","_metrics$fontBounding2","_metrics$actualBoundi","_metrics$actualBoundi2","cacheKey","getFontDeclaration","fontMetricsCache","sample","fontFamily","document","fonts","check","e","testChars","char","script","font","fallbackWidth","test","Math","abs","getRepresentativeCharacter","fontSize","fontBoundingBoxAscent","fontBoundingBoxDescent","result","actualBoundingBoxAscent","actualBoundingBoxDescent","fontDeclaration","letterSpacing","direction","textBaseline","fontStyle","fontWeight","includes","LRUCache","constructor","maxSize","arguments","length","undefined","_defineProperty","this","Map","key","entry","cache","timestamp","Date","now","hits","value","misses","size","oldestKey","findOldestKey","delete","oldestTime","Infinity","entries","clear","getStats","total","hitRate","MeasurementCache","getCacheKey","pair","kerning","clearAllCaches","fontLacksEnglishGlyphs","lowerFontFamily","toLowerCase","some","englishChars","targetWidths","map","fallbackWidths","identicalCount","i","addEventListener","fontGlyphCache","fontLacksEnglishGlyphsCached","has"],"mappings":"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"}