/** * Canvas transformation operations * Rotate, flip, and other canvas manipulations */ import { useHistoryStore } from '@/store/history-store'; import { useLayerStore } from '@/store'; import { DrawCommand } from '@/core/commands'; /** * Rotate a canvas by the specified degrees */ export function rotateCanvas(canvas: HTMLCanvasElement, degrees: 90 | 180 | 270): HTMLCanvasElement { const tempCanvas = document.createElement('canvas'); const ctx = tempCanvas.getContext('2d'); if (!ctx) return canvas; // For 90° and 270° rotations, swap width and height if (degrees === 90 || degrees === 270) { tempCanvas.width = canvas.height; tempCanvas.height = canvas.width; } else { tempCanvas.width = canvas.width; tempCanvas.height = canvas.height; } ctx.save(); // Translate and rotate based on degrees switch (degrees) { case 90: ctx.translate(tempCanvas.width, 0); ctx.rotate(Math.PI / 2); break; case 180: ctx.translate(tempCanvas.width, tempCanvas.height); ctx.rotate(Math.PI); break; case 270: ctx.translate(0, tempCanvas.height); ctx.rotate(-Math.PI / 2); break; } ctx.drawImage(canvas, 0, 0); ctx.restore(); return tempCanvas; } /** * Flip a canvas horizontally or vertically */ export function flipCanvas(canvas: HTMLCanvasElement, direction: 'horizontal' | 'vertical'): HTMLCanvasElement { const tempCanvas = document.createElement('canvas'); tempCanvas.width = canvas.width; tempCanvas.height = canvas.height; const ctx = tempCanvas.getContext('2d'); if (!ctx) return canvas; ctx.save(); if (direction === 'horizontal') { ctx.translate(tempCanvas.width, 0); ctx.scale(-1, 1); } else { ctx.translate(0, tempCanvas.height); ctx.scale(1, -1); } ctx.drawImage(canvas, 0, 0); ctx.restore(); return tempCanvas; } /** * Rotate the active layer with history support */ export function rotateLayerWithHistory(layerId: string, degrees: 90 | 180 | 270): void { const { getActiveLayer } = useLayerStore.getState(); const layer = getActiveLayer(); if (!layer || !layer.canvas || layer.id !== layerId) return; // Create command for history (capture before state) const command = new DrawCommand(layerId, `Rotate ${degrees}°`); const rotatedCanvas = rotateCanvas(layer.canvas, degrees); // Replace the layer's canvas const ctx = layer.canvas.getContext('2d'); if (!ctx) return; // Update canvas dimensions if rotated 90° or 270° if (degrees === 90 || degrees === 270) { layer.canvas.width = rotatedCanvas.width; layer.canvas.height = rotatedCanvas.height; } ctx.clearRect(0, 0, layer.canvas.width, layer.canvas.height); ctx.drawImage(rotatedCanvas, 0, 0); // Capture after state and execute command command.captureAfterState(); useHistoryStore.getState().executeCommand(command); } /** * Flip the active layer with history support */ export function flipLayerWithHistory(layerId: string, direction: 'horizontal' | 'vertical'): void { const { getActiveLayer } = useLayerStore.getState(); const layer = getActiveLayer(); if (!layer || !layer.canvas || layer.id !== layerId) return; // Create command for history (capture before state) const command = new DrawCommand(layerId, `Flip ${direction}`); const flippedCanvas = flipCanvas(layer.canvas, direction); // Replace the layer's canvas const ctx = layer.canvas.getContext('2d'); if (!ctx) return; ctx.clearRect(0, 0, layer.canvas.width, layer.canvas.height); ctx.drawImage(flippedCanvas, 0, 0); // Capture after state and execute command command.captureAfterState(); useHistoryStore.getState().executeCommand(command); }