{"version":3,"file":"useClips.mjs","names":[],"sources":["../../../../../../packages/components/watermark/src/useClips.ts"],"sourcesContent":["import { isArray } from '@element-plus/utils'\n\nimport type { WatermarkProps } from './watermark'\n\n// [alignRatio, spaceRatio]\nconst TEXT_ALIGN_RATIO_MAP = {\n  left: [0, 0.5],\n  start: [0, 0.5],\n  center: [0.5, 0],\n  right: [1, -0.5],\n  end: [1, -0.5],\n} as const\n\nfunction prepareCanvas(\n  width: number,\n  height: number,\n  ratio = 1\n): [\n  ctx: CanvasRenderingContext2D,\n  canvas: HTMLCanvasElement,\n  realWidth: number,\n  realHeight: number,\n] {\n  const canvas = document.createElement('canvas')\n  const ctx = canvas.getContext('2d')!\n  const realWidth = width * ratio\n  const realHeight = height * ratio\n  canvas.setAttribute('width', `${realWidth}px`)\n  canvas.setAttribute('height', `${realHeight}px`)\n  ctx.save()\n\n  return [ctx, canvas, realWidth, realHeight]\n}\n\n/**\n * Get the clips of text content.\n * This is a lazy hook function since SSR no need this\n */\nexport default function useClips() {\n  // Get single clips\n  function getClips(\n    content: NonNullable<WatermarkProps['content']> | HTMLImageElement,\n    rotate: number,\n    ratio: number,\n    width: number,\n    height: number,\n    font: Required<NonNullable<WatermarkProps['font']>>,\n    gapX: number,\n    gapY: number,\n    space: number\n  ): [dataURL: string, finalWidth: number, finalHeight: number] {\n    // ================= Text / Image =================\n    const [ctx, canvas, contentWidth, contentHeight] = prepareCanvas(\n      width,\n      height,\n      ratio\n    )\n    let baselineOffset = 0\n    if (content instanceof HTMLImageElement) {\n      // Image\n      ctx.drawImage(content, 0, 0, contentWidth, contentHeight)\n    } else {\n      // Text\n      const {\n        color,\n        fontSize,\n        fontStyle,\n        fontWeight,\n        fontFamily,\n        textAlign,\n        textBaseline,\n      } = font\n      const mergedFontSize = Number(fontSize) * ratio\n\n      ctx.font = `${fontStyle} normal ${fontWeight} ${mergedFontSize}px/${height}px ${fontFamily}`\n      ctx.fillStyle = color\n      ctx.textAlign = textAlign\n      ctx.textBaseline = textBaseline\n      const contents = isArray(content) ? content : [content]\n      if (textBaseline !== 'top' && contents[0]) {\n        const argumentMetrics = ctx.measureText(contents[0])\n        ctx.textBaseline = 'top'\n        const topMetrics = ctx.measureText(contents[0])\n        baselineOffset =\n          argumentMetrics.actualBoundingBoxAscent -\n          topMetrics.actualBoundingBoxAscent\n      }\n      contents?.forEach((item, index) => {\n        const [alignRatio, spaceRatio] = TEXT_ALIGN_RATIO_MAP[textAlign]\n        ctx.fillText(\n          item ?? '',\n          contentWidth * alignRatio + space * spaceRatio,\n          index * (mergedFontSize + font.fontGap * ratio)\n        )\n      })\n    }\n\n    // ==================== Rotate ====================\n    const angle = (Math.PI / 180) * Number(rotate)\n    const maxSize = Math.max(width, height)\n    const [rCtx, rCanvas, realMaxSize] = prepareCanvas(maxSize, maxSize, ratio)\n\n    // Copy from `ctx` and rotate\n    rCtx.translate(realMaxSize / 2, realMaxSize / 2)\n    rCtx.rotate(angle)\n    if (contentWidth > 0 && contentHeight > 0) {\n      rCtx.drawImage(canvas, -contentWidth / 2, -contentHeight / 2)\n    }\n\n    // Get boundary of rotated text\n    function getRotatePos(x: number, y: number) {\n      const targetX = x * Math.cos(angle) - y * Math.sin(angle)\n      const targetY = x * Math.sin(angle) + y * Math.cos(angle)\n      return [targetX, targetY]\n    }\n\n    let left = 0\n    let right = 0\n    let top = 0\n    let bottom = 0\n\n    const halfWidth = contentWidth / 2\n    const halfHeight = contentHeight / 2\n    const points = [\n      [0 - halfWidth, 0 - halfHeight],\n      [0 + halfWidth, 0 - halfHeight],\n      [0 + halfWidth, 0 + halfHeight],\n      [0 - halfWidth, 0 + halfHeight],\n    ]\n    points.forEach(([x, y]) => {\n      const [targetX, targetY] = getRotatePos(x, y)\n      left = Math.min(left, targetX)\n      right = Math.max(right, targetX)\n      top = Math.min(top, targetY)\n      bottom = Math.max(bottom, targetY)\n    })\n\n    const cutLeft = left + realMaxSize / 2\n    const cutTop = top + realMaxSize / 2\n    const cutWidth = right - left\n    const cutHeight = bottom - top\n\n    // ================ Fill Alternate ================\n    const realGapX = gapX * ratio\n    const realGapY = gapY * ratio\n    const filledWidth = (cutWidth + realGapX) * 2\n    const filledHeight = cutHeight + realGapY\n\n    const [fCtx, fCanvas] = prepareCanvas(filledWidth, filledHeight)\n\n    function drawImg(targetX = 0, targetY = 0) {\n      fCtx.drawImage(\n        rCanvas,\n        cutLeft,\n        cutTop,\n        cutWidth,\n        cutHeight,\n        targetX,\n        targetY + baselineOffset,\n        cutWidth,\n        cutHeight\n      )\n    }\n    drawImg()\n    drawImg(cutWidth + realGapX, -cutHeight / 2 - realGapY / 2)\n    drawImg(cutWidth + realGapX, +cutHeight / 2 + realGapY / 2)\n\n    return [fCanvas.toDataURL(), filledWidth / ratio, filledHeight / ratio]\n  }\n\n  return getClips\n}\n"],"mappings":"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"}