{"version":3,"file":"Path.min.mjs","sources":["../../../src/shapes/Path.ts"],"sourcesContent":["import { config } from '../config';\nimport { SHARED_ATTRIBUTES } from '../parser/attributes';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport type { XY } from '../Point';\nimport { Point } from '../Point';\nimport { makeBoundingBoxFromPoints } from '../util/misc/boundingBoxFromPoints';\nimport { toFixed } from '../util/misc/toFixed';\nimport {\n  getBoundsOfCurve,\n  joinPath,\n  makePathSimpler,\n  parsePath,\n} from '../util/path';\nimport { classRegistry } from '../ClassRegistry';\nimport { FabricObject, cacheProperties } from './Object/FabricObject';\nimport type {\n  TComplexPathData,\n  TPathSegmentInfo,\n  TSimplePathData,\n} from '../util/path/typedefs';\nimport type { FabricObjectProps, SerializedObjectProps } from './Object/types';\nimport type { ObjectEvents } from '../EventTypeDefs';\nimport type {\n  TBBox,\n  TClassProperties,\n  TSVGReviver,\n  TOptions,\n} from '../typedefs';\nimport { CENTER, LEFT, TOP } from '../constants';\nimport type { CSSRules } from '../parser/typedefs';\n\ninterface UniquePathProps {\n  sourcePath?: string;\n  path?: TSimplePathData;\n}\n\nexport interface SerializedPathProps\n  extends SerializedObjectProps,\n    UniquePathProps {}\n\nexport interface PathProps extends FabricObjectProps, UniquePathProps {}\n\nexport interface IPathBBox extends TBBox {\n  left: number;\n  top: number;\n  pathOffset: Point;\n}\n\nexport class Path<\n  Props extends TOptions<PathProps> = Partial<PathProps>,\n  SProps extends SerializedPathProps = SerializedPathProps,\n  EventSpec extends ObjectEvents = ObjectEvents\n> extends FabricObject<Props, SProps, EventSpec> {\n  /**\n   * Array of path points\n   * @type Array\n   * @default\n   */\n  declare path: TSimplePathData;\n\n  declare pathOffset: Point;\n\n  declare sourcePath?: string;\n\n  declare segmentsInfo?: TPathSegmentInfo[];\n\n  static type = 'Path';\n  fromObjectId: string;\n  toObjectId: string;\n\n  static cacheProperties = [...cacheProperties, 'path', 'fillRule'];\n\n  /**\n   * Constructor\n   * @param {TComplexPathData} path Path data (sequence of coordinates and corresponding \"command\" tokens)\n   * @param {Partial<PathProps>} [options] Options object\n   * @return {Path} thisArg\n   */\n  constructor(\n    path: TComplexPathData | string,\n    { path: _, left, top, ...options }: Partial<Props> = {}\n  ) {\n    super(options as Props);\n    this._setPath(path || [], true);\n    typeof left === 'number' && this.set(LEFT, left);\n    typeof top === 'number' && this.set(TOP, top);\n  }\n\n  /**\n   * @private\n   * @param {TComplexPathData | string} path Path data (sequence of coordinates and corresponding \"command\" tokens)\n   * @param {boolean} [adjustPosition] pass true to reposition the object according to the bounding box\n   * @returns {Point} top left position of the bounding box, useful for complementary positioning\n   */\n  _setPath(path: TComplexPathData | string, adjustPosition?: boolean) {\n    this.path = makePathSimpler(Array.isArray(path) ? path : parsePath(path));\n    this.setBoundingBox(adjustPosition);\n  }\n\n  /**\n   * This function is an helper for svg import. it returns the center of the object in the svg\n   * untransformed coordinates, by look at the polyline/polygon points.\n   * @private\n   * @return {Point} center point from element coordinates\n   */\n  _findCenterFromElement(): Point {\n    const bbox = this._calcBoundsFromPath();\n    return new Point(bbox.left + bbox.width / 2, bbox.top + bbox.height / 2);\n  }\n\n  /**\n   * @private\n   * @param {CanvasRenderingContext2D} ctx context to render path on\n   */\n  _renderPathCommands(ctx: CanvasRenderingContext2D) {\n    const l = -this.pathOffset.x,\n      t = -this.pathOffset.y;\n\n    ctx.beginPath();\n\n    for (const command of this.path) {\n      switch (\n        command[0] // first letter\n      ) {\n        case 'L': // lineto, absolute\n          ctx.lineTo(command[1] + l, command[2] + t);\n          break;\n\n        case 'M': // moveTo, absolute\n          ctx.moveTo(command[1] + l, command[2] + t);\n          break;\n\n        case 'C': // bezierCurveTo, absolute\n          ctx.bezierCurveTo(\n            command[1] + l,\n            command[2] + t,\n            command[3] + l,\n            command[4] + t,\n            command[5] + l,\n            command[6] + t\n          );\n          break;\n\n        case 'Q': // quadraticCurveTo, absolute\n          ctx.quadraticCurveTo(\n            command[1] + l,\n            command[2] + t,\n            command[3] + l,\n            command[4] + t\n          );\n          break;\n\n        case 'Z':\n          ctx.closePath();\n          break;\n      }\n    }\n  }\n\n  /**\n   * @private\n   * @param {CanvasRenderingContext2D} ctx context to render path on\n   */\n  _render(ctx: CanvasRenderingContext2D) {\n    this._renderPathCommands(ctx);\n    this._renderPaintInOrder(ctx);\n  }\n\n  /**\n   * Returns string representation of an instance\n   * @return {string} string representation of an instance\n   */\n  toString() {\n    return `#<Path (${this.complexity()}): { \"top\": ${this.top}, \"left\": ${\n      this.left\n    } }>`;\n  }\n\n  /**\n   * Returns object representation of an instance\n   * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n   * @return {Object} object representation of an instance\n   */\n  toObject<\n    T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n    K extends keyof T = never\n  >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n    return {\n      ...super.toObject(propertiesToInclude),\n      path: this.path.map((pathCmd) => pathCmd.slice()),\n    };\n  }\n\n  /**\n   * Returns dataless object representation of an instance\n   * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n   * @return {Object} object representation of an instance\n   */\n  toDatalessObject<\n    T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n    K extends keyof T = never\n  >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n    const o = this.toObject<T, K>(propertiesToInclude);\n    if (this.sourcePath) {\n      delete o.path;\n      o.sourcePath = this.sourcePath;\n    }\n    return o;\n  }\n\n  /**\n   * Returns svg representation of an instance\n   * @return {Array} an array of strings with the specific svg representation\n   * of the instance\n   */\n  _toSVG() {\n    const path = joinPath(this.path, config.NUM_FRACTION_DIGITS);\n    return [\n      '<path ',\n      'COMMON_PARTS',\n      `d=\"${path}\" stroke-linecap=\"round\" />\\n`,\n    ];\n  }\n\n  /**\n   * @private\n   * @return the path command's translate transform attribute\n   */\n  _getOffsetTransform() {\n    const digits = config.NUM_FRACTION_DIGITS;\n    return ` translate(${toFixed(-this.pathOffset.x, digits)}, ${toFixed(\n      -this.pathOffset.y,\n      digits\n    )})`;\n  }\n\n  /**\n   * Returns svg clipPath representation of an instance\n   * @param {Function} [reviver] Method for further parsing of svg representation.\n   * @return {string} svg representation of an instance\n   */\n  toClipPathSVG(reviver: TSVGReviver): string {\n    const additionalTransform = this._getOffsetTransform();\n    return (\n      '\\t' +\n      this._createBaseClipPathSVGMarkup(this._toSVG(), {\n        reviver: reviver,\n        additionalTransform: additionalTransform,\n      })\n    );\n  }\n\n  /**\n   * Returns svg representation of an instance\n   * @param {Function} [reviver] Method for further parsing of svg representation.\n   * @return {string} svg representation of an instance\n   */\n  toSVG(reviver: TSVGReviver): string {\n    const additionalTransform = this._getOffsetTransform();\n    return this._createBaseSVGMarkup(this._toSVG(), {\n      reviver: reviver,\n      additionalTransform: additionalTransform,\n    });\n  }\n\n  /**\n   * Returns number representation of an instance complexity\n   * @return {number} complexity of this instance\n   */\n  complexity() {\n    return this.path.length;\n  }\n\n  setDimensions() {\n    this.setBoundingBox();\n  }\n\n  setBoundingBox(adjustPosition?: boolean) {\n    const { width, height, pathOffset } = this._calcDimensions();\n    this.set({ width, height, pathOffset });\n    // using pathOffset because it match the use case.\n    // if pathOffset change here we need to use left + width/2 , top + height/2\n    adjustPosition && this.setPositionByOrigin(pathOffset, CENTER, CENTER);\n  }\n\n  _calcBoundsFromPath(): TBBox {\n    const bounds: XY[] = [];\n    let subpathStartX = 0,\n      subpathStartY = 0,\n      x = 0, // current x\n      y = 0; // current y\n\n    for (const command of this.path) {\n      // current instruction\n      switch (\n        command[0] // first letter\n      ) {\n        case 'L': // lineto, absolute\n          x = command[1];\n          y = command[2];\n          bounds.push(new Point(subpathStartX, subpathStartY), new Point(x, y));\n          break;\n\n        case 'M': // moveTo, absolute\n          x = command[1];\n          y = command[2];\n          subpathStartX = x;\n          subpathStartY = y;\n          break;\n\n        case 'C': // bezierCurveTo, absolute\n          bounds.push(\n            ...getBoundsOfCurve(\n              x,\n              y,\n              command[1],\n              command[2],\n              command[3],\n              command[4],\n              command[5],\n              command[6]\n            )\n          );\n          x = command[5];\n          y = command[6];\n          break;\n\n        case 'Q': // quadraticCurveTo, absolute\n          bounds.push(\n            ...getBoundsOfCurve(\n              x,\n              y,\n              command[1],\n              command[2],\n              command[1],\n              command[2],\n              command[3],\n              command[4]\n            )\n          );\n          x = command[3];\n          y = command[4];\n          break;\n\n        case 'Z':\n          x = subpathStartX;\n          y = subpathStartY;\n          break;\n      }\n    }\n    return makeBoundingBoxFromPoints(bounds);\n  }\n\n  /**\n   * @private\n   */\n  _calcDimensions(): IPathBBox {\n    const bbox = this._calcBoundsFromPath();\n\n    return {\n      ...bbox,\n      pathOffset: new Point(\n        bbox.left + bbox.width / 2,\n        bbox.top + bbox.height / 2\n      ),\n    };\n  }\n\n  /**\n   * List of attribute names to account for when parsing SVG element (used by `Path.fromElement`)\n   * @static\n   * @memberOf Path\n   * @see http://www.w3.org/TR/SVG/paths.html#PathElement\n   */\n  static ATTRIBUTE_NAMES = [...SHARED_ATTRIBUTES, 'd'];\n\n  /**\n   * Creates an instance of Path from an object\n   * @static\n   * @memberOf Path\n   * @param {Object} object\n   * @returns {Promise<Path>}\n   */\n  static fromObject<T extends TOptions<SerializedPathProps>>(object: T) {\n    return this._fromObject<Path>(object, {\n      extraParam: 'path',\n    });\n  }\n\n  /**\n   * Creates an instance of Path from an SVG <path> element\n   * @static\n   * @memberOf Path\n   * @param {HTMLElement} element to parse\n   * @param {Partial<PathProps>} [options] Options object\n   */\n  static async fromElement(\n    element: HTMLElement,\n    options: Partial<PathProps>,\n    cssRules?: CSSRules\n  ) {\n    const { d, ...parsedAttributes } = parseAttributes(\n      element,\n      this.ATTRIBUTE_NAMES,\n      cssRules\n    );\n    return new this(d, {\n      ...parsedAttributes,\n      ...options,\n      // we pass undefined to instruct the constructor to position the object using the bbox\n      left: undefined,\n      top: undefined,\n    });\n  }\n}\n\nclassRegistry.setClass(Path);\nclassRegistry.setSVGClass(Path);\n\n/* _FROM_SVG_START_ */\n"],"names":["Path","FabricObject","constructor","path","_ref","arguments","length","undefined","_","left","top","super","_objectWithoutProperties","_excluded","_defineProperty","this","_setPath","set","LEFT","TOP","adjustPosition","makePathSimpler","Array","isArray","parsePath","setBoundingBox","_findCenterFromElement","bbox","_calcBoundsFromPath","Point","width","height","_renderPathCommands","ctx","l","pathOffset","x","t","y","beginPath","command","lineTo","moveTo","bezierCurveTo","quadraticCurveTo","closePath","_render","_renderPaintInOrder","toString","concat","complexity","toObject","propertiesToInclude","_objectSpread","map","pathCmd","slice","toDatalessObject","o","sourcePath","_toSVG","joinPath","config","NUM_FRACTION_DIGITS","_getOffsetTransform","digits","toFixed","toClipPathSVG","reviver","additionalTransform","_createBaseClipPathSVGMarkup","toSVG","_createBaseSVGMarkup","setDimensions","_calcDimensions","setPositionByOrigin","CENTER","bounds","subpathStartX","subpathStartY","push","getBoundsOfCurve","makeBoundingBoxFromPoints","fromObject","object","_fromObject","extraParam","fromElement","element","options","cssRules","_parseAttributes","parseAttributes","ATTRIBUTE_NAMES","d","parsedAttributes","_excluded2","cacheProperties","SHARED_ATTRIBUTES","classRegistry","setClass","setSVGClass"],"mappings":"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"}