{"version":3,"file":"croppingHandlers.mjs","names":[],"sources":["../../extensions/cropping_controls/croppingHandlers.ts"],"sourcesContent":["import type {\n  TModificationEvents,\n  TransformActionHandler,\n  FabricImage,\n  ObjectEvents,\n  Control,\n  TMat2D,\n} from 'fabric';\nimport { controlsUtils, Point, util } from 'fabric';\n\nconst { wrapWithFixedAnchor, wrapWithFireEvent } = controlsUtils;\n\n/**\n * Wraps a handler to swap behavior based on flip state.\n */\nexport const withFlip = (\n  handler: TransformActionHandler,\n  flippedHandler: TransformActionHandler,\n  axis: 'flipX' | 'flipY',\n): TransformActionHandler => {\n  return (eventData, transform, x, y) => {\n    if (transform.target[axis]) {\n      return flippedHandler(eventData, transform, x, y);\n    }\n    return handler(eventData, transform, x, y);\n  };\n};\n\n/**\n * Wraps corner handlers to swap both X and Y behavior based on flip state.\n */\nexport const withCornerFlip = (\n  xHandler: TransformActionHandler,\n  xFlippedHandler: TransformActionHandler,\n  yHandler: TransformActionHandler,\n  yFlippedHandler: TransformActionHandler,\n): TransformActionHandler => {\n  return (eventData, transform, x, y) => {\n    const target = transform.target as FabricImage;\n    const xResult = (target.flipX ? xFlippedHandler : xHandler)(\n      eventData,\n      transform,\n      x,\n      y,\n    );\n    const yResult = (target.flipY ? yFlippedHandler : yHandler)(\n      eventData,\n      transform,\n      x,\n      y,\n    );\n    return xResult || yResult;\n  };\n};\n\n/**\n * Wrap controlsUtils.changeObjectWidth with image constrains\n */\nexport const changeImageWidth: TransformActionHandler = (\n  eventData,\n  transform,\n  x,\n  y,\n) => {\n  const { target } = transform;\n  const { width } = target;\n  const image = target as FabricImage;\n  const modified = controlsUtils.changeObjectWidth(eventData, transform, x, y);\n  const availableWidth = image._element.width - image.cropX;\n  if (modified) {\n    if (image.width > availableWidth) {\n      image.width = availableWidth;\n    }\n    if (image.width < 1) {\n      image.width = 1;\n    }\n  }\n  return width !== image.width;\n};\n\nexport const changeCropWidth = wrapWithFireEvent(\n  'CROPPING' as TModificationEvents,\n  wrapWithFixedAnchor(changeImageWidth),\n);\n\n/**\n * Wrap controlsUtils.changeObjectHeight with image constrains\n */\nexport const changeImageHeight: TransformActionHandler = (\n  eventData,\n  transform,\n  x,\n  y,\n) => {\n  const { target } = transform;\n  const { height } = target;\n  const image = target as FabricImage;\n  const modified = controlsUtils.changeObjectHeight(eventData, transform, x, y);\n  const availableHeight = image._element.height - image.cropY;\n  if (modified) {\n    if (image.height > availableHeight) {\n      image.height = availableHeight;\n    }\n    if (image.height < 1) {\n      image.height = 1;\n    }\n  }\n  return height !== image.height;\n};\n\nexport const changeCropHeight = wrapWithFireEvent(\n  'CROPPING' as TModificationEvents,\n  wrapWithFixedAnchor(changeImageHeight),\n);\n\nexport const changeImageCropX: TransformActionHandler = (\n  eventData,\n  transform,\n  x,\n  y,\n) => {\n  const { target } = transform;\n  const image = target as FabricImage;\n  const { width, cropX } = image;\n  const modified = controlsUtils.changeObjectWidth(eventData, transform, x, y);\n  let newCropX = cropX + width - image.width;\n  image.width = width;\n  if (modified) {\n    if (newCropX < 0) {\n      newCropX = 0;\n    }\n    image.cropX = newCropX;\n    // calculate new width on the base of how much crop we have now\n    image.width += cropX - newCropX;\n  }\n  return newCropX !== cropX;\n};\n\nexport const changeImageCropY: TransformActionHandler = (\n  eventData,\n  transform,\n  x,\n  y,\n) => {\n  const { target } = transform;\n  const image = target as FabricImage;\n  const { height, cropY } = image;\n  const modified = controlsUtils.changeObjectHeight(eventData, transform, x, y);\n  let newCropY = cropY + height - image.height;\n  image.height = height;\n  if (modified) {\n    if (newCropY < 0) {\n      newCropY = 0;\n    }\n    image.cropY = newCropY;\n    image.height += cropY - newCropY;\n  }\n  return newCropY !== cropY;\n};\n\nexport const changeCropX = wrapWithFireEvent(\n  'CROPPING' as TModificationEvents,\n  wrapWithFixedAnchor(changeImageCropX),\n);\n\nexport const changeCropY = wrapWithFireEvent(\n  'CROPPING' as TModificationEvents,\n  wrapWithFixedAnchor(changeImageCropY),\n);\n\n/**\n * A function to counter the move action and change cropX/cropY of an image\n * Keep the image steady, but moves it inside its own cropping rectangle\n */\nexport const cropPanMoveHandler = ({ transform }: ObjectEvents['moving']) => {\n  // this makes the image pan too fast.\n  const { target, original } = transform;\n  const fabricImage = target as FabricImage;\n  const p = new Point(\n    target.left - original.left,\n    target.top - original.top,\n  ).transform(\n    util.invertTransform(\n      util.createRotateMatrix({ angle: fabricImage.getTotalAngle() }),\n    ),\n  );\n  let cropX =\n    original.cropX! - (p.x / fabricImage.scaleX) * (fabricImage.flipX ? -1 : 1);\n  let cropY =\n    original.cropY! - (p.y / fabricImage.scaleY) * (fabricImage.flipY ? -1 : 1);\n  const { width, height, _element } = fabricImage;\n  if (cropX < 0) {\n    cropX = 0;\n  }\n  if (cropY < 0) {\n    cropY = 0;\n  }\n  if (cropX + width > _element.width) {\n    cropX = _element.width - width;\n  }\n  if (cropY + height > _element.height) {\n    cropY = _element.height - height;\n  }\n  fabricImage.cropX = cropX;\n  fabricImage.cropY = cropY;\n  fabricImage.left = original.left;\n  fabricImage.top = original.top;\n};\n\n/**\n * This position handler works only for this specific use case.\n * It does not support padding nor offset, and it reduces all possible positions\n * to the main 4 corners only.\n * Any position that is < 0 is the extreme left/top, the rest are right/bottom\n */\nexport function ghostScalePositionHandler(\n  this: Control,\n  dim: Point, // currentDimension\n  finalMatrix: TMat2D,\n  fabricObject: FabricImage,\n  // currentControl: Control,\n) {\n  const matrix = fabricObject.calcTransformMatrix();\n  const vpt = fabricObject.getViewportTransform();\n  const _finalMatrix = util.multiplyTransformMatrices(vpt, matrix);\n\n  let x = 0;\n  let y = 0;\n  if (this.x < 0) {\n    x = -fabricObject.width / 2 - fabricObject.cropX;\n  } else {\n    x =\n      fabricObject.getElement().width -\n      fabricObject.width / 2 -\n      fabricObject.cropX;\n  }\n\n  if (this.y < 0) {\n    y = -fabricObject.height / 2 - fabricObject.cropY;\n  } else {\n    y =\n      fabricObject.getElement().height -\n      fabricObject.height / 2 -\n      fabricObject.cropY;\n  }\n  return new Point(x, y).transform(_finalMatrix);\n}\n\nconst calcScale = (currentPoint: Point, height: number, width: number) =>\n  Math.min(Math.abs(currentPoint.x / width), Math.abs(currentPoint.y / height));\n\nconst flipNumericOrigin = (origin: number, flipped: boolean) =>\n  flipped ? 1 - origin : origin;\n\n/**\n * Reflects pointer position across object center when image is flipped.\n * This compensates for the inverted local coordinate system.\n */\n// const reflectPointerForFlip = (\n//   target: FabricImage,\n//   x: number,\n//   y: number,\n// ): Point => {\n//   if (!target.flipX && !target.flipY) {\n//     return new Point(x, y);\n//   }\n//   const center = target.getCenterPoint();\n//   return new Point(\n//     target.flipX ? center.x - x : x,\n//     target.flipY ? center.y - y : y,\n//   );\n// };\n\n/**\n * Action handler generator that handles scaling of an image in crop mode.\n * The goal is to keep the current bounding box steady.\n * So this action handler has its own calculations for a dynamic anchor point\n */\nexport const scaleEquallyCropGenerator =\n  (cx: number, cy: number): TransformActionHandler =>\n  (eventData, transform, x, y) => {\n    const { target } = transform as unknown as { target: FabricImage };\n    const { width: fullWidth, height: fullHeight } = target.getElement();\n    const remainderX = fullWidth - target.width - target.cropX;\n    const remainderY = fullHeight - target.height - target.cropY;\n    const anchorOriginX = flipNumericOrigin(\n      cx < 0 ? 1 + remainderX / target.width : -target.cropX / target.width,\n      target.flipX,\n    );\n    const anchorOriginY = flipNumericOrigin(\n      cy < 0 ? 1 + remainderY / target.height : -target.cropY / target.height,\n      target.flipY,\n    );\n    const constraint = target.translateToOriginPoint(\n      target.getCenterPoint(),\n      anchorOriginX,\n      anchorOriginY,\n    );\n\n    const newPoint = controlsUtils.getLocalPoint(\n      transform,\n      anchorOriginX,\n      anchorOriginY,\n      x,\n      y,\n    );\n\n    const scale = calcScale(newPoint, fullHeight, fullWidth);\n\n    const scaleChangeX = scale / target.scaleX;\n    const scaleChangeY = scale / target.scaleY;\n    const scaledRemainderX = remainderX / scaleChangeX;\n    const scaledRemainderY = remainderY / scaleChangeY;\n    const newWidth = target.width / scaleChangeX;\n    const newHeight = target.height / scaleChangeY;\n    const newCropX =\n      cx < 0\n        ? fullWidth - newWidth - scaledRemainderX\n        : target.cropX / scaleChangeX;\n    const newCropY =\n      cy < 0\n        ? fullHeight - newHeight - scaledRemainderY\n        : target.cropY / scaleChangeY;\n\n    const boundsFailX =\n      (cx < 0 ? scaledRemainderX : newCropX) + newWidth > fullWidth;\n    const boundsFailY =\n      (cy < 0 ? scaledRemainderY : newCropY) + newHeight > fullHeight;\n\n    if (boundsFailX || boundsFailY) {\n      return false;\n    }\n\n    target.scaleX = scale;\n    target.scaleY = scale;\n    target.width = newWidth;\n    target.height = newHeight;\n    target.cropX = newCropX;\n    target.cropY = newCropY;\n    const newAnchorOriginX = flipNumericOrigin(\n      cx < 0 ? 1 + scaledRemainderX / newWidth : -newCropX / newWidth,\n      target.flipX,\n    );\n    const newAnchorOriginY = flipNumericOrigin(\n      cy < 0 ? 1 + scaledRemainderY / newHeight : -newCropY / newHeight,\n      target.flipY,\n    );\n\n    target.setPositionByOrigin(constraint, newAnchorOriginX, newAnchorOriginY);\n    return true;\n  };\n\nexport function renderGhostImage(\n  this: FabricImage,\n  { ctx }: { ctx: CanvasRenderingContext2D },\n) {\n  const element = this._element;\n  const ghostX = -this.width / 2 - this.cropX;\n  const ghostY = -this.height / 2 - this.cropY;\n\n  const alpha = ctx.globalAlpha;\n  ctx.globalAlpha *= 0.5;\n  ctx.drawImage(element, ghostX, ghostY);\n\n  ctx.strokeStyle = this.borderColor;\n  // we assume this.scaleX and this.scaleY are same in an image.\n  // it is not common use case to stretch images, and if it is, and is brought up,\n  // this border for the image needs to be drawn differently.\n  ctx.lineWidth = this.borderScaleFactor / this.scaleX;\n  ctx.strokeRect(ghostX, ghostY, element.width, element.height);\n\n  ctx.globalAlpha = alpha;\n}\n\nconst { capValue } = util;\n\n/**\n * Those are controls used to resize an image, similar to cropX,cropY,width,height\n * But they change the scale of an image to accomodate out of bounds resizing.\n * When resize comes back they scale the image back to what was before.\n * The memory effect for bounce back works for the same transform.\n * Once you mouseup, the bounce back is lost.\n */\nconst changeImageSizeWithAutoCoverGenerator =\n  (axis: 'x' | 'y'): TransformActionHandler =>\n  (_eventData, transform, x, y) => {\n    const image = transform.target as FabricImage;\n    const original = transform.original;\n\n    const isX = axis === 'x';\n    const isFlipped = isX ? image.flipX : image.flipY;\n    const elementSize = isX ? image._element.width : image._element.height;\n    const crossElementSize = isX ? image._element.height : image._element.width;\n    const isNegativeEdge = isX\n      ? transform.originX === 'right'\n      : transform.originY === 'bottom';\n\n    const initialSize = isX ? transform.width : transform.height;\n    const initialCrossSize = isX ? transform.height : transform.width;\n    const initialCrop = isX ? (original.cropX ?? 0) : (original.cropY ?? 0);\n    const initialCrossCrop = isX\n      ? (original.cropY ?? 0)\n      : (original.cropX ?? 0);\n    const initialScale = isX ? original.scaleX : original.scaleY;\n    const initialCrossScale = isX ? original.scaleY : original.scaleX;\n\n    const localPoint = controlsUtils.getLocalPoint(\n      transform,\n      transform.originX,\n      transform.originY,\n      x,\n      y,\n    );\n\n    const coordinate = isX ? localPoint.x : localPoint.y;\n    const rawSize = isNegativeEdge ? -coordinate : coordinate;\n    const requestedSize = Math.max(10, rawSize / initialScale);\n\n    const availableSize =\n      isNegativeEdge !== isFlipped\n        ? initialCrop + initialSize\n        : elementSize - initialCrop;\n\n    const setImageProps = (\n      size: number,\n      crossSize: number,\n      scale: number,\n      crop: number,\n      crossCrop: number,\n    ) => {\n      if (isX) {\n        image.width = size;\n        image.height = crossSize;\n        image.cropX = crop;\n        image.cropY = crossCrop;\n      } else {\n        image.height = size;\n        image.width = crossSize;\n        image.cropY = crop;\n        image.cropX = crossCrop;\n      }\n      image.scaleX = scale;\n      image.scaleY = scale;\n    };\n\n    if (requestedSize <= availableSize) {\n      const newCrop =\n        isNegativeEdge !== isFlipped\n          ? Math.max(0, initialCrop + initialSize - requestedSize)\n          : initialCrop;\n      setImageProps(\n        Math.max(1, requestedSize),\n        initialCrossSize,\n        initialScale,\n        newCrop,\n        initialCrossCrop,\n      );\n    } else {\n      const targetScaledSize = requestedSize * initialScale;\n      const newScale = targetScaledSize / availableSize;\n\n      const scaledCrossSize = initialCrossSize * initialCrossScale;\n      const crossNaturalInView = scaledCrossSize / newScale;\n      const newCrossSize = Math.min(crossNaturalInView, crossElementSize);\n      const crossCenter = initialCrossCrop + initialCrossSize / 2;\n      const newCrossCrop = capValue(\n        crossCenter - newCrossSize / 2,\n        0,\n        crossElementSize - newCrossSize,\n      );\n\n      setImageProps(\n        availableSize,\n        newCrossSize,\n        newScale,\n        isNegativeEdge !== isFlipped ? 0 : initialCrop,\n        newCrossCrop,\n      );\n    }\n\n    return true;\n  };\n\nexport const changeImageWidthWithAutoCover =\n  changeImageSizeWithAutoCoverGenerator('x');\nexport const changeImageHeightWithAutoCover =\n  changeImageSizeWithAutoCoverGenerator('y');\n\nexport const changeWidthAndScaleToCover = wrapWithFireEvent(\n  'RESIZING' as TModificationEvents,\n  wrapWithFixedAnchor(changeImageWidthWithAutoCover),\n);\n\nexport const changeHeightAndScaleToCover = wrapWithFireEvent(\n  'RESIZING' as TModificationEvents,\n  wrapWithFixedAnchor(changeImageHeightWithAutoCover),\n);\n"],"mappings":"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"}