import type { CanvasDocument, StickerAsset } from '../types'; import { serializeDocument } from './svgExport'; const PNG_TYPE = 'image/png'; /** * Render the full visible canvas document to a PNG Blob. WebKit returns the * Blob directly from toBlob; the standard-track callback form and the * data-URL fallback keep other browsers working. */ export async function createDesignPreviewBlob( document: CanvasDocument, stickers: Map, ): Promise { const width = Math.max(1, Math.floor(document.width || 0)); const height = Math.max(1, Math.floor(document.height || 0)); const svgMarkup = await serializeDocument(document, stickers, { includeBackground: true }); const svgBlob = new Blob([svgMarkup], { type: 'image/svg+xml;charset=utf-8' }); const objectUrl = URL.createObjectURL(svgBlob); try { const image: HTMLImageElement = typeof Image === 'function' ? new Image() : globalThis.document.createElement('img'); image.src = objectUrl; await image.decode(); const canvas = globalThis.document.createElement('canvas'); canvas.width = width; canvas.height = height; const ctx = canvas.getContext('2d'); if (!ctx) throw new Error('设计预览画布上下文不可用'); ctx.drawImage(image, 0, 0, canvas.width, canvas.height); const pngBlob = await canvasToPngBlob(canvas); if (pngBlob.type !== PNG_TYPE || pngBlob.size === 0) { throw new Error('设计预览未生成有效的 PNG 输出'); } return pngBlob; } finally { URL.revokeObjectURL(objectUrl); } } async function canvasToPngBlob(canvas: HTMLCanvasElement): Promise { if (typeof canvas.toBlob === 'function') { try { const direct = (canvas.toBlob as unknown as (type: string) => Blob | undefined)('image/png'); if (direct) return direct; } catch { // Non-WebKit browsers wait for the callback form below. } return new Promise((resolve, reject) => { canvas.toBlob(blob => { if (blob) resolve(blob); else reject(new Error('设计预览画布未生成 PNG Blob')); }, 'image/png'); }); } if (typeof canvas.toDataURL === 'function') { const res = await fetch(canvas.toDataURL('image/png')); if (!res.ok) throw new Error('设计预览 PNG 输出读取失败'); return res.blob(); } throw new Error('当前浏览器不支持设计预览 PNG 输出'); }