{"version":3,"file":"pathControl.mjs","sources":["../../../src/controls/pathControl.ts"],"sourcesContent":["import { 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\nconst 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\nconst 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  pathObject.set('dirty', true);\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 */\nfunction 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":["ACTION_NAME","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","newAnchorPointInParentPlane","diff","left","top","set","pathPositionHandler","dim","finalMatrix","pathActionHandler","eventData","target","actionPerformed","fireEvent","actionName","_objectSpread","commonEventInfo","indexFromPrevCommand","previousCommandType","PathPointControl","Control","constructor","options","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","forEach","concat"],"mappings":"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"}