import type { MaskDefinition, RectangleMaskParams } from "@/lib/masks/types"; import { BOX_LIKE_MASK_PARAMS, computeBoxMaskParamUpdate, getBoxLikeGeometry, getDefaultSquareMaskParams, getStrokeOffset, rotatePoint, } from "./box-like"; function buildRectanglePath({ centerX, centerY, halfWidth, halfHeight, rotationRad, }: { centerX: number; centerY: number; halfWidth: number; halfHeight: number; rotationRad: number; }): Path2D { const corners = [ { x: centerX - halfWidth, y: centerY - halfHeight }, { x: centerX + halfWidth, y: centerY - halfHeight }, { x: centerX + halfWidth, y: centerY + halfHeight }, { x: centerX - halfWidth, y: centerY + halfHeight }, ].map((point) => rotatePoint({ ...point, centerX, centerY, rotationRad, }), ); const path = new Path2D(); path.moveTo(corners[0].x, corners[0].y); for (const corner of corners.slice(1)) { path.lineTo(corner.x, corner.y); } path.closePath(); return path; } export const rectangleMaskDefinition: MaskDefinition = { type: "rectangle", name: "Rectangle", overlayShape: "box", features: { hasPosition: true, hasRotation: true, sizeMode: "width-height", }, params: BOX_LIKE_MASK_PARAMS, buildDefault(context) { return { type: "rectangle", params: getDefaultSquareMaskParams(context), }; }, computeParamUpdate: computeBoxMaskParamUpdate, renderer: { buildPath({ resolvedParams, width, height }) { const params = resolvedParams as RectangleMaskParams; const { centerX, centerY, maskWidth, maskHeight, rotationRad } = getBoxLikeGeometry({ params, width, height }); return buildRectanglePath({ centerX, centerY, halfWidth: maskWidth / 2, halfHeight: maskHeight / 2, rotationRad, }); }, buildStrokePath({ resolvedParams, width, height }) { const params = resolvedParams as RectangleMaskParams; const { centerX, centerY, maskWidth, maskHeight, rotationRad } = getBoxLikeGeometry({ params, width, height }); const offset = getStrokeOffset({ strokeAlign: params.strokeAlign, strokeWidth: params.strokeWidth, }); return buildRectanglePath({ centerX, centerY, halfWidth: Math.max(1, maskWidth / 2 + offset), halfHeight: Math.max(1, maskHeight / 2 + offset), rotationRad, }); }, }, };