fabric-vectr 6.7.7 → 6.7.9
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.
- package/dist/index.js +32 -15
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.min.mjs +1 -1
- package/dist/index.min.mjs.map +1 -1
- package/dist/index.mjs +32 -15
- package/dist/index.mjs.map +1 -1
- package/dist/index.node.cjs +32 -15
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +32 -15
- package/dist/index.node.mjs.map +1 -1
- package/dist/package.json.min.mjs +1 -1
- package/dist/package.json.mjs +1 -1
- package/dist/src/Collection.d.ts +1 -1
- package/dist/src/Collection.d.ts.map +1 -1
- package/dist/src/Collection.min.mjs +1 -1
- package/dist/src/Collection.min.mjs.map +1 -1
- package/dist/src/Collection.mjs +4 -4
- package/dist/src/Collection.mjs.map +1 -1
- package/dist/src/canvas/Canvas.d.ts.map +1 -1
- package/dist/src/canvas/Canvas.min.mjs +1 -1
- package/dist/src/canvas/Canvas.min.mjs.map +1 -1
- package/dist/src/canvas/Canvas.mjs +15 -7
- package/dist/src/canvas/Canvas.mjs.map +1 -1
- package/dist/src/canvas/SelectableCanvas.d.ts.map +1 -1
- package/dist/src/canvas/SelectableCanvas.min.mjs +1 -1
- package/dist/src/canvas/SelectableCanvas.min.mjs.map +1 -1
- package/dist/src/canvas/SelectableCanvas.mjs +3 -1
- package/dist/src/canvas/SelectableCanvas.mjs.map +1 -1
- package/dist/src/canvas/StaticCanvas.d.ts +1 -1
- package/dist/src/canvas/StaticCanvas.min.mjs +1 -1
- package/dist/src/canvas/StaticCanvas.min.mjs.map +1 -1
- package/dist/src/canvas/StaticCanvas.mjs +1 -1
- package/dist/src/canvas/StaticCanvas.mjs.map +1 -1
- package/dist/src/shapes/Group.d.ts +1 -1
- package/dist/src/shapes/IText/IText.d.ts.map +1 -1
- package/dist/src/shapes/IText/IText.min.mjs +1 -1
- package/dist/src/shapes/IText/IText.min.mjs.map +1 -1
- package/dist/src/shapes/IText/IText.mjs +7 -0
- package/dist/src/shapes/IText/IText.mjs.map +1 -1
- package/dist/src/shapes/Textbox.min.mjs +1 -1
- package/dist/src/shapes/Textbox.min.mjs.map +1 -1
- package/dist/src/shapes/Textbox.mjs +1 -1
- package/dist/src/shapes/Textbox.mjs.map +1 -1
- package/dist-extensions/src/Collection.d.ts +1 -1
- package/dist-extensions/src/Collection.d.ts.map +1 -1
- package/dist-extensions/src/canvas/Canvas.d.ts.map +1 -1
- package/dist-extensions/src/canvas/SelectableCanvas.d.ts.map +1 -1
- package/dist-extensions/src/canvas/StaticCanvas.d.ts +1 -1
- package/dist-extensions/src/shapes/Group.d.ts +1 -1
- package/dist-extensions/src/shapes/IText/IText.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Collection.ts +3 -2
- package/src/canvas/Canvas.ts +15 -6
- package/src/canvas/SelectableCanvas.ts +7 -1
- package/src/canvas/StaticCanvas.ts +1 -1
- package/src/shapes/IText/IText.ts +7 -0
- package/src/shapes/Textbox.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Textbox.min.mjs","sources":["../../../src/shapes/Textbox.ts"],"sourcesContent":["import type { Abortable, TClassProperties, TOptions } from '../typedefs';\nimport { IText } from './IText/IText';\nimport { classRegistry } from '../ClassRegistry';\nimport { createTextboxDefaultControls } from '../controls/commonControls';\nimport { JUSTIFY } from './Text/constants';\nimport type { TextStyleDeclaration } from './Text/StyledText';\nimport type { SerializedITextProps, ITextProps } from './IText/IText';\nimport type { ITextEvents } from './IText/ITextBehavior';\nimport type {\n FabricText,\n SerializedTextProps,\n TextLinesInfo,\n} from './Text/Text';\nimport type { Control } from '../controls/Control';\nimport { stylesFromArray } from '../util';\nimport type { CSSRules } from '../parser/typedefs';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport { Path } from './Path';\nimport { DEFAULT_SVG_FONT_SIZE } from '../constants';\n\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\n// regexes, list of properties that are not suppose to change by instances, magic consts.\n// this will be a separated effort\nexport const textboxDefaultValues: Partial<TClassProperties<Textbox>> = {\n minWidth: 20,\n dynamicMinWidth: 2,\n lockScalingFlip: true,\n noScaleCache: false,\n _wordJoiners: /[ \\t\\r]/,\n splitByGrapheme: false,\n};\n\nexport type GraphemeData = {\n wordsData: {\n word: string[];\n width: number;\n }[][];\n largestWordWidth: number;\n};\n\nexport type StyleMap = Record<string, { line: number; offset: number }>;\n\n// @TODO this is not complete\ninterface UniqueTextboxProps {\n minWidth: number;\n splitByGrapheme: boolean;\n dynamicMinWidth: number;\n _wordJoiners: RegExp;\n}\n\nexport interface SerializedTextboxProps\n extends SerializedITextProps,\n Pick<UniqueTextboxProps, 'minWidth' | 'splitByGrapheme'> {}\n\nexport interface TextboxProps extends ITextProps, UniqueTextboxProps {}\n\n/**\n * Textbox class, based on IText, allows the user to resize the text rectangle\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\n * user can only change width. Height is adjusted automatically based on the\n * wrapping of lines.\n */\nexport class Textbox<\n Props extends TOptions<TextboxProps> = Partial<TextboxProps>,\n SProps extends SerializedTextboxProps = SerializedTextboxProps,\n EventSpec extends ITextEvents = ITextEvents,\n >\n extends IText<Props, SProps, EventSpec>\n implements UniqueTextboxProps\n{\n /**\n * Minimum width of textbox, in pixels.\n * @type Number\n * @default\n */\n declare minWidth: number;\n\n /**\n * Minimum calculated width of a textbox, in pixels.\n * fixed to 2 so that an empty textbox cannot go to 0\n * and is still selectable without text.\n * @type Number\n * @default\n */\n declare dynamicMinWidth: number;\n\n /**\n * Use this boolean property in order to split strings that have no white space concept.\n * this is a cheap way to help with chinese/japanese\n * @type Boolean\n * @since 2.6.0\n */\n declare splitByGrapheme: boolean;\n\n declare _wordJoiners: RegExp;\n\n declare _styleMap: StyleMap;\n\n declare isWrapping: boolean;\n\n static type = 'Textbox';\n\n static textLayoutProperties = [...IText.textLayoutProperties, 'width'];\n\n static ownDefaults = textboxDefaultValues;\n\n // James modified 自动计算文字高度\n static enableCalcTextHeight = false;\n\n /**\n * James modified 自动计算文字高度\n * 增加wrap宽度,设置为page的宽度\n * 增加textbox wrap的默认宽度\n * @type Number\n * @default\n */\n static defaultWrapWidth = 1920;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Textbox.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n */\n constructor(text: string, options?: Props) {\n super(text, { ...Textbox.ownDefaults, ...options } as Props);\n }\n\n /**\n * Creates the default control object.\n * If you prefer to have on instance of controls shared among all objects\n * make this function return an empty object and add controls to the ownDefaults object\n */\n static createControls(): { controls: Record<string, Control> } {\n return { controls: createTextboxDefaultControls() };\n }\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @private\n * @override\n */\n initDimensions() {\n if (!this.initialized) {\n return;\n }\n this.isEditing && this.initDelayedCursor();\n this._clearCache();\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n // wrap lines\n this._styleMap = this._generateStyleMap(this._splitText());\n // James modified\n // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n if (!this.path && this.dynamicMinWidth > this.width) {\n this._set('width', this.dynamicMinWidth);\n }\n if (this.textAlign.includes(JUSTIFY)) {\n // once text is measured we need to make space fatter to make justified text.\n this.enlargeSpaces();\n }\n // James modified 取消 textbox 自动计算高度\n if (!this.path && Textbox.enableCalcTextHeight) {\n // clear cache and re-calculate height\n this.height = this.calcTextHeight();\n }\n this.preventGroupCache = this.path ? true : false;\n }\n\n /**\n * Generate an object that translates the style object so that it is\n * broken up by visual lines (new lines and automatic wrapping).\n * The original text styles object is broken up by actual lines (new lines only),\n * which is only sufficient for Text / IText\n * @private\n */\n _generateStyleMap(textInfo: TextLinesInfo): StyleMap {\n let realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0;\n const map: StyleMap = {};\n\n for (let i = 0; i < textInfo.graphemeLines.length; i++) {\n if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n } else if (\n !this.splitByGrapheme &&\n this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\n i > 0\n ) {\n // this case deals with space's that are removed from end of lines when wrapping\n realLineCharCount++;\n charCount++;\n }\n\n map[i] = { line: realLineCount, offset: realLineCharCount };\n\n charCount += textInfo.graphemeLines[i].length;\n realLineCharCount += textInfo.graphemeLines[i].length;\n }\n\n return map;\n }\n\n /**\n * Returns true if object has a style property or has it on a specified line\n * @param {Number} lineIndex\n * @return {Boolean}\n */\n styleHas(property: keyof TextStyleDeclaration, lineIndex: number): boolean {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (map) {\n lineIndex = map.line;\n }\n }\n return super.styleHas(property, lineIndex);\n }\n\n /**\n * Returns true if object has no styling or no styling in a line\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\n * @return {Boolean}\n */\n isEmptyStyles(lineIndex: number): boolean {\n if (!this.styles) {\n return true;\n }\n let offset = 0,\n nextLineIndex = lineIndex + 1,\n nextOffset: number,\n shouldLimit = false;\n const map = this._styleMap[lineIndex],\n mapNextLine = this._styleMap[lineIndex + 1];\n if (map) {\n lineIndex = map.line;\n offset = map.offset;\n }\n if (mapNextLine) {\n nextLineIndex = mapNextLine.line;\n shouldLimit = nextLineIndex === lineIndex;\n nextOffset = mapNextLine.offset;\n }\n const obj =\n typeof lineIndex === 'undefined'\n ? this.styles\n : { line: this.styles[lineIndex] };\n for (const p1 in obj) {\n for (const p2 in obj[p1]) {\n const p2Number = parseInt(p2, 10);\n if (p2Number >= offset && (!shouldLimit || p2Number < nextOffset!)) {\n // eslint-disable-next-line no-unused-vars\n for (const p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n }\n return true;\n }\n\n /**\n * @protected\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined\n */\n _getStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n ): TextStyleDeclaration {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (!map) {\n return {};\n }\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n return super._getStyleDeclaration(lineIndex, charIndex);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n protected _setStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n style: object,\n ) {\n const map = this._styleMap[lineIndex];\n super._setStyleDeclaration(map.line, map.offset + charIndex, style);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n protected _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\n const map = this._styleMap[lineIndex];\n super._deleteStyleDeclaration(map.line, map.offset + charIndex);\n }\n\n /**\n * probably broken need a fix\n * Returns the real style line that correspond to the wrapped lineIndex line\n * Used just to verify if the line does exist or not.\n * @param {Number} lineIndex\n * @returns {Boolean} if the line exists or not\n * @private\n */\n protected _getLineStyle(lineIndex: number): boolean {\n const map = this._styleMap[lineIndex];\n return !!this.styles[map.line];\n }\n\n /**\n * Set the line style to an empty object so that is initialized\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n protected _setLineStyle(lineIndex: number) {\n const map = this._styleMap[lineIndex];\n super._setLineStyle(map.line);\n }\n\n /**\n * Wraps text using the 'width' property of Textbox. First this function\n * splits text on newlines, so we preserve newlines entered by the user.\n * Then it wraps each line using the width of the Textbox by calling\n * _wrapLine().\n * @param {Array} lines The string array of text that is split into lines\n * @param {Number} desiredWidth width you want to wrap to\n * @returns {Array} Array of lines\n */\n _wrapText(lines: string[], desiredWidth: number): string[][] {\n this.isWrapping = true;\n // extract all thewords and the widths to optimally wrap lines.\n const data = this.getGraphemeDataForRender(lines);\n const wrapped: string[][] = [];\n for (let i = 0; i < data.wordsData.length; i++) {\n wrapped.push(...this._wrapLine(i, desiredWidth, data));\n }\n this.isWrapping = false;\n return wrapped;\n }\n\n /**\n * For each line of text terminated by an hard line stop,\n * measure each word width and extract the largest word from all.\n * The returned words here are the one that at the end will be rendered.\n * @param {string[]} lines the lines we need to measure\n *\n */\n getGraphemeDataForRender(lines: string[]): GraphemeData {\n const splitByGrapheme = this.splitByGrapheme,\n infix = splitByGrapheme ? '' : ' ';\n\n let largestWordWidth = 0;\n\n const data = lines.map((line, lineIndex) => {\n let offset = 0;\n const wordsOrGraphemes = splitByGrapheme\n ? this.graphemeSplit(line)\n : this.wordSplit(line);\n\n if (wordsOrGraphemes.length === 0) {\n return [{ word: [], width: 0 }];\n }\n\n return wordsOrGraphemes.map((word: string) => {\n // if using splitByGrapheme words are already in graphemes.\n const graphemeArray = splitByGrapheme\n ? [word]\n : this.graphemeSplit(word);\n const width = this._measureWord(graphemeArray, lineIndex, offset);\n largestWordWidth = Math.max(width, largestWordWidth);\n offset += graphemeArray.length + infix.length;\n return { word: graphemeArray, width };\n });\n });\n\n return {\n wordsData: data,\n largestWordWidth,\n };\n }\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n * It gets called when charBounds are not available yet.\n * Override if necessary\n * Use with {@link Textbox#wordSplit}\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n */\n _measureWord(word: string[], lineIndex: number, charOffset = 0): number {\n let width = 0,\n prevGrapheme;\n const skipLeft = true;\n for (let i = 0, len = word.length; i < len; i++) {\n const box = this._getGraphemeBox(\n word[i],\n lineIndex,\n i + charOffset,\n prevGrapheme,\n skipLeft,\n );\n width += box.kernedWidth;\n prevGrapheme = word[i];\n }\n return width;\n }\n\n /**\n * Override this method to customize word splitting\n * Use with {@link Textbox#_measureWord}\n * @param {string} value\n * @returns {string[]} array of words\n */\n wordSplit(value: string): string[] {\n return value.split(this._wordJoiners);\n }\n\n /**\n * Wraps a line of text using the width of the Textbox as desiredWidth\n * and leveraging the known width o words from GraphemeData\n * @private\n * @param {Number} lineIndex\n * @param {Number} desiredWidth width you want to wrap the line to\n * @param {GraphemeData} graphemeData an object containing all the lines' words width.\n * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine(\n lineIndex: number,\n desiredWidth: number,\n { largestWordWidth, wordsData }: GraphemeData,\n reservedSpace = 0,\n ): string[][] {\n const additionalSpace = this._getWidthOfCharSpacing(),\n splitByGrapheme = this.splitByGrapheme,\n graphemeLines = [],\n infix = splitByGrapheme ? '' : ' ';\n\n let lineWidth = 0,\n line: string[] = [],\n // spaces in different languages?\n offset = 0,\n infixWidth = 0,\n lineJustStarted = true;\n\n desiredWidth -= reservedSpace;\n\n const maxWidth = Math.max(\n desiredWidth,\n largestWordWidth,\n this.dynamicMinWidth,\n );\n // layout words\n const data = wordsData[lineIndex];\n offset = 0;\n let i;\n for (i = 0; i < data.length; i++) {\n const { word, width: wordWidth } = data[i];\n offset += word.length;\n\n lineWidth += infixWidth + wordWidth - additionalSpace;\n if (lineWidth > maxWidth && !lineJustStarted) {\n graphemeLines.push(line);\n line = [];\n lineWidth = wordWidth;\n lineJustStarted = true;\n } else {\n lineWidth += additionalSpace;\n }\n\n if (!lineJustStarted && !splitByGrapheme) {\n line.push(infix);\n }\n line = line.concat(word);\n\n infixWidth = splitByGrapheme\n ? 0\n : this._measureWord([infix], lineIndex, offset);\n offset++;\n lineJustStarted = false;\n }\n\n i && graphemeLines.push(line);\n\n // TODO: this code is probably not necessary anymore.\n // it can be moved out of this function since largestWordWidth is now\n // known in advance\n if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n }\n return graphemeLines;\n }\n\n /**\n * Detect if the text line is ended with an hard break\n * text and itext do not have wrapping, return false\n * @param {Number} lineIndex text to split\n * @return {Boolean}\n */\n isEndOfWrapping(lineIndex: number): boolean {\n if (!this._styleMap[lineIndex + 1]) {\n // is last line, return true;\n return true;\n }\n if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n // this is last line before a line break, return true;\n return true;\n }\n return false;\n }\n\n /**\n * Detect if a line has a linebreak and so we need to account for it when moving\n * and counting style.\n * This is important only for splitByGrapheme at the end of wrapping.\n * If we are not wrapping the offset is always 1\n * @return Number\n */\n missingNewlineOffset(lineIndex: number, skipWrapping?: boolean): 0 | 1 {\n if (this.splitByGrapheme && !skipWrapping) {\n return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n }\n return 1;\n }\n\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly every time it is called.\n * @param {String} text text to split\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines(text: string) {\n // James modified 存在path时候不按照宽度换行\n var wrapWidth = this.path ? 10000000 : this.width;\n // 如果width 不存在, 使用page width\n wrapWidth = wrapWidth || Textbox.defaultWrapWidth;\n const newText = super._splitTextIntoLines(text),\n graphemeLines = this._wrapText(newText.lines, wrapWidth),\n lines = new Array(graphemeLines.length);\n for (let i = 0; i < graphemeLines.length; i++) {\n lines[i] = graphemeLines[i].join('');\n }\n newText.lines = lines;\n newText.graphemeLines = graphemeLines;\n return newText;\n }\n\n getMinWidth() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\n }\n\n _removeExtraneousStyles() {\n const linesToKeep = new Map();\n for (const prop in this._styleMap) {\n const propNumber = parseInt(prop, 10);\n if (this._textLines[propNumber]) {\n const lineIndex = this._styleMap[prop].line;\n linesToKeep.set(`${lineIndex}`, true);\n }\n }\n for (const prop in this.styles) {\n if (!linesToKeep.has(prop)) {\n delete this.styles[prop];\n }\n }\n }\n\n /**\n * Returns object representation of an instance\n * @method toObject\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return super.toObject<T, K>([\n 'minWidth',\n 'splitByGrapheme',\n ...propertiesToInclude,\n ] as K[]) as Pick<T, K> & SProps;\n }\n\n /**\n * Returns FabricText instance from an SVG element (<b>not yet implemented</b>)\n * @static\n * @memberOf Text\n * @param {HTMLElement} element Element to parse\n * @param {Object} [options] Options object\n */\n static async fromElement(\n element: HTMLElement,\n options: Abortable,\n cssRules?: CSSRules,\n ) {\n if (!element) {\n return null;\n }\n\n var parsedAttributes = parseAttributes(\n element,\n Textbox.ATTRIBUTE_NAMES,\n cssRules,\n );\n const textOptions = {\n ...(cssRules ? JSON.parse(JSON.stringify(cssRules)) : {}),\n ...parsedAttributes,\n };\n // 处理style中字体样式带单引号问题\n let reg = /^'(.*)'$/;\n if (reg.test(textOptions.fontFamily)) {\n textOptions.fontFamily = textOptions.fontFamily.slice(1, -1);\n }\n\n textOptions.top = textOptions.top || 0;\n textOptions.left = textOptions.left || 0;\n if (parsedAttributes.textDecoration) {\n var textDecoration = parsedAttributes.textDecoration;\n if (textDecoration.indexOf('underline') !== -1) {\n textOptions.underline = true;\n }\n if (textDecoration.indexOf('overline') !== -1) {\n textOptions.overline = true;\n }\n if (textDecoration.indexOf('line-through') !== -1) {\n textOptions.linethrough = true;\n }\n delete textOptions.textDecoration;\n }\n if ('dx' in parsedAttributes) {\n textOptions.left += parsedAttributes.dx;\n }\n if ('dy' in parsedAttributes) {\n textOptions.top += parsedAttributes.dy;\n }\n if (!('fontSize' in textOptions)) {\n textOptions.fontSize = DEFAULT_SVG_FONT_SIZE;\n }\n\n let text: Textbox;\n const paths = element.getElementsByTagName('textPath');\n if (paths.length) {\n text = this._fromTextPath(paths[0], textOptions, parsedAttributes);\n } else {\n text = this._fromTextSpan(element, textOptions, parsedAttributes);\n }\n return text;\n }\n\n static _findSvgTextPath(element: any, id: string) {\n const svg = element.closest('svg');\n return svg.querySelector(id);\n }\n\n static _fromTextPath = (\n textPath: any,\n options: any,\n parsedAttributes: { [key: string]: string },\n ): Textbox => {\n var parsedAnchor = parsedAttributes.textAnchor || 'left';\n\n var textPathParsedAttributes = parseAttributes(textPath, [\n 'href',\n 'text-anchor',\n 'startOffset',\n ]);\n if (textPathParsedAttributes.textAnchor) {\n parsedAnchor = textPathParsedAttributes.textAnchor;\n }\n if (parsedAnchor === 'middle') {\n parsedAnchor = 'center';\n } else if (parsedAnchor === 'end') {\n parsedAnchor = 'right';\n }\n options.textAlign = parsedAnchor;\n\n var textContent = textPath.textContent;\n var text = new Textbox(textContent, options);\n\n const href = textPathParsedAttributes.href;\n if (href && href.startsWith('#')) {\n const pathElement = Textbox._findSvgTextPath(textPath, href);\n if (pathElement) {\n var pathParsedAttributes = parseAttributes(\n pathElement,\n Path.ATTRIBUTE_NAMES,\n );\n const path = new Path(pathParsedAttributes.d, {\n ...pathParsedAttributes,\n ...{\n strokeWidth: 1,\n stroke: '#ff0000',\n fill: null as any,\n visible: false,\n },\n });\n // 需要计算实际字体大小\n Textbox.enableCalcTextHeight = true;\n const textHeight =\n new Textbox('i', {\n fontFamily: options.fontFamily,\n fontSize: options.fontSize,\n fontStyle: options.fontStyle,\n fontWeight: options.fontWeight,\n width: undefined,\n height: undefined,\n }).height || 20;\n text.set({\n width: (path.width || 0) + textHeight * 2,\n height: (path.height || 0) + textHeight * 2,\n path,\n pathType: 'custom',\n } as any);\n // 取消自动计算文字高度\n Textbox.enableCalcTextHeight = false;\n }\n }\n // 设置位置中心点为左上角\n text.set({\n left: options.left - (text.width || 0) / 2,\n top: options.top - (text.height || 0) / 2,\n });\n return text;\n };\n\n static _fromTextSpan(\n element: any,\n options: any,\n parsedAttributes: { [key: string]: string },\n ): Textbox {\n var textContent = '';\n var parsedAnchor = parsedAttributes.textAnchor || 'left';\n // 是否需要根据tspan位置计算对齐\n let calcHorAlign = !parsedAttributes.textAnchor;\n let calcAdjustHorAlign = '';\n\n // The XML is not properly parsed in IE9 so a workaround to get\n // textContent is through firstChild.data. Another workaround would be\n // to convert XML loaded from a file to be converted using DOMParser (same way loadSVGFromString() does)\n\n let lineCnt = 1;\n let alignmentBaseline = 'auto';\n let spanOffX = 0,\n minSpanX: number | null = null,\n spanOffY = 0;\n\n if (element.hasAttribute('line-height')) {\n options.lineHeight = parseFloat(element.getAttribute('line-height'));\n } else if (options['line-height']) {\n // 从style 转换过来\n options.lineHeight = parseFloat(options['line-height']) / 100;\n } else {\n options.lineHeight = 1;\n }\n\n if (!('textContent' in element)) {\n if ('firstChild' in element && element.firstChild !== null) {\n if ('data' in element.firstChild && element.firstChild.data !== null) {\n textContent = element.firstChild.data;\n }\n }\n } else {\n textContent = element.textContent;\n let spans = element.getElementsByTagName('tspan');\n if (spans.length > 0) {\n // 多行文字\n let lines: {\n text: string;\n left: number;\n width?: number;\n right?: number;\n }[] = [],\n lineText = '',\n curLineLeft = 0, // 本行的 水平方向位置\n preSpanTop = 0, // 前一个tspan的 垂直方向位置\n sumDx = 0,\n sumDy = 0;\n for (let i = 0; i < spans.length; i++) {\n var parsedSpanAttributes = parseAttributes(\n spans[i],\n Textbox.ATTRIBUTE_NAMES,\n );\n\n sumDx += Number(parsedSpanAttributes.dx) || 0;\n sumDy += Number(parsedSpanAttributes.dy) || 0;\n // 在使用tspan判断对齐时spanX取最小的值\n if ('left' in parsedSpanAttributes) {\n let spanX = parseFloat(parsedSpanAttributes.left);\n minSpanX = minSpanX != null ? Math.min(minSpanX, spanX) : spanX;\n }\n // 现在多个tspan用多行文字, 所以对齐和位置只处理第一个 tspan\n if (i === 0) {\n if (spans[i].hasAttribute('text-anchor')) {\n // 水平方向\n let anchor = spans[i].getAttribute('text-anchor');\n // left | center | right\n // start | middle | end\n if (anchor === 'middle') {\n parsedAnchor = 'center';\n } else if (anchor === 'end') {\n parsedAnchor = 'right';\n }\n calcHorAlign = false;\n }\n if (spans[i].hasAttribute('alignment-baseline')) {\n // 垂直方向\n alignmentBaseline = spans[i].getAttribute('alignment-baseline');\n }\n\n // 处理tspan设置的位置和偏移\n // top只处理第一行\n if ('top' in parsedSpanAttributes) {\n let spanY = parseFloat(parsedSpanAttributes.top);\n spanY += sumDy;\n\n spanOffY = options.top - spanY;\n }\n }\n\n // 多个tspan可能在一行 根据 y position判断是否换行\n // 另外没有对齐方式的,计算判断对齐方式,根据left的值判断对齐方式\n (parsedSpanAttributes as any).left =\n Number(parsedSpanAttributes.left || 0) + sumDx;\n (parsedSpanAttributes as any).top =\n Number(parsedSpanAttributes.top || 0) + sumDy;\n\n if (i === 0 || preSpanTop === (parsedSpanAttributes as any).top) {\n lineText += spans[i].textContent;\n if (i === 0) {\n curLineLeft = Number((parsedSpanAttributes as any).left || 0);\n }\n } else {\n lines.push({ text: lineText, left: curLineLeft });\n lineText = spans[i].textContent;\n curLineLeft = Number((parsedSpanAttributes as any).left || 0);\n }\n\n // 记住上一个span的Y位置\n preSpanTop = (parsedSpanAttributes as any).top;\n }\n // 加上最后一行\n if (lineText.length) {\n lines.push({ text: lineText, left: curLineLeft });\n }\n // 加上换行符号\n textContent = lines.map((v) => v.text).join('\\n');\n lineCnt = lines.length;\n\n if (calcHorAlign) {\n if (lines.some((v) => v.left !== curLineLeft)) {\n // 取最left的最小值,和right最大值\n let minLeft = lines[0].left,\n maxRight = lines[0].left,\n maxWidth = 0,\n minCenter: number | null = null,\n maxCenter: number | null = null,\n maxChar = 0,\n maxCharIdx = 0;\n\n lines.forEach((v, idx) => {\n minLeft = Math.min(minLeft, v.left);\n v.width = (new Textbox(v.text, options) as any).calcTextWidth();\n v.right = v.left + (v.width || 0);\n maxRight = Math.max(maxRight, v.right);\n maxWidth = Math.max(maxWidth, v.width || 0);\n if (v.width) {\n const center = v.left + (v.width || 0) / 2;\n minCenter = minCenter ? Math.min(minCenter, center) : center;\n maxCenter = maxCenter ? Math.max(maxCenter, center) : center;\n\n if (v.text.length > maxChar) {\n maxChar = v.text.length;\n maxCharIdx = idx;\n }\n }\n });\n let leftGap = 0,\n rightGap = 0;\n lines.forEach((v) => {\n leftGap = Math.max(leftGap, (v.left || 0) - minLeft);\n rightGap = Math.max(rightGap, maxRight - (v.right || 0));\n });\n // 计算中心点位置\n if (maxCenter && minCenter) {\n const centerOff = maxCenter - minCenter;\n const onCharWidth =\n (lines[maxCharIdx].width || 0) / lines[maxCharIdx].text.length;\n // 左边间距大于右边两倍 或者 中心点偏移超过1/2字符且右边间距小于1/3字符\n if (\n leftGap / (rightGap || 1) > 2 &&\n centerOff > onCharWidth / 2 &&\n rightGap < onCharWidth / 3\n ) {\n calcAdjustHorAlign = 'right';\n } else if (centerOff < onCharWidth / 2) {\n calcAdjustHorAlign = 'center';\n }\n }\n }\n }\n }\n }\n\n // 处理文字的水平偏移\n spanOffX = options.left - (minSpanX || 0);\n\n // textAlign保持和parsedAnchor一致\n options.textAlign = parsedAnchor;\n\n // 注释掉原来删除换行等符号的代码\n //textContent = textContent.replace(/^\\s+|\\s+$|\\n+/g, '').replace(/\\s+/g, ' ');\n var originalStrokeWidth = options.strokeWidth;\n options.strokeWidth = 0;\n\n // 导入时打开自动计算文字高度,否则文字高度和 Y 轴位置错误\n Textbox.enableCalcTextHeight = true;\n var text = new Textbox(textContent, options),\n textOneLineHeight = text.height / lineCnt,\n textHeightScaleFactor = text.getScaledHeight() / text.height,\n lineHeightDiff =\n (textOneLineHeight + text.strokeWidth) * text.lineHeight -\n textOneLineHeight,\n scaledDiff = lineHeightDiff * textHeightScaleFactor,\n textHeight = text.getScaledHeight() / lineCnt + scaledDiff,\n offX = 0,\n offY = 0;\n\n // 默认 alignment-baseline=\"before-edge\" offY = 0\n let offScale = 0;\n if (alignmentBaseline === 'before-edge') {\n // 这个是1.0 导出的偏移值,多行且间距设置大于1也会有变化\n // 暂时这么处理, 以后再解决\n offScale = 1.1;\n } else if (alignmentBaseline === 'auto') {\n // alignment-baseline=\"auto\" 或者 没有设置\n offScale = 0.02913333333;\n }\n\n if (offScale !== 0) {\n offY =\n (textHeight - text.fontSize * (offScale + text._fontSizeFraction)) /\n text.lineHeight;\n }\n\n // 取消自动计算文字高度\n Textbox.enableCalcTextHeight = false;\n /*\n Adjust positioning:\n x/y attributes in SVG correspond to the bottom-left corner of text bounding box\n fabric output by default at top, left.\n */\n const adjustOption: Partial<ITextProps> = {};\n // 源码中options.width总是等于svg的宽度, 之前是new Text不能编辑文字,宽度设置为svg宽度也无效\n // 修改为 new fabric.Textbox,并且设置为计算的正确宽度\n const originWidth = options.width;\n let width = text.calcTextWidth();\n // 有时候计算出来的大小是不对的, 可能是字体的原因, 导致TextBox自动换行了, 所以加i字符的宽度\n const oneIWidth = (new Textbox('i', options) as any).calcTextWidth();\n width += oneIWidth;\n\n if (originWidth !== width) {\n adjustOption.width = width;\n }\n if (calcAdjustHorAlign) {\n // tspan 按字符分开计算的对齐\n adjustOption.textAlign = calcAdjustHorAlign;\n }\n\n // 2021.1.29修改\n // Vectr1.0导出的svg,需要处理水平居中或右对齐偏移\n // Vectr2.0导出的是按照span位置判断的对齐不需要处理整个width的位置偏移, 但是需要处理 oneIWidth的位置偏移\n const textAlign = calcAdjustHorAlign || parsedAnchor;\n if (textAlign === 'center') {\n offX = (parsedAnchor === 'center' ? width : oneIWidth) / 2;\n } else if (textAlign === 'right') {\n offX = parsedAnchor === 'right' ? width : oneIWidth;\n }\n\n text.set({\n ...adjustOption,\n left: text.left - offX - spanOffX,\n top: text.top - offY - spanOffY,\n strokeWidth:\n typeof originalStrokeWidth !== 'undefined' ? originalStrokeWidth : 1,\n });\n return text;\n }\n}\n\nclassRegistry.setClass(Textbox);\nclassRegistry.setSVGClass(Textbox);\n"],"names":["textboxDefaultValues","minWidth","dynamicMinWidth","lockScalingFlip","noScaleCache","_wordJoiners","splitByGrapheme","Textbox","IText","getDefaults","super","ownDefaults","constructor","text","options","createControls","controls","createTextboxDefaultControls","initDimensions","this","initialized","isEditing","initDelayedCursor","_clearCache","_styleMap","_generateStyleMap","_splitText","path","width","_set","textAlign","includes","JUSTIFY","enlargeSpaces","enableCalcTextHeight","height","calcTextHeight","preventGroupCache","textInfo","realLineCount","realLineCharCount","charCount","map","i","graphemeLines","length","graphemeText","_reSpaceAndTab","test","line","offset","styleHas","property","lineIndex","isWrapping","isEmptyStyles","styles","nextOffset","nextLineIndex","shouldLimit","mapNextLine","obj","p1","p2","p2Number","parseInt","p3","_getStyleDeclaration","charIndex","_setStyleDeclaration","style","_deleteStyleDeclaration","_getLineStyle","_setLineStyle","_wrapText","lines","desiredWidth","data","getGraphemeDataForRender","wrapped","wordsData","push","_wrapLine","infix","largestWordWidth","wordsOrGraphemes","graphemeSplit","wordSplit","word","graphemeArray","_measureWord","Math","max","prevGrapheme","charOffset","arguments","undefined","len","_getGraphemeBox","kernedWidth","value","split","_ref","reservedSpace","additionalSpace","_getWidthOfCharSpacing","lineWidth","infixWidth","lineJustStarted","maxWidth","wordWidth","concat","isEndOfWrapping","missingNewlineOffset","skipWrapping","_splitTextIntoLines","wrapWidth","defaultWrapWidth","newText","Array","join","getMinWidth","_removeExtraneousStyles","linesToKeep","Map","prop","propNumber","_textLines","set","has","toObject","propertiesToInclude","fromElement","element","cssRules","parsedAttributes","parseAttributes","ATTRIBUTE_NAMES","textOptions","JSON","parse","stringify","fontFamily","slice","top","left","textDecoration","indexOf","underline","overline","linethrough","dx","dy","fontSize","DEFAULT_SVG_FONT_SIZE","paths","getElementsByTagName","_fromTextPath","_fromTextSpan","_findSvgTextPath","id","closest","querySelector","textContent","parsedAnchor","textAnchor","calcHorAlign","calcAdjustHorAlign","lineCnt","alignmentBaseline","spanOffX","minSpanX","spanOffY","hasAttribute","lineHeight","parseFloat","getAttribute","spans","lineText","curLineLeft","preSpanTop","sumDx","sumDy","parsedSpanAttributes","Number","spanX","min","anchor","spanY","v","some","minLeft","maxRight","minCenter","maxCenter","maxChar","maxCharIdx","forEach","idx","calcTextWidth","right","center","leftGap","rightGap","centerOff","onCharWidth","firstChild","originalStrokeWidth","strokeWidth","textOneLineHeight","textHeightScaleFactor","getScaledHeight","scaledDiff","textHeight","offX","offY","offScale","_fontSizeFraction","adjustOption","originWidth","oneIWidth","_Textbox","_defineProperty","textLayoutProperties","textPath","textPathParsedAttributes","href","startsWith","pathElement","pathParsedAttributes","Path","d","stroke","fill","visible","fontStyle","fontWeight","pathType","classRegistry","setClass","setSVGClass"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Textbox.min.mjs","sources":["../../../src/shapes/Textbox.ts"],"sourcesContent":["import type { Abortable, TClassProperties, TOptions } from '../typedefs';\nimport { IText } from './IText/IText';\nimport { classRegistry } from '../ClassRegistry';\nimport { createTextboxDefaultControls } from '../controls/commonControls';\nimport { JUSTIFY } from './Text/constants';\nimport type { TextStyleDeclaration } from './Text/StyledText';\nimport type { SerializedITextProps, ITextProps } from './IText/IText';\nimport type { ITextEvents } from './IText/ITextBehavior';\nimport type {\n FabricText,\n SerializedTextProps,\n TextLinesInfo,\n} from './Text/Text';\nimport type { Control } from '../controls/Control';\nimport { stylesFromArray } from '../util';\nimport type { CSSRules } from '../parser/typedefs';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport { Path } from './Path';\nimport { DEFAULT_SVG_FONT_SIZE } from '../constants';\n\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\n// regexes, list of properties that are not suppose to change by instances, magic consts.\n// this will be a separated effort\nexport const textboxDefaultValues: Partial<TClassProperties<Textbox>> = {\n minWidth: 20,\n dynamicMinWidth: 2,\n lockScalingFlip: true,\n noScaleCache: false,\n _wordJoiners: /[ \\t\\r]/,\n splitByGrapheme: false,\n};\n\nexport type GraphemeData = {\n wordsData: {\n word: string[];\n width: number;\n }[][];\n largestWordWidth: number;\n};\n\nexport type StyleMap = Record<string, { line: number; offset: number }>;\n\n// @TODO this is not complete\ninterface UniqueTextboxProps {\n minWidth: number;\n splitByGrapheme: boolean;\n dynamicMinWidth: number;\n _wordJoiners: RegExp;\n}\n\nexport interface SerializedTextboxProps\n extends SerializedITextProps,\n Pick<UniqueTextboxProps, 'minWidth' | 'splitByGrapheme'> {}\n\nexport interface TextboxProps extends ITextProps, UniqueTextboxProps {}\n\n/**\n * Textbox class, based on IText, allows the user to resize the text rectangle\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\n * user can only change width. Height is adjusted automatically based on the\n * wrapping of lines.\n */\nexport class Textbox<\n Props extends TOptions<TextboxProps> = Partial<TextboxProps>,\n SProps extends SerializedTextboxProps = SerializedTextboxProps,\n EventSpec extends ITextEvents = ITextEvents,\n >\n extends IText<Props, SProps, EventSpec>\n implements UniqueTextboxProps\n{\n /**\n * Minimum width of textbox, in pixels.\n * @type Number\n * @default\n */\n declare minWidth: number;\n\n /**\n * Minimum calculated width of a textbox, in pixels.\n * fixed to 2 so that an empty textbox cannot go to 0\n * and is still selectable without text.\n * @type Number\n * @default\n */\n declare dynamicMinWidth: number;\n\n /**\n * Use this boolean property in order to split strings that have no white space concept.\n * this is a cheap way to help with chinese/japanese\n * @type Boolean\n * @since 2.6.0\n */\n declare splitByGrapheme: boolean;\n\n declare _wordJoiners: RegExp;\n\n declare _styleMap: StyleMap;\n\n declare isWrapping: boolean;\n\n static type = 'Textbox';\n\n static textLayoutProperties = [...IText.textLayoutProperties, 'width'];\n\n static ownDefaults = textboxDefaultValues;\n\n // James modified 自动计算文字高度\n static enableCalcTextHeight = false;\n\n /**\n * James modified 自动计算文字高度\n * 增加wrap宽度,设置为page的宽度\n * 增加textbox wrap的默认宽度\n * @type Number\n * @default\n */\n static defaultWrapWidth = 1920;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Textbox.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n */\n constructor(text: string, options?: Props) {\n super(text, { ...Textbox.ownDefaults, ...options } as Props);\n }\n\n /**\n * Creates the default control object.\n * If you prefer to have on instance of controls shared among all objects\n * make this function return an empty object and add controls to the ownDefaults object\n */\n static createControls(): { controls: Record<string, Control> } {\n return { controls: createTextboxDefaultControls() };\n }\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @private\n * @override\n */\n initDimensions() {\n if (!this.initialized) {\n return;\n }\n this.isEditing && this.initDelayedCursor();\n this._clearCache();\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n // wrap lines\n this._styleMap = this._generateStyleMap(this._splitText());\n // James modified\n // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n if (!this.path && this.dynamicMinWidth > this.width) {\n this._set('width', this.dynamicMinWidth);\n }\n if (this.textAlign.includes(JUSTIFY)) {\n // once text is measured we need to make space fatter to make justified text.\n this.enlargeSpaces();\n }\n // James modified 取消 textbox 自动计算高度\n if (!this.path && Textbox.enableCalcTextHeight) {\n // clear cache and re-calculate height\n this.height = this.calcTextHeight();\n }\n this.preventGroupCache = this.path ? true : false;\n }\n\n /**\n * Generate an object that translates the style object so that it is\n * broken up by visual lines (new lines and automatic wrapping).\n * The original text styles object is broken up by actual lines (new lines only),\n * which is only sufficient for Text / IText\n * @private\n */\n _generateStyleMap(textInfo: TextLinesInfo): StyleMap {\n let realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0;\n const map: StyleMap = {};\n\n for (let i = 0; i < textInfo.graphemeLines.length; i++) {\n if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n } else if (\n !this.splitByGrapheme &&\n this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\n i > 0\n ) {\n // this case deals with space's that are removed from end of lines when wrapping\n realLineCharCount++;\n charCount++;\n }\n\n map[i] = { line: realLineCount, offset: realLineCharCount };\n\n charCount += textInfo.graphemeLines[i].length;\n realLineCharCount += textInfo.graphemeLines[i].length;\n }\n\n return map;\n }\n\n /**\n * Returns true if object has a style property or has it on a specified line\n * @param {Number} lineIndex\n * @return {Boolean}\n */\n styleHas(property: keyof TextStyleDeclaration, lineIndex: number): boolean {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (map) {\n lineIndex = map.line;\n }\n }\n return super.styleHas(property, lineIndex);\n }\n\n /**\n * Returns true if object has no styling or no styling in a line\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\n * @return {Boolean}\n */\n isEmptyStyles(lineIndex: number): boolean {\n if (!this.styles) {\n return true;\n }\n let offset = 0,\n nextLineIndex = lineIndex + 1,\n nextOffset: number,\n shouldLimit = false;\n const map = this._styleMap[lineIndex],\n mapNextLine = this._styleMap[lineIndex + 1];\n if (map) {\n lineIndex = map.line;\n offset = map.offset;\n }\n if (mapNextLine) {\n nextLineIndex = mapNextLine.line;\n shouldLimit = nextLineIndex === lineIndex;\n nextOffset = mapNextLine.offset;\n }\n const obj =\n typeof lineIndex === 'undefined'\n ? this.styles\n : { line: this.styles[lineIndex] };\n for (const p1 in obj) {\n for (const p2 in obj[p1]) {\n const p2Number = parseInt(p2, 10);\n if (p2Number >= offset && (!shouldLimit || p2Number < nextOffset!)) {\n // eslint-disable-next-line no-unused-vars\n for (const p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n }\n return true;\n }\n\n /**\n * @protected\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined\n */\n _getStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n ): TextStyleDeclaration {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (!map) {\n return {};\n }\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n return super._getStyleDeclaration(lineIndex, charIndex);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n protected _setStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n style: object,\n ) {\n const map = this._styleMap[lineIndex];\n super._setStyleDeclaration(map.line, map.offset + charIndex, style);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n protected _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\n const map = this._styleMap[lineIndex];\n super._deleteStyleDeclaration(map.line, map.offset + charIndex);\n }\n\n /**\n * probably broken need a fix\n * Returns the real style line that correspond to the wrapped lineIndex line\n * Used just to verify if the line does exist or not.\n * @param {Number} lineIndex\n * @returns {Boolean} if the line exists or not\n * @private\n */\n protected _getLineStyle(lineIndex: number): boolean {\n const map = this._styleMap[lineIndex];\n return !!this.styles[map.line];\n }\n\n /**\n * Set the line style to an empty object so that is initialized\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n protected _setLineStyle(lineIndex: number) {\n const map = this._styleMap[lineIndex];\n super._setLineStyle(map.line);\n }\n\n /**\n * Wraps text using the 'width' property of Textbox. First this function\n * splits text on newlines, so we preserve newlines entered by the user.\n * Then it wraps each line using the width of the Textbox by calling\n * _wrapLine().\n * @param {Array} lines The string array of text that is split into lines\n * @param {Number} desiredWidth width you want to wrap to\n * @returns {Array} Array of lines\n */\n _wrapText(lines: string[], desiredWidth: number): string[][] {\n this.isWrapping = true;\n // extract all thewords and the widths to optimally wrap lines.\n const data = this.getGraphemeDataForRender(lines);\n const wrapped: string[][] = [];\n for (let i = 0; i < data.wordsData.length; i++) {\n wrapped.push(...this._wrapLine(i, desiredWidth, data));\n }\n this.isWrapping = false;\n return wrapped;\n }\n\n /**\n * For each line of text terminated by an hard line stop,\n * measure each word width and extract the largest word from all.\n * The returned words here are the one that at the end will be rendered.\n * @param {string[]} lines the lines we need to measure\n *\n */\n getGraphemeDataForRender(lines: string[]): GraphemeData {\n const splitByGrapheme = this.splitByGrapheme,\n infix = splitByGrapheme ? '' : ' ';\n\n let largestWordWidth = 0;\n\n const data = lines.map((line, lineIndex) => {\n let offset = 0;\n const wordsOrGraphemes = splitByGrapheme\n ? this.graphemeSplit(line)\n : this.wordSplit(line);\n\n if (wordsOrGraphemes.length === 0) {\n return [{ word: [], width: 0 }];\n }\n\n return wordsOrGraphemes.map((word: string) => {\n // if using splitByGrapheme words are already in graphemes.\n const graphemeArray = splitByGrapheme\n ? [word]\n : this.graphemeSplit(word);\n const width = this._measureWord(graphemeArray, lineIndex, offset);\n largestWordWidth = Math.max(width, largestWordWidth);\n offset += graphemeArray.length + infix.length;\n return { word: graphemeArray, width };\n });\n });\n\n return {\n wordsData: data,\n largestWordWidth,\n };\n }\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n * It gets called when charBounds are not available yet.\n * Override if necessary\n * Use with {@link Textbox#wordSplit}\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n */\n _measureWord(word: string[], lineIndex: number, charOffset = 0): number {\n let width = 0,\n prevGrapheme;\n const skipLeft = true;\n for (let i = 0, len = word.length; i < len; i++) {\n const box = this._getGraphemeBox(\n word[i],\n lineIndex,\n i + charOffset,\n prevGrapheme,\n skipLeft,\n );\n width += box.kernedWidth;\n prevGrapheme = word[i];\n }\n return width;\n }\n\n /**\n * Override this method to customize word splitting\n * Use with {@link Textbox#_measureWord}\n * @param {string} value\n * @returns {string[]} array of words\n */\n wordSplit(value: string): string[] {\n return value.split(this._wordJoiners);\n }\n\n /**\n * Wraps a line of text using the width of the Textbox as desiredWidth\n * and leveraging the known width o words from GraphemeData\n * @private\n * @param {Number} lineIndex\n * @param {Number} desiredWidth width you want to wrap the line to\n * @param {GraphemeData} graphemeData an object containing all the lines' words width.\n * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine(\n lineIndex: number,\n desiredWidth: number,\n { largestWordWidth, wordsData }: GraphemeData,\n reservedSpace = 0,\n ): string[][] {\n const additionalSpace = this._getWidthOfCharSpacing(),\n splitByGrapheme = this.splitByGrapheme,\n graphemeLines = [],\n infix = splitByGrapheme ? '' : ' ';\n\n let lineWidth = 0,\n line: string[] = [],\n // spaces in different languages?\n offset = 0,\n infixWidth = 0,\n lineJustStarted = true;\n\n desiredWidth -= reservedSpace;\n\n const maxWidth = Math.max(\n desiredWidth,\n largestWordWidth,\n this.dynamicMinWidth,\n );\n // layout words\n const data = wordsData[lineIndex];\n offset = 0;\n let i;\n for (i = 0; i < data.length; i++) {\n const { word, width: wordWidth } = data[i];\n offset += word.length;\n\n lineWidth += infixWidth + wordWidth - additionalSpace;\n if (lineWidth > maxWidth && !lineJustStarted) {\n graphemeLines.push(line);\n line = [];\n lineWidth = wordWidth;\n lineJustStarted = true;\n } else {\n lineWidth += additionalSpace;\n }\n\n if (!lineJustStarted && !splitByGrapheme) {\n line.push(infix);\n }\n line = line.concat(word);\n\n infixWidth = splitByGrapheme\n ? 0\n : this._measureWord([infix], lineIndex, offset);\n offset++;\n lineJustStarted = false;\n }\n\n i && graphemeLines.push(line);\n\n // TODO: this code is probably not necessary anymore.\n // it can be moved out of this function since largestWordWidth is now\n // known in advance\n if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n }\n return graphemeLines;\n }\n\n /**\n * Detect if the text line is ended with an hard break\n * text and itext do not have wrapping, return false\n * @param {Number} lineIndex text to split\n * @return {Boolean}\n */\n isEndOfWrapping(lineIndex: number): boolean {\n if (!this._styleMap[lineIndex + 1]) {\n // is last line, return true;\n return true;\n }\n if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n // this is last line before a line break, return true;\n return true;\n }\n return false;\n }\n\n /**\n * Detect if a line has a linebreak and so we need to account for it when moving\n * and counting style.\n * This is important only for splitByGrapheme at the end of wrapping.\n * If we are not wrapping the offset is always 1\n * @return Number\n */\n missingNewlineOffset(lineIndex: number, skipWrapping?: boolean): 0 | 1 {\n if (this.splitByGrapheme && !skipWrapping) {\n return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n }\n return 1;\n }\n\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly every time it is called.\n * @param {String} text text to split\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines(text: string) {\n // James modified 存在path时候不按照宽度换行\n var wrapWidth = this.path ? 10000000 : this.width;\n // 如果width 不存在, 使用page width\n wrapWidth = wrapWidth || Textbox.defaultWrapWidth;\n const newText = super._splitTextIntoLines(text),\n graphemeLines = this._wrapText(newText.lines, wrapWidth),\n lines = new Array(graphemeLines.length);\n for (let i = 0; i < graphemeLines.length; i++) {\n lines[i] = graphemeLines[i].join('');\n }\n newText.lines = lines;\n newText.graphemeLines = graphemeLines;\n return newText;\n }\n\n getMinWidth() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\n }\n\n _removeExtraneousStyles() {\n const linesToKeep = new Map();\n for (const prop in this._styleMap) {\n const propNumber = parseInt(prop, 10);\n if (this._textLines[propNumber]) {\n const lineIndex = this._styleMap[prop].line;\n linesToKeep.set(`${lineIndex}`, true);\n }\n }\n for (const prop in this.styles) {\n if (!linesToKeep.has(prop)) {\n delete this.styles[prop];\n }\n }\n }\n\n /**\n * Returns object representation of an instance\n * @method toObject\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return super.toObject<T, K>([\n 'minWidth',\n 'splitByGrapheme',\n ...propertiesToInclude,\n ] as K[]) as Pick<T, K> & SProps;\n }\n\n /**\n * Returns FabricText instance from an SVG element (<b>not yet implemented</b>)\n * @static\n * @memberOf Text\n * @param {HTMLElement} element Element to parse\n * @param {Object} [options] Options object\n */\n static async fromElement(\n element: HTMLElement,\n options: Abortable,\n cssRules?: CSSRules,\n ) {\n if (!element) {\n return null;\n }\n\n var parsedAttributes = parseAttributes(\n element,\n Textbox.ATTRIBUTE_NAMES,\n cssRules,\n );\n const textOptions = {\n ...(cssRules ? JSON.parse(JSON.stringify(cssRules)) : {}),\n ...parsedAttributes,\n };\n // 处理style中字体样式带单引号问题\n let reg = /^'(.*)'$/;\n if (reg.test(textOptions.fontFamily)) {\n textOptions.fontFamily = textOptions.fontFamily.slice(1, -1);\n }\n\n textOptions.top = textOptions.top || 0;\n textOptions.left = textOptions.left || 0;\n if (parsedAttributes.textDecoration) {\n var textDecoration = parsedAttributes.textDecoration;\n if (textDecoration.indexOf('underline') !== -1) {\n textOptions.underline = true;\n }\n if (textDecoration.indexOf('overline') !== -1) {\n textOptions.overline = true;\n }\n if (textDecoration.indexOf('line-through') !== -1) {\n textOptions.linethrough = true;\n }\n delete textOptions.textDecoration;\n }\n if ('dx' in parsedAttributes) {\n textOptions.left += parsedAttributes.dx;\n }\n if ('dy' in parsedAttributes) {\n textOptions.top += parsedAttributes.dy;\n }\n if (!('fontSize' in textOptions)) {\n textOptions.fontSize = DEFAULT_SVG_FONT_SIZE;\n }\n\n let text: Textbox;\n const paths = element.getElementsByTagName('textPath');\n if (paths.length) {\n text = this._fromTextPath(paths[0], textOptions, parsedAttributes);\n } else {\n text = this._fromTextSpan(element, textOptions, parsedAttributes);\n }\n return text;\n }\n\n static _findSvgTextPath(element: any, id: string) {\n const svg = element.closest('svg');\n return svg.querySelector(id);\n }\n\n static _fromTextPath = (\n textPath: any,\n options: any,\n parsedAttributes: { [key: string]: string },\n ): Textbox => {\n var parsedAnchor = parsedAttributes.textAnchor || 'left';\n\n var textPathParsedAttributes = parseAttributes(textPath, [\n 'href',\n 'text-anchor',\n 'startOffset',\n ]);\n if (textPathParsedAttributes.textAnchor) {\n parsedAnchor = textPathParsedAttributes.textAnchor;\n }\n if (parsedAnchor === 'middle') {\n parsedAnchor = 'center';\n } else if (parsedAnchor === 'end') {\n parsedAnchor = 'right';\n }\n options.textAlign = parsedAnchor;\n\n var textContent = textPath.textContent;\n var text = new Textbox(textContent, options);\n\n const href = textPathParsedAttributes.href;\n if (href && href.startsWith('#')) {\n const pathElement = Textbox._findSvgTextPath(textPath, href);\n if (pathElement) {\n var pathParsedAttributes = parseAttributes(\n pathElement,\n Path.ATTRIBUTE_NAMES,\n );\n const path = new Path(pathParsedAttributes.d, {\n ...pathParsedAttributes,\n ...{\n strokeWidth: 1,\n stroke: '#ff0000',\n fill: null as any,\n visible: false,\n },\n });\n // 需要计算实际字体大小\n Textbox.enableCalcTextHeight = true;\n const textHeight =\n new Textbox('i', {\n fontFamily: options.fontFamily,\n fontSize: options.fontSize,\n fontStyle: options.fontStyle,\n fontWeight: options.fontWeight,\n width: undefined,\n height: undefined,\n }).height || 20;\n text.set({\n width: (path.width || 0) + textHeight * 2,\n height: (path.height || 0) + textHeight * 2,\n path,\n pathType: 'custom',\n } as any);\n // 取消自动计算文字高度\n Textbox.enableCalcTextHeight = false;\n }\n }\n // 设置位置中心点为左上角\n text.set({\n left: options.left - (text.width || 0) / 2,\n top: options.top - (text.height || 0) / 2,\n });\n return text;\n };\n\n static _fromTextSpan(\n element: any,\n options: any,\n parsedAttributes: { [key: string]: string },\n ): Textbox {\n var textContent = '';\n var parsedAnchor = parsedAttributes.textAnchor || 'left';\n // 是否需要根据tspan位置计算对齐\n let calcHorAlign = !parsedAttributes.textAnchor;\n let calcAdjustHorAlign = '';\n\n // The XML is not properly parsed in IE9 so a workaround to get\n // textContent is through firstChild.data. Another workaround would be\n // to convert XML loaded from a file to be converted using DOMParser (same way loadSVGFromString() does)\n\n let lineCnt = 1;\n let alignmentBaseline = 'auto';\n let spanOffX = 0,\n minSpanX: number | null = null,\n spanOffY = 0;\n\n if (element.hasAttribute('line-height')) {\n options.lineHeight = parseFloat(element.getAttribute('line-height'));\n } else if (options['line-height']) {\n // 从style 转换过来\n options.lineHeight = parseFloat(options['line-height']) / 100;\n } else {\n options.lineHeight = 1;\n }\n\n if (!('textContent' in element)) {\n if ('firstChild' in element && element.firstChild !== null) {\n if ('data' in element.firstChild && element.firstChild.data !== null) {\n textContent = element.firstChild.data;\n }\n }\n } else {\n textContent = element.textContent;\n let spans = element.getElementsByTagName('tspan');\n if (spans.length > 0) {\n // 多行文字\n let lines: {\n text: string;\n left: number;\n width?: number;\n right?: number;\n }[] = [],\n lineText = '',\n curLineLeft = 0, // 本行的 水平方向位置\n preSpanTop = 0, // 前一个tspan的 垂直方向位置\n sumDx = 0,\n sumDy = 0;\n for (let i = 0; i < spans.length; i++) {\n var parsedSpanAttributes = parseAttributes(\n spans[i],\n Textbox.ATTRIBUTE_NAMES,\n );\n\n sumDx += Number(parsedSpanAttributes.dx) || 0;\n sumDy += Number(parsedSpanAttributes.dy) || 0;\n // 在使用tspan判断对齐时spanX取最小的值\n if ('left' in parsedSpanAttributes) {\n let spanX = parseFloat(parsedSpanAttributes.left);\n minSpanX = minSpanX != null ? Math.min(minSpanX, spanX) : spanX;\n }\n // 现在多个tspan用多行文字, 所以对齐和位置只处理第一个 tspan\n if (i === 0) {\n if (spans[i].hasAttribute('text-anchor')) {\n // 水平方向\n let anchor = spans[i].getAttribute('text-anchor');\n // left | center | right\n // start | middle | end\n if (anchor === 'middle') {\n parsedAnchor = 'center';\n } else if (anchor === 'end') {\n parsedAnchor = 'right';\n }\n calcHorAlign = false;\n }\n if (spans[i].hasAttribute('alignment-baseline')) {\n // 垂直方向\n alignmentBaseline = spans[i].getAttribute('alignment-baseline');\n }\n\n // 处理tspan设置的位置和偏移\n // top只处理第一行\n if ('top' in parsedSpanAttributes) {\n let spanY = parseFloat(parsedSpanAttributes.top);\n spanY += sumDy;\n\n spanOffY = options.top - spanY;\n }\n }\n\n // 多个tspan可能在一行 根据 y position判断是否换行\n // 另外没有对齐方式的,计算判断对齐方式,根据left的值判断对齐方式\n (parsedSpanAttributes as any).left =\n Number(parsedSpanAttributes.left || 0) + sumDx;\n (parsedSpanAttributes as any).top =\n Number(parsedSpanAttributes.top || 0) + sumDy;\n\n if (i === 0 || preSpanTop === (parsedSpanAttributes as any).top) {\n lineText += spans[i].textContent;\n if (i === 0) {\n curLineLeft = Number((parsedSpanAttributes as any).left || 0);\n }\n } else {\n lines.push({ text: lineText, left: curLineLeft });\n lineText = spans[i].textContent;\n curLineLeft = Number((parsedSpanAttributes as any).left || 0);\n }\n\n // 记住上一个span的Y位置\n preSpanTop = (parsedSpanAttributes as any).top;\n }\n // 加上最后一行\n if (lineText.length) {\n lines.push({ text: lineText, left: curLineLeft });\n }\n // 加上换行符号\n textContent = lines.map((v) => v.text).join('\\n');\n lineCnt = lines.length;\n\n if (calcHorAlign) {\n if (lines.some((v) => v.left !== curLineLeft)) {\n // 取最left的最小值,和right最大值\n let minLeft = lines[0].left,\n maxRight = lines[0].left,\n maxWidth = 0,\n minCenter: number | null = null,\n maxCenter: number | null = null,\n maxChar = 0,\n maxCharIdx = 0;\n\n lines.forEach((v, idx) => {\n minLeft = Math.min(minLeft, v.left);\n v.width = (new Textbox(v.text, options) as any).calcTextWidth();\n v.right = v.left + (v.width || 0);\n maxRight = Math.max(maxRight, v.right);\n maxWidth = Math.max(maxWidth, v.width || 0);\n if (v.width) {\n const center = v.left + (v.width || 0) / 2;\n minCenter = minCenter ? Math.min(minCenter, center) : center;\n maxCenter = maxCenter ? Math.max(maxCenter, center) : center;\n\n if (v.text.length > maxChar) {\n maxChar = v.text.length;\n maxCharIdx = idx;\n }\n }\n });\n let leftGap = 0,\n rightGap = 0;\n lines.forEach((v) => {\n leftGap = Math.max(leftGap, (v.left || 0) - minLeft);\n rightGap = Math.max(rightGap, maxRight - (v.right || 0));\n });\n // 计算中心点位置\n if (maxCenter !== null && minCenter !== null) {\n const centerOff = maxCenter - minCenter;\n const onCharWidth =\n (lines[maxCharIdx].width || 0) / lines[maxCharIdx].text.length;\n // 左边间距大于右边两倍 或者 中心点偏移超过1/2字符且右边间距小于1/3字符\n if (\n leftGap / (rightGap || 1) > 2 &&\n centerOff > onCharWidth / 2 &&\n rightGap < onCharWidth / 3\n ) {\n calcAdjustHorAlign = 'right';\n } else if (centerOff < onCharWidth / 2) {\n calcAdjustHorAlign = 'center';\n }\n }\n }\n }\n }\n }\n\n // 处理文字的水平偏移\n spanOffX = options.left - (minSpanX || 0);\n\n // textAlign保持和parsedAnchor一致\n options.textAlign = parsedAnchor;\n\n // 注释掉原来删除换行等符号的代码\n //textContent = textContent.replace(/^\\s+|\\s+$|\\n+/g, '').replace(/\\s+/g, ' ');\n var originalStrokeWidth = options.strokeWidth;\n options.strokeWidth = 0;\n\n // 导入时打开自动计算文字高度,否则文字高度和 Y 轴位置错误\n Textbox.enableCalcTextHeight = true;\n var text = new Textbox(textContent, options),\n textOneLineHeight = text.height / lineCnt,\n textHeightScaleFactor = text.getScaledHeight() / text.height,\n lineHeightDiff =\n (textOneLineHeight + text.strokeWidth) * text.lineHeight -\n textOneLineHeight,\n scaledDiff = lineHeightDiff * textHeightScaleFactor,\n textHeight = text.getScaledHeight() / lineCnt + scaledDiff,\n offX = 0,\n offY = 0;\n\n // 默认 alignment-baseline=\"before-edge\" offY = 0\n let offScale = 0;\n if (alignmentBaseline === 'before-edge') {\n // 这个是1.0 导出的偏移值,多行且间距设置大于1也会有变化\n // 暂时这么处理, 以后再解决\n offScale = 1.1;\n } else if (alignmentBaseline === 'auto') {\n // alignment-baseline=\"auto\" 或者 没有设置\n offScale = 0.02913333333;\n }\n\n if (offScale !== 0) {\n offY =\n (textHeight - text.fontSize * (offScale + text._fontSizeFraction)) /\n text.lineHeight;\n }\n\n // 取消自动计算文字高度\n Textbox.enableCalcTextHeight = false;\n /*\n Adjust positioning:\n x/y attributes in SVG correspond to the bottom-left corner of text bounding box\n fabric output by default at top, left.\n */\n const adjustOption: Partial<ITextProps> = {};\n // 源码中options.width总是等于svg的宽度, 之前是new Text不能编辑文字,宽度设置为svg宽度也无效\n // 修改为 new fabric.Textbox,并且设置为计算的正确宽度\n const originWidth = options.width;\n let width = text.calcTextWidth();\n // 有时候计算出来的大小是不对的, 可能是字体的原因, 导致TextBox自动换行了, 所以加i字符的宽度\n const oneIWidth = (new Textbox('i', options) as any).calcTextWidth();\n width += oneIWidth;\n\n if (originWidth !== width) {\n adjustOption.width = width;\n }\n if (calcAdjustHorAlign) {\n // tspan 按字符分开计算的对齐\n adjustOption.textAlign = calcAdjustHorAlign;\n }\n\n // 2021.1.29修改\n // Vectr1.0导出的svg,需要处理水平居中或右对齐偏移\n // Vectr2.0导出的是按照span位置判断的对齐不需要处理整个width的位置偏移, 但是需要处理 oneIWidth的位置偏移\n const textAlign = calcAdjustHorAlign || parsedAnchor;\n if (textAlign === 'center') {\n offX = (parsedAnchor === 'center' ? width : oneIWidth) / 2;\n } else if (textAlign === 'right') {\n offX = parsedAnchor === 'right' ? width : oneIWidth;\n }\n\n text.set({\n ...adjustOption,\n left: text.left - offX - spanOffX,\n top: text.top - offY - spanOffY,\n strokeWidth:\n typeof originalStrokeWidth !== 'undefined' ? originalStrokeWidth : 1,\n });\n return text;\n }\n}\n\nclassRegistry.setClass(Textbox);\nclassRegistry.setSVGClass(Textbox);\n"],"names":["textboxDefaultValues","minWidth","dynamicMinWidth","lockScalingFlip","noScaleCache","_wordJoiners","splitByGrapheme","Textbox","IText","getDefaults","super","ownDefaults","constructor","text","options","createControls","controls","createTextboxDefaultControls","initDimensions","this","initialized","isEditing","initDelayedCursor","_clearCache","_styleMap","_generateStyleMap","_splitText","path","width","_set","textAlign","includes","JUSTIFY","enlargeSpaces","enableCalcTextHeight","height","calcTextHeight","preventGroupCache","textInfo","realLineCount","realLineCharCount","charCount","map","i","graphemeLines","length","graphemeText","_reSpaceAndTab","test","line","offset","styleHas","property","lineIndex","isWrapping","isEmptyStyles","styles","nextOffset","nextLineIndex","shouldLimit","mapNextLine","obj","p1","p2","p2Number","parseInt","p3","_getStyleDeclaration","charIndex","_setStyleDeclaration","style","_deleteStyleDeclaration","_getLineStyle","_setLineStyle","_wrapText","lines","desiredWidth","data","getGraphemeDataForRender","wrapped","wordsData","push","_wrapLine","infix","largestWordWidth","wordsOrGraphemes","graphemeSplit","wordSplit","word","graphemeArray","_measureWord","Math","max","prevGrapheme","charOffset","arguments","undefined","len","_getGraphemeBox","kernedWidth","value","split","_ref","reservedSpace","additionalSpace","_getWidthOfCharSpacing","lineWidth","infixWidth","lineJustStarted","maxWidth","wordWidth","concat","isEndOfWrapping","missingNewlineOffset","skipWrapping","_splitTextIntoLines","wrapWidth","defaultWrapWidth","newText","Array","join","getMinWidth","_removeExtraneousStyles","linesToKeep","Map","prop","propNumber","_textLines","set","has","toObject","propertiesToInclude","fromElement","element","cssRules","parsedAttributes","parseAttributes","ATTRIBUTE_NAMES","textOptions","JSON","parse","stringify","fontFamily","slice","top","left","textDecoration","indexOf","underline","overline","linethrough","dx","dy","fontSize","DEFAULT_SVG_FONT_SIZE","paths","getElementsByTagName","_fromTextPath","_fromTextSpan","_findSvgTextPath","id","closest","querySelector","textContent","parsedAnchor","textAnchor","calcHorAlign","calcAdjustHorAlign","lineCnt","alignmentBaseline","spanOffX","minSpanX","spanOffY","hasAttribute","lineHeight","parseFloat","getAttribute","spans","lineText","curLineLeft","preSpanTop","sumDx","sumDy","parsedSpanAttributes","Number","spanX","min","anchor","spanY","v","some","minLeft","maxRight","minCenter","maxCenter","maxChar","maxCharIdx","forEach","idx","calcTextWidth","right","center","leftGap","rightGap","centerOff","onCharWidth","firstChild","originalStrokeWidth","strokeWidth","textOneLineHeight","textHeightScaleFactor","getScaledHeight","scaledDiff","textHeight","offX","offY","offScale","_fontSizeFraction","adjustOption","originWidth","oneIWidth","_Textbox","_defineProperty","textLayoutProperties","textPath","textPathParsedAttributes","href","startsWith","pathElement","pathParsedAttributes","Path","d","stroke","fill","visible","fontStyle","fontWeight","pathType","classRegistry","setClass","setSVGClass"],"mappings":"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"}
|
|
@@ -691,7 +691,7 @@ class Textbox extends IText {
|
|
|
691
691
|
rightGap = Math.max(rightGap, maxRight - (v.right || 0));
|
|
692
692
|
});
|
|
693
693
|
// 计算中心点位置
|
|
694
|
-
if (maxCenter && minCenter) {
|
|
694
|
+
if (maxCenter !== null && minCenter !== null) {
|
|
695
695
|
const centerOff = maxCenter - minCenter;
|
|
696
696
|
const onCharWidth = (lines[maxCharIdx].width || 0) / lines[maxCharIdx].text.length;
|
|
697
697
|
// 左边间距大于右边两倍 或者 中心点偏移超过1/2字符且右边间距小于1/3字符
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Textbox.mjs","sources":["../../../src/shapes/Textbox.ts"],"sourcesContent":["import type { Abortable, TClassProperties, TOptions } from '../typedefs';\nimport { IText } from './IText/IText';\nimport { classRegistry } from '../ClassRegistry';\nimport { createTextboxDefaultControls } from '../controls/commonControls';\nimport { JUSTIFY } from './Text/constants';\nimport type { TextStyleDeclaration } from './Text/StyledText';\nimport type { SerializedITextProps, ITextProps } from './IText/IText';\nimport type { ITextEvents } from './IText/ITextBehavior';\nimport type {\n FabricText,\n SerializedTextProps,\n TextLinesInfo,\n} from './Text/Text';\nimport type { Control } from '../controls/Control';\nimport { stylesFromArray } from '../util';\nimport type { CSSRules } from '../parser/typedefs';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport { Path } from './Path';\nimport { DEFAULT_SVG_FONT_SIZE } from '../constants';\n\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\n// regexes, list of properties that are not suppose to change by instances, magic consts.\n// this will be a separated effort\nexport const textboxDefaultValues: Partial<TClassProperties<Textbox>> = {\n minWidth: 20,\n dynamicMinWidth: 2,\n lockScalingFlip: true,\n noScaleCache: false,\n _wordJoiners: /[ \\t\\r]/,\n splitByGrapheme: false,\n};\n\nexport type GraphemeData = {\n wordsData: {\n word: string[];\n width: number;\n }[][];\n largestWordWidth: number;\n};\n\nexport type StyleMap = Record<string, { line: number; offset: number }>;\n\n// @TODO this is not complete\ninterface UniqueTextboxProps {\n minWidth: number;\n splitByGrapheme: boolean;\n dynamicMinWidth: number;\n _wordJoiners: RegExp;\n}\n\nexport interface SerializedTextboxProps\n extends SerializedITextProps,\n Pick<UniqueTextboxProps, 'minWidth' | 'splitByGrapheme'> {}\n\nexport interface TextboxProps extends ITextProps, UniqueTextboxProps {}\n\n/**\n * Textbox class, based on IText, allows the user to resize the text rectangle\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\n * user can only change width. Height is adjusted automatically based on the\n * wrapping of lines.\n */\nexport class Textbox<\n Props extends TOptions<TextboxProps> = Partial<TextboxProps>,\n SProps extends SerializedTextboxProps = SerializedTextboxProps,\n EventSpec extends ITextEvents = ITextEvents,\n >\n extends IText<Props, SProps, EventSpec>\n implements UniqueTextboxProps\n{\n /**\n * Minimum width of textbox, in pixels.\n * @type Number\n * @default\n */\n declare minWidth: number;\n\n /**\n * Minimum calculated width of a textbox, in pixels.\n * fixed to 2 so that an empty textbox cannot go to 0\n * and is still selectable without text.\n * @type Number\n * @default\n */\n declare dynamicMinWidth: number;\n\n /**\n * Use this boolean property in order to split strings that have no white space concept.\n * this is a cheap way to help with chinese/japanese\n * @type Boolean\n * @since 2.6.0\n */\n declare splitByGrapheme: boolean;\n\n declare _wordJoiners: RegExp;\n\n declare _styleMap: StyleMap;\n\n declare isWrapping: boolean;\n\n static type = 'Textbox';\n\n static textLayoutProperties = [...IText.textLayoutProperties, 'width'];\n\n static ownDefaults = textboxDefaultValues;\n\n // James modified 自动计算文字高度\n static enableCalcTextHeight = false;\n\n /**\n * James modified 自动计算文字高度\n * 增加wrap宽度,设置为page的宽度\n * 增加textbox wrap的默认宽度\n * @type Number\n * @default\n */\n static defaultWrapWidth = 1920;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Textbox.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n */\n constructor(text: string, options?: Props) {\n super(text, { ...Textbox.ownDefaults, ...options } as Props);\n }\n\n /**\n * Creates the default control object.\n * If you prefer to have on instance of controls shared among all objects\n * make this function return an empty object and add controls to the ownDefaults object\n */\n static createControls(): { controls: Record<string, Control> } {\n return { controls: createTextboxDefaultControls() };\n }\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @private\n * @override\n */\n initDimensions() {\n if (!this.initialized) {\n return;\n }\n this.isEditing && this.initDelayedCursor();\n this._clearCache();\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n // wrap lines\n this._styleMap = this._generateStyleMap(this._splitText());\n // James modified\n // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n if (!this.path && this.dynamicMinWidth > this.width) {\n this._set('width', this.dynamicMinWidth);\n }\n if (this.textAlign.includes(JUSTIFY)) {\n // once text is measured we need to make space fatter to make justified text.\n this.enlargeSpaces();\n }\n // James modified 取消 textbox 自动计算高度\n if (!this.path && Textbox.enableCalcTextHeight) {\n // clear cache and re-calculate height\n this.height = this.calcTextHeight();\n }\n this.preventGroupCache = this.path ? true : false;\n }\n\n /**\n * Generate an object that translates the style object so that it is\n * broken up by visual lines (new lines and automatic wrapping).\n * The original text styles object is broken up by actual lines (new lines only),\n * which is only sufficient for Text / IText\n * @private\n */\n _generateStyleMap(textInfo: TextLinesInfo): StyleMap {\n let realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0;\n const map: StyleMap = {};\n\n for (let i = 0; i < textInfo.graphemeLines.length; i++) {\n if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n } else if (\n !this.splitByGrapheme &&\n this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\n i > 0\n ) {\n // this case deals with space's that are removed from end of lines when wrapping\n realLineCharCount++;\n charCount++;\n }\n\n map[i] = { line: realLineCount, offset: realLineCharCount };\n\n charCount += textInfo.graphemeLines[i].length;\n realLineCharCount += textInfo.graphemeLines[i].length;\n }\n\n return map;\n }\n\n /**\n * Returns true if object has a style property or has it on a specified line\n * @param {Number} lineIndex\n * @return {Boolean}\n */\n styleHas(property: keyof TextStyleDeclaration, lineIndex: number): boolean {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (map) {\n lineIndex = map.line;\n }\n }\n return super.styleHas(property, lineIndex);\n }\n\n /**\n * Returns true if object has no styling or no styling in a line\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\n * @return {Boolean}\n */\n isEmptyStyles(lineIndex: number): boolean {\n if (!this.styles) {\n return true;\n }\n let offset = 0,\n nextLineIndex = lineIndex + 1,\n nextOffset: number,\n shouldLimit = false;\n const map = this._styleMap[lineIndex],\n mapNextLine = this._styleMap[lineIndex + 1];\n if (map) {\n lineIndex = map.line;\n offset = map.offset;\n }\n if (mapNextLine) {\n nextLineIndex = mapNextLine.line;\n shouldLimit = nextLineIndex === lineIndex;\n nextOffset = mapNextLine.offset;\n }\n const obj =\n typeof lineIndex === 'undefined'\n ? this.styles\n : { line: this.styles[lineIndex] };\n for (const p1 in obj) {\n for (const p2 in obj[p1]) {\n const p2Number = parseInt(p2, 10);\n if (p2Number >= offset && (!shouldLimit || p2Number < nextOffset!)) {\n // eslint-disable-next-line no-unused-vars\n for (const p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n }\n return true;\n }\n\n /**\n * @protected\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined\n */\n _getStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n ): TextStyleDeclaration {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (!map) {\n return {};\n }\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n return super._getStyleDeclaration(lineIndex, charIndex);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n protected _setStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n style: object,\n ) {\n const map = this._styleMap[lineIndex];\n super._setStyleDeclaration(map.line, map.offset + charIndex, style);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n protected _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\n const map = this._styleMap[lineIndex];\n super._deleteStyleDeclaration(map.line, map.offset + charIndex);\n }\n\n /**\n * probably broken need a fix\n * Returns the real style line that correspond to the wrapped lineIndex line\n * Used just to verify if the line does exist or not.\n * @param {Number} lineIndex\n * @returns {Boolean} if the line exists or not\n * @private\n */\n protected _getLineStyle(lineIndex: number): boolean {\n const map = this._styleMap[lineIndex];\n return !!this.styles[map.line];\n }\n\n /**\n * Set the line style to an empty object so that is initialized\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n protected _setLineStyle(lineIndex: number) {\n const map = this._styleMap[lineIndex];\n super._setLineStyle(map.line);\n }\n\n /**\n * Wraps text using the 'width' property of Textbox. First this function\n * splits text on newlines, so we preserve newlines entered by the user.\n * Then it wraps each line using the width of the Textbox by calling\n * _wrapLine().\n * @param {Array} lines The string array of text that is split into lines\n * @param {Number} desiredWidth width you want to wrap to\n * @returns {Array} Array of lines\n */\n _wrapText(lines: string[], desiredWidth: number): string[][] {\n this.isWrapping = true;\n // extract all thewords and the widths to optimally wrap lines.\n const data = this.getGraphemeDataForRender(lines);\n const wrapped: string[][] = [];\n for (let i = 0; i < data.wordsData.length; i++) {\n wrapped.push(...this._wrapLine(i, desiredWidth, data));\n }\n this.isWrapping = false;\n return wrapped;\n }\n\n /**\n * For each line of text terminated by an hard line stop,\n * measure each word width and extract the largest word from all.\n * The returned words here are the one that at the end will be rendered.\n * @param {string[]} lines the lines we need to measure\n *\n */\n getGraphemeDataForRender(lines: string[]): GraphemeData {\n const splitByGrapheme = this.splitByGrapheme,\n infix = splitByGrapheme ? '' : ' ';\n\n let largestWordWidth = 0;\n\n const data = lines.map((line, lineIndex) => {\n let offset = 0;\n const wordsOrGraphemes = splitByGrapheme\n ? this.graphemeSplit(line)\n : this.wordSplit(line);\n\n if (wordsOrGraphemes.length === 0) {\n return [{ word: [], width: 0 }];\n }\n\n return wordsOrGraphemes.map((word: string) => {\n // if using splitByGrapheme words are already in graphemes.\n const graphemeArray = splitByGrapheme\n ? [word]\n : this.graphemeSplit(word);\n const width = this._measureWord(graphemeArray, lineIndex, offset);\n largestWordWidth = Math.max(width, largestWordWidth);\n offset += graphemeArray.length + infix.length;\n return { word: graphemeArray, width };\n });\n });\n\n return {\n wordsData: data,\n largestWordWidth,\n };\n }\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n * It gets called when charBounds are not available yet.\n * Override if necessary\n * Use with {@link Textbox#wordSplit}\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n */\n _measureWord(word: string[], lineIndex: number, charOffset = 0): number {\n let width = 0,\n prevGrapheme;\n const skipLeft = true;\n for (let i = 0, len = word.length; i < len; i++) {\n const box = this._getGraphemeBox(\n word[i],\n lineIndex,\n i + charOffset,\n prevGrapheme,\n skipLeft,\n );\n width += box.kernedWidth;\n prevGrapheme = word[i];\n }\n return width;\n }\n\n /**\n * Override this method to customize word splitting\n * Use with {@link Textbox#_measureWord}\n * @param {string} value\n * @returns {string[]} array of words\n */\n wordSplit(value: string): string[] {\n return value.split(this._wordJoiners);\n }\n\n /**\n * Wraps a line of text using the width of the Textbox as desiredWidth\n * and leveraging the known width o words from GraphemeData\n * @private\n * @param {Number} lineIndex\n * @param {Number} desiredWidth width you want to wrap the line to\n * @param {GraphemeData} graphemeData an object containing all the lines' words width.\n * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine(\n lineIndex: number,\n desiredWidth: number,\n { largestWordWidth, wordsData }: GraphemeData,\n reservedSpace = 0,\n ): string[][] {\n const additionalSpace = this._getWidthOfCharSpacing(),\n splitByGrapheme = this.splitByGrapheme,\n graphemeLines = [],\n infix = splitByGrapheme ? '' : ' ';\n\n let lineWidth = 0,\n line: string[] = [],\n // spaces in different languages?\n offset = 0,\n infixWidth = 0,\n lineJustStarted = true;\n\n desiredWidth -= reservedSpace;\n\n const maxWidth = Math.max(\n desiredWidth,\n largestWordWidth,\n this.dynamicMinWidth,\n );\n // layout words\n const data = wordsData[lineIndex];\n offset = 0;\n let i;\n for (i = 0; i < data.length; i++) {\n const { word, width: wordWidth } = data[i];\n offset += word.length;\n\n lineWidth += infixWidth + wordWidth - additionalSpace;\n if (lineWidth > maxWidth && !lineJustStarted) {\n graphemeLines.push(line);\n line = [];\n lineWidth = wordWidth;\n lineJustStarted = true;\n } else {\n lineWidth += additionalSpace;\n }\n\n if (!lineJustStarted && !splitByGrapheme) {\n line.push(infix);\n }\n line = line.concat(word);\n\n infixWidth = splitByGrapheme\n ? 0\n : this._measureWord([infix], lineIndex, offset);\n offset++;\n lineJustStarted = false;\n }\n\n i && graphemeLines.push(line);\n\n // TODO: this code is probably not necessary anymore.\n // it can be moved out of this function since largestWordWidth is now\n // known in advance\n if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n }\n return graphemeLines;\n }\n\n /**\n * Detect if the text line is ended with an hard break\n * text and itext do not have wrapping, return false\n * @param {Number} lineIndex text to split\n * @return {Boolean}\n */\n isEndOfWrapping(lineIndex: number): boolean {\n if (!this._styleMap[lineIndex + 1]) {\n // is last line, return true;\n return true;\n }\n if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n // this is last line before a line break, return true;\n return true;\n }\n return false;\n }\n\n /**\n * Detect if a line has a linebreak and so we need to account for it when moving\n * and counting style.\n * This is important only for splitByGrapheme at the end of wrapping.\n * If we are not wrapping the offset is always 1\n * @return Number\n */\n missingNewlineOffset(lineIndex: number, skipWrapping?: boolean): 0 | 1 {\n if (this.splitByGrapheme && !skipWrapping) {\n return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n }\n return 1;\n }\n\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly every time it is called.\n * @param {String} text text to split\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines(text: string) {\n // James modified 存在path时候不按照宽度换行\n var wrapWidth = this.path ? 10000000 : this.width;\n // 如果width 不存在, 使用page width\n wrapWidth = wrapWidth || Textbox.defaultWrapWidth;\n const newText = super._splitTextIntoLines(text),\n graphemeLines = this._wrapText(newText.lines, wrapWidth),\n lines = new Array(graphemeLines.length);\n for (let i = 0; i < graphemeLines.length; i++) {\n lines[i] = graphemeLines[i].join('');\n }\n newText.lines = lines;\n newText.graphemeLines = graphemeLines;\n return newText;\n }\n\n getMinWidth() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\n }\n\n _removeExtraneousStyles() {\n const linesToKeep = new Map();\n for (const prop in this._styleMap) {\n const propNumber = parseInt(prop, 10);\n if (this._textLines[propNumber]) {\n const lineIndex = this._styleMap[prop].line;\n linesToKeep.set(`${lineIndex}`, true);\n }\n }\n for (const prop in this.styles) {\n if (!linesToKeep.has(prop)) {\n delete this.styles[prop];\n }\n }\n }\n\n /**\n * Returns object representation of an instance\n * @method toObject\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return super.toObject<T, K>([\n 'minWidth',\n 'splitByGrapheme',\n ...propertiesToInclude,\n ] as K[]) as Pick<T, K> & SProps;\n }\n\n /**\n * Returns FabricText instance from an SVG element (<b>not yet implemented</b>)\n * @static\n * @memberOf Text\n * @param {HTMLElement} element Element to parse\n * @param {Object} [options] Options object\n */\n static async fromElement(\n element: HTMLElement,\n options: Abortable,\n cssRules?: CSSRules,\n ) {\n if (!element) {\n return null;\n }\n\n var parsedAttributes = parseAttributes(\n element,\n Textbox.ATTRIBUTE_NAMES,\n cssRules,\n );\n const textOptions = {\n ...(cssRules ? JSON.parse(JSON.stringify(cssRules)) : {}),\n ...parsedAttributes,\n };\n // 处理style中字体样式带单引号问题\n let reg = /^'(.*)'$/;\n if (reg.test(textOptions.fontFamily)) {\n textOptions.fontFamily = textOptions.fontFamily.slice(1, -1);\n }\n\n textOptions.top = textOptions.top || 0;\n textOptions.left = textOptions.left || 0;\n if (parsedAttributes.textDecoration) {\n var textDecoration = parsedAttributes.textDecoration;\n if (textDecoration.indexOf('underline') !== -1) {\n textOptions.underline = true;\n }\n if (textDecoration.indexOf('overline') !== -1) {\n textOptions.overline = true;\n }\n if (textDecoration.indexOf('line-through') !== -1) {\n textOptions.linethrough = true;\n }\n delete textOptions.textDecoration;\n }\n if ('dx' in parsedAttributes) {\n textOptions.left += parsedAttributes.dx;\n }\n if ('dy' in parsedAttributes) {\n textOptions.top += parsedAttributes.dy;\n }\n if (!('fontSize' in textOptions)) {\n textOptions.fontSize = DEFAULT_SVG_FONT_SIZE;\n }\n\n let text: Textbox;\n const paths = element.getElementsByTagName('textPath');\n if (paths.length) {\n text = this._fromTextPath(paths[0], textOptions, parsedAttributes);\n } else {\n text = this._fromTextSpan(element, textOptions, parsedAttributes);\n }\n return text;\n }\n\n static _findSvgTextPath(element: any, id: string) {\n const svg = element.closest('svg');\n return svg.querySelector(id);\n }\n\n static _fromTextPath = (\n textPath: any,\n options: any,\n parsedAttributes: { [key: string]: string },\n ): Textbox => {\n var parsedAnchor = parsedAttributes.textAnchor || 'left';\n\n var textPathParsedAttributes = parseAttributes(textPath, [\n 'href',\n 'text-anchor',\n 'startOffset',\n ]);\n if (textPathParsedAttributes.textAnchor) {\n parsedAnchor = textPathParsedAttributes.textAnchor;\n }\n if (parsedAnchor === 'middle') {\n parsedAnchor = 'center';\n } else if (parsedAnchor === 'end') {\n parsedAnchor = 'right';\n }\n options.textAlign = parsedAnchor;\n\n var textContent = textPath.textContent;\n var text = new Textbox(textContent, options);\n\n const href = textPathParsedAttributes.href;\n if (href && href.startsWith('#')) {\n const pathElement = Textbox._findSvgTextPath(textPath, href);\n if (pathElement) {\n var pathParsedAttributes = parseAttributes(\n pathElement,\n Path.ATTRIBUTE_NAMES,\n );\n const path = new Path(pathParsedAttributes.d, {\n ...pathParsedAttributes,\n ...{\n strokeWidth: 1,\n stroke: '#ff0000',\n fill: null as any,\n visible: false,\n },\n });\n // 需要计算实际字体大小\n Textbox.enableCalcTextHeight = true;\n const textHeight =\n new Textbox('i', {\n fontFamily: options.fontFamily,\n fontSize: options.fontSize,\n fontStyle: options.fontStyle,\n fontWeight: options.fontWeight,\n width: undefined,\n height: undefined,\n }).height || 20;\n text.set({\n width: (path.width || 0) + textHeight * 2,\n height: (path.height || 0) + textHeight * 2,\n path,\n pathType: 'custom',\n } as any);\n // 取消自动计算文字高度\n Textbox.enableCalcTextHeight = false;\n }\n }\n // 设置位置中心点为左上角\n text.set({\n left: options.left - (text.width || 0) / 2,\n top: options.top - (text.height || 0) / 2,\n });\n return text;\n };\n\n static _fromTextSpan(\n element: any,\n options: any,\n parsedAttributes: { [key: string]: string },\n ): Textbox {\n var textContent = '';\n var parsedAnchor = parsedAttributes.textAnchor || 'left';\n // 是否需要根据tspan位置计算对齐\n let calcHorAlign = !parsedAttributes.textAnchor;\n let calcAdjustHorAlign = '';\n\n // The XML is not properly parsed in IE9 so a workaround to get\n // textContent is through firstChild.data. Another workaround would be\n // to convert XML loaded from a file to be converted using DOMParser (same way loadSVGFromString() does)\n\n let lineCnt = 1;\n let alignmentBaseline = 'auto';\n let spanOffX = 0,\n minSpanX: number | null = null,\n spanOffY = 0;\n\n if (element.hasAttribute('line-height')) {\n options.lineHeight = parseFloat(element.getAttribute('line-height'));\n } else if (options['line-height']) {\n // 从style 转换过来\n options.lineHeight = parseFloat(options['line-height']) / 100;\n } else {\n options.lineHeight = 1;\n }\n\n if (!('textContent' in element)) {\n if ('firstChild' in element && element.firstChild !== null) {\n if ('data' in element.firstChild && element.firstChild.data !== null) {\n textContent = element.firstChild.data;\n }\n }\n } else {\n textContent = element.textContent;\n let spans = element.getElementsByTagName('tspan');\n if (spans.length > 0) {\n // 多行文字\n let lines: {\n text: string;\n left: number;\n width?: number;\n right?: number;\n }[] = [],\n lineText = '',\n curLineLeft = 0, // 本行的 水平方向位置\n preSpanTop = 0, // 前一个tspan的 垂直方向位置\n sumDx = 0,\n sumDy = 0;\n for (let i = 0; i < spans.length; i++) {\n var parsedSpanAttributes = parseAttributes(\n spans[i],\n Textbox.ATTRIBUTE_NAMES,\n );\n\n sumDx += Number(parsedSpanAttributes.dx) || 0;\n sumDy += Number(parsedSpanAttributes.dy) || 0;\n // 在使用tspan判断对齐时spanX取最小的值\n if ('left' in parsedSpanAttributes) {\n let spanX = parseFloat(parsedSpanAttributes.left);\n minSpanX = minSpanX != null ? Math.min(minSpanX, spanX) : spanX;\n }\n // 现在多个tspan用多行文字, 所以对齐和位置只处理第一个 tspan\n if (i === 0) {\n if (spans[i].hasAttribute('text-anchor')) {\n // 水平方向\n let anchor = spans[i].getAttribute('text-anchor');\n // left | center | right\n // start | middle | end\n if (anchor === 'middle') {\n parsedAnchor = 'center';\n } else if (anchor === 'end') {\n parsedAnchor = 'right';\n }\n calcHorAlign = false;\n }\n if (spans[i].hasAttribute('alignment-baseline')) {\n // 垂直方向\n alignmentBaseline = spans[i].getAttribute('alignment-baseline');\n }\n\n // 处理tspan设置的位置和偏移\n // top只处理第一行\n if ('top' in parsedSpanAttributes) {\n let spanY = parseFloat(parsedSpanAttributes.top);\n spanY += sumDy;\n\n spanOffY = options.top - spanY;\n }\n }\n\n // 多个tspan可能在一行 根据 y position判断是否换行\n // 另外没有对齐方式的,计算判断对齐方式,根据left的值判断对齐方式\n (parsedSpanAttributes as any).left =\n Number(parsedSpanAttributes.left || 0) + sumDx;\n (parsedSpanAttributes as any).top =\n Number(parsedSpanAttributes.top || 0) + sumDy;\n\n if (i === 0 || preSpanTop === (parsedSpanAttributes as any).top) {\n lineText += spans[i].textContent;\n if (i === 0) {\n curLineLeft = Number((parsedSpanAttributes as any).left || 0);\n }\n } else {\n lines.push({ text: lineText, left: curLineLeft });\n lineText = spans[i].textContent;\n curLineLeft = Number((parsedSpanAttributes as any).left || 0);\n }\n\n // 记住上一个span的Y位置\n preSpanTop = (parsedSpanAttributes as any).top;\n }\n // 加上最后一行\n if (lineText.length) {\n lines.push({ text: lineText, left: curLineLeft });\n }\n // 加上换行符号\n textContent = lines.map((v) => v.text).join('\\n');\n lineCnt = lines.length;\n\n if (calcHorAlign) {\n if (lines.some((v) => v.left !== curLineLeft)) {\n // 取最left的最小值,和right最大值\n let minLeft = lines[0].left,\n maxRight = lines[0].left,\n maxWidth = 0,\n minCenter: number | null = null,\n maxCenter: number | null = null,\n maxChar = 0,\n maxCharIdx = 0;\n\n lines.forEach((v, idx) => {\n minLeft = Math.min(minLeft, v.left);\n v.width = (new Textbox(v.text, options) as any).calcTextWidth();\n v.right = v.left + (v.width || 0);\n maxRight = Math.max(maxRight, v.right);\n maxWidth = Math.max(maxWidth, v.width || 0);\n if (v.width) {\n const center = v.left + (v.width || 0) / 2;\n minCenter = minCenter ? Math.min(minCenter, center) : center;\n maxCenter = maxCenter ? Math.max(maxCenter, center) : center;\n\n if (v.text.length > maxChar) {\n maxChar = v.text.length;\n maxCharIdx = idx;\n }\n }\n });\n let leftGap = 0,\n rightGap = 0;\n lines.forEach((v) => {\n leftGap = Math.max(leftGap, (v.left || 0) - minLeft);\n rightGap = Math.max(rightGap, maxRight - (v.right || 0));\n });\n // 计算中心点位置\n if (maxCenter && minCenter) {\n const centerOff = maxCenter - minCenter;\n const onCharWidth =\n (lines[maxCharIdx].width || 0) / lines[maxCharIdx].text.length;\n // 左边间距大于右边两倍 或者 中心点偏移超过1/2字符且右边间距小于1/3字符\n if (\n leftGap / (rightGap || 1) > 2 &&\n centerOff > onCharWidth / 2 &&\n rightGap < onCharWidth / 3\n ) {\n calcAdjustHorAlign = 'right';\n } else if (centerOff < onCharWidth / 2) {\n calcAdjustHorAlign = 'center';\n }\n }\n }\n }\n }\n }\n\n // 处理文字的水平偏移\n spanOffX = options.left - (minSpanX || 0);\n\n // textAlign保持和parsedAnchor一致\n options.textAlign = parsedAnchor;\n\n // 注释掉原来删除换行等符号的代码\n //textContent = textContent.replace(/^\\s+|\\s+$|\\n+/g, '').replace(/\\s+/g, ' ');\n var originalStrokeWidth = options.strokeWidth;\n options.strokeWidth = 0;\n\n // 导入时打开自动计算文字高度,否则文字高度和 Y 轴位置错误\n Textbox.enableCalcTextHeight = true;\n var text = new Textbox(textContent, options),\n textOneLineHeight = text.height / lineCnt,\n textHeightScaleFactor = text.getScaledHeight() / text.height,\n lineHeightDiff =\n (textOneLineHeight + text.strokeWidth) * text.lineHeight -\n textOneLineHeight,\n scaledDiff = lineHeightDiff * textHeightScaleFactor,\n textHeight = text.getScaledHeight() / lineCnt + scaledDiff,\n offX = 0,\n offY = 0;\n\n // 默认 alignment-baseline=\"before-edge\" offY = 0\n let offScale = 0;\n if (alignmentBaseline === 'before-edge') {\n // 这个是1.0 导出的偏移值,多行且间距设置大于1也会有变化\n // 暂时这么处理, 以后再解决\n offScale = 1.1;\n } else if (alignmentBaseline === 'auto') {\n // alignment-baseline=\"auto\" 或者 没有设置\n offScale = 0.02913333333;\n }\n\n if (offScale !== 0) {\n offY =\n (textHeight - text.fontSize * (offScale + text._fontSizeFraction)) /\n text.lineHeight;\n }\n\n // 取消自动计算文字高度\n Textbox.enableCalcTextHeight = false;\n /*\n Adjust positioning:\n x/y attributes in SVG correspond to the bottom-left corner of text bounding box\n fabric output by default at top, left.\n */\n const adjustOption: Partial<ITextProps> = {};\n // 源码中options.width总是等于svg的宽度, 之前是new Text不能编辑文字,宽度设置为svg宽度也无效\n // 修改为 new fabric.Textbox,并且设置为计算的正确宽度\n const originWidth = options.width;\n let width = text.calcTextWidth();\n // 有时候计算出来的大小是不对的, 可能是字体的原因, 导致TextBox自动换行了, 所以加i字符的宽度\n const oneIWidth = (new Textbox('i', options) as any).calcTextWidth();\n width += oneIWidth;\n\n if (originWidth !== width) {\n adjustOption.width = width;\n }\n if (calcAdjustHorAlign) {\n // tspan 按字符分开计算的对齐\n adjustOption.textAlign = calcAdjustHorAlign;\n }\n\n // 2021.1.29修改\n // Vectr1.0导出的svg,需要处理水平居中或右对齐偏移\n // Vectr2.0导出的是按照span位置判断的对齐不需要处理整个width的位置偏移, 但是需要处理 oneIWidth的位置偏移\n const textAlign = calcAdjustHorAlign || parsedAnchor;\n if (textAlign === 'center') {\n offX = (parsedAnchor === 'center' ? width : oneIWidth) / 2;\n } else if (textAlign === 'right') {\n offX = parsedAnchor === 'right' ? width : oneIWidth;\n }\n\n text.set({\n ...adjustOption,\n left: text.left - offX - spanOffX,\n top: text.top - offY - spanOffY,\n strokeWidth:\n typeof originalStrokeWidth !== 'undefined' ? originalStrokeWidth : 1,\n });\n return text;\n }\n}\n\nclassRegistry.setClass(Textbox);\nclassRegistry.setSVGClass(Textbox);\n"],"names":["textboxDefaultValues","minWidth","dynamicMinWidth","lockScalingFlip","noScaleCache","_wordJoiners","splitByGrapheme","Textbox","IText","getDefaults","ownDefaults","constructor","text","options","createControls","controls","createTextboxDefaultControls","initDimensions","initialized","isEditing","initDelayedCursor","_clearCache","_styleMap","_generateStyleMap","_splitText","path","width","_set","textAlign","includes","JUSTIFY","enlargeSpaces","enableCalcTextHeight","height","calcTextHeight","preventGroupCache","textInfo","realLineCount","realLineCharCount","charCount","map","i","graphemeLines","length","graphemeText","_reSpaceAndTab","test","line","offset","styleHas","property","lineIndex","isWrapping","isEmptyStyles","styles","nextLineIndex","nextOffset","shouldLimit","mapNextLine","obj","p1","p2","p2Number","parseInt","p3","_getStyleDeclaration","charIndex","_setStyleDeclaration","style","_deleteStyleDeclaration","_getLineStyle","_setLineStyle","_wrapText","lines","desiredWidth","data","getGraphemeDataForRender","wrapped","wordsData","push","_wrapLine","infix","largestWordWidth","wordsOrGraphemes","graphemeSplit","wordSplit","word","graphemeArray","_measureWord","Math","max","charOffset","arguments","undefined","prevGrapheme","skipLeft","len","box","_getGraphemeBox","kernedWidth","value","split","_ref","reservedSpace","additionalSpace","_getWidthOfCharSpacing","lineWidth","infixWidth","lineJustStarted","maxWidth","wordWidth","concat","isEndOfWrapping","missingNewlineOffset","skipWrapping","_splitTextIntoLines","wrapWidth","defaultWrapWidth","newText","Array","join","getMinWidth","_removeExtraneousStyles","linesToKeep","Map","prop","propNumber","_textLines","set","has","toObject","propertiesToInclude","fromElement","element","cssRules","parsedAttributes","parseAttributes","ATTRIBUTE_NAMES","textOptions","JSON","parse","stringify","reg","fontFamily","slice","top","left","textDecoration","indexOf","underline","overline","linethrough","dx","dy","fontSize","DEFAULT_SVG_FONT_SIZE","paths","getElementsByTagName","_fromTextPath","_fromTextSpan","_findSvgTextPath","id","svg","closest","querySelector","textContent","parsedAnchor","textAnchor","calcHorAlign","calcAdjustHorAlign","lineCnt","alignmentBaseline","spanOffX","minSpanX","spanOffY","hasAttribute","lineHeight","parseFloat","getAttribute","firstChild","spans","lineText","curLineLeft","preSpanTop","sumDx","sumDy","parsedSpanAttributes","Number","spanX","min","anchor","spanY","v","some","minLeft","maxRight","minCenter","maxCenter","maxChar","maxCharIdx","forEach","idx","calcTextWidth","right","center","leftGap","rightGap","centerOff","onCharWidth","originalStrokeWidth","strokeWidth","textOneLineHeight","textHeightScaleFactor","getScaledHeight","lineHeightDiff","scaledDiff","textHeight","offX","offY","offScale","_fontSizeFraction","adjustOption","originWidth","oneIWidth","_Textbox","_defineProperty","textLayoutProperties","textPath","textPathParsedAttributes","href","startsWith","pathElement","pathParsedAttributes","Path","d","stroke","fill","visible","fontStyle","fontWeight","pathType","classRegistry","setClass","setSVGClass"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Textbox.mjs","sources":["../../../src/shapes/Textbox.ts"],"sourcesContent":["import type { Abortable, TClassProperties, TOptions } from '../typedefs';\nimport { IText } from './IText/IText';\nimport { classRegistry } from '../ClassRegistry';\nimport { createTextboxDefaultControls } from '../controls/commonControls';\nimport { JUSTIFY } from './Text/constants';\nimport type { TextStyleDeclaration } from './Text/StyledText';\nimport type { SerializedITextProps, ITextProps } from './IText/IText';\nimport type { ITextEvents } from './IText/ITextBehavior';\nimport type {\n FabricText,\n SerializedTextProps,\n TextLinesInfo,\n} from './Text/Text';\nimport type { Control } from '../controls/Control';\nimport { stylesFromArray } from '../util';\nimport type { CSSRules } from '../parser/typedefs';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport { Path } from './Path';\nimport { DEFAULT_SVG_FONT_SIZE } from '../constants';\n\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\n// regexes, list of properties that are not suppose to change by instances, magic consts.\n// this will be a separated effort\nexport const textboxDefaultValues: Partial<TClassProperties<Textbox>> = {\n minWidth: 20,\n dynamicMinWidth: 2,\n lockScalingFlip: true,\n noScaleCache: false,\n _wordJoiners: /[ \\t\\r]/,\n splitByGrapheme: false,\n};\n\nexport type GraphemeData = {\n wordsData: {\n word: string[];\n width: number;\n }[][];\n largestWordWidth: number;\n};\n\nexport type StyleMap = Record<string, { line: number; offset: number }>;\n\n// @TODO this is not complete\ninterface UniqueTextboxProps {\n minWidth: number;\n splitByGrapheme: boolean;\n dynamicMinWidth: number;\n _wordJoiners: RegExp;\n}\n\nexport interface SerializedTextboxProps\n extends SerializedITextProps,\n Pick<UniqueTextboxProps, 'minWidth' | 'splitByGrapheme'> {}\n\nexport interface TextboxProps extends ITextProps, UniqueTextboxProps {}\n\n/**\n * Textbox class, based on IText, allows the user to resize the text rectangle\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\n * user can only change width. Height is adjusted automatically based on the\n * wrapping of lines.\n */\nexport class Textbox<\n Props extends TOptions<TextboxProps> = Partial<TextboxProps>,\n SProps extends SerializedTextboxProps = SerializedTextboxProps,\n EventSpec extends ITextEvents = ITextEvents,\n >\n extends IText<Props, SProps, EventSpec>\n implements UniqueTextboxProps\n{\n /**\n * Minimum width of textbox, in pixels.\n * @type Number\n * @default\n */\n declare minWidth: number;\n\n /**\n * Minimum calculated width of a textbox, in pixels.\n * fixed to 2 so that an empty textbox cannot go to 0\n * and is still selectable without text.\n * @type Number\n * @default\n */\n declare dynamicMinWidth: number;\n\n /**\n * Use this boolean property in order to split strings that have no white space concept.\n * this is a cheap way to help with chinese/japanese\n * @type Boolean\n * @since 2.6.0\n */\n declare splitByGrapheme: boolean;\n\n declare _wordJoiners: RegExp;\n\n declare _styleMap: StyleMap;\n\n declare isWrapping: boolean;\n\n static type = 'Textbox';\n\n static textLayoutProperties = [...IText.textLayoutProperties, 'width'];\n\n static ownDefaults = textboxDefaultValues;\n\n // James modified 自动计算文字高度\n static enableCalcTextHeight = false;\n\n /**\n * James modified 自动计算文字高度\n * 增加wrap宽度,设置为page的宽度\n * 增加textbox wrap的默认宽度\n * @type Number\n * @default\n */\n static defaultWrapWidth = 1920;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Textbox.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n */\n constructor(text: string, options?: Props) {\n super(text, { ...Textbox.ownDefaults, ...options } as Props);\n }\n\n /**\n * Creates the default control object.\n * If you prefer to have on instance of controls shared among all objects\n * make this function return an empty object and add controls to the ownDefaults object\n */\n static createControls(): { controls: Record<string, Control> } {\n return { controls: createTextboxDefaultControls() };\n }\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @private\n * @override\n */\n initDimensions() {\n if (!this.initialized) {\n return;\n }\n this.isEditing && this.initDelayedCursor();\n this._clearCache();\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n // wrap lines\n this._styleMap = this._generateStyleMap(this._splitText());\n // James modified\n // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n if (!this.path && this.dynamicMinWidth > this.width) {\n this._set('width', this.dynamicMinWidth);\n }\n if (this.textAlign.includes(JUSTIFY)) {\n // once text is measured we need to make space fatter to make justified text.\n this.enlargeSpaces();\n }\n // James modified 取消 textbox 自动计算高度\n if (!this.path && Textbox.enableCalcTextHeight) {\n // clear cache and re-calculate height\n this.height = this.calcTextHeight();\n }\n this.preventGroupCache = this.path ? true : false;\n }\n\n /**\n * Generate an object that translates the style object so that it is\n * broken up by visual lines (new lines and automatic wrapping).\n * The original text styles object is broken up by actual lines (new lines only),\n * which is only sufficient for Text / IText\n * @private\n */\n _generateStyleMap(textInfo: TextLinesInfo): StyleMap {\n let realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0;\n const map: StyleMap = {};\n\n for (let i = 0; i < textInfo.graphemeLines.length; i++) {\n if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n } else if (\n !this.splitByGrapheme &&\n this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\n i > 0\n ) {\n // this case deals with space's that are removed from end of lines when wrapping\n realLineCharCount++;\n charCount++;\n }\n\n map[i] = { line: realLineCount, offset: realLineCharCount };\n\n charCount += textInfo.graphemeLines[i].length;\n realLineCharCount += textInfo.graphemeLines[i].length;\n }\n\n return map;\n }\n\n /**\n * Returns true if object has a style property or has it on a specified line\n * @param {Number} lineIndex\n * @return {Boolean}\n */\n styleHas(property: keyof TextStyleDeclaration, lineIndex: number): boolean {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (map) {\n lineIndex = map.line;\n }\n }\n return super.styleHas(property, lineIndex);\n }\n\n /**\n * Returns true if object has no styling or no styling in a line\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\n * @return {Boolean}\n */\n isEmptyStyles(lineIndex: number): boolean {\n if (!this.styles) {\n return true;\n }\n let offset = 0,\n nextLineIndex = lineIndex + 1,\n nextOffset: number,\n shouldLimit = false;\n const map = this._styleMap[lineIndex],\n mapNextLine = this._styleMap[lineIndex + 1];\n if (map) {\n lineIndex = map.line;\n offset = map.offset;\n }\n if (mapNextLine) {\n nextLineIndex = mapNextLine.line;\n shouldLimit = nextLineIndex === lineIndex;\n nextOffset = mapNextLine.offset;\n }\n const obj =\n typeof lineIndex === 'undefined'\n ? this.styles\n : { line: this.styles[lineIndex] };\n for (const p1 in obj) {\n for (const p2 in obj[p1]) {\n const p2Number = parseInt(p2, 10);\n if (p2Number >= offset && (!shouldLimit || p2Number < nextOffset!)) {\n // eslint-disable-next-line no-unused-vars\n for (const p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n }\n return true;\n }\n\n /**\n * @protected\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined\n */\n _getStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n ): TextStyleDeclaration {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (!map) {\n return {};\n }\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n return super._getStyleDeclaration(lineIndex, charIndex);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n protected _setStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n style: object,\n ) {\n const map = this._styleMap[lineIndex];\n super._setStyleDeclaration(map.line, map.offset + charIndex, style);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n protected _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\n const map = this._styleMap[lineIndex];\n super._deleteStyleDeclaration(map.line, map.offset + charIndex);\n }\n\n /**\n * probably broken need a fix\n * Returns the real style line that correspond to the wrapped lineIndex line\n * Used just to verify if the line does exist or not.\n * @param {Number} lineIndex\n * @returns {Boolean} if the line exists or not\n * @private\n */\n protected _getLineStyle(lineIndex: number): boolean {\n const map = this._styleMap[lineIndex];\n return !!this.styles[map.line];\n }\n\n /**\n * Set the line style to an empty object so that is initialized\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n protected _setLineStyle(lineIndex: number) {\n const map = this._styleMap[lineIndex];\n super._setLineStyle(map.line);\n }\n\n /**\n * Wraps text using the 'width' property of Textbox. First this function\n * splits text on newlines, so we preserve newlines entered by the user.\n * Then it wraps each line using the width of the Textbox by calling\n * _wrapLine().\n * @param {Array} lines The string array of text that is split into lines\n * @param {Number} desiredWidth width you want to wrap to\n * @returns {Array} Array of lines\n */\n _wrapText(lines: string[], desiredWidth: number): string[][] {\n this.isWrapping = true;\n // extract all thewords and the widths to optimally wrap lines.\n const data = this.getGraphemeDataForRender(lines);\n const wrapped: string[][] = [];\n for (let i = 0; i < data.wordsData.length; i++) {\n wrapped.push(...this._wrapLine(i, desiredWidth, data));\n }\n this.isWrapping = false;\n return wrapped;\n }\n\n /**\n * For each line of text terminated by an hard line stop,\n * measure each word width and extract the largest word from all.\n * The returned words here are the one that at the end will be rendered.\n * @param {string[]} lines the lines we need to measure\n *\n */\n getGraphemeDataForRender(lines: string[]): GraphemeData {\n const splitByGrapheme = this.splitByGrapheme,\n infix = splitByGrapheme ? '' : ' ';\n\n let largestWordWidth = 0;\n\n const data = lines.map((line, lineIndex) => {\n let offset = 0;\n const wordsOrGraphemes = splitByGrapheme\n ? this.graphemeSplit(line)\n : this.wordSplit(line);\n\n if (wordsOrGraphemes.length === 0) {\n return [{ word: [], width: 0 }];\n }\n\n return wordsOrGraphemes.map((word: string) => {\n // if using splitByGrapheme words are already in graphemes.\n const graphemeArray = splitByGrapheme\n ? [word]\n : this.graphemeSplit(word);\n const width = this._measureWord(graphemeArray, lineIndex, offset);\n largestWordWidth = Math.max(width, largestWordWidth);\n offset += graphemeArray.length + infix.length;\n return { word: graphemeArray, width };\n });\n });\n\n return {\n wordsData: data,\n largestWordWidth,\n };\n }\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n * It gets called when charBounds are not available yet.\n * Override if necessary\n * Use with {@link Textbox#wordSplit}\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n */\n _measureWord(word: string[], lineIndex: number, charOffset = 0): number {\n let width = 0,\n prevGrapheme;\n const skipLeft = true;\n for (let i = 0, len = word.length; i < len; i++) {\n const box = this._getGraphemeBox(\n word[i],\n lineIndex,\n i + charOffset,\n prevGrapheme,\n skipLeft,\n );\n width += box.kernedWidth;\n prevGrapheme = word[i];\n }\n return width;\n }\n\n /**\n * Override this method to customize word splitting\n * Use with {@link Textbox#_measureWord}\n * @param {string} value\n * @returns {string[]} array of words\n */\n wordSplit(value: string): string[] {\n return value.split(this._wordJoiners);\n }\n\n /**\n * Wraps a line of text using the width of the Textbox as desiredWidth\n * and leveraging the known width o words from GraphemeData\n * @private\n * @param {Number} lineIndex\n * @param {Number} desiredWidth width you want to wrap the line to\n * @param {GraphemeData} graphemeData an object containing all the lines' words width.\n * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine(\n lineIndex: number,\n desiredWidth: number,\n { largestWordWidth, wordsData }: GraphemeData,\n reservedSpace = 0,\n ): string[][] {\n const additionalSpace = this._getWidthOfCharSpacing(),\n splitByGrapheme = this.splitByGrapheme,\n graphemeLines = [],\n infix = splitByGrapheme ? '' : ' ';\n\n let lineWidth = 0,\n line: string[] = [],\n // spaces in different languages?\n offset = 0,\n infixWidth = 0,\n lineJustStarted = true;\n\n desiredWidth -= reservedSpace;\n\n const maxWidth = Math.max(\n desiredWidth,\n largestWordWidth,\n this.dynamicMinWidth,\n );\n // layout words\n const data = wordsData[lineIndex];\n offset = 0;\n let i;\n for (i = 0; i < data.length; i++) {\n const { word, width: wordWidth } = data[i];\n offset += word.length;\n\n lineWidth += infixWidth + wordWidth - additionalSpace;\n if (lineWidth > maxWidth && !lineJustStarted) {\n graphemeLines.push(line);\n line = [];\n lineWidth = wordWidth;\n lineJustStarted = true;\n } else {\n lineWidth += additionalSpace;\n }\n\n if (!lineJustStarted && !splitByGrapheme) {\n line.push(infix);\n }\n line = line.concat(word);\n\n infixWidth = splitByGrapheme\n ? 0\n : this._measureWord([infix], lineIndex, offset);\n offset++;\n lineJustStarted = false;\n }\n\n i && graphemeLines.push(line);\n\n // TODO: this code is probably not necessary anymore.\n // it can be moved out of this function since largestWordWidth is now\n // known in advance\n if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n }\n return graphemeLines;\n }\n\n /**\n * Detect if the text line is ended with an hard break\n * text and itext do not have wrapping, return false\n * @param {Number} lineIndex text to split\n * @return {Boolean}\n */\n isEndOfWrapping(lineIndex: number): boolean {\n if (!this._styleMap[lineIndex + 1]) {\n // is last line, return true;\n return true;\n }\n if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n // this is last line before a line break, return true;\n return true;\n }\n return false;\n }\n\n /**\n * Detect if a line has a linebreak and so we need to account for it when moving\n * and counting style.\n * This is important only for splitByGrapheme at the end of wrapping.\n * If we are not wrapping the offset is always 1\n * @return Number\n */\n missingNewlineOffset(lineIndex: number, skipWrapping?: boolean): 0 | 1 {\n if (this.splitByGrapheme && !skipWrapping) {\n return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n }\n return 1;\n }\n\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly every time it is called.\n * @param {String} text text to split\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines(text: string) {\n // James modified 存在path时候不按照宽度换行\n var wrapWidth = this.path ? 10000000 : this.width;\n // 如果width 不存在, 使用page width\n wrapWidth = wrapWidth || Textbox.defaultWrapWidth;\n const newText = super._splitTextIntoLines(text),\n graphemeLines = this._wrapText(newText.lines, wrapWidth),\n lines = new Array(graphemeLines.length);\n for (let i = 0; i < graphemeLines.length; i++) {\n lines[i] = graphemeLines[i].join('');\n }\n newText.lines = lines;\n newText.graphemeLines = graphemeLines;\n return newText;\n }\n\n getMinWidth() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\n }\n\n _removeExtraneousStyles() {\n const linesToKeep = new Map();\n for (const prop in this._styleMap) {\n const propNumber = parseInt(prop, 10);\n if (this._textLines[propNumber]) {\n const lineIndex = this._styleMap[prop].line;\n linesToKeep.set(`${lineIndex}`, true);\n }\n }\n for (const prop in this.styles) {\n if (!linesToKeep.has(prop)) {\n delete this.styles[prop];\n }\n }\n }\n\n /**\n * Returns object representation of an instance\n * @method toObject\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return super.toObject<T, K>([\n 'minWidth',\n 'splitByGrapheme',\n ...propertiesToInclude,\n ] as K[]) as Pick<T, K> & SProps;\n }\n\n /**\n * Returns FabricText instance from an SVG element (<b>not yet implemented</b>)\n * @static\n * @memberOf Text\n * @param {HTMLElement} element Element to parse\n * @param {Object} [options] Options object\n */\n static async fromElement(\n element: HTMLElement,\n options: Abortable,\n cssRules?: CSSRules,\n ) {\n if (!element) {\n return null;\n }\n\n var parsedAttributes = parseAttributes(\n element,\n Textbox.ATTRIBUTE_NAMES,\n cssRules,\n );\n const textOptions = {\n ...(cssRules ? JSON.parse(JSON.stringify(cssRules)) : {}),\n ...parsedAttributes,\n };\n // 处理style中字体样式带单引号问题\n let reg = /^'(.*)'$/;\n if (reg.test(textOptions.fontFamily)) {\n textOptions.fontFamily = textOptions.fontFamily.slice(1, -1);\n }\n\n textOptions.top = textOptions.top || 0;\n textOptions.left = textOptions.left || 0;\n if (parsedAttributes.textDecoration) {\n var textDecoration = parsedAttributes.textDecoration;\n if (textDecoration.indexOf('underline') !== -1) {\n textOptions.underline = true;\n }\n if (textDecoration.indexOf('overline') !== -1) {\n textOptions.overline = true;\n }\n if (textDecoration.indexOf('line-through') !== -1) {\n textOptions.linethrough = true;\n }\n delete textOptions.textDecoration;\n }\n if ('dx' in parsedAttributes) {\n textOptions.left += parsedAttributes.dx;\n }\n if ('dy' in parsedAttributes) {\n textOptions.top += parsedAttributes.dy;\n }\n if (!('fontSize' in textOptions)) {\n textOptions.fontSize = DEFAULT_SVG_FONT_SIZE;\n }\n\n let text: Textbox;\n const paths = element.getElementsByTagName('textPath');\n if (paths.length) {\n text = this._fromTextPath(paths[0], textOptions, parsedAttributes);\n } else {\n text = this._fromTextSpan(element, textOptions, parsedAttributes);\n }\n return text;\n }\n\n static _findSvgTextPath(element: any, id: string) {\n const svg = element.closest('svg');\n return svg.querySelector(id);\n }\n\n static _fromTextPath = (\n textPath: any,\n options: any,\n parsedAttributes: { [key: string]: string },\n ): Textbox => {\n var parsedAnchor = parsedAttributes.textAnchor || 'left';\n\n var textPathParsedAttributes = parseAttributes(textPath, [\n 'href',\n 'text-anchor',\n 'startOffset',\n ]);\n if (textPathParsedAttributes.textAnchor) {\n parsedAnchor = textPathParsedAttributes.textAnchor;\n }\n if (parsedAnchor === 'middle') {\n parsedAnchor = 'center';\n } else if (parsedAnchor === 'end') {\n parsedAnchor = 'right';\n }\n options.textAlign = parsedAnchor;\n\n var textContent = textPath.textContent;\n var text = new Textbox(textContent, options);\n\n const href = textPathParsedAttributes.href;\n if (href && href.startsWith('#')) {\n const pathElement = Textbox._findSvgTextPath(textPath, href);\n if (pathElement) {\n var pathParsedAttributes = parseAttributes(\n pathElement,\n Path.ATTRIBUTE_NAMES,\n );\n const path = new Path(pathParsedAttributes.d, {\n ...pathParsedAttributes,\n ...{\n strokeWidth: 1,\n stroke: '#ff0000',\n fill: null as any,\n visible: false,\n },\n });\n // 需要计算实际字体大小\n Textbox.enableCalcTextHeight = true;\n const textHeight =\n new Textbox('i', {\n fontFamily: options.fontFamily,\n fontSize: options.fontSize,\n fontStyle: options.fontStyle,\n fontWeight: options.fontWeight,\n width: undefined,\n height: undefined,\n }).height || 20;\n text.set({\n width: (path.width || 0) + textHeight * 2,\n height: (path.height || 0) + textHeight * 2,\n path,\n pathType: 'custom',\n } as any);\n // 取消自动计算文字高度\n Textbox.enableCalcTextHeight = false;\n }\n }\n // 设置位置中心点为左上角\n text.set({\n left: options.left - (text.width || 0) / 2,\n top: options.top - (text.height || 0) / 2,\n });\n return text;\n };\n\n static _fromTextSpan(\n element: any,\n options: any,\n parsedAttributes: { [key: string]: string },\n ): Textbox {\n var textContent = '';\n var parsedAnchor = parsedAttributes.textAnchor || 'left';\n // 是否需要根据tspan位置计算对齐\n let calcHorAlign = !parsedAttributes.textAnchor;\n let calcAdjustHorAlign = '';\n\n // The XML is not properly parsed in IE9 so a workaround to get\n // textContent is through firstChild.data. Another workaround would be\n // to convert XML loaded from a file to be converted using DOMParser (same way loadSVGFromString() does)\n\n let lineCnt = 1;\n let alignmentBaseline = 'auto';\n let spanOffX = 0,\n minSpanX: number | null = null,\n spanOffY = 0;\n\n if (element.hasAttribute('line-height')) {\n options.lineHeight = parseFloat(element.getAttribute('line-height'));\n } else if (options['line-height']) {\n // 从style 转换过来\n options.lineHeight = parseFloat(options['line-height']) / 100;\n } else {\n options.lineHeight = 1;\n }\n\n if (!('textContent' in element)) {\n if ('firstChild' in element && element.firstChild !== null) {\n if ('data' in element.firstChild && element.firstChild.data !== null) {\n textContent = element.firstChild.data;\n }\n }\n } else {\n textContent = element.textContent;\n let spans = element.getElementsByTagName('tspan');\n if (spans.length > 0) {\n // 多行文字\n let lines: {\n text: string;\n left: number;\n width?: number;\n right?: number;\n }[] = [],\n lineText = '',\n curLineLeft = 0, // 本行的 水平方向位置\n preSpanTop = 0, // 前一个tspan的 垂直方向位置\n sumDx = 0,\n sumDy = 0;\n for (let i = 0; i < spans.length; i++) {\n var parsedSpanAttributes = parseAttributes(\n spans[i],\n Textbox.ATTRIBUTE_NAMES,\n );\n\n sumDx += Number(parsedSpanAttributes.dx) || 0;\n sumDy += Number(parsedSpanAttributes.dy) || 0;\n // 在使用tspan判断对齐时spanX取最小的值\n if ('left' in parsedSpanAttributes) {\n let spanX = parseFloat(parsedSpanAttributes.left);\n minSpanX = minSpanX != null ? Math.min(minSpanX, spanX) : spanX;\n }\n // 现在多个tspan用多行文字, 所以对齐和位置只处理第一个 tspan\n if (i === 0) {\n if (spans[i].hasAttribute('text-anchor')) {\n // 水平方向\n let anchor = spans[i].getAttribute('text-anchor');\n // left | center | right\n // start | middle | end\n if (anchor === 'middle') {\n parsedAnchor = 'center';\n } else if (anchor === 'end') {\n parsedAnchor = 'right';\n }\n calcHorAlign = false;\n }\n if (spans[i].hasAttribute('alignment-baseline')) {\n // 垂直方向\n alignmentBaseline = spans[i].getAttribute('alignment-baseline');\n }\n\n // 处理tspan设置的位置和偏移\n // top只处理第一行\n if ('top' in parsedSpanAttributes) {\n let spanY = parseFloat(parsedSpanAttributes.top);\n spanY += sumDy;\n\n spanOffY = options.top - spanY;\n }\n }\n\n // 多个tspan可能在一行 根据 y position判断是否换行\n // 另外没有对齐方式的,计算判断对齐方式,根据left的值判断对齐方式\n (parsedSpanAttributes as any).left =\n Number(parsedSpanAttributes.left || 0) + sumDx;\n (parsedSpanAttributes as any).top =\n Number(parsedSpanAttributes.top || 0) + sumDy;\n\n if (i === 0 || preSpanTop === (parsedSpanAttributes as any).top) {\n lineText += spans[i].textContent;\n if (i === 0) {\n curLineLeft = Number((parsedSpanAttributes as any).left || 0);\n }\n } else {\n lines.push({ text: lineText, left: curLineLeft });\n lineText = spans[i].textContent;\n curLineLeft = Number((parsedSpanAttributes as any).left || 0);\n }\n\n // 记住上一个span的Y位置\n preSpanTop = (parsedSpanAttributes as any).top;\n }\n // 加上最后一行\n if (lineText.length) {\n lines.push({ text: lineText, left: curLineLeft });\n }\n // 加上换行符号\n textContent = lines.map((v) => v.text).join('\\n');\n lineCnt = lines.length;\n\n if (calcHorAlign) {\n if (lines.some((v) => v.left !== curLineLeft)) {\n // 取最left的最小值,和right最大值\n let minLeft = lines[0].left,\n maxRight = lines[0].left,\n maxWidth = 0,\n minCenter: number | null = null,\n maxCenter: number | null = null,\n maxChar = 0,\n maxCharIdx = 0;\n\n lines.forEach((v, idx) => {\n minLeft = Math.min(minLeft, v.left);\n v.width = (new Textbox(v.text, options) as any).calcTextWidth();\n v.right = v.left + (v.width || 0);\n maxRight = Math.max(maxRight, v.right);\n maxWidth = Math.max(maxWidth, v.width || 0);\n if (v.width) {\n const center = v.left + (v.width || 0) / 2;\n minCenter = minCenter ? Math.min(minCenter, center) : center;\n maxCenter = maxCenter ? Math.max(maxCenter, center) : center;\n\n if (v.text.length > maxChar) {\n maxChar = v.text.length;\n maxCharIdx = idx;\n }\n }\n });\n let leftGap = 0,\n rightGap = 0;\n lines.forEach((v) => {\n leftGap = Math.max(leftGap, (v.left || 0) - minLeft);\n rightGap = Math.max(rightGap, maxRight - (v.right || 0));\n });\n // 计算中心点位置\n if (maxCenter !== null && minCenter !== null) {\n const centerOff = maxCenter - minCenter;\n const onCharWidth =\n (lines[maxCharIdx].width || 0) / lines[maxCharIdx].text.length;\n // 左边间距大于右边两倍 或者 中心点偏移超过1/2字符且右边间距小于1/3字符\n if (\n leftGap / (rightGap || 1) > 2 &&\n centerOff > onCharWidth / 2 &&\n rightGap < onCharWidth / 3\n ) {\n calcAdjustHorAlign = 'right';\n } else if (centerOff < onCharWidth / 2) {\n calcAdjustHorAlign = 'center';\n }\n }\n }\n }\n }\n }\n\n // 处理文字的水平偏移\n spanOffX = options.left - (minSpanX || 0);\n\n // textAlign保持和parsedAnchor一致\n options.textAlign = parsedAnchor;\n\n // 注释掉原来删除换行等符号的代码\n //textContent = textContent.replace(/^\\s+|\\s+$|\\n+/g, '').replace(/\\s+/g, ' ');\n var originalStrokeWidth = options.strokeWidth;\n options.strokeWidth = 0;\n\n // 导入时打开自动计算文字高度,否则文字高度和 Y 轴位置错误\n Textbox.enableCalcTextHeight = true;\n var text = new Textbox(textContent, options),\n textOneLineHeight = text.height / lineCnt,\n textHeightScaleFactor = text.getScaledHeight() / text.height,\n lineHeightDiff =\n (textOneLineHeight + text.strokeWidth) * text.lineHeight -\n textOneLineHeight,\n scaledDiff = lineHeightDiff * textHeightScaleFactor,\n textHeight = text.getScaledHeight() / lineCnt + scaledDiff,\n offX = 0,\n offY = 0;\n\n // 默认 alignment-baseline=\"before-edge\" offY = 0\n let offScale = 0;\n if (alignmentBaseline === 'before-edge') {\n // 这个是1.0 导出的偏移值,多行且间距设置大于1也会有变化\n // 暂时这么处理, 以后再解决\n offScale = 1.1;\n } else if (alignmentBaseline === 'auto') {\n // alignment-baseline=\"auto\" 或者 没有设置\n offScale = 0.02913333333;\n }\n\n if (offScale !== 0) {\n offY =\n (textHeight - text.fontSize * (offScale + text._fontSizeFraction)) /\n text.lineHeight;\n }\n\n // 取消自动计算文字高度\n Textbox.enableCalcTextHeight = false;\n /*\n Adjust positioning:\n x/y attributes in SVG correspond to the bottom-left corner of text bounding box\n fabric output by default at top, left.\n */\n const adjustOption: Partial<ITextProps> = {};\n // 源码中options.width总是等于svg的宽度, 之前是new Text不能编辑文字,宽度设置为svg宽度也无效\n // 修改为 new fabric.Textbox,并且设置为计算的正确宽度\n const originWidth = options.width;\n let width = text.calcTextWidth();\n // 有时候计算出来的大小是不对的, 可能是字体的原因, 导致TextBox自动换行了, 所以加i字符的宽度\n const oneIWidth = (new Textbox('i', options) as any).calcTextWidth();\n width += oneIWidth;\n\n if (originWidth !== width) {\n adjustOption.width = width;\n }\n if (calcAdjustHorAlign) {\n // tspan 按字符分开计算的对齐\n adjustOption.textAlign = calcAdjustHorAlign;\n }\n\n // 2021.1.29修改\n // Vectr1.0导出的svg,需要处理水平居中或右对齐偏移\n // Vectr2.0导出的是按照span位置判断的对齐不需要处理整个width的位置偏移, 但是需要处理 oneIWidth的位置偏移\n const textAlign = calcAdjustHorAlign || parsedAnchor;\n if (textAlign === 'center') {\n offX = (parsedAnchor === 'center' ? width : oneIWidth) / 2;\n } else if (textAlign === 'right') {\n offX = parsedAnchor === 'right' ? width : oneIWidth;\n }\n\n text.set({\n ...adjustOption,\n left: text.left - offX - spanOffX,\n top: text.top - offY - spanOffY,\n strokeWidth:\n typeof originalStrokeWidth !== 'undefined' ? originalStrokeWidth : 1,\n });\n return text;\n }\n}\n\nclassRegistry.setClass(Textbox);\nclassRegistry.setSVGClass(Textbox);\n"],"names":["textboxDefaultValues","minWidth","dynamicMinWidth","lockScalingFlip","noScaleCache","_wordJoiners","splitByGrapheme","Textbox","IText","getDefaults","ownDefaults","constructor","text","options","createControls","controls","createTextboxDefaultControls","initDimensions","initialized","isEditing","initDelayedCursor","_clearCache","_styleMap","_generateStyleMap","_splitText","path","width","_set","textAlign","includes","JUSTIFY","enlargeSpaces","enableCalcTextHeight","height","calcTextHeight","preventGroupCache","textInfo","realLineCount","realLineCharCount","charCount","map","i","graphemeLines","length","graphemeText","_reSpaceAndTab","test","line","offset","styleHas","property","lineIndex","isWrapping","isEmptyStyles","styles","nextLineIndex","nextOffset","shouldLimit","mapNextLine","obj","p1","p2","p2Number","parseInt","p3","_getStyleDeclaration","charIndex","_setStyleDeclaration","style","_deleteStyleDeclaration","_getLineStyle","_setLineStyle","_wrapText","lines","desiredWidth","data","getGraphemeDataForRender","wrapped","wordsData","push","_wrapLine","infix","largestWordWidth","wordsOrGraphemes","graphemeSplit","wordSplit","word","graphemeArray","_measureWord","Math","max","charOffset","arguments","undefined","prevGrapheme","skipLeft","len","box","_getGraphemeBox","kernedWidth","value","split","_ref","reservedSpace","additionalSpace","_getWidthOfCharSpacing","lineWidth","infixWidth","lineJustStarted","maxWidth","wordWidth","concat","isEndOfWrapping","missingNewlineOffset","skipWrapping","_splitTextIntoLines","wrapWidth","defaultWrapWidth","newText","Array","join","getMinWidth","_removeExtraneousStyles","linesToKeep","Map","prop","propNumber","_textLines","set","has","toObject","propertiesToInclude","fromElement","element","cssRules","parsedAttributes","parseAttributes","ATTRIBUTE_NAMES","textOptions","JSON","parse","stringify","reg","fontFamily","slice","top","left","textDecoration","indexOf","underline","overline","linethrough","dx","dy","fontSize","DEFAULT_SVG_FONT_SIZE","paths","getElementsByTagName","_fromTextPath","_fromTextSpan","_findSvgTextPath","id","svg","closest","querySelector","textContent","parsedAnchor","textAnchor","calcHorAlign","calcAdjustHorAlign","lineCnt","alignmentBaseline","spanOffX","minSpanX","spanOffY","hasAttribute","lineHeight","parseFloat","getAttribute","firstChild","spans","lineText","curLineLeft","preSpanTop","sumDx","sumDy","parsedSpanAttributes","Number","spanX","min","anchor","spanY","v","some","minLeft","maxRight","minCenter","maxCenter","maxChar","maxCharIdx","forEach","idx","calcTextWidth","right","center","leftGap","rightGap","centerOff","onCharWidth","originalStrokeWidth","strokeWidth","textOneLineHeight","textHeightScaleFactor","getScaledHeight","lineHeightDiff","scaledDiff","textHeight","offX","offY","offScale","_fontSizeFraction","adjustOption","originWidth","oneIWidth","_Textbox","_defineProperty","textLayoutProperties","textPath","textPathParsedAttributes","href","startsWith","pathElement","pathParsedAttributes","Path","d","stroke","fill","visible","fontStyle","fontWeight","pathType","classRegistry","setClass","setSVGClass"],"mappings":"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"}
|
|
@@ -133,7 +133,7 @@ export declare function createCollectionMixin<TBase extends Constructor>(Base: T
|
|
|
133
133
|
* @param {{ includeIntersecting?: boolean }} options an object with includeIntersecting
|
|
134
134
|
* @returns array of objects contained in the bounding box, ordered from top to bottom stacking wise
|
|
135
135
|
*/
|
|
136
|
-
collectObjects({ left, top, width, height }: TBBox, { includeIntersecting }?: {
|
|
136
|
+
collectObjects(fromObjects: InteractiveFabricObject[], { left, top, width, height }: TBBox, { includeIntersecting }?: {
|
|
137
137
|
includeIntersecting?: boolean;
|
|
138
138
|
}): InteractiveFabricObject<Partial<import("..").FabricObjectProps>, import("..").SerializedObjectProps, import("./EventTypeDefs").ObjectEvents>[];
|
|
139
139
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../../src/Collection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE,eAAO,MAAM,YAAY,kBACR,YAAY,KAC1B,YAAY,IAAI,KAAK,GAAG,eAE1B,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,KAAK,SAAS,WAAW,EAAE,IAAI,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../../src/Collection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE,eAAO,MAAM,YAAY,kBACR,YAAY,KAC1B,YAAY,IAAI,KAAK,GAAG,eAE1B,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,KAAK,SAAS,WAAW,EAAE,IAAI,EAAE,KAAK,GAoVrD;;QAlVnB;;;WAGG;kBACO,YAAY,EAAE;+BAGD,YAAY;iCAKV,YAAY;qCAKR,YAAY;QAIzC;;;;;WAKG;wBACa,YAAY,EAAE,GAAG,MAAM;QAMvC;;;;;WAKG;wBACa,MAAM,cAAc,YAAY,EAAE;QAMlD;;;;;WAKG;2BACgB,YAAY,EAAE;QAejC;;;;;;;WAOG;gCAES,CACR,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,EAAE,KAClB,GAAG;QAOV;;;;WAIG;6BACkB,MAAM,EAAE;QAO7B;;;;WAIG;oBACS,MAAM;QAIlB;;;WAGG;;QAKH;;;WAGG;;QAKH;;;;;;;WAOG;yBACc,YAAY,SAAS,OAAO,GAAG,OAAO;QAavD;;;WAGG;;QAQH;;;;;WAKG;iCACsB,YAAY;QAUrC;;;;;WAKG;mCACwB,YAAY;QAUvC;;;;;;;;;WASG;oCACyB,YAAY,iBAAiB,OAAO;QAgBhE;;;;;;;;;WASG;mCACwB,YAAY,iBAAiB,OAAO;QAgB/D;;;;;WAKG;6BACkB,YAAY,SAAS,MAAM;kCAWtC,YAAY,OACf,MAAM,iBACI,OAAO;kCAqBd,YAAY,OACf,MAAM,iBACI,OAAO;QAoBxB;;;;;;;WAOG;oCAEY,uBAAuB,EAAE,gCACR,KAAK,4BACH;YAAE,mBAAmB,CAAC,EAAE,OAAO,CAAA;SAAE;;aA0B5B,KAAK,CAC/C"}
|