{"version":3,"file":"pathControl.min.mjs","sources":["../../../src/controls/pathControl.ts"],"sourcesContent":["//@ts-nocheck\nimport { Point } from '../Point';\nimport { Control } from './Control';\nimport type { TMat2D } from '../typedefs';\nimport type { Path } from '../shapes/Path';\nimport { multiplyTransformMatrices } from '../util/misc/matrix';\nimport type {\n  TModificationEvents,\n  TPointerEvent,\n  Transform,\n} from '../EventTypeDefs';\nimport { sendPointToPlane } from '../util/misc/planeChange';\nimport type { TSimpleParseCommandType } from '../util/path/typedefs';\nimport type { ControlRenderingStyleOverride } from './controlRendering';\nimport { fireEvent } from './fireEvent';\nimport { commonEventInfo } from './util';\n\nconst ACTION_NAME: TModificationEvents = 'modifyPath' as const;\n\ntype TTransformAnchor = Transform;\n\nexport type PathPointControlStyle = {\n  controlFill?: string;\n  controlStroke?: string;\n  connectionDashArray?: number[];\n};\n\nexport const calcPathPointPosition = (\n  pathObject: Path,\n  commandIndex: number,\n  pointIndex: number\n) => {\n  const { path, pathOffset } = pathObject;\n  const command = path[commandIndex];\n  return new Point(\n    (command[pointIndex] as number) - pathOffset.x,\n    (command[pointIndex + 1] as number) - pathOffset.y\n  ).transform(\n    multiplyTransformMatrices(\n      pathObject.getViewportTransform(),\n      pathObject.calcTransformMatrix()\n    )\n  );\n};\n\nexport const movePathPoint = (\n  pathObject: Path,\n  x: number,\n  y: number,\n  commandIndex: number,\n  pointIndex: number\n) => {\n  const { path, pathOffset } = pathObject;\n\n  const anchorCommand =\n    path[(commandIndex > 0 ? commandIndex : path.length) - 1];\n  const anchorPoint = new Point(\n    anchorCommand[pointIndex] as number,\n    anchorCommand[pointIndex + 1] as number\n  );\n\n  const anchorPointInParentPlane = anchorPoint\n    .subtract(pathOffset)\n    .transform(pathObject.calcOwnMatrix());\n\n  const mouseLocalPosition = sendPointToPlane(\n    new Point(x, y),\n    undefined,\n    pathObject.calcOwnMatrix()\n  );\n\n  path[commandIndex][pointIndex] = mouseLocalPosition.x + pathOffset.x;\n  path[commandIndex][pointIndex + 1] = mouseLocalPosition.y + pathOffset.y;\n  pathObject.setDimensions();\n\n  const newAnchorPointInParentPlane = anchorPoint\n    .subtract(pathObject.pathOffset)\n    .transform(pathObject.calcOwnMatrix());\n\n  const diff = newAnchorPointInParentPlane.subtract(anchorPointInParentPlane);\n  pathObject.left -= diff.x;\n  pathObject.top -= diff.y;\n\n  return true;\n};\n\n/**\n * This function locates the controls.\n * It'll be used both for drawing and for interaction.\n */\nfunction pathPositionHandler(\n  this: PathPointControl,\n  dim: Point,\n  finalMatrix: TMat2D,\n  pathObject: Path\n) {\n  const { commandIndex, pointIndex } = this;\n  return calcPathPointPosition(pathObject, commandIndex, pointIndex);\n}\n\n/**\n * This function defines what the control does.\n * It'll be called on every mouse move after a control has been clicked and is being dragged.\n * The function receives as argument the mouse event, the current transform object\n * and the current position in canvas coordinate `transform.target` is a reference to the\n * current object being transformed.\n */\nexport function pathActionHandler(\n  this: PathPointControl,\n  eventData: TPointerEvent,\n  transform: TTransformAnchor,\n  x: number,\n  y: number\n) {\n  const { target } = transform;\n  const { commandIndex, pointIndex } = this;\n  const actionPerformed = movePathPoint(\n    target as Path,\n    x,\n    y,\n    commandIndex,\n    pointIndex\n  );\n  if (actionPerformed) {\n    fireEvent(this.actionName as TModificationEvents, {\n      ...commonEventInfo(eventData, transform, x, y),\n      commandIndex,\n      pointIndex,\n    });\n  }\n  return actionPerformed;\n}\n\nconst indexFromPrevCommand = (previousCommandType: TSimpleParseCommandType) =>\n  previousCommandType === 'C' ? 5 : previousCommandType === 'Q' ? 3 : 1;\n\nclass PathPointControl extends Control {\n  declare commandIndex: number;\n  declare pointIndex: number;\n  declare controlFill: string;\n  declare controlStroke: string;\n  constructor(options?: Partial<PathPointControl>) {\n    super(options);\n  }\n\n  render(\n    ctx: CanvasRenderingContext2D,\n    left: number,\n    top: number,\n    styleOverride: ControlRenderingStyleOverride | undefined,\n    fabricObject: Path\n  ) {\n    const overrides: ControlRenderingStyleOverride = {\n      ...styleOverride,\n      cornerColor: this.controlFill,\n      cornerStrokeColor: this.controlStroke,\n      transparentCorners: !this.controlFill,\n    };\n    super.render(ctx, left, top, overrides, fabricObject);\n  }\n}\n\nclass PathControlPointControl extends PathPointControl {\n  declare connectionDashArray?: number[];\n  declare connectToCommandIndex: number;\n  declare connectToPointIndex: number;\n  constructor(options?: Partial<PathControlPointControl>) {\n    super(options);\n  }\n\n  render(\n    this: PathControlPointControl,\n    ctx: CanvasRenderingContext2D,\n    left: number,\n    top: number,\n    styleOverride: ControlRenderingStyleOverride | undefined,\n    fabricObject: Path\n  ) {\n    const { path } = fabricObject;\n    const {\n      commandIndex,\n      pointIndex,\n      connectToCommandIndex,\n      connectToPointIndex,\n    } = this;\n    ctx.save();\n    ctx.strokeStyle = this.controlStroke;\n    if (this.connectionDashArray) {\n      ctx.setLineDash(this.connectionDashArray);\n    }\n    const [commandType] = path[commandIndex];\n    const point = calcPathPointPosition(\n      fabricObject,\n      connectToCommandIndex,\n      connectToPointIndex\n    );\n\n    if (commandType === 'Q') {\n      // one control point connects to 2 points\n      const point2 = calcPathPointPosition(\n        fabricObject,\n        commandIndex,\n        pointIndex + 2\n      );\n      ctx.moveTo(point2.x, point2.y);\n      ctx.lineTo(left, top);\n    } else {\n      ctx.moveTo(left, top);\n    }\n    ctx.lineTo(point.x, point.y);\n    ctx.stroke();\n    ctx.restore();\n\n    super.render(ctx, left, top, styleOverride, fabricObject);\n  }\n}\n\nconst createControl = (\n  commandIndexPos: number,\n  pointIndexPos: number,\n  isControlPoint: boolean,\n  options: Partial<Control> & {\n    controlPointStyle?: PathPointControlStyle;\n    pointStyle?: PathPointControlStyle;\n  },\n  connectToCommandIndex?: number,\n  connectToPointIndex?: number\n) =>\n  new (isControlPoint ? PathControlPointControl : PathPointControl)({\n    commandIndex: commandIndexPos,\n    pointIndex: pointIndexPos,\n    actionName: ACTION_NAME,\n    positionHandler: pathPositionHandler,\n    actionHandler: pathActionHandler,\n    connectToCommandIndex,\n    connectToPointIndex,\n    ...options,\n    ...(isControlPoint ? options.controlPointStyle : options.pointStyle),\n  } as Partial<PathControlPointControl>);\n\nexport function createPathControls(\n  path: Path,\n  options: Partial<Control> & {\n    controlPointStyle?: PathPointControlStyle;\n    pointStyle?: PathPointControlStyle;\n  } = {}\n): Record<string, Control> {\n  const controls = {} as Record<string, Control>;\n  let previousCommandType: TSimpleParseCommandType = 'M';\n  path.path.forEach((command, commandIndex) => {\n    const commandType = command[0];\n\n    if (commandType !== 'Z') {\n      controls[`c_${commandIndex}_${commandType}`] = createControl(\n        commandIndex,\n        command.length - 2,\n        false,\n        options\n      );\n    }\n    switch (commandType) {\n      case 'C':\n        controls[`c_${commandIndex}_C_CP_1`] = createControl(\n          commandIndex,\n          1,\n          true,\n          options,\n          commandIndex - 1,\n          indexFromPrevCommand(previousCommandType)\n        );\n        controls[`c_${commandIndex}_C_CP_2`] = createControl(\n          commandIndex,\n          3,\n          true,\n          options,\n          commandIndex,\n          5\n        );\n        break;\n      case 'Q':\n        controls[`c_${commandIndex}_Q_CP_1`] = createControl(\n          commandIndex,\n          1,\n          true,\n          options,\n          commandIndex,\n          3\n        );\n        break;\n    }\n    previousCommandType = commandType;\n  });\n  return controls;\n}\n"],"names":["calcPathPointPosition","pathObject","commandIndex","pointIndex","path","pathOffset","command","Point","x","y","transform","multiplyTransformMatrices","getViewportTransform","calcTransformMatrix","movePathPoint","anchorCommand","length","anchorPoint","anchorPointInParentPlane","subtract","calcOwnMatrix","mouseLocalPosition","sendPointToPlane","undefined","setDimensions","diff","left","top","pathPositionHandler","dim","finalMatrix","this","pathActionHandler","eventData","target","actionPerformed","fireEvent","actionName","_objectSpread","commonEventInfo","PathPointControl","Control","constructor","options","super","render","ctx","styleOverride","fabricObject","overrides","cornerColor","controlFill","cornerStrokeColor","controlStroke","transparentCorners","PathControlPointControl","connectToCommandIndex","connectToPointIndex","save","strokeStyle","connectionDashArray","setLineDash","commandType","point","point2","moveTo","lineTo","stroke","restore","createControl","commandIndexPos","pointIndexPos","isControlPoint","positionHandler","actionHandler","controlPointStyle","pointStyle","createPathControls","arguments","controls","previousCommandType","forEach","concat","indexFromPrevCommand"],"mappings":"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"}