embroidery-qc-image 1.0.26 → 1.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../node_modules/style-inject/dist/style-inject.es.js","../src/components/EmbroideryQCImage.tsx"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n","import React, { useState, useEffect, useRef } from \"react\";\r\nimport { EmbroideryQCConfig, EmbroideryQCImageProps, Position } from \"../types\";\r\nimport \"./EmbroideryQCImage.css\";\r\n\r\n// ============================================================================\r\n// CONSTANTS\r\n// ============================================================================\r\n\r\nconst COLOR_MAP: Record<string, string> = {\r\n \"Army (1394)\": \"#545541\",\r\n Army: \"#545541\",\r\n \"Black (8)\": \"#060608\",\r\n Black: \"#060608\",\r\n \"Bubblegum (1309)\": \"#E77B9F\",\r\n Bubblegum: \"#E77B9F\",\r\n \"Carolina Blue (1274)\": \"#608CC9\",\r\n \"Carolina Blue\": \"#608CC9\",\r\n \"Celadon (1098)\": \"#8EAD8D\",\r\n Celadon: \"#8EAD8D\",\r\n \"Coffee Bean (1145)\": \"#502B23\",\r\n \"Coffee Bean\": \"#502B23\",\r\n \"Daffodil (1180)\": \"#FBE30D\",\r\n Daffodil: \"#FBE30D\",\r\n \"Dark Gray (1131)\": \"#2E272E\",\r\n \"Dark Gray\": \"#2E272E\",\r\n \"Doe Skin Beige (1344)\": \"#AE9B8B\",\r\n \"Doe Skin Beige\": \"#AE9B8B\",\r\n \"Dusty Blue (1373)\": \"#7B90A9\",\r\n \"Dusty Blue\": \"#7B90A9\",\r\n \"Forest Green (1397)\": \"#073020\",\r\n \"Forest Green\": \"#073020\",\r\n \"Gold (1425)\": \"#D2920A\",\r\n Gold: \"#D2920A\",\r\n \"Gray (1118)\": \"#9999A3\",\r\n Gray: \"#9999A3\",\r\n \"Ivory (1072)\": \"#E3DAC9\",\r\n Ivory: \"#E3DAC9\",\r\n \"Lavender (1032)\": \"#9274B6\",\r\n Lavender: \"#9274B6\",\r\n \"Light Denim (1133)\": \"#366696\",\r\n \"Light Denim\": \"#366696\",\r\n \"Light Salmon (1018)\": \"#E0A793\",\r\n \"Light Salmon\": \"#E0A793\",\r\n \"Maroon (1374)\": \"#480C1C\",\r\n Maroon: \"#480C1C\",\r\n \"Navy Blue (1044)\": \"#04072A\",\r\n \"Navy Blue\": \"#04072A\",\r\n \"Olive Green (1157)\": \"#625E1F\",\r\n \"Olive Green\": \"#625E1F\",\r\n \"Orange (1278)\": \"#D45D03\",\r\n Orange: \"#D45D03\",\r\n \"Peach Blush (1053)\": \"#E2C0B6\",\r\n \"Peach Blush\": \"#E2C0B6\",\r\n \"Pink (1148)\": \"#EFAFBF\",\r\n Pink: \"#EFAFBF\",\r\n \"Purple (1412)\": \"#37196F\",\r\n Purple: \"#37196F\",\r\n \"Red (1037)\": \"#9D000B\",\r\n Red: \"#9D000B\",\r\n \"Silver Sage (1396)\": \"#424F45\",\r\n \"Silver Sage\": \"#424F45\",\r\n \"Summer Sky (1432)\": \"#65A8D2\",\r\n \"Summer Sky\": \"#65A8D2\",\r\n \"Terra Cotta (1477)\": \"#AE3111\",\r\n \"Terra Cotta\": \"#AE3111\",\r\n \"Sand (1055)\": \"#D2C2AB\",\r\n Sand: \"#D2C2AB\",\r\n \"White (9)\": \"#D8D7DC\",\r\n White: \"#D8D7DC\",\r\n};\r\n\r\nconst DEFAULT_ERROR_COLOR = \"#CC1F1A\";\r\nconst DEFAULT_WARNING_COLOR = \"#FF8C00\";\r\n\r\nconst BASE_URLS = {\r\n FONT: \"https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/fonts\",\r\n ICON: \"https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/icons-resized\",\r\n FLORAL:\r\n \"https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/florals-resized\",\r\n THREAD_COLOR:\r\n \"https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/thread-colors-resized\",\r\n};\r\n\r\nconst LAYOUT = {\r\n // Font families\r\n HEADER_FONT_FAMILY: \"Times New Roman\",\r\n FONT_FAMILY: \"Arial\",\r\n\r\n // Font sizes (base values, will be multiplied by scaleFactor)\r\n HEADER_FONT_SIZE: 220,\r\n TEXT_FONT_SIZE: 200,\r\n OTHER_FONT_SIZE: 160,\r\n\r\n // Colors\r\n HEADER_COLOR: \"#000000\",\r\n LABEL_COLOR: \"#444444\",\r\n BACKGROUND_COLOR: \"#FFFFFF\",\r\n\r\n // Text alignment\r\n TEXT_ALIGN: \"left\" as CanvasTextAlign,\r\n TEXT_BASELINE: \"top\" as CanvasTextBaseline,\r\n\r\n // Spacing\r\n LINE_GAP: 50,\r\n PADDING: 50,\r\n SECTION_SPACING: 60,\r\n ELEMENT_SPACING: 100,\r\n SWATCH_SPACING: 25,\r\n FLORAL_SPACING: 100,\r\n\r\n // Visual styling\r\n SWATCH_HEIGHT_RATIO: 2.025,\r\n UNDERLINE_POSITION: 0.9,\r\n UNDERLINE_WIDTH: 10,\r\n\r\n // Swatch reserved space\r\n SWATCH_RESERVED_SPACE: 1000,\r\n MIN_TEXT_WIDTH: 400,\r\n};\r\n\r\n// ============================================================================\r\n// HELPER FUNCTIONS\r\n// ============================================================================\r\n\r\nconst loadFont = (fontName: string): Promise<void> => {\r\n // Check if font is already loaded in document.fonts (browser cache)\r\n const fontFaceSet = document.fonts;\r\n for (const font of fontFaceSet) {\r\n if (font.family === fontName && font.status === 'loaded') {\r\n return Promise.resolve();\r\n }\r\n }\r\n\r\n return new Promise((resolve) => {\r\n const fontUrl = `${BASE_URLS.FONT}/${encodeURIComponent(fontName)}.woff2`;\r\n const fontFace = new FontFace(fontName, `url(${fontUrl})`);\r\n\r\n fontFace\r\n .load()\r\n .then((loadedFont) => {\r\n document.fonts.add(loadedFont);\r\n resolve();\r\n })\r\n .catch(() => {\r\n console.warn(`Could not load font ${fontName} from CDN`);\r\n resolve();\r\n });\r\n });\r\n};\r\n\r\nconst getImageUrl = (\r\n type: \"icon\" | \"floral\" | \"threadColor\",\r\n value: string | number\r\n): string => {\r\n if (type === \"icon\") return `${BASE_URLS.ICON}/Icon ${value}.webp`;\r\n if (type === \"floral\") return `${BASE_URLS.FLORAL}/${value}.webp`;\r\n return `${BASE_URLS.THREAD_COLOR}/${value}.webp`;\r\n};\r\n\r\ntype ImageMapRef = {\r\n current: Map<string, HTMLImageElement>;\r\n};\r\n\r\nexport interface EmbroideryQCImageRenderOptions {\r\n width?: number;\r\n height?: number;\r\n mimeType?: \"image/png\" | \"image/jpeg\" | \"image/webp\";\r\n quality?: number;\r\n}\r\n\r\nconst getProxyUrl = (url: string): string =>\r\n `https://proxy-img.c8p.workers.dev?url=${encodeURIComponent(url)}`;\r\n\r\nconst getIconImageUrl = (position: Position & { type: \"ICON\" }): string | null => {\r\n if (position.is_delete_icon) return null;\r\n\r\n if (position.icon_image && position.icon_image.trim().length > 0) {\r\n return position.icon_image;\r\n }\r\n\r\n if (position.icon !== 0) {\r\n return getImageUrl(\"icon\", position.icon);\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst ensureImage = (existing?: HTMLImageElement | null): HTMLImageElement => {\r\n if (existing && existing.crossOrigin === \"anonymous\") {\r\n return existing;\r\n }\r\n\r\n const img = new Image();\r\n img.crossOrigin = \"anonymous\";\r\n img.decoding = \"async\";\r\n return img;\r\n};\r\n\r\nconst loadImage = (url: string, imageRefs: ImageMapRef, onLoad: () => void) => {\r\n const existing = imageRefs.current.get(url);\r\n if (\r\n existing?.complete &&\r\n existing.naturalWidth > 0 &&\r\n existing.crossOrigin === \"anonymous\"\r\n ) {\r\n return;\r\n }\r\n\r\n const img = ensureImage(existing);\r\n imageRefs.current.set(url, img);\r\n\r\n let attemptedProxy = existing?.dataset?.proxyUsed === \"true\";\r\n\r\n const cleanup = () => {\r\n img.onload = null;\r\n img.onerror = null;\r\n };\r\n\r\n img.onload = () => {\r\n img.dataset.proxyUsed = attemptedProxy ? \"true\" : \"false\";\r\n cleanup();\r\n onLoad();\r\n };\r\n\r\n img.onerror = () => {\r\n if (!attemptedProxy) {\r\n attemptedProxy = true;\r\n img.src = getProxyUrl(getResizeUrl(url));\r\n return;\r\n }\r\n img.dataset.proxyUsed = attemptedProxy ? \"true\" : \"false\";\r\n cleanup();\r\n onLoad();\r\n };\r\n\r\n img.src = attemptedProxy ? getProxyUrl(getResizeUrl(url)) : getResizeUrl(url);\r\n};\r\n\r\nconst loadImageAsync = (\r\n url: string,\r\n imageRefs: ImageMapRef,\r\n cacheKey?: string\r\n): Promise<HTMLImageElement> => {\r\n const key = cacheKey ?? url;\r\n const existing = imageRefs.current.get(key) ?? imageRefs.current.get(url);\r\n\r\n if (\r\n existing?.complete &&\r\n existing.naturalWidth > 0 &&\r\n existing.crossOrigin === \"anonymous\" &&\r\n existing.dataset?.proxyUsed !== undefined\r\n ) {\r\n if (existing !== imageRefs.current.get(key)) {\r\n imageRefs.current.set(key, existing);\r\n }\r\n if (existing !== imageRefs.current.get(url)) {\r\n imageRefs.current.set(url, existing);\r\n }\r\n return Promise.resolve(existing);\r\n }\r\n\r\n return new Promise((resolve) => {\r\n const target = ensureImage(existing);\r\n if (target !== existing) {\r\n imageRefs.current.set(key, target);\r\n imageRefs.current.set(url, target);\r\n }\r\n let attemptedProxy = target.dataset.proxyUsed === \"true\";\r\n\r\n const finalize = () => {\r\n target.onload = null;\r\n target.onerror = null;\r\n if (target.complete && target.naturalWidth > 0) {\r\n imageRefs.current.set(key, target);\r\n imageRefs.current.set(url, target);\r\n }\r\n target.dataset.proxyUsed = attemptedProxy ? \"true\" : \"false\";\r\n resolve(target);\r\n };\r\n\r\n target.onload = finalize;\r\n target.onerror = () => {\r\n if (!attemptedProxy) {\r\n attemptedProxy = true;\r\n target.src = getProxyUrl(getResizeUrl(url));\r\n return;\r\n }\r\n target.dataset.proxyUsed = attemptedProxy ? \"true\" : \"false\";\r\n finalize();\r\n };\r\n\r\n const desiredSrc = attemptedProxy ? getProxyUrl(getResizeUrl(url)) : getResizeUrl(url);\r\n\r\n if (target.src !== desiredSrc) {\r\n target.src = desiredSrc;\r\n } else if (target.complete && target.naturalWidth > 0) {\r\n finalize();\r\n }\r\n });\r\n};\r\n\r\nconst getResizeUrl = (url: string): string => {\r\n try {\r\n const urlObj = new URL(url);\r\n \r\n // Xử lý cdn.shopify.com\r\n if (urlObj.hostname === 'cdn.shopify.com') {\r\n // Set hoặc update query param width=400\r\n urlObj.searchParams.set('width', '400');\r\n return urlObj.toString();\r\n }\r\n \r\n // Xử lý m.media-amazon.com\r\n if (urlObj.hostname === 'm.media-amazon.com') {\r\n const pathname = urlObj.pathname;\r\n // Split pathname theo dấu /\r\n const pathArr = pathname.split('/');\r\n // Lấy filename (phần cuối cùng)\r\n const filename = pathArr[pathArr.length - 1];\r\n // Xóa pattern ._.*_ (ví dụ: ._AC_SX569_)\r\n const cleanedFilename = filename.replace(/\\._.*_/g, '');\r\n // Split filename đã clean theo dấu .\r\n const parts = cleanedFilename.split('.');\r\n \r\n if (parts.length >= 2) {\r\n // Lấy phần đầu và phần cuối\r\n const firstPart = parts[0];\r\n const lastPart = parts[parts.length - 1];\r\n // Chèn _AC_SX400_ vào giữa và join lại\r\n const newFilename = `${firstPart}._AC_SX400_.${lastPart}`;\r\n // Thay filename mới vào pathArr\r\n pathArr[pathArr.length - 1] = newFilename;\r\n // Join lại\r\n urlObj.pathname = pathArr.join('/');\r\n return urlObj.toString();\r\n }\r\n }\r\n \r\n // Xử lý i.etsystatic.com\r\n if (urlObj.hostname === 'i.etsystatic.com') {\r\n const pathname = urlObj.pathname;\r\n // Thay il_fullxfull bằng il_400x400\r\n if (pathname.includes('il_fullxfull')) {\r\n const newPathname = pathname.replace(/il_fullxfull/g, 'il_400x400');\r\n urlObj.pathname = newPathname;\r\n return urlObj.toString();\r\n }\r\n }\r\n \r\n // Nếu không phải các domain cần xử lý, return URL gốc\r\n return url;\r\n } catch (error) {\r\n // Nếu URL không hợp lệ, return URL gốc\r\n return url;\r\n }\r\n};\r\n\r\nconst preloadFonts = async (config: EmbroideryQCConfig) => {\r\n if (config.error_message || !config.sides?.length) return;\r\n\r\n const fonts = new Set<string>();\r\n\r\n config.sides.forEach((side) => {\r\n side.positions.forEach((position) => {\r\n if (position.type === \"TEXT\" && position.font) {\r\n fonts.add(position.font);\r\n }\r\n });\r\n });\r\n\r\n if (fonts.size === 0) return;\r\n\r\n await Promise.all([...fonts].map((font) => loadFont(font)));\r\n};\r\n\r\nconst preloadImages = async (\r\n config: EmbroideryQCConfig,\r\n imageRefs: ImageMapRef\r\n) => {\r\n const entries: Array<{ url: string; cacheKey?: string }> = [];\r\n const seen = new Set<string>();\r\n\r\n if (config.image_url) {\r\n entries.push({ url: config.image_url, cacheKey: \"mockup\" });\r\n seen.add(config.image_url);\r\n }\r\n\r\n if (!config.sides?.length) {\r\n await Promise.all(\r\n entries.map(({ url, cacheKey }) =>\r\n loadImageAsync(url, imageRefs, cacheKey)\r\n )\r\n );\r\n return;\r\n }\r\n\r\n config.sides.forEach((side) => {\r\n side.positions.forEach((position) => {\r\n if (position.type === \"ICON\") {\r\n const iconUrl = getIconImageUrl(position);\r\n\r\n if (iconUrl && !seen.has(iconUrl)) {\r\n entries.push({ url: iconUrl });\r\n seen.add(iconUrl);\r\n }\r\n\r\n if (position.color) {\r\n const threadUrl = getImageUrl(\"threadColor\", position.color);\r\n if (!seen.has(threadUrl)) {\r\n entries.push({ url: threadUrl });\r\n seen.add(threadUrl);\r\n }\r\n }\r\n\r\n position.layer_colors?.forEach((color) => {\r\n const colorUrl = getImageUrl(\"threadColor\", color);\r\n if (!seen.has(colorUrl)) {\r\n entries.push({ url: colorUrl });\r\n seen.add(colorUrl);\r\n }\r\n });\r\n }\r\n\r\n if (position.type === \"TEXT\") {\r\n if (position.floral_pattern) {\r\n const floralUrl = getImageUrl(\"floral\", position.floral_pattern);\r\n if (!seen.has(floralUrl)) {\r\n entries.push({ url: floralUrl });\r\n seen.add(floralUrl);\r\n }\r\n }\r\n\r\n if (position.color) {\r\n const threadUrl = getImageUrl(\"threadColor\", position.color);\r\n if (!seen.has(threadUrl)) {\r\n entries.push({ url: threadUrl });\r\n seen.add(threadUrl);\r\n }\r\n }\r\n\r\n position.character_colors?.forEach((color) => {\r\n const characterColorUrl = getImageUrl(\"threadColor\", color);\r\n if (!seen.has(characterColorUrl)) {\r\n entries.push({ url: characterColorUrl });\r\n seen.add(characterColorUrl);\r\n }\r\n });\r\n }\r\n });\r\n });\r\n\r\n if (entries.length === 0) return;\r\n\r\n await Promise.all(\r\n entries.map(({ url, cacheKey }) => loadImageAsync(url, imageRefs, cacheKey))\r\n );\r\n};\r\n\r\nconst wrapText = (\r\n ctx: CanvasRenderingContext2D,\r\n text: string,\r\n x: number,\r\n y: number,\r\n maxWidth: number,\r\n lineHeight: number\r\n): { height: number; lastLineWidth: number; lastLineY: number } => {\r\n const words = text.split(\" \");\r\n const lines: string[] = [];\r\n let currentLine = words[0];\r\n\r\n for (let i = 1; i < words.length; i++) {\r\n const testLine = currentLine + \" \" + words[i];\r\n if (ctx.measureText(testLine).width > maxWidth && currentLine.length > 0) {\r\n lines.push(currentLine);\r\n currentLine = words[i];\r\n } else {\r\n currentLine = testLine;\r\n }\r\n }\r\n lines.push(currentLine);\r\n\r\n let currentY = y;\r\n lines.forEach((line) => {\r\n ctx.fillText(line, x, currentY);\r\n currentY += lineHeight;\r\n });\r\n\r\n return {\r\n height: lines.length * lineHeight,\r\n lastLineWidth: ctx.measureText(lines[lines.length - 1]).width,\r\n lastLineY: y + (lines.length - 1) * lineHeight,\r\n };\r\n};\r\n\r\nconst buildWrappedLines = (\r\n ctx: CanvasRenderingContext2D,\r\n text: string,\r\n maxWidth: number\r\n): string[] => {\r\n // Mỗi '\\n' tương đương với một line break giống như khi wrap tự động.\r\n const segments = text.split(\"\\n\");\r\n const result: string[] = [];\r\n\r\n segments.forEach((segment) => {\r\n const words = segment.split(\" \").filter((word) => word.length > 0);\r\n if (words.length === 0) {\r\n // Nếu đoạn rỗng, thêm một dòng trống (break đúng 1 line)\r\n result.push(\"\");\r\n return;\r\n }\r\n\r\n let currentLine = words[0];\r\n for (let i = 1; i < words.length; i++) {\r\n const testLine = `${currentLine} ${words[i]}`;\r\n if (ctx.measureText(testLine).width > maxWidth && currentLine.length > 0) {\r\n result.push(currentLine);\r\n currentLine = words[i];\r\n } else {\r\n currentLine = testLine;\r\n }\r\n }\r\n result.push(currentLine);\r\n });\r\n\r\n return result.length ? result : [\"\"];\r\n};\r\n\r\nconst wrapTextMultiColor = (\r\n ctx: CanvasRenderingContext2D,\r\n text: string,\r\n colors: string[],\r\n x: number,\r\n y: number,\r\n maxWidth: number,\r\n lineHeight: number\r\n): number => {\r\n const words = text.split(\" \");\r\n const lines: string[] = [];\r\n const lineStartIndices: number[] = [0];\r\n let currentLine = words[0];\r\n let currentCharIndex = words[0].length;\r\n\r\n for (let i = 1; i < words.length; i++) {\r\n const testLine = currentLine + \" \" + words[i];\r\n if (ctx.measureText(testLine).width > maxWidth && currentLine.length > 0) {\r\n lines.push(currentLine);\r\n lineStartIndices.push(currentCharIndex + 1);\r\n currentLine = words[i];\r\n currentCharIndex += words[i].length + 1;\r\n } else {\r\n currentLine = testLine;\r\n currentCharIndex += words[i].length + 1;\r\n }\r\n }\r\n lines.push(currentLine);\r\n\r\n let currentY = y;\r\n lines.forEach((line, lineIdx) => {\r\n let currentX = x;\r\n const startCharIdx = lineIdx > 0 ? lineStartIndices[lineIdx] : 0;\r\n for (let i = 0; i < line.length; i++) {\r\n const char = line[i];\r\n const globalCharIdx = startCharIdx + i;\r\n const colorIndex = globalCharIdx % colors.length;\r\n const color = colors[colorIndex];\r\n ctx.fillStyle = COLOR_MAP[color] || LAYOUT.LABEL_COLOR;\r\n ctx.fillText(char, currentX, currentY);\r\n currentX += ctx.measureText(char).width;\r\n }\r\n currentY += lineHeight;\r\n });\r\n\r\n return lines.length * lineHeight;\r\n};\r\n\r\nconst calculateSwatchesWidth = (\r\n colors: string[],\r\n swatchHeight: number,\r\n scaleFactor: number,\r\n imageRefs: ImageMapRef\r\n): number => {\r\n let totalWidth = 0;\r\n colors.forEach((color, index) => {\r\n const url = getImageUrl(\"threadColor\", color);\r\n const img = imageRefs.current.get(url);\r\n if (img && img.complete && img.naturalHeight > 0) {\r\n const ratio = img.naturalWidth / img.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchHeight * ratio));\r\n totalWidth += swatchW;\r\n if (index < colors.length - 1) {\r\n totalWidth += LAYOUT.SWATCH_SPACING * scaleFactor;\r\n }\r\n }\r\n });\r\n return totalWidth;\r\n};\r\n\r\nconst drawSwatches = (\r\n ctx: CanvasRenderingContext2D,\r\n colors: string[],\r\n startX: number,\r\n startY: number,\r\n swatchHeight: number,\r\n scaleFactor: number,\r\n imageRefs: ImageMapRef\r\n) => {\r\n let swatchX = startX;\r\n colors.forEach((color) => {\r\n const url = getImageUrl(\"threadColor\", color);\r\n const img = imageRefs.current.get(url);\r\n if (img && img.complete && img.naturalHeight > 0) {\r\n const ratio = img.naturalWidth / img.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchHeight * ratio));\r\n ctx.drawImage(img, swatchX, startY, swatchW, swatchHeight);\r\n swatchX += swatchW + LAYOUT.SWATCH_SPACING * scaleFactor;\r\n }\r\n });\r\n};\r\n\r\n// ============================================================================\r\n// MAIN COMPONENT\r\n// ============================================================================\r\n\r\nconst EmbroideryQCImage: React.FC<EmbroideryQCImageProps> = ({\r\n config,\r\n className = \"\",\r\n style = {},\r\n}) => {\r\n const [canvasSize] = useState({ width: 4200, height: 4800 });\r\n const [loadedFonts, setLoadedFonts] = useState<Set<string>>(new Set());\r\n const [imagesLoaded, setImagesLoaded] = useState(0);\r\n const canvasRef = useRef<HTMLCanvasElement>(null);\r\n const imageRefs = useRef<Map<string, HTMLImageElement>>(new Map());\r\n\r\n // Load fonts\r\n useEffect(() => {\r\n const loadFonts = async () => {\r\n if (config.error_message || !config.sides?.length) return;\r\n\r\n const fontsToLoad = new Set<string>();\r\n config.sides.forEach((side) => {\r\n side.positions.forEach((position) => {\r\n if (position.type === \"TEXT\" && position.font) {\r\n fontsToLoad.add(position.font);\r\n }\r\n });\r\n });\r\n\r\n for (const fontName of fontsToLoad) {\r\n if (!loadedFonts.has(fontName)) {\r\n try {\r\n await loadFont(fontName);\r\n setLoadedFonts((prev) => new Set(prev).add(fontName));\r\n } catch (error) {\r\n console.warn(`Could not load font ${fontName}:`, error);\r\n }\r\n }\r\n }\r\n };\r\n\r\n loadFonts();\r\n }, [config.sides, loadedFonts]);\r\n\r\n // Load images\r\n useEffect(() => {\r\n if (config.error_message || !config.sides?.length) return;\r\n\r\n const incrementCounter = () => setImagesLoaded((prev) => prev + 1);\r\n\r\n // Load mockup\r\n if (config.image_url) {\r\n loadImage(config.image_url, imageRefs, incrementCounter);\r\n }\r\n\r\n // Load all other images\r\n config.sides.forEach((side) => {\r\n side.positions.forEach((position) => {\r\n if (position.type === \"ICON\") {\r\n const iconUrl = getIconImageUrl(position);\r\n\r\n if (iconUrl) {\r\n loadImage(iconUrl, imageRefs, incrementCounter);\r\n }\r\n position.layer_colors?.forEach((color) => {\r\n loadImage(\r\n getImageUrl(\"threadColor\", color),\r\n imageRefs,\r\n incrementCounter\r\n );\r\n });\r\n }\r\n\r\n if (position.type === \"TEXT\") {\r\n if (position.floral_pattern) {\r\n loadImage(\r\n getImageUrl(\"floral\", position.floral_pattern),\r\n imageRefs,\r\n incrementCounter\r\n );\r\n }\r\n if (position.color) {\r\n loadImage(\r\n getImageUrl(\"threadColor\", position.color),\r\n imageRefs,\r\n incrementCounter\r\n );\r\n }\r\n position.character_colors?.forEach((color) => {\r\n loadImage(\r\n getImageUrl(\"threadColor\", color),\r\n imageRefs,\r\n incrementCounter\r\n );\r\n });\r\n }\r\n });\r\n });\r\n }, [config]);\r\n\r\n // Render canvas\r\n useEffect(() => {\r\n const renderCanvas = () => {\r\n if (!canvasRef.current) return;\r\n renderEmbroideryCanvas(canvasRef.current, config, canvasSize, imageRefs);\r\n };\r\n\r\n const timer = setTimeout(renderCanvas, 100);\r\n return () => clearTimeout(timer);\r\n }, [config, canvasSize, loadedFonts, imagesLoaded]);\r\n\r\n return (\r\n <div\r\n className={`render-embroidery${className ? ` ${className}` : \"\"}`}\r\n style={style}\r\n >\r\n <canvas ref={canvasRef} className=\"render-embroidery-canvas\" />\r\n </div>\r\n );\r\n};\r\n\r\n// ============================================================================\r\n// RENDERING FUNCTIONS\r\n// ============================================================================\r\n\r\nconst renderEmbroideryCanvas = (\r\n canvas: HTMLCanvasElement,\r\n config: EmbroideryQCConfig,\r\n canvasSize: { width: number; height: number },\r\n imageRefs: ImageMapRef\r\n) => {\r\n const ctx = canvas.getContext(\"2d\");\r\n if (!ctx) return;\r\n\r\n canvas.width = canvasSize.width;\r\n canvas.height = canvasSize.height;\r\n\r\n ctx.fillStyle = LAYOUT.BACKGROUND_COLOR;\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n if (config.error_message) {\r\n renderErrorState(ctx, canvas, config.error_message);\r\n return;\r\n }\r\n\r\n if (!config.sides?.length) return;\r\n\r\n ctx.textAlign = LAYOUT.TEXT_ALIGN;\r\n ctx.textBaseline = LAYOUT.TEXT_BASELINE;\r\n\r\n // Calculate warning & message height (with scaleFactor = 1 for measurement)\r\n let warningHeight = 0;\r\n let warningLineHeight = 0;\r\n let warningLineCount = 0;\r\n if (config.warning_message) {\r\n const measureWarningCanvas = document.createElement(\"canvas\");\r\n measureWarningCanvas.width = canvas.width;\r\n measureWarningCanvas.height = canvas.height;\r\n const measureWarningCtx = measureWarningCanvas.getContext(\"2d\");\r\n if (measureWarningCtx) {\r\n measureWarningCtx.textAlign = \"left\";\r\n measureWarningCtx.textBaseline = \"top\";\r\n measureWarningCtx.font = `${LAYOUT.HEADER_FONT_SIZE * 0.7}px ${LAYOUT.FONT_FAMILY}`;\r\n const warningLines = buildWrappedLines(\r\n measureWarningCtx,\r\n `Note: ${config.warning_message.trim()}`,\r\n canvas.width - LAYOUT.PADDING * 4\r\n );\r\n warningLineCount = warningLines.length;\r\n warningLineHeight = LAYOUT.HEADER_FONT_SIZE * 0.7 + LAYOUT.LINE_GAP;\r\n warningHeight = warningLineCount * warningLineHeight + LAYOUT.PADDING;\r\n }\r\n }\r\n\r\n let messageHeight = 0;\r\n let messageLineHeight = 0;\r\n let messageLineCount = 0;\r\n if (config.message) {\r\n const measureMessageCanvas = document.createElement(\"canvas\");\r\n measureMessageCanvas.width = canvas.width;\r\n measureMessageCanvas.height = canvas.height;\r\n const measureMessageCtx = measureMessageCanvas.getContext(\"2d\");\r\n if (measureMessageCtx) {\r\n measureMessageCtx.textAlign = \"left\";\r\n measureMessageCtx.textBaseline = \"top\";\r\n measureMessageCtx.font = `${LAYOUT.HEADER_FONT_SIZE * 0.7}px ${LAYOUT.FONT_FAMILY}`;\r\n const messageLines = buildWrappedLines(\r\n measureMessageCtx,\r\n config.message.trim(),\r\n canvas.width - LAYOUT.PADDING * 4\r\n );\r\n messageLineCount = messageLines.length;\r\n messageLineHeight = LAYOUT.HEADER_FONT_SIZE * 0.7 + LAYOUT.LINE_GAP;\r\n messageHeight = messageLineCount * messageLineHeight + LAYOUT.PADDING;\r\n }\r\n }\r\n\r\n if (config.image_url) {\r\n const mockupImage = imageRefs.current.get(config.image_url);\r\n if (mockupImage) {\r\n imageRefs.current.set(\"mockup\", mockupImage);\r\n }\r\n }\r\n\r\n const measureCanvas = document.createElement(\"canvas\");\r\n measureCanvas.width = canvas.width;\r\n measureCanvas.height = canvas.height;\r\n const measureCtx = measureCanvas.getContext(\"2d\");\r\n if (!measureCtx) return;\r\n\r\n measureCtx.textAlign = LAYOUT.TEXT_ALIGN;\r\n measureCtx.textBaseline = LAYOUT.TEXT_BASELINE;\r\n\r\n let measureY = LAYOUT.PADDING;\r\n const measureSpacing = LAYOUT.ELEMENT_SPACING;\r\n \r\n // Add warning & message text height (without bottom padding, no spacing)\r\n if (config.warning_message) {\r\n const warningTextHeight = warningHeight - LAYOUT.PADDING;\r\n measureY += warningTextHeight;\r\n }\r\n if (config.message) {\r\n const messageTextHeight = messageHeight - LAYOUT.PADDING;\r\n measureY += messageTextHeight;\r\n }\r\n\r\n config.sides.forEach((side) => {\r\n const sideHeight = renderSide(\r\n measureCtx,\r\n side,\r\n measureY,\r\n canvas.width,\r\n 1,\r\n imageRefs\r\n );\r\n measureY += sideHeight + measureSpacing;\r\n });\r\n\r\n const scaleFactor = Math.max(\r\n 0.5,\r\n Math.min(\r\n 1,\r\n (canvas.height - LAYOUT.PADDING - warningHeight - messageHeight) / measureY\r\n )\r\n );\r\n\r\n drawMockupAndFlorals(ctx, canvas, imageRefs);\r\n\r\n // Render warning & message with scaleFactor and get actual heights\r\n let actualWarningHeight = 0;\r\n let actualMessageHeight = 0;\r\n if (config.warning_message) {\r\n actualWarningHeight = renderWarning(\r\n ctx,\r\n canvas,\r\n config.warning_message,\r\n scaleFactor\r\n );\r\n }\r\n if (config.message) {\r\n actualMessageHeight = renderWarning(\r\n ctx,\r\n canvas,\r\n config.message,\r\n scaleFactor,\r\n actualWarningHeight,\r\n \"\", // message: không cần prefix \"Note\"\r\n DEFAULT_ERROR_COLOR // message: hiển thị màu đỏ\r\n );\r\n }\r\n\r\n // Calculate currentY: padding top + actual warning & message height (no spacing)\r\n let currentY = LAYOUT.PADDING * scaleFactor;\r\n if (config.warning_message && actualWarningHeight > 0) {\r\n currentY += actualWarningHeight;\r\n }\r\n if (config.message && actualMessageHeight > 0) {\r\n currentY += actualMessageHeight;\r\n }\r\n config.sides.forEach((side) => {\r\n const sideHeight = renderSide(\r\n ctx,\r\n side,\r\n currentY,\r\n canvas.width,\r\n scaleFactor,\r\n imageRefs\r\n );\r\n currentY += sideHeight + measureSpacing * scaleFactor;\r\n });\r\n};\r\n\r\nconst renderErrorState = (\r\n ctx: CanvasRenderingContext2D,\r\n canvas: HTMLCanvasElement,\r\n message: string\r\n) => {\r\n const sanitizedMessage = message.trim() || \"Đã xảy ra lỗi\";\r\n const horizontalPadding = LAYOUT.PADDING * 3;\r\n const maxWidth = canvas.width - horizontalPadding * 2;\r\n const baseFontSize = LAYOUT.HEADER_FONT_SIZE;\r\n const minFontSize = 60;\r\n const centerX = canvas.width / 2;\r\n\r\n ctx.save();\r\n ctx.textAlign = \"center\";\r\n ctx.textBaseline = \"top\";\r\n ctx.fillStyle = DEFAULT_ERROR_COLOR;\r\n\r\n let fontSize = baseFontSize;\r\n let lineGap = LAYOUT.LINE_GAP;\r\n let lineHeight = fontSize + lineGap;\r\n\r\n const adjustMetrics = () => {\r\n ctx.font = `bold ${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n lineGap = LAYOUT.LINE_GAP * (fontSize / baseFontSize);\r\n lineHeight = fontSize + lineGap;\r\n };\r\n\r\n adjustMetrics();\r\n let lines = buildWrappedLines(ctx, sanitizedMessage, maxWidth);\r\n let longestLineWidth = Math.max(\r\n ...lines.map((line) => ctx.measureText(line).width)\r\n );\r\n\r\n while (longestLineWidth > maxWidth && fontSize > minFontSize) {\r\n fontSize = Math.max(minFontSize, Math.floor(fontSize * 0.9));\r\n adjustMetrics();\r\n lines = buildWrappedLines(ctx, sanitizedMessage, maxWidth);\r\n longestLineWidth = Math.max(\r\n ...lines.map((line) => ctx.measureText(line).width)\r\n );\r\n }\r\n\r\n const totalHeight = lines.length * lineHeight;\r\n const startY = Math.max(\r\n LAYOUT.PADDING * 2,\r\n canvas.height / 2 - totalHeight / 2\r\n );\r\n\r\n lines.forEach((line, index) => {\r\n const y = startY + index * lineHeight;\r\n ctx.fillText(line, centerX, y);\r\n });\r\n\r\n ctx.restore();\r\n};\r\n\r\nconst renderWarning = (\r\n ctx: CanvasRenderingContext2D,\r\n canvas: HTMLCanvasElement,\r\n message: string,\r\n scaleFactor: number = 1,\r\n offsetY: number = 0,\r\n prefix: string = \"Note: \",\r\n color: string = DEFAULT_WARNING_COLOR\r\n): number => {\r\n const sanitizedMessage = `${prefix}${message.trim()}`;\r\n const horizontalPadding = LAYOUT.PADDING * 2 * scaleFactor;\r\n const maxWidth = canvas.width - horizontalPadding * 2;\r\n const baseFontSize = LAYOUT.HEADER_FONT_SIZE * 0.7 * scaleFactor;\r\n const minFontSize = 50 * scaleFactor;\r\n const leftX = LAYOUT.PADDING * scaleFactor;\r\n\r\n ctx.save();\r\n ctx.textAlign = \"left\";\r\n ctx.textBaseline = \"top\";\r\n ctx.fillStyle = color;\r\n ctx.font = `${baseFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n\r\n let fontSize = baseFontSize;\r\n let lineGap = LAYOUT.LINE_GAP * scaleFactor;\r\n let lineHeight = fontSize + lineGap;\r\n\r\n const adjustMetrics = () => {\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n lineGap = LAYOUT.LINE_GAP * scaleFactor * (fontSize / baseFontSize);\r\n lineHeight = fontSize + lineGap;\r\n };\r\n\r\n adjustMetrics();\r\n let lines = buildWrappedLines(ctx, sanitizedMessage, maxWidth);\r\n let longestLineWidth = Math.max(\r\n ...lines.map((line) => ctx.measureText(line).width)\r\n );\r\n\r\n while (longestLineWidth > maxWidth && fontSize > minFontSize) {\r\n fontSize = Math.max(minFontSize, Math.floor(fontSize * 0.9));\r\n adjustMetrics();\r\n lines = buildWrappedLines(ctx, sanitizedMessage, maxWidth);\r\n longestLineWidth = Math.max(\r\n ...lines.map((line) => ctx.measureText(line).width)\r\n );\r\n }\r\n\r\n const startY = LAYOUT.PADDING * scaleFactor + offsetY;\r\n\r\n lines.forEach((line, index) => {\r\n const y = startY + index * lineHeight;\r\n ctx.fillText(line, leftX, y);\r\n });\r\n\r\n ctx.restore();\r\n \r\n // Return the actual height of the warning (number of lines * lineHeight)\r\n return lines.length * lineHeight;\r\n};\r\n\r\nconst drawMockupAndFlorals = (\r\n ctx: CanvasRenderingContext2D,\r\n canvas: HTMLCanvasElement,\r\n imageRefs: ImageMapRef\r\n) => {\r\n const mockupImg = imageRefs.current.get(\"mockup\");\r\n if (!mockupImg?.complete || !mockupImg.naturalWidth) return;\r\n\r\n const margin = LAYOUT.PADDING;\r\n const maxWidth = Math.min(1800, canvas.width * 0.375);\r\n const maxHeight = canvas.height * 0.375;\r\n const scale = Math.min(\r\n maxWidth / mockupImg.naturalWidth,\r\n maxHeight / mockupImg.naturalHeight\r\n );\r\n const width = Math.max(1, Math.floor(mockupImg.naturalWidth * scale));\r\n const height = Math.max(1, Math.floor(mockupImg.naturalHeight * scale));\r\n const x = canvas.width - margin - width;\r\n const y = canvas.height - margin - height;\r\n\r\n ctx.drawImage(mockupImg, x, y, width, height);\r\n\r\n // Bỏ phần vẽ florals cạnh mockup vì đã hiển thị cạnh text rồi\r\n};\r\n\r\nconst renderSide = (\r\n ctx: CanvasRenderingContext2D,\r\n side: any,\r\n startY: number,\r\n width: number,\r\n scaleFactor: number,\r\n imageRefs: ImageMapRef\r\n): number => {\r\n let currentY = startY;\r\n const padding = LAYOUT.PADDING * scaleFactor;\r\n const sideWidth = width - 2 * padding;\r\n\r\n // Draw header\r\n ctx.save();\r\n const headerFontSize = LAYOUT.HEADER_FONT_SIZE * scaleFactor;\r\n ctx.font = `bold ${headerFontSize}px ${LAYOUT.HEADER_FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.HEADER_COLOR;\r\n\r\n const headerResult = wrapText(\r\n ctx,\r\n side.print_side.toUpperCase(),\r\n padding,\r\n currentY,\r\n sideWidth,\r\n headerFontSize\r\n );\r\n\r\n // Draw underline\r\n const underlineY =\r\n headerResult.lastLineY + headerFontSize * LAYOUT.UNDERLINE_POSITION;\r\n ctx.strokeStyle = LAYOUT.HEADER_COLOR;\r\n ctx.lineWidth = LAYOUT.UNDERLINE_WIDTH * scaleFactor;\r\n ctx.beginPath();\r\n ctx.moveTo(padding, underlineY);\r\n ctx.lineTo(padding + headerResult.lastLineWidth, underlineY);\r\n ctx.stroke();\r\n\r\n currentY += headerResult.height + LAYOUT.SECTION_SPACING * scaleFactor;\r\n ctx.restore();\r\n\r\n // Kiểm tra xem có phải trường hợp \"không thêu gì\" không\r\n const textPositions = side.positions.filter(\r\n (p: Position) => p.type === \"TEXT\"\r\n );\r\n const iconPositions = side.positions.filter(\r\n (p: Position) => p.type === \"ICON\"\r\n );\r\n \r\n // Kiểm tra tất cả TEXT positions có trống không\r\n // Nếu không có TEXT positions, coi như \"tất cả TEXT trống\" = true\r\n const allTextEmpty = textPositions.length === 0 || textPositions.every((p: Position & { type: \"TEXT\" }) => {\r\n const text = p.text ?? \"\";\r\n return text.trim() === \"\";\r\n });\r\n \r\n // Kiểm tra tất cả ICON positions có is_delete_icon = true không\r\n // Nếu không có ICON positions, coi như \"tất cả ICON bị xóa\" = true\r\n const allIconsDeleted = iconPositions.length === 0 || iconPositions.every((p: Position & { type: \"ICON\" }) => {\r\n return p.is_delete_icon === true;\r\n });\r\n \r\n // Nếu tất cả TEXT trống và tất cả ICON bị xóa, chỉ render dòng \"(không thêu gì)\"\r\n if (allTextEmpty && allIconsDeleted && side.positions.length > 0) {\r\n ctx.save();\r\n const otherFontSize = LAYOUT.OTHER_FONT_SIZE * scaleFactor;\r\n const lineGap = LAYOUT.LINE_GAP * scaleFactor;\r\n ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = DEFAULT_ERROR_COLOR;\r\n ctx.fillText(\"(không thêu gì)\", padding, currentY);\r\n currentY += otherFontSize + lineGap;\r\n ctx.restore();\r\n return currentY - startY;\r\n }\r\n\r\n // Compute uniform properties\r\n const iconColorPositions = side.positions.filter(\r\n (p: Position): p is Position & { type: \"ICON\" } =>\r\n p.type === \"ICON\" && (!p.layer_colors?.length || p.layer_colors.length === 1)\r\n );\r\n const iconColorValues = iconColorPositions\r\n .map((p: Position & { type: \"ICON\" }) => {\r\n if (p.layer_colors?.length === 1) return p.layer_colors[0];\r\n return p.color ?? null;\r\n })\r\n .filter((color: string | null): color is string => Boolean(color));\r\n const uniformProps = computeUniformProperties(textPositions, {\r\n additionalColorValues: iconColorValues,\r\n });\r\n const hasMultipleTextPositions = textPositions.length > 1;\r\n const hasSharedIconColor = iconColorValues.length > 0;\r\n const shouldRenderSharedColorLabel =\r\n !hasMultipleTextPositions &&\r\n hasSharedIconColor &&\r\n uniformProps.isUniform.color &&\r\n Boolean(uniformProps.values.color);\r\n const shouldShowUniformLabels =\r\n hasMultipleTextPositions || shouldRenderSharedColorLabel;\r\n const uniformLabelFields = hasMultipleTextPositions\r\n ? undefined\r\n : { color: true as const };\r\n\r\n // Render uniform labels (when applicable)\r\n if (shouldShowUniformLabels) {\r\n currentY += renderUniformLabels(\r\n ctx,\r\n uniformProps,\r\n padding,\r\n currentY,\r\n sideWidth,\r\n scaleFactor,\r\n imageRefs,\r\n textPositions,\r\n uniformLabelFields\r\n );\r\n }\r\n\r\n // Group text positions by common properties\r\n const textGroups = groupTextPositions(textPositions);\r\n\r\n // Render text positions (with proper spacing between groups)\r\n let textCounter = 1;\r\n textGroups.forEach((group, groupIndex) => {\r\n group.forEach((position, index) => {\r\n // Add extra spacing between different groups\r\n if (index === 0 && groupIndex !== 0) {\r\n currentY += LAYOUT.SECTION_SPACING * scaleFactor;\r\n }\r\n\r\n // If only 1 TEXT position, show all labels (no uniform labels rendered)\r\n const showLabels =\r\n textPositions.length === 1\r\n ? {\r\n font: true,\r\n shape: true,\r\n floral: true,\r\n color: !shouldRenderSharedColorLabel,\r\n }\r\n : {\r\n font: !uniformProps.isUniform.font,\r\n shape: !uniformProps.isUniform.shape,\r\n floral: !uniformProps.isUniform.floral,\r\n color: !uniformProps.isUniform.color,\r\n };\r\n const height = renderTextPosition(\r\n ctx,\r\n position as any,\r\n padding,\r\n currentY,\r\n sideWidth,\r\n textCounter,\r\n showLabels,\r\n scaleFactor,\r\n imageRefs\r\n );\r\n if (height > 0) {\r\n currentY += height + LAYOUT.PADDING * scaleFactor;\r\n textCounter++;\r\n }\r\n });\r\n });\r\n\r\n // Render icon positions\r\n currentY += LAYOUT.LINE_GAP * scaleFactor;\r\n side.positions.forEach((position: Position) => {\r\n if (position.type === \"ICON\") {\r\n const layerCount = position.layer_colors?.length ?? 0;\r\n const iconUsesSingleColor =\r\n layerCount === 0 || layerCount === 1;\r\n const iconColorValue =\r\n layerCount === 1\r\n ? position.layer_colors?.[0] ?? null\r\n : position.color ?? null;\r\n const hideColor =\r\n shouldShowUniformLabels &&\r\n uniformProps.isUniform.color &&\r\n iconColorValue !== null &&\r\n uniformProps.values.color === iconColorValue &&\r\n iconUsesSingleColor;\r\n currentY += renderIconPosition(\r\n ctx,\r\n position as any,\r\n padding,\r\n currentY,\r\n sideWidth,\r\n scaleFactor,\r\n imageRefs,\r\n { hideColor }\r\n );\r\n currentY += (LAYOUT.LINE_GAP / 3) * scaleFactor;\r\n }\r\n });\r\n\r\n return currentY - startY;\r\n};\r\n\r\nconst groupTextPositions = (\r\n textPositions: Array<Position & { type: \"TEXT\" }>\r\n): Array<Array<Position & { type: \"TEXT\" }>> => {\r\n const groups: Array<Array<Position & { type: \"TEXT\" }>> = [];\r\n let currentGroup: Array<Position & { type: \"TEXT\" }> | null = null;\r\n let currentProps: any = null;\r\n\r\n textPositions.forEach((position) => {\r\n const posProps = {\r\n font: position.font,\r\n text_shape: position.text_shape,\r\n color: position.color,\r\n character_colors: position.character_colors?.join(\",\"),\r\n };\r\n\r\n if (\r\n !currentGroup ||\r\n currentProps.font !== posProps.font ||\r\n currentProps.text_shape !== posProps.text_shape ||\r\n currentProps.color !== posProps.color ||\r\n currentProps.character_colors !== posProps.character_colors\r\n ) {\r\n if (currentGroup) {\r\n groups.push(currentGroup);\r\n }\r\n currentGroup = [position];\r\n currentProps = posProps;\r\n } else {\r\n currentGroup.push(position);\r\n }\r\n });\r\n\r\n if (currentGroup) {\r\n groups.push(currentGroup);\r\n }\r\n\r\n return groups;\r\n};\r\n\r\nconst computeUniformProperties = (\r\n textPositions: Array<Position & { type: \"TEXT\" }>,\r\n options?: { additionalColorValues?: string[] }\r\n) => {\r\n const defaults = {\r\n values: { font: null, shape: null, floral: null, color: null },\r\n isUniform: { font: false, shape: false, floral: false, color: false },\r\n };\r\n\r\n const fonts = new Set(textPositions.map((p) => p.font));\r\n const shapes = new Set(textPositions.map((p) => p.text_shape));\r\n const florals = new Set(textPositions.map((p) => p.floral_pattern ?? \"None\"));\r\n const colorSources = [\r\n ...textPositions.map((p) =>\r\n p.character_colors?.length\r\n ? p.character_colors.join(\",\")\r\n : p.color ?? \"None\"\r\n ),\r\n ...(options?.additionalColorValues?.map((color) => color ?? \"None\") ?? []),\r\n ];\r\n\r\n if (\r\n textPositions.length === 0 &&\r\n (!options?.additionalColorValues || options.additionalColorValues.length === 0)\r\n ) {\r\n return defaults;\r\n }\r\n\r\n const colors = new Set(colorSources);\r\n\r\n return {\r\n values: {\r\n font: fonts.size === 1 ? [...fonts][0] : null,\r\n shape: shapes.size === 1 ? [...shapes][0] : null,\r\n floral: florals.size === 1 ? [...florals][0] : null,\r\n color: colorSources.length > 0 && colors.size === 1 ? [...colors][0] : null,\r\n },\r\n isUniform: {\r\n font: fonts.size === 1,\r\n shape: shapes.size === 1,\r\n floral: florals.size === 1,\r\n color: colorSources.length > 0 && colors.size === 1,\r\n },\r\n };\r\n};\r\n\r\nconst renderUniformLabels = (\r\n ctx: CanvasRenderingContext2D,\r\n uniformProps: ReturnType<typeof computeUniformProperties>,\r\n x: number,\r\n y: number,\r\n maxWidth: number,\r\n scaleFactor: number,\r\n imageRefs: ImageMapRef,\r\n textPositions: Array<Position & { type: \"TEXT\" }>,\r\n fields?: { font?: boolean; shape?: boolean; floral?: boolean; color?: boolean }\r\n): number => {\r\n const { values } = uniformProps;\r\n const fontSize = LAYOUT.OTHER_FONT_SIZE * scaleFactor;\r\n const lineGap = LAYOUT.LINE_GAP * scaleFactor;\r\n\r\n const shouldRenderField = (field: keyof NonNullable<typeof fields>) => {\r\n if (!fields) return true;\r\n return fields[field] === true;\r\n };\r\n\r\n ctx.save();\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n\r\n let cursorY = y;\r\n let rendered = 0;\r\n\r\n if (values.font && shouldRenderField(\"font\")) {\r\n const allDefault = textPositions.every((p) => p.is_font_default === true);\r\n // Render \"Font: \" với font mặc định\r\n const prefix = \"Font: \";\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const prefixWidth = ctx.measureText(prefix).width;\r\n let currentX = x + prefixWidth;\r\n ctx.fillText(prefix, x, cursorY);\r\n \r\n // Render tên font với font từ config\r\n ctx.font = `${fontSize}px ${values.font}`;\r\n const fontNameWidth = ctx.measureText(values.font).width;\r\n ctx.fillText(values.font, currentX, cursorY);\r\n currentX += fontNameWidth;\r\n \r\n // Render \"(Mặc định)\" hoặc \"(Custom)\" với font mặc định\r\n const suffix = allDefault ? \" (Mặc định)\" : \" (Custom)\";\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const suffixWidth = ctx.measureText(suffix).width;\r\n ctx.fillText(suffix, currentX, cursorY);\r\n \r\n // Tính toán height và di chuyển cursorY\r\n const lineHeight = fontSize + lineGap;\r\n cursorY += lineHeight;\r\n rendered++;\r\n }\r\n\r\n if (values.shape && values.shape !== \"None\" && shouldRenderField(\"shape\")) {\r\n const result = wrapText(\r\n ctx,\r\n `Kiểu chữ: ${values.shape}`,\r\n x,\r\n cursorY,\r\n maxWidth,\r\n fontSize + lineGap\r\n );\r\n cursorY += result.height;\r\n rendered++;\r\n }\r\n\r\n if (values.color && values.color !== \"None\" && shouldRenderField(\"color\")) {\r\n const colors = values.color.includes(\",\")\r\n ? values.color.split(\",\").map((s) => s.trim())\r\n : [values.color];\r\n \r\n const swatchH = Math.floor(fontSize * LAYOUT.SWATCH_HEIGHT_RATIO);\r\n const totalSwatchWidth = calculateSwatchesWidth(colors, swatchH, scaleFactor, imageRefs);\r\n \r\n // Vẽ text với maxWidth bình thường (không trừ SWATCH_RESERVED_SPACE)\r\n const result = wrapText(\r\n ctx,\r\n `Màu chỉ: ${values.color}`,\r\n x,\r\n cursorY,\r\n maxWidth,\r\n fontSize + lineGap\r\n );\r\n\r\n // Kiểm tra xem có đủ chỗ cho swatches trên cùng dòng không\r\n const textEndX = x + Math.ceil(result.lastLineWidth);\r\n const spacing = LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n const swatchesStartX = textEndX + spacing;\r\n const swatchesEndX = swatchesStartX + totalSwatchWidth;\r\n const shouldWrapSwatches = swatchesEndX > x + maxWidth;\r\n\r\n let swatchX: number;\r\n let swatchY: number;\r\n \r\n if (shouldWrapSwatches) {\r\n // Không đủ chỗ, cho TẤT CẢ swatches xuống dòng mới\r\n swatchX = x;\r\n swatchY = result.lastLineY + fontSize + lineGap;\r\n cursorY += result.height + fontSize + lineGap;\r\n } else {\r\n // Đủ chỗ, vẽ swatches ngay sau text trên cùng dòng\r\n swatchX = swatchesStartX;\r\n swatchY = result.lastLineY + Math.floor(fontSize / 2 - swatchH / 2);\r\n cursorY += result.height;\r\n }\r\n\r\n drawSwatches(\r\n ctx,\r\n colors,\r\n swatchX,\r\n swatchY,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\r\n \r\n if (shouldWrapSwatches) {\r\n cursorY += swatchH;\r\n }\r\n \r\n rendered++;\r\n }\r\n\r\n if (values.floral && values.floral !== \"None\" && shouldRenderField(\"floral\")) {\r\n const floralUrl = getImageUrl(\"floral\", values.floral);\r\n const floralImg = imageRefs.current.get(floralUrl);\r\n \r\n // Tính kích thước ảnh floral (thêm 50% = 2.5x fontSize)\r\n const floralH = fontSize * 2.5;\r\n let totalFloralWidth = 0;\r\n if (floralImg?.complete && floralImg.naturalHeight > 0) {\r\n const ratio = floralImg.naturalWidth / floralImg.naturalHeight;\r\n totalFloralWidth = Math.max(1, Math.floor(floralH * ratio));\r\n }\r\n \r\n // Line height giống icon_image: floralH + lineGap\r\n const floralLineHeight = floralH + lineGap;\r\n \r\n // Text align bottom: đặt text ở dưới cùng của dòng\r\n const textBottomY = cursorY + floralH;\r\n \r\n // Đo width trước khi vẽ\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const labelText = `Mẫu hoa: ${values.floral}`;\r\n const labelWidth = ctx.measureText(labelText).width;\r\n \r\n // Vẽ text với textBaseline = bottom\r\n ctx.textBaseline = \"bottom\";\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n ctx.fillText(labelText, x, textBottomY);\r\n \r\n // Reset textBaseline về top cho các phần tiếp theo\r\n ctx.textBaseline = LAYOUT.TEXT_BASELINE;\r\n\r\n // Kiểm tra xem có đủ chỗ cho ảnh floral trên cùng dòng không\r\n const textEndX = x + labelWidth;\r\n const spacing = LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n const floralStartX = textEndX + spacing;\r\n const floralEndX = floralStartX + totalFloralWidth;\r\n const shouldWrapFloral = floralEndX > x + maxWidth;\r\n\r\n let floralX: number;\r\n let floralY: number;\r\n \r\n if (shouldWrapFloral) {\r\n // Không đủ chỗ, cho ảnh floral xuống dòng mới\r\n floralX = x;\r\n floralY = textBottomY + lineGap;\r\n cursorY += floralLineHeight;\r\n } else {\r\n // Đủ chỗ, vẽ ảnh floral ngay sau text trên cùng dòng\r\n floralX = floralStartX;\r\n floralY = textBottomY - floralH; // Align bottom với text\r\n cursorY += floralLineHeight;\r\n }\r\n\r\n // Vẽ ảnh floral\r\n if (floralImg?.complete && floralImg.naturalHeight > 0) {\r\n ctx.drawImage(floralImg, floralX, floralY, totalFloralWidth, floralH);\r\n }\r\n \r\n rendered++;\r\n }\r\n\r\n if (rendered > 0) cursorY += LAYOUT.SECTION_SPACING * scaleFactor;\r\n\r\n ctx.restore();\r\n return cursorY - y;\r\n};\r\n\r\nconst renderTextPosition = (\r\n ctx: CanvasRenderingContext2D,\r\n position: Position & { type: \"TEXT\" },\r\n x: number,\r\n y: number,\r\n maxWidth: number, // tổng chiều rộng usable (không tính padding ngoài)\r\n displayIndex: number,\r\n showLabels: {\r\n font: boolean;\r\n shape: boolean;\r\n floral: boolean;\r\n color: boolean;\r\n },\r\n scaleFactor: number,\r\n imageRefs: ImageMapRef\r\n): number => {\r\n ctx.save();\r\n\r\n const textFontSize = LAYOUT.TEXT_FONT_SIZE * scaleFactor;\r\n const otherFontSize = LAYOUT.OTHER_FONT_SIZE * scaleFactor;\r\n const lineGap = LAYOUT.LINE_GAP * scaleFactor;\r\n\r\n let currentY = y;\r\n let drawnHeight = 0;\r\n\r\n // Chuẩn hóa xuống dòng:\r\n // - Hỗ trợ cả newline thật (\\n) và chuỗi literal \"\\\\n\" từ JSON\r\n const normalizeNewlines = (text: string) =>\r\n text\r\n .replace(/\\r\\n/g, \"\\n\")\r\n .replace(/\\r/g, \"\\n\")\r\n .replace(/\\\\n/g, \"\\n\");\r\n\r\n // Get display text (handle empty/null/undefined) sau khi normalize\r\n const rawOriginalText = position.text ?? \"\";\r\n const normalizedText = normalizeNewlines(rawOriginalText);\r\n const isEmptyText = normalizedText.trim() === \"\";\r\n\r\n // ===========================================================================\r\n // PHẦN TEXT CHÍNH\r\n // - Giữ nguyên format: chỉ xuống dòng khi có '\\n'\r\n // - Không tự wrap theo maxWidth\r\n // - Nếu tổng chiều ngang > maxWidth, tự động giảm font-size để vừa\r\n // ===========================================================================\r\n\r\n // Label \"Text N: \" luôn là font mặc định (không bị co theo nội dung)\r\n const textLabel = `Text ${displayIndex}: `;\r\n ctx.font = `bold ${textFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n const labelWidth = ctx.measureText(textLabel).width;\r\n ctx.fillText(textLabel, x, currentY);\r\n\r\n // Phần text value bắt đầu sau label\r\n const valueStartX = x + labelWidth;\r\n const availableWidth = Math.max(1, maxWidth - labelWidth);\r\n\r\n // Chuẩn hóa nội dung text để render\r\n const rawText = isEmptyText ? \"(không có text)\" : normalizedText;\r\n const lines = rawText.split(\"\\n\");\r\n\r\n // Tính font-size hiệu dụng cho phần value sao cho:\r\n // - Không vượt quá availableWidth\r\n // - Có thể thu nhỏ tùy ý (theo yêu cầu, không giới hạn tối thiểu)\r\n const measureMaxLineWidth = (fontSize: number) => {\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n let maxLineWidth = 0;\r\n lines.forEach((line) => {\r\n const w = ctx.measureText(line).width;\r\n if (w > maxLineWidth) maxLineWidth = w;\r\n });\r\n return maxLineWidth;\r\n };\r\n\r\n let effectiveTextFontSize = textFontSize;\r\n if (!isEmptyText) {\r\n const baseMaxWidth = measureMaxLineWidth(textFontSize);\r\n if (baseMaxWidth > availableWidth) {\r\n const shrinkRatio = availableWidth / baseMaxWidth;\r\n effectiveTextFontSize = textFontSize * shrinkRatio;\r\n }\r\n }\r\n\r\n // Vẽ phần value với font hiệu dụng, màu đỏ\r\n ctx.font = `${effectiveTextFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = DEFAULT_ERROR_COLOR;\r\n\r\n const valueLineHeight = effectiveTextFontSize; // giữ giống wrapText cũ (lineHeight = fontSize)\r\n let localY = currentY;\r\n\r\n lines.forEach((line, idx) => {\r\n ctx.fillText(line, valueStartX, localY);\r\n localY += valueLineHeight;\r\n });\r\n\r\n const textBlockHeight = lines.length * valueLineHeight;\r\n currentY += textBlockHeight;\r\n drawnHeight += textBlockHeight;\r\n\r\n // Draw additional labels (skip when text is empty)\r\n if (!isEmptyText) {\r\n currentY += lineGap;\r\n ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n\r\n // Lưu ý: phần dưới này vẫn có thể wrap theo maxWidth vì đây chỉ là label mô tả,\r\n // không phải nội dung Text chính cần giữ nguyên format.\r\n\r\n if (showLabels.shape && position.text_shape) {\r\n const result = wrapText(\r\n ctx,\r\n `Kiểu chữ: ${position.text_shape}`,\r\n x,\r\n currentY,\r\n maxWidth,\r\n otherFontSize + lineGap\r\n );\r\n currentY += result.height;\r\n drawnHeight += result.height;\r\n }\r\n\r\n if (showLabels.font && position.font) {\r\n // Render \"Font: \" với font mặc định\r\n const prefix = \"Font: \";\r\n ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const prefixWidth = ctx.measureText(prefix).width;\r\n let currentX = x + prefixWidth;\r\n ctx.fillText(prefix, x, currentY);\r\n \r\n // Render tên font với font từ config\r\n ctx.font = `${otherFontSize}px ${position.font}`;\r\n const fontNameWidth = ctx.measureText(position.font).width;\r\n ctx.fillText(position.font, currentX, currentY);\r\n currentX += fontNameWidth;\r\n \r\n // Render \"(Mặc định)\" hoặc \"(Custom)\" với font mặc định\r\n const suffix = position.is_font_default === true ? \" (Mặc định)\" : \" (Custom)\";\r\n ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const suffixWidth = ctx.measureText(suffix).width;\r\n ctx.fillText(suffix, currentX, currentY);\r\n \r\n // Tính toán height và di chuyển cursorY\r\n const lineHeight = otherFontSize + lineGap;\r\n currentY += lineHeight;\r\n drawnHeight += lineHeight;\r\n }\r\n\r\n if (showLabels.color) {\r\n const colorValue = position.character_colors?.join(\", \") || position.color;\r\n if (colorValue) {\r\n const colors = position.character_colors || [position.color!];\r\n const swatchH = Math.floor(otherFontSize * LAYOUT.SWATCH_HEIGHT_RATIO);\r\n const totalSwatchWidth = calculateSwatchesWidth(colors, swatchH, scaleFactor, imageRefs);\r\n \r\n // Vẽ text với maxWidth bình thường (không trừ SWATCH_RESERVED_SPACE)\r\n const result = wrapText(\r\n ctx,\r\n `Màu chỉ: ${colorValue}`,\r\n x,\r\n currentY,\r\n maxWidth,\r\n otherFontSize + lineGap\r\n );\r\n\r\n // Kiểm tra xem có đủ chỗ cho swatches trên cùng dòng không\r\n const textEndX = x + Math.ceil(result.lastLineWidth);\r\n const spacing = LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n const swatchesStartX = textEndX + spacing;\r\n const swatchesEndX = swatchesStartX + totalSwatchWidth;\r\n const shouldWrapSwatches = swatchesEndX > x + maxWidth;\r\n\r\n let swatchX: number;\r\n let swatchY: number;\r\n \r\n if (shouldWrapSwatches) {\r\n // Không đủ chỗ, cho TẤT CẢ swatches xuống dòng mới\r\n swatchX = x;\r\n swatchY = result.lastLineY + otherFontSize + lineGap;\r\n currentY += result.height + otherFontSize + lineGap;\r\n drawnHeight += result.height + otherFontSize + lineGap;\r\n } else {\r\n // Đủ chỗ, vẽ swatches ngay sau text trên cùng dòng\r\n swatchX = swatchesStartX;\r\n swatchY = result.lastLineY + Math.floor(otherFontSize / 2 - swatchH / 2);\r\n currentY += result.height;\r\n drawnHeight += result.height;\r\n }\r\n\r\n drawSwatches(\r\n ctx,\r\n colors,\r\n swatchX,\r\n swatchY,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\r\n \r\n if (shouldWrapSwatches) {\r\n currentY += swatchH;\r\n drawnHeight += swatchH;\r\n }\r\n }\r\n }\r\n\r\n if (showLabels.floral && position.floral_pattern) {\r\n const floralUrl = getImageUrl(\"floral\", position.floral_pattern);\r\n const floralImg = imageRefs.current.get(floralUrl);\r\n \r\n // Tính kích thước ảnh floral (thêm 50% = 2.5x otherFontSize)\r\n const floralH = otherFontSize * 2.5;\r\n let totalFloralWidth = 0;\r\n if (floralImg?.complete && floralImg.naturalHeight > 0) {\r\n const ratio = floralImg.naturalWidth / floralImg.naturalHeight;\r\n totalFloralWidth = Math.max(1, Math.floor(floralH * ratio));\r\n }\r\n \r\n // Line height giống icon_image: floralH + lineGap\r\n const floralLineHeight = floralH + lineGap;\r\n \r\n // Text align bottom: đặt text ở dưới cùng của dòng\r\n const textBottomY = currentY + floralH;\r\n \r\n // Đo width trước khi vẽ\r\n ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const labelText = `Mẫu hoa: ${position.floral_pattern}`;\r\n const labelWidth = ctx.measureText(labelText).width;\r\n \r\n // Vẽ text với textBaseline = bottom\r\n ctx.textBaseline = \"bottom\";\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n ctx.fillText(labelText, x, textBottomY);\r\n \r\n // Reset textBaseline về top cho các phần tiếp theo\r\n ctx.textBaseline = LAYOUT.TEXT_BASELINE;\r\n\r\n // Kiểm tra xem có đủ chỗ cho ảnh floral trên cùng dòng không\r\n const textEndX = x + labelWidth;\r\n const spacing = LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n const floralStartX = textEndX + spacing;\r\n const floralEndX = floralStartX + totalFloralWidth;\r\n const shouldWrapFloral = floralEndX > x + maxWidth;\r\n\r\n let floralX: number;\r\n let floralY: number;\r\n \r\n if (shouldWrapFloral) {\r\n // Không đủ chỗ, cho ảnh floral xuống dòng mới\r\n floralX = x;\r\n floralY = textBottomY + lineGap;\r\n currentY += floralLineHeight;\r\n drawnHeight += floralLineHeight;\r\n } else {\r\n // Đủ chỗ, vẽ ảnh floral ngay sau text trên cùng dòng\r\n floralX = floralStartX;\r\n floralY = textBottomY - floralH; // Align bottom với text\r\n currentY += floralLineHeight;\r\n drawnHeight += floralLineHeight;\r\n }\r\n\r\n // Vẽ ảnh floral\r\n if (floralImg?.complete && floralImg.naturalHeight > 0) {\r\n ctx.drawImage(floralImg, floralX, floralY, totalFloralWidth, floralH);\r\n }\r\n }\r\n }\r\n\r\n ctx.restore();\r\n return drawnHeight;\r\n};\r\n\r\nconst renderIconPosition = (\r\n ctx: CanvasRenderingContext2D,\r\n position: Position & { type: \"ICON\" },\r\n x: number,\r\n y: number,\r\n maxWidth: number,\r\n scaleFactor: number,\r\n imageRefs: ImageMapRef,\r\n options?: { hideColor?: boolean }\r\n): number => {\r\n // Dùng cùng font size với Text cho label và value icon\r\n const iconFontSize = LAYOUT.TEXT_FONT_SIZE * scaleFactor;\r\n const lineGap = LAYOUT.LINE_GAP * scaleFactor;\r\n\r\n ctx.save();\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n\r\n let cursorY = y;\r\n\r\n // Tách label \"Icon:\" (in đậm) và phần value (thường)\r\n const iconLabel = \"Icon:\";\r\n let iconValue: string;\r\n if (position.is_delete_icon) {\r\n // Ưu tiên hiển thị không có icon nếu được đánh dấu xóa\r\n iconValue = \"(không có icon)\";\r\n } else if (position.note) {\r\n iconValue = position.note;\r\n } else if (position.icon_name && position.icon_name.trim().length > 0) {\r\n // Nếu có icon_name thì hiển thị tên đó\r\n iconValue = position.icon_name;\r\n } else if (position.icon === 0) {\r\n // Icon mặc định theo file thêu\r\n iconValue = \"(icon mặc định theo file thêu)\";\r\n } else {\r\n // Fallback: hiển thị mã icon (ép sang string)\r\n iconValue = String(position.icon);\r\n }\r\n\r\n // Kiểm tra xem có icon_image không để tính height phù hợp\r\n const hasIconImage = position.icon_image && position.icon_image.trim().length > 0;\r\n const iconImageHeight = hasIconImage ? iconFontSize * 2 : iconFontSize;\r\n \r\n // Text align bottom: đặt text ở dưới cùng của dòng\r\n const textBottomY = cursorY + iconImageHeight;\r\n \r\n // Đo width trước khi vẽ\r\n ctx.font = `bold ${iconFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const labelWidth = ctx.measureText(iconLabel).width;\r\n \r\n ctx.font = `${iconFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const valueText = ` ${iconValue}`;\r\n const valueWidth = ctx.measureText(valueText).width;\r\n \r\n // Vẽ text với textBaseline = bottom\r\n ctx.textBaseline = \"bottom\";\r\n ctx.font = `bold ${iconFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n ctx.fillText(iconLabel, x, textBottomY);\r\n \r\n ctx.font = `${iconFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = DEFAULT_ERROR_COLOR;\r\n ctx.fillText(valueText, x + labelWidth, textBottomY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n \r\n // Reset textBaseline về top cho các phần tiếp theo\r\n ctx.textBaseline = LAYOUT.TEXT_BASELINE;\r\n \r\n const iconResult = {\r\n height: iconImageHeight + lineGap,\r\n // tổng width của cả label + value, dùng để canh icon image lệch sang phải\r\n lastLineWidth: labelWidth + valueWidth,\r\n lastLineY: textBottomY,\r\n };\r\n\r\n // Draw icon image\r\n const iconUrl = getIconImageUrl(position);\r\n\r\n if (iconUrl) {\r\n const img = imageRefs.current.get(iconUrl);\r\n if (img?.complete && img.naturalHeight > 0) {\r\n const ratio = img.naturalWidth / img.naturalHeight;\r\n // Nếu có icon_image thì hiển thị to gấp đôi\r\n const iconHeight = hasIconImage ? iconFontSize * 2 : iconFontSize;\r\n const swatchW = Math.max(1, Math.floor(iconHeight * ratio));\r\n const iconX =\r\n x +\r\n Math.ceil(iconResult.lastLineWidth) +\r\n LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n const iconY =\r\n textBottomY - iconHeight; // Align bottom với text\r\n ctx.drawImage(img, iconX, iconY, swatchW, iconHeight);\r\n }\r\n }\r\n\r\n cursorY += iconResult.height;\r\n\r\n // Draw color swatches (prefer layer_colors, fallback to single color)\r\n // Nếu icon đã bị xóa thì không cần hiển thị màu chỉ nữa\r\n const iconColors = position.is_delete_icon\r\n ? null\r\n : position.layer_colors?.length\r\n ? position.layer_colors\r\n : position.color\r\n ? [position.color]\r\n : null;\r\n const layerCount = position.layer_colors?.length ?? 0;\r\n const hasMultiLayerColors = layerCount > 1;\r\n const shouldSkipColorSection = options?.hideColor && !hasMultiLayerColors;\r\n\r\n if (iconColors?.length && !shouldSkipColorSection) {\r\n // Dòng \"Màu chỉ:\" của icon dùng OTHER_FONT_SIZE, không dùng iconFontSize\r\n const otherFontSize = LAYOUT.OTHER_FONT_SIZE * scaleFactor;\r\n const swatchH = Math.floor(otherFontSize * LAYOUT.SWATCH_HEIGHT_RATIO);\r\n const totalSwatchWidth = calculateSwatchesWidth(iconColors, swatchH, scaleFactor, imageRefs);\r\n \r\n // Set font về OTHER_FONT_SIZE trước khi vẽ text \"Màu chỉ:\"\r\n ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n \r\n // Vẽ text với maxWidth bình thường (không trừ SWATCH_RESERVED_SPACE)\r\n const colorResult = wrapText(\r\n ctx,\r\n `Màu chỉ: ${iconColors.join(\", \")}`,\r\n x,\r\n cursorY,\r\n maxWidth,\r\n otherFontSize + lineGap\r\n );\r\n\r\n // Kiểm tra xem có đủ chỗ cho swatches trên cùng dòng không\r\n const textEndX = x + Math.ceil(colorResult.lastLineWidth);\r\n const spacing = LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n const swatchesStartX = textEndX + spacing;\r\n const swatchesEndX = swatchesStartX + totalSwatchWidth;\r\n const shouldWrapSwatches = swatchesEndX > x + maxWidth;\r\n\r\n let swatchX: number;\r\n let swatchY: number;\r\n \r\n if (shouldWrapSwatches) {\r\n // Không đủ chỗ, cho TẤT CẢ swatches xuống dòng mới\r\n swatchX = x;\r\n swatchY = colorResult.lastLineY + otherFontSize + lineGap;\r\n cursorY += colorResult.height + otherFontSize + lineGap;\r\n } else {\r\n // Đủ chỗ, vẽ swatches ngay sau text trên cùng dòng\r\n swatchX = swatchesStartX;\r\n swatchY = colorResult.lastLineY + Math.floor(otherFontSize / 2 - swatchH / 2);\r\n cursorY += colorResult.height;\r\n }\r\n\r\n drawSwatches(ctx, iconColors, swatchX, swatchY, swatchH, scaleFactor, imageRefs);\r\n \r\n if (shouldWrapSwatches) {\r\n cursorY += swatchH;\r\n }\r\n }\r\n\r\n ctx.restore();\r\n return cursorY - y;\r\n};\r\n\r\nconst prepareExportCanvas = async (\r\n config: EmbroideryQCConfig,\r\n options: EmbroideryQCImageRenderOptions = {}\r\n): Promise<HTMLCanvasElement | null> => {\r\n const { width = 4200, height = 4800 } = options;\r\n\r\n const canvas = document.createElement(\"canvas\");\r\n const imageRefs: ImageMapRef = {\r\n current: new Map<string, HTMLImageElement>(),\r\n };\r\n\r\n // Load fonts and images in parallel\r\n await Promise.all([\r\n preloadFonts(config),\r\n preloadImages(config, imageRefs)\r\n ]);\r\n\r\n renderEmbroideryCanvas(canvas, config, { width, height }, imageRefs);\r\n\r\n if (!canvas.width || !canvas.height) {\r\n return null;\r\n }\r\n\r\n return canvas;\r\n};\r\n\r\nexport const generateEmbroideryQCImageBlob = async (\r\n config: EmbroideryQCConfig,\r\n options: EmbroideryQCImageRenderOptions = {}\r\n): Promise<Blob | null> => {\r\n if (typeof document === \"undefined\") {\r\n throw new Error(\r\n \"generateEmbroideryQCImageBlob requires a browser environment.\"\r\n );\r\n }\r\n\r\n if (!config) {\r\n throw new Error(\"config is required\");\r\n }\r\n\r\n const { mimeType = \"image/png\", quality } = options;\r\n\r\n const canvas = await prepareExportCanvas(config, options);\r\n if (!canvas || typeof canvas.toBlob !== \"function\") {\r\n return null;\r\n }\r\n\r\n const blob = await new Promise<Blob | null>((resolve) => {\r\n canvas.toBlob((result) => resolve(result), mimeType, quality);\r\n });\r\n\r\n return blob;\r\n};\r\n\r\nexport const generateEmbroideryQCImageData = async (\r\n config: EmbroideryQCConfig,\r\n options: EmbroideryQCImageRenderOptions = {}\r\n): Promise<string | null> => {\r\n if (typeof document === \"undefined\") {\r\n throw new Error(\r\n \"generateEmbroideryQCImageData requires a browser environment.\"\r\n );\r\n }\r\n\r\n if (!config) {\r\n throw new Error(\"config is required\");\r\n };\r\n\r\n const { mimeType = \"image/png\", quality } = options;\r\n\r\n const canvas = await prepareExportCanvas(config, options);\r\n if (!canvas) {\r\n return null;\r\n }\r\n\r\n if (mimeType === \"image/png\" || typeof quality === \"undefined\") {\r\n return canvas.toDataURL(mimeType);\r\n }\r\n\r\n return canvas.toDataURL(mimeType, quality);\r\n};\r\n\r\nexport default EmbroideryQCImage;\r\n"],"names":["_jsx"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"index.esm.js","sources":["../node_modules/style-inject/dist/style-inject.es.js","../src/components/EmbroideryQCImage.tsx"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n","import React, { useState, useEffect, useRef } from \"react\";\r\nimport { EmbroideryQCConfig, EmbroideryQCImageProps, Position } from \"../types\";\r\nimport \"./EmbroideryQCImage.css\";\r\n\r\n// ============================================================================\r\n// CONSTANTS\r\n// ============================================================================\r\n\r\nconst COLOR_MAP: Record<string, string> = {\r\n \"Army (1394)\": \"#545541\",\r\n Army: \"#545541\",\r\n \"Black (8)\": \"#060608\",\r\n Black: \"#060608\",\r\n \"Bubblegum (1309)\": \"#E77B9F\",\r\n Bubblegum: \"#E77B9F\",\r\n \"Carolina Blue (1274)\": \"#608CC9\",\r\n \"Carolina Blue\": \"#608CC9\",\r\n \"Celadon (1098)\": \"#8EAD8D\",\r\n Celadon: \"#8EAD8D\",\r\n \"Coffee Bean (1145)\": \"#502B23\",\r\n \"Coffee Bean\": \"#502B23\",\r\n \"Daffodil (1180)\": \"#FBE30D\",\r\n Daffodil: \"#FBE30D\",\r\n \"Dark Gray (1131)\": \"#2E272E\",\r\n \"Dark Gray\": \"#2E272E\",\r\n \"Doe Skin Beige (1344)\": \"#AE9B8B\",\r\n \"Doe Skin Beige\": \"#AE9B8B\",\r\n \"Dusty Blue (1373)\": \"#7B90A9\",\r\n \"Dusty Blue\": \"#7B90A9\",\r\n \"Forest Green (1397)\": \"#073020\",\r\n \"Forest Green\": \"#073020\",\r\n \"Gold (1425)\": \"#D2920A\",\r\n Gold: \"#D2920A\",\r\n \"Gray (1118)\": \"#9999A3\",\r\n Gray: \"#9999A3\",\r\n \"Ivory (1072)\": \"#E3DAC9\",\r\n Ivory: \"#E3DAC9\",\r\n \"Lavender (1032)\": \"#9274B6\",\r\n Lavender: \"#9274B6\",\r\n \"Light Denim (1133)\": \"#366696\",\r\n \"Light Denim\": \"#366696\",\r\n \"Light Salmon (1018)\": \"#E0A793\",\r\n \"Light Salmon\": \"#E0A793\",\r\n \"Maroon (1374)\": \"#480C1C\",\r\n Maroon: \"#480C1C\",\r\n \"Navy Blue (1044)\": \"#04072A\",\r\n \"Navy Blue\": \"#04072A\",\r\n \"Olive Green (1157)\": \"#625E1F\",\r\n \"Olive Green\": \"#625E1F\",\r\n \"Orange (1278)\": \"#D45D03\",\r\n Orange: \"#D45D03\",\r\n \"Peach Blush (1053)\": \"#E2C0B6\",\r\n \"Peach Blush\": \"#E2C0B6\",\r\n \"Pink (1148)\": \"#EFAFBF\",\r\n Pink: \"#EFAFBF\",\r\n \"Purple (1412)\": \"#37196F\",\r\n Purple: \"#37196F\",\r\n \"Red (1037)\": \"#9D000B\",\r\n Red: \"#9D000B\",\r\n \"Silver Sage (1396)\": \"#424F45\",\r\n \"Silver Sage\": \"#424F45\",\r\n \"Summer Sky (1432)\": \"#65A8D2\",\r\n \"Summer Sky\": \"#65A8D2\",\r\n \"Terra Cotta (1477)\": \"#AE3111\",\r\n \"Terra Cotta\": \"#AE3111\",\r\n \"Sand (1055)\": \"#D2C2AB\",\r\n Sand: \"#D2C2AB\",\r\n \"White (9)\": \"#D8D7DC\",\r\n White: \"#D8D7DC\",\r\n};\r\n\r\nconst DEFAULT_ERROR_COLOR = \"#CC1F1A\";\r\nconst DEFAULT_WARNING_COLOR = \"#FF8C00\";\r\n\r\nconst BASE_URLS = {\r\n FONT: \"https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/fonts\",\r\n ICON: \"https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/icons-resized\",\r\n FLORAL:\r\n \"https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/florals-resized\",\r\n THREAD_COLOR:\r\n \"https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/thread-colors-resized\",\r\n};\r\n\r\nconst LAYOUT = {\r\n // Font families\r\n HEADER_FONT_FAMILY: \"Times New Roman\",\r\n FONT_FAMILY: \"Arial\",\r\n\r\n // Font sizes (base values, will be multiplied by scaleFactor)\r\n HEADER_FONT_SIZE: 220,\r\n TEXT_FONT_SIZE: 200,\r\n OTHER_FONT_SIZE: 160,\r\n\r\n // Colors\r\n HEADER_COLOR: \"#000000\",\r\n LABEL_COLOR: \"#444444\",\r\n BACKGROUND_COLOR: \"#FFFFFF\",\r\n\r\n // Text alignment\r\n TEXT_ALIGN: \"left\" as CanvasTextAlign,\r\n TEXT_BASELINE: \"top\" as CanvasTextBaseline,\r\n\r\n // Spacing\r\n LINE_GAP: 50,\r\n PADDING: 50,\r\n SECTION_SPACING: 60,\r\n ELEMENT_SPACING: 100,\r\n SWATCH_SPACING: 25,\r\n FLORAL_SPACING: 100,\r\n\r\n // Visual styling\r\n SWATCH_HEIGHT_RATIO: 2.025,\r\n UNDERLINE_POSITION: 0.9,\r\n UNDERLINE_WIDTH: 10,\r\n\r\n // Swatch reserved space\r\n SWATCH_RESERVED_SPACE: 1000,\r\n MIN_TEXT_WIDTH: 400,\r\n};\r\n\r\n// ============================================================================\r\n// HELPER FUNCTIONS\r\n// ============================================================================\r\n\r\nconst loadFont = (fontName: string): Promise<void> => {\r\n // Check if font is already loaded in document.fonts (browser cache)\r\n const fontFaceSet = document.fonts;\r\n for (const font of fontFaceSet) {\r\n if (font.family === fontName && font.status === 'loaded') {\r\n return Promise.resolve();\r\n }\r\n }\r\n\r\n return new Promise((resolve) => {\r\n const fontUrl = `${BASE_URLS.FONT}/${encodeURIComponent(fontName)}.woff2`;\r\n const fontFace = new FontFace(fontName, `url(${fontUrl})`);\r\n\r\n fontFace\r\n .load()\r\n .then((loadedFont) => {\r\n document.fonts.add(loadedFont);\r\n resolve();\r\n })\r\n .catch(() => {\r\n console.warn(`Could not load font ${fontName} from CDN`);\r\n resolve();\r\n });\r\n });\r\n};\r\n\r\nconst getImageUrl = (\r\n type: \"icon\" | \"floral\" | \"threadColor\",\r\n value: string | number\r\n): string => {\r\n if (type === \"icon\") return `${BASE_URLS.ICON}/Icon ${value}.webp`;\r\n if (type === \"floral\") return `${BASE_URLS.FLORAL}/${value}.webp`;\r\n return `${BASE_URLS.THREAD_COLOR}/${value}.webp`;\r\n};\r\n\r\ntype ImageMapRef = {\r\n current: Map<string, HTMLImageElement>;\r\n};\r\n\r\nexport interface EmbroideryQCImageRenderOptions {\r\n width?: number;\r\n height?: number;\r\n mimeType?: \"image/png\" | \"image/jpeg\" | \"image/webp\";\r\n quality?: number;\r\n}\r\n\r\nconst getProxyUrl = (url: string): string =>\r\n `https://proxy-img.c8p.workers.dev?url=${encodeURIComponent(url)}`;\r\n\r\nconst getIconImageUrl = (position: Position & { type: \"ICON\" }): string | null => {\r\n if (position.is_delete_icon) return null;\r\n\r\n if (position.icon_image && position.icon_image.trim().length > 0) {\r\n return position.icon_image;\r\n }\r\n\r\n if (position.icon !== 0) {\r\n return getImageUrl(\"icon\", position.icon);\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst ensureImage = (existing?: HTMLImageElement | null): HTMLImageElement => {\r\n if (existing && existing.crossOrigin === \"anonymous\") {\r\n return existing;\r\n }\r\n\r\n const img = new Image();\r\n img.crossOrigin = \"anonymous\";\r\n img.decoding = \"async\";\r\n return img;\r\n};\r\n\r\nconst loadImage = (url: string, imageRefs: ImageMapRef, onLoad: () => void) => {\r\n const existing = imageRefs.current.get(url);\r\n if (\r\n existing?.complete &&\r\n existing.naturalWidth > 0 &&\r\n existing.crossOrigin === \"anonymous\"\r\n ) {\r\n return;\r\n }\r\n\r\n const img = ensureImage(existing);\r\n imageRefs.current.set(url, img);\r\n\r\n let attemptedProxy = existing?.dataset?.proxyUsed === \"true\";\r\n\r\n const cleanup = () => {\r\n img.onload = null;\r\n img.onerror = null;\r\n };\r\n\r\n img.onload = () => {\r\n img.dataset.proxyUsed = attemptedProxy ? \"true\" : \"false\";\r\n cleanup();\r\n onLoad();\r\n };\r\n\r\n img.onerror = () => {\r\n if (!attemptedProxy) {\r\n attemptedProxy = true;\r\n img.src = getProxyUrl(getResizeUrl(url));\r\n return;\r\n }\r\n img.dataset.proxyUsed = attemptedProxy ? \"true\" : \"false\";\r\n cleanup();\r\n onLoad();\r\n };\r\n\r\n img.src = attemptedProxy ? getProxyUrl(getResizeUrl(url)) : getResizeUrl(url);\r\n};\r\n\r\nconst loadImageAsync = (\r\n url: string,\r\n imageRefs: ImageMapRef,\r\n cacheKey?: string\r\n): Promise<HTMLImageElement> => {\r\n const key = cacheKey ?? url;\r\n const existing = imageRefs.current.get(key) ?? imageRefs.current.get(url);\r\n\r\n if (\r\n existing?.complete &&\r\n existing.naturalWidth > 0 &&\r\n existing.crossOrigin === \"anonymous\" &&\r\n existing.dataset?.proxyUsed !== undefined\r\n ) {\r\n if (existing !== imageRefs.current.get(key)) {\r\n imageRefs.current.set(key, existing);\r\n }\r\n if (existing !== imageRefs.current.get(url)) {\r\n imageRefs.current.set(url, existing);\r\n }\r\n return Promise.resolve(existing);\r\n }\r\n\r\n return new Promise((resolve) => {\r\n const target = ensureImage(existing);\r\n if (target !== existing) {\r\n imageRefs.current.set(key, target);\r\n imageRefs.current.set(url, target);\r\n }\r\n let attemptedProxy = target.dataset.proxyUsed === \"true\";\r\n\r\n const finalize = () => {\r\n target.onload = null;\r\n target.onerror = null;\r\n if (target.complete && target.naturalWidth > 0) {\r\n imageRefs.current.set(key, target);\r\n imageRefs.current.set(url, target);\r\n }\r\n target.dataset.proxyUsed = attemptedProxy ? \"true\" : \"false\";\r\n resolve(target);\r\n };\r\n\r\n target.onload = finalize;\r\n target.onerror = () => {\r\n if (!attemptedProxy) {\r\n attemptedProxy = true;\r\n target.src = getProxyUrl(getResizeUrl(url));\r\n return;\r\n }\r\n target.dataset.proxyUsed = attemptedProxy ? \"true\" : \"false\";\r\n finalize();\r\n };\r\n\r\n const desiredSrc = attemptedProxy ? getProxyUrl(getResizeUrl(url)) : getResizeUrl(url);\r\n\r\n if (target.src !== desiredSrc) {\r\n target.src = desiredSrc;\r\n } else if (target.complete && target.naturalWidth > 0) {\r\n finalize();\r\n }\r\n });\r\n};\r\n\r\nconst getResizeUrl = (url: string): string => {\r\n try {\r\n const urlObj = new URL(url);\r\n \r\n // Xử lý cdn.shopify.com\r\n if (urlObj.hostname === 'cdn.shopify.com') {\r\n // Set hoặc update query param width=400\r\n urlObj.searchParams.set('width', '400');\r\n return urlObj.toString();\r\n }\r\n \r\n // Xử lý m.media-amazon.com\r\n if (urlObj.hostname === 'm.media-amazon.com') {\r\n const pathname = urlObj.pathname;\r\n // Split pathname theo dấu /\r\n const pathArr = pathname.split('/');\r\n // Lấy filename (phần cuối cùng)\r\n const filename = pathArr[pathArr.length - 1];\r\n // Xóa pattern ._.*_ (ví dụ: ._AC_SX569_)\r\n const cleanedFilename = filename.replace(/\\._.*_/g, '');\r\n // Split filename đã clean theo dấu .\r\n const parts = cleanedFilename.split('.');\r\n \r\n if (parts.length >= 2) {\r\n // Lấy phần đầu và phần cuối\r\n const firstPart = parts[0];\r\n const lastPart = parts[parts.length - 1];\r\n // Chèn _AC_SX400_ vào giữa và join lại\r\n const newFilename = `${firstPart}._AC_SX400_.${lastPart}`;\r\n // Thay filename mới vào pathArr\r\n pathArr[pathArr.length - 1] = newFilename;\r\n // Join lại\r\n urlObj.pathname = pathArr.join('/');\r\n return urlObj.toString();\r\n }\r\n }\r\n \r\n // Xử lý i.etsystatic.com\r\n if (urlObj.hostname === 'i.etsystatic.com') {\r\n const pathname = urlObj.pathname;\r\n // Thay il_fullxfull bằng il_400x400\r\n if (pathname.includes('il_fullxfull')) {\r\n const newPathname = pathname.replace(/il_fullxfull/g, 'il_400x400');\r\n urlObj.pathname = newPathname;\r\n return urlObj.toString();\r\n }\r\n }\r\n \r\n // Nếu không phải các domain cần xử lý, return URL gốc\r\n return url;\r\n } catch (error) {\r\n // Nếu URL không hợp lệ, return URL gốc\r\n return url;\r\n }\r\n};\r\n\r\nconst preloadFonts = async (config: EmbroideryQCConfig) => {\r\n if (config.error_message || !config.sides?.length) return;\r\n\r\n const fonts = new Set<string>();\r\n\r\n config.sides.forEach((side) => {\r\n side.positions.forEach((position) => {\r\n if (position.type === \"TEXT\" && position.font) {\r\n fonts.add(position.font);\r\n }\r\n });\r\n });\r\n\r\n if (fonts.size === 0) return;\r\n\r\n await Promise.all([...fonts].map((font) => loadFont(font)));\r\n};\r\n\r\nconst preloadImages = async (\r\n config: EmbroideryQCConfig,\r\n imageRefs: ImageMapRef\r\n) => {\r\n const entries: Array<{ url: string; cacheKey?: string }> = [];\r\n const seen = new Set<string>();\r\n\r\n if (config.image_url) {\r\n entries.push({ url: config.image_url, cacheKey: \"mockup\" });\r\n seen.add(config.image_url);\r\n }\r\n\r\n if (!config.sides?.length) {\r\n await Promise.all(\r\n entries.map(({ url, cacheKey }) =>\r\n loadImageAsync(url, imageRefs, cacheKey)\r\n )\r\n );\r\n return;\r\n }\r\n\r\n config.sides.forEach((side) => {\r\n side.positions.forEach((position) => {\r\n if (position.type === \"ICON\") {\r\n const iconUrl = getIconImageUrl(position);\r\n\r\n if (iconUrl && !seen.has(iconUrl)) {\r\n entries.push({ url: iconUrl });\r\n seen.add(iconUrl);\r\n }\r\n\r\n if (position.color) {\r\n const threadUrl = getImageUrl(\"threadColor\", position.color);\r\n if (!seen.has(threadUrl)) {\r\n entries.push({ url: threadUrl });\r\n seen.add(threadUrl);\r\n }\r\n }\r\n\r\n position.layer_colors?.forEach((color) => {\r\n const colorUrl = getImageUrl(\"threadColor\", color);\r\n if (!seen.has(colorUrl)) {\r\n entries.push({ url: colorUrl });\r\n seen.add(colorUrl);\r\n }\r\n });\r\n }\r\n\r\n if (position.type === \"TEXT\") {\r\n if (position.floral_pattern) {\r\n const floralUrl = getImageUrl(\"floral\", position.floral_pattern);\r\n if (!seen.has(floralUrl)) {\r\n entries.push({ url: floralUrl });\r\n seen.add(floralUrl);\r\n }\r\n }\r\n\r\n if (position.color) {\r\n const threadUrl = getImageUrl(\"threadColor\", position.color);\r\n if (!seen.has(threadUrl)) {\r\n entries.push({ url: threadUrl });\r\n seen.add(threadUrl);\r\n }\r\n }\r\n\r\n position.character_colors?.forEach((color) => {\r\n const characterColorUrl = getImageUrl(\"threadColor\", color);\r\n if (!seen.has(characterColorUrl)) {\r\n entries.push({ url: characterColorUrl });\r\n seen.add(characterColorUrl);\r\n }\r\n });\r\n }\r\n });\r\n });\r\n\r\n if (entries.length === 0) return;\r\n\r\n await Promise.all(\r\n entries.map(({ url, cacheKey }) => loadImageAsync(url, imageRefs, cacheKey))\r\n );\r\n};\r\n\r\nconst wrapText = (\r\n ctx: CanvasRenderingContext2D,\r\n text: string,\r\n x: number,\r\n y: number,\r\n maxWidth: number,\r\n lineHeight: number,\r\n mockupBounds: { x: number; y: number; width: number; height: number } | null = null\r\n): { height: number; lastLineWidth: number; lastLineY: number } => {\r\n const words = text.split(\" \");\r\n const lines: string[] = [];\r\n let currentLine = words[0];\r\n let currentY = y;\r\n\r\n for (let i = 1; i < words.length; i++) {\r\n const testLine = currentLine + \" \" + words[i];\r\n \r\n // Tính maxWidth hiệu dụng cho dòng hiện tại\r\n const effectiveMaxWidth = getEffectiveMaxWidth(x, currentY, lineHeight, maxWidth, mockupBounds);\r\n const testWidth = ctx.measureText(testLine).width;\r\n \r\n // Kiểm tra overlap với mockup\r\n let shouldWrap = false;\r\n if (testWidth > effectiveMaxWidth && currentLine.length > 0) {\r\n shouldWrap = true;\r\n }\r\n \r\n if (shouldWrap) {\r\n lines.push(currentLine);\r\n currentLine = words[i];\r\n currentY += lineHeight;\r\n } else {\r\n currentLine = testLine;\r\n }\r\n }\r\n lines.push(currentLine);\r\n\r\n currentY = y;\r\n lines.forEach((line) => {\r\n // Tính maxWidth hiệu dụng cho từng dòng khi render\r\n const effectiveMaxWidth = getEffectiveMaxWidth(x, currentY, lineHeight, maxWidth, mockupBounds);\r\n // Nếu dòng quá dài, cắt bớt\r\n let lineToRender = line;\r\n if (ctx.measureText(line).width > effectiveMaxWidth) {\r\n // Cắt từng ký tự cho đến khi vừa\r\n while (ctx.measureText(lineToRender).width > effectiveMaxWidth && lineToRender.length > 0) {\r\n lineToRender = lineToRender.slice(0, -1);\r\n }\r\n }\r\n ctx.fillText(lineToRender, x, currentY);\r\n currentY += lineHeight;\r\n });\r\n\r\n return {\r\n height: lines.length * lineHeight,\r\n lastLineWidth: ctx.measureText(lines[lines.length - 1]).width,\r\n lastLineY: y + (lines.length - 1) * lineHeight,\r\n };\r\n};\r\n\r\nconst buildWrappedLines = (\r\n ctx: CanvasRenderingContext2D,\r\n text: string,\r\n maxWidth: number,\r\n startX: number = 0,\r\n startY: number = 0,\r\n lineHeight: number = 0,\r\n mockupBounds: { x: number; y: number; width: number; height: number } | null = null\r\n): string[] => {\r\n // Mỗi '\\n' tương đương với một line break giống như khi wrap tự động.\r\n const segments = text.split(\"\\n\");\r\n const result: string[] = [];\r\n let currentY = startY;\r\n\r\n segments.forEach((segment) => {\r\n const words = segment.split(\" \").filter((word) => word.length > 0);\r\n if (words.length === 0) {\r\n // Nếu đoạn rỗng, thêm một dòng trống (break đúng 1 line)\r\n result.push(\"\");\r\n if (lineHeight > 0) currentY += lineHeight;\r\n return;\r\n }\r\n\r\n let currentLine = words[0];\r\n for (let i = 1; i < words.length; i++) {\r\n const testLine = `${currentLine} ${words[i]}`;\r\n \r\n // Tính maxWidth hiệu dụng cho dòng hiện tại\r\n const effectiveMaxWidth = lineHeight > 0 \r\n ? getEffectiveMaxWidth(startX, currentY, lineHeight, maxWidth, mockupBounds)\r\n : maxWidth;\r\n const testWidth = ctx.measureText(testLine).width;\r\n \r\n // Kiểm tra overlap với mockup\r\n let shouldWrap = false;\r\n if (testWidth > effectiveMaxWidth && currentLine.length > 0) {\r\n shouldWrap = true;\r\n }\r\n \r\n if (shouldWrap) {\r\n result.push(currentLine);\r\n currentLine = words[i];\r\n if (lineHeight > 0) currentY += lineHeight;\r\n } else {\r\n currentLine = testLine;\r\n }\r\n }\r\n result.push(currentLine);\r\n if (lineHeight > 0) currentY += lineHeight;\r\n });\r\n\r\n return result.length ? result : [\"\"];\r\n};\r\n\r\nconst wrapTextMultiColor = (\r\n ctx: CanvasRenderingContext2D,\r\n text: string,\r\n colors: string[],\r\n x: number,\r\n y: number,\r\n maxWidth: number,\r\n lineHeight: number\r\n): number => {\r\n const words = text.split(\" \");\r\n const lines: string[] = [];\r\n const lineStartIndices: number[] = [0];\r\n let currentLine = words[0];\r\n let currentCharIndex = words[0].length;\r\n\r\n for (let i = 1; i < words.length; i++) {\r\n const testLine = currentLine + \" \" + words[i];\r\n if (ctx.measureText(testLine).width > maxWidth && currentLine.length > 0) {\r\n lines.push(currentLine);\r\n lineStartIndices.push(currentCharIndex + 1);\r\n currentLine = words[i];\r\n currentCharIndex += words[i].length + 1;\r\n } else {\r\n currentLine = testLine;\r\n currentCharIndex += words[i].length + 1;\r\n }\r\n }\r\n lines.push(currentLine);\r\n\r\n let currentY = y;\r\n lines.forEach((line, lineIdx) => {\r\n let currentX = x;\r\n const startCharIdx = lineIdx > 0 ? lineStartIndices[lineIdx] : 0;\r\n for (let i = 0; i < line.length; i++) {\r\n const char = line[i];\r\n const globalCharIdx = startCharIdx + i;\r\n const colorIndex = globalCharIdx % colors.length;\r\n const color = colors[colorIndex];\r\n ctx.fillStyle = COLOR_MAP[color] || LAYOUT.LABEL_COLOR;\r\n ctx.fillText(char, currentX, currentY);\r\n currentX += ctx.measureText(char).width;\r\n }\r\n currentY += lineHeight;\r\n });\r\n\r\n return lines.length * lineHeight;\r\n};\r\n\r\nconst calculateSwatchesWidth = (\r\n colors: string[],\r\n swatchHeight: number,\r\n scaleFactor: number,\r\n imageRefs: ImageMapRef\r\n): number => {\r\n let totalWidth = 0;\r\n colors.forEach((color, index) => {\r\n const url = getImageUrl(\"threadColor\", color);\r\n const img = imageRefs.current.get(url);\r\n if (img && img.complete && img.naturalHeight > 0) {\r\n const ratio = img.naturalWidth / img.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchHeight * ratio));\r\n totalWidth += swatchW;\r\n if (index < colors.length - 1) {\r\n totalWidth += LAYOUT.SWATCH_SPACING * scaleFactor;\r\n }\r\n }\r\n });\r\n return totalWidth;\r\n};\r\n\r\nconst drawSwatches = (\r\n ctx: CanvasRenderingContext2D,\r\n colors: string[],\r\n startX: number,\r\n startY: number,\r\n swatchHeight: number,\r\n scaleFactor: number,\r\n imageRefs: ImageMapRef\r\n) => {\r\n let swatchX = startX;\r\n colors.forEach((color) => {\r\n const url = getImageUrl(\"threadColor\", color);\r\n const img = imageRefs.current.get(url);\r\n if (img && img.complete && img.naturalHeight > 0) {\r\n const ratio = img.naturalWidth / img.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchHeight * ratio));\r\n ctx.drawImage(img, swatchX, startY, swatchW, swatchHeight);\r\n swatchX += swatchW + LAYOUT.SWATCH_SPACING * scaleFactor;\r\n }\r\n });\r\n};\r\n\r\n// ============================================================================\r\n// MAIN COMPONENT\r\n// ============================================================================\r\n\r\nconst EmbroideryQCImage: React.FC<EmbroideryQCImageProps> = ({\r\n config,\r\n className = \"\",\r\n style = {},\r\n}) => {\r\n const [canvasSize] = useState({ width: 4200, height: 4800 });\r\n const [loadedFonts, setLoadedFonts] = useState<Set<string>>(new Set());\r\n const [imagesLoaded, setImagesLoaded] = useState(0);\r\n const canvasRef = useRef<HTMLCanvasElement>(null);\r\n const imageRefs = useRef<Map<string, HTMLImageElement>>(new Map());\r\n\r\n // Load fonts\r\n useEffect(() => {\r\n const loadFonts = async () => {\r\n if (config.error_message || !config.sides?.length) return;\r\n\r\n const fontsToLoad = new Set<string>();\r\n config.sides.forEach((side) => {\r\n side.positions.forEach((position) => {\r\n if (position.type === \"TEXT\" && position.font) {\r\n fontsToLoad.add(position.font);\r\n }\r\n });\r\n });\r\n\r\n for (const fontName of fontsToLoad) {\r\n if (!loadedFonts.has(fontName)) {\r\n try {\r\n await loadFont(fontName);\r\n setLoadedFonts((prev) => new Set(prev).add(fontName));\r\n } catch (error) {\r\n console.warn(`Could not load font ${fontName}:`, error);\r\n }\r\n }\r\n }\r\n };\r\n\r\n loadFonts();\r\n }, [config.sides, loadedFonts]);\r\n\r\n // Load images\r\n useEffect(() => {\r\n if (config.error_message || !config.sides?.length) return;\r\n\r\n const incrementCounter = () => setImagesLoaded((prev) => prev + 1);\r\n\r\n // Load mockup\r\n if (config.image_url) {\r\n loadImage(config.image_url, imageRefs, incrementCounter);\r\n }\r\n\r\n // Load all other images\r\n config.sides.forEach((side) => {\r\n side.positions.forEach((position) => {\r\n if (position.type === \"ICON\") {\r\n const iconUrl = getIconImageUrl(position);\r\n\r\n if (iconUrl) {\r\n loadImage(iconUrl, imageRefs, incrementCounter);\r\n }\r\n position.layer_colors?.forEach((color) => {\r\n loadImage(\r\n getImageUrl(\"threadColor\", color),\r\n imageRefs,\r\n incrementCounter\r\n );\r\n });\r\n }\r\n\r\n if (position.type === \"TEXT\") {\r\n if (position.floral_pattern) {\r\n loadImage(\r\n getImageUrl(\"floral\", position.floral_pattern),\r\n imageRefs,\r\n incrementCounter\r\n );\r\n }\r\n if (position.color) {\r\n loadImage(\r\n getImageUrl(\"threadColor\", position.color),\r\n imageRefs,\r\n incrementCounter\r\n );\r\n }\r\n position.character_colors?.forEach((color) => {\r\n loadImage(\r\n getImageUrl(\"threadColor\", color),\r\n imageRefs,\r\n incrementCounter\r\n );\r\n });\r\n }\r\n });\r\n });\r\n }, [config]);\r\n\r\n // Render canvas\r\n useEffect(() => {\r\n const renderCanvas = () => {\r\n if (!canvasRef.current) return;\r\n renderEmbroideryCanvas(canvasRef.current, config, canvasSize, imageRefs);\r\n };\r\n\r\n const timer = setTimeout(renderCanvas, 100);\r\n return () => clearTimeout(timer);\r\n }, [config, canvasSize, loadedFonts, imagesLoaded]);\r\n\r\n return (\r\n <div\r\n className={`render-embroidery${className ? ` ${className}` : \"\"}`}\r\n style={style}\r\n >\r\n <canvas ref={canvasRef} className=\"render-embroidery-canvas\" />\r\n </div>\r\n );\r\n};\r\n\r\n// ============================================================================\r\n// RENDERING FUNCTIONS\r\n// ============================================================================\r\n\r\nconst renderEmbroideryCanvas = (\r\n canvas: HTMLCanvasElement,\r\n config: EmbroideryQCConfig,\r\n canvasSize: { width: number; height: number },\r\n imageRefs: ImageMapRef\r\n) => {\r\n const ctx = canvas.getContext(\"2d\");\r\n if (!ctx) return;\r\n\r\n canvas.width = canvasSize.width;\r\n canvas.height = canvasSize.height;\r\n\r\n ctx.fillStyle = LAYOUT.BACKGROUND_COLOR;\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n if (config.error_message) {\r\n renderErrorState(ctx, canvas, config.error_message);\r\n return;\r\n }\r\n\r\n if (!config.sides?.length) return;\r\n\r\n ctx.textAlign = LAYOUT.TEXT_ALIGN;\r\n ctx.textBaseline = LAYOUT.TEXT_BASELINE;\r\n\r\n if (config.image_url) {\r\n const mockupImage = imageRefs.current.get(config.image_url);\r\n if (mockupImage) {\r\n imageRefs.current.set(\"mockup\", mockupImage);\r\n }\r\n }\r\n\r\n // Tính mockup bounds để tránh text overlap\r\n const mockupBounds = getMockupBounds(canvas, imageRefs);\r\n\r\n const measureCanvas = document.createElement(\"canvas\");\r\n measureCanvas.width = canvas.width;\r\n measureCanvas.height = canvas.height;\r\n const measureCtx = measureCanvas.getContext(\"2d\");\r\n if (!measureCtx) return;\r\n\r\n measureCtx.textAlign = LAYOUT.TEXT_ALIGN;\r\n measureCtx.textBaseline = LAYOUT.TEXT_BASELINE;\r\n\r\n const measureSpacing = LAYOUT.ELEMENT_SPACING;\r\n\r\n // Tìm scaleFactor tối ưu bằng binary search trong [0, 1]\r\n const maxIterations = 12;\r\n const epsilon = 0.001; // độ chính xác cho khoảng cách low-high\r\n const contentHeight = canvas.height - LAYOUT.PADDING;\r\n\r\n let low = 0;\r\n let high = 1;\r\n\r\n for (let i = 0; i < maxIterations; i++) {\r\n const testScale = (low + high) / 2;\r\n\r\n // (Không cần clear measureCanvas vì chỉ dùng để đo chiều cao, nhưng làm sạch cho dễ debug)\r\n measureCtx.clearRect(0, 0, measureCanvas.width, measureCanvas.height);\r\n\r\n // Đo warning & message đúng theo renderWarning, không cộng padding ở đây\r\n let testMeasureY = 0;\r\n\r\n if (config.warning_message) {\r\n const testWarningHeight = renderWarning(\r\n measureCtx,\r\n measureCanvas,\r\n config.warning_message,\r\n testScale\r\n );\r\n testMeasureY += testWarningHeight;\r\n }\r\n\r\n if (config.message) {\r\n const testMessageHeight = renderWarning(\r\n measureCtx,\r\n measureCanvas,\r\n config.message,\r\n testScale,\r\n 0,\r\n \"\",\r\n DEFAULT_ERROR_COLOR\r\n );\r\n testMeasureY += testMessageHeight;\r\n }\r\n\r\n // Đo lại chiều cao của các sides với scaleFactor, tiếp nối sau warning/message\r\n config.sides.forEach((side) => {\r\n const sideHeight = renderSide(\r\n measureCtx,\r\n side,\r\n testMeasureY,\r\n canvas.width,\r\n canvas.height,\r\n testScale,\r\n imageRefs,\r\n mockupBounds\r\n );\r\n testMeasureY += sideHeight + measureSpacing * testScale;\r\n });\r\n \r\n // Tổng chiều cao content (không gồm padding)\r\n const totalHeight = testMeasureY;\r\n\r\n if (totalHeight > contentHeight) {\r\n // Content đang cao hơn vùng cho phép -> giảm scale\r\n high = testScale;\r\n } else {\r\n // Content vẫn fit trong vùng cho phép -> có thể tăng scale\r\n low = testScale;\r\n }\r\n\r\n if (high - low < epsilon) {\r\n break;\r\n }\r\n }\r\n \r\n const scaleFactor = low;\r\n\r\n drawMockup(ctx, canvas, imageRefs);\r\n\r\n // Render warning & message with scaleFactor and get actual heights\r\n let actualWarningHeight = 0;\r\n let actualMessageHeight = 0;\r\n if (config.warning_message) {\r\n actualWarningHeight = renderWarning(\r\n ctx,\r\n canvas,\r\n config.warning_message,\r\n scaleFactor\r\n );\r\n }\r\n if (config.message) {\r\n actualMessageHeight = renderWarning(\r\n ctx,\r\n canvas,\r\n config.message,\r\n scaleFactor,\r\n actualWarningHeight,\r\n \"\", // message: không cần prefix \"Note\"\r\n DEFAULT_ERROR_COLOR // message: hiển thị màu đỏ\r\n );\r\n }\r\n\r\n // Calculate currentY: padding top + actual warning & message height (no spacing)\r\n let currentY = LAYOUT.PADDING;\r\n if (config.warning_message && actualWarningHeight > 0) {\r\n currentY += actualWarningHeight;\r\n }\r\n if (config.message && actualMessageHeight > 0) {\r\n currentY += actualMessageHeight;\r\n }\r\n config.sides.forEach((side) => {\r\n const sideHeight = renderSide(\r\n ctx,\r\n side,\r\n currentY,\r\n canvas.width,\r\n canvas.height,\r\n scaleFactor,\r\n imageRefs,\r\n mockupBounds\r\n );\r\n currentY += sideHeight + measureSpacing * scaleFactor;\r\n });\r\n};\r\n\r\nconst renderErrorState = (\r\n ctx: CanvasRenderingContext2D,\r\n canvas: HTMLCanvasElement,\r\n message: string\r\n) => {\r\n const sanitizedMessage = message.trim() || \"Đã xảy ra lỗi\";\r\n const horizontalPadding = LAYOUT.PADDING * 3;\r\n const maxWidth = canvas.width - horizontalPadding * 2;\r\n const baseFontSize = LAYOUT.HEADER_FONT_SIZE;\r\n const minFontSize = 60;\r\n const centerX = canvas.width / 2;\r\n\r\n ctx.save();\r\n ctx.textAlign = \"center\";\r\n ctx.textBaseline = \"top\";\r\n ctx.fillStyle = DEFAULT_ERROR_COLOR;\r\n\r\n let fontSize = baseFontSize;\r\n let lineGap = LAYOUT.LINE_GAP;\r\n let lineHeight = fontSize + lineGap;\r\n\r\n const adjustMetrics = () => {\r\n ctx.font = `bold ${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n lineGap = LAYOUT.LINE_GAP * (fontSize / baseFontSize);\r\n lineHeight = fontSize + lineGap;\r\n };\r\n\r\n adjustMetrics();\r\n let lines = buildWrappedLines(ctx, sanitizedMessage, maxWidth);\r\n let longestLineWidth = Math.max(\r\n ...lines.map((line) => ctx.measureText(line).width)\r\n );\r\n\r\n while (longestLineWidth > maxWidth && fontSize > minFontSize) {\r\n fontSize = Math.max(minFontSize, Math.floor(fontSize * 0.9));\r\n adjustMetrics();\r\n lines = buildWrappedLines(ctx, sanitizedMessage, maxWidth);\r\n longestLineWidth = Math.max(\r\n ...lines.map((line) => ctx.measureText(line).width)\r\n );\r\n }\r\n\r\n const totalHeight = lines.length * lineHeight;\r\n const startY = Math.max(\r\n LAYOUT.PADDING * 2,\r\n canvas.height / 2 - totalHeight / 2\r\n );\r\n\r\n lines.forEach((line, index) => {\r\n const y = startY + index * lineHeight;\r\n ctx.fillText(line, centerX, y);\r\n });\r\n\r\n ctx.restore();\r\n};\r\n\r\nconst renderWarning = (\r\n ctx: CanvasRenderingContext2D,\r\n canvas: HTMLCanvasElement,\r\n message: string,\r\n scaleFactor: number = 1,\r\n offsetY: number = 0,\r\n prefix: string = \"Note: \",\r\n color: string = DEFAULT_WARNING_COLOR\r\n): number => {\r\n const sanitizedMessage = `${prefix}${message.trim()}`;\r\n const horizontalPadding = LAYOUT.PADDING * 2 * scaleFactor;\r\n const maxWidth = canvas.width - horizontalPadding * 2;\r\n const baseFontSize = LAYOUT.HEADER_FONT_SIZE * 0.7 * scaleFactor;\r\n const minFontSize = 50 * scaleFactor;\r\n const leftX = LAYOUT.PADDING * scaleFactor;\r\n\r\n ctx.save();\r\n ctx.textAlign = \"left\";\r\n ctx.textBaseline = \"top\";\r\n ctx.fillStyle = color;\r\n ctx.font = `${baseFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n\r\n let fontSize = baseFontSize;\r\n let lineGap = LAYOUT.LINE_GAP * scaleFactor;\r\n let lineHeight = fontSize + lineGap;\r\n\r\n const adjustMetrics = () => {\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n lineGap = LAYOUT.LINE_GAP * scaleFactor * (fontSize / baseFontSize);\r\n lineHeight = fontSize + lineGap;\r\n };\r\n\r\n adjustMetrics();\r\n let lines = buildWrappedLines(ctx, sanitizedMessage, maxWidth);\r\n let longestLineWidth = Math.max(\r\n ...lines.map((line) => ctx.measureText(line).width)\r\n );\r\n\r\n while (longestLineWidth > maxWidth && fontSize > minFontSize) {\r\n fontSize = Math.max(minFontSize, Math.floor(fontSize * 0.9));\r\n adjustMetrics();\r\n lines = buildWrappedLines(ctx, sanitizedMessage, maxWidth);\r\n longestLineWidth = Math.max(\r\n ...lines.map((line) => ctx.measureText(line).width)\r\n );\r\n }\r\n\r\n const startY = LAYOUT.PADDING * scaleFactor + offsetY;\r\n\r\n lines.forEach((line, index) => {\r\n const y = startY + index * lineHeight;\r\n ctx.fillText(line, leftX, y);\r\n });\r\n\r\n ctx.restore();\r\n \r\n // Return the actual height of the warning (number of lines * lineHeight)\r\n return lines.length * lineHeight;\r\n};\r\n\r\nconst getMockupBounds = (\r\n canvas: HTMLCanvasElement,\r\n imageRefs: ImageMapRef\r\n): { x: number; y: number; width: number; height: number } | null => {\r\n const mockupImg = imageRefs.current.get(\"mockup\");\r\n if (!mockupImg?.complete || !mockupImg.naturalWidth) return null;\r\n\r\n const margin = LAYOUT.PADDING;\r\n const maxWidth = Math.min(1800, canvas.width * 0.375);\r\n const maxHeight = canvas.height * 0.375;\r\n const scale = Math.min(\r\n maxWidth / mockupImg.naturalWidth,\r\n maxHeight / mockupImg.naturalHeight\r\n );\r\n const width = Math.max(1, Math.floor(mockupImg.naturalWidth * scale));\r\n const height = Math.max(1, Math.floor(mockupImg.naturalHeight * scale));\r\n const x = canvas.width - margin - width;\r\n const y = canvas.height - margin - height;\r\n\r\n return { x, y, width, height };\r\n};\r\n\r\n// Helper function để tính maxWidth hiệu dụng dựa trên vị trí Y và mockupBounds\r\nconst getEffectiveMaxWidth = (\r\n x: number,\r\n y: number,\r\n lineHeight: number,\r\n originalMaxWidth: number,\r\n mockupBounds: { x: number; y: number; width: number; height: number } | null\r\n): number => {\r\n if (!mockupBounds) return originalMaxWidth;\r\n \r\n // Kiểm tra xem dòng text có nằm trong phạm vi Y của mockup không\r\n const lineTopY = y;\r\n const lineBottomY = y + lineHeight;\r\n const overlapsY = lineTopY < mockupBounds.y + mockupBounds.height && lineBottomY > mockupBounds.y;\r\n \r\n if (overlapsY) {\r\n // Nếu overlap theo Y, giới hạn maxWidth để text không vượt quá mockup.x\r\n const maxAllowedWidth = mockupBounds.x - x;\r\n // Chỉ giới hạn nếu maxAllowedWidth > 0 và nhỏ hơn originalMaxWidth\r\n if (maxAllowedWidth > 0 && maxAllowedWidth < originalMaxWidth) {\r\n return maxAllowedWidth;\r\n }\r\n // Nếu x >= mockupBounds.x, text đã nằm sau mockup, không cần giới hạn\r\n // Hoặc nếu maxAllowedWidth >= originalMaxWidth, không cần giới hạn\r\n }\r\n \r\n return originalMaxWidth;\r\n};\r\n\r\nconst drawMockup = (\r\n ctx: CanvasRenderingContext2D,\r\n canvas: HTMLCanvasElement,\r\n imageRefs: ImageMapRef\r\n) => {\r\n const mockupBounds = getMockupBounds(canvas, imageRefs);\r\n if (!mockupBounds) return;\r\n\r\n const mockupImg = imageRefs.current.get(\"mockup\");\r\n if (!mockupImg) return;\r\n\r\n ctx.drawImage(\r\n mockupImg,\r\n mockupBounds.x,\r\n mockupBounds.y,\r\n mockupBounds.width,\r\n mockupBounds.height\r\n );\r\n};\r\n\r\nconst renderSide = (\r\n ctx: CanvasRenderingContext2D,\r\n side: any,\r\n startY: number,\r\n width: number,\r\n height: number,\r\n scaleFactor: number,\r\n imageRefs: ImageMapRef,\r\n mockupBounds: { x: number; y: number; width: number; height: number } | null = null\r\n): number => {\r\n let currentY = startY;\r\n const padding = LAYOUT.PADDING * scaleFactor;\r\n const sideWidth = width - 2 * padding;\r\n\r\n // Draw header\r\n ctx.save();\r\n const headerFontSize = LAYOUT.HEADER_FONT_SIZE * scaleFactor;\r\n ctx.font = `bold ${headerFontSize}px ${LAYOUT.HEADER_FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.HEADER_COLOR;\r\n\r\n const headerResult = wrapText(\r\n ctx,\r\n side.print_side.toUpperCase(),\r\n padding,\r\n currentY,\r\n sideWidth,\r\n headerFontSize,\r\n mockupBounds\r\n );\r\n\r\n // Draw underline\r\n const underlineY =\r\n headerResult.lastLineY + headerFontSize * LAYOUT.UNDERLINE_POSITION;\r\n ctx.strokeStyle = LAYOUT.HEADER_COLOR;\r\n ctx.lineWidth = LAYOUT.UNDERLINE_WIDTH * scaleFactor;\r\n ctx.beginPath();\r\n ctx.moveTo(padding, underlineY);\r\n ctx.lineTo(padding + headerResult.lastLineWidth, underlineY);\r\n ctx.stroke();\r\n\r\n currentY += headerResult.height + LAYOUT.SECTION_SPACING * scaleFactor;\r\n ctx.restore();\r\n\r\n // Kiểm tra xem có phải trường hợp \"không thêu gì\" không\r\n const textPositions = side.positions.filter(\r\n (p: Position) => p.type === \"TEXT\"\r\n );\r\n const iconPositions = side.positions.filter(\r\n (p: Position) => p.type === \"ICON\"\r\n );\r\n \r\n // Kiểm tra tất cả TEXT positions có trống không\r\n // Nếu không có TEXT positions, coi như \"tất cả TEXT trống\" = true\r\n const allTextEmpty = textPositions.length === 0 || textPositions.every((p: Position & { type: \"TEXT\" }) => {\r\n const text = p.text ?? \"\";\r\n return text.trim() === \"\";\r\n });\r\n \r\n // Kiểm tra tất cả ICON positions có is_delete_icon = true không\r\n // Nếu không có ICON positions, coi như \"tất cả ICON bị xóa\" = true\r\n const allIconsDeleted = iconPositions.length === 0 || iconPositions.every((p: Position & { type: \"ICON\" }) => {\r\n return p.is_delete_icon === true;\r\n });\r\n \r\n // Nếu tất cả TEXT trống và tất cả ICON bị xóa, chỉ render dòng \"(không thêu gì)\"\r\n if (allTextEmpty && allIconsDeleted && side.positions.length > 0) {\r\n ctx.save();\r\n const otherFontSize = LAYOUT.OTHER_FONT_SIZE * scaleFactor;\r\n const lineGap = LAYOUT.LINE_GAP * scaleFactor;\r\n ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = DEFAULT_ERROR_COLOR;\r\n ctx.fillText(\"(không thêu gì)\", padding, currentY);\r\n currentY += otherFontSize + lineGap;\r\n ctx.restore();\r\n return currentY - startY;\r\n }\r\n\r\n // Compute uniform properties\r\n const iconColorPositions = side.positions.filter(\r\n (p: Position): p is Position & { type: \"ICON\" } =>\r\n p.type === \"ICON\" && (!p.layer_colors?.length || p.layer_colors.length === 1)\r\n );\r\n const iconColorValues = iconColorPositions\r\n .map((p: Position & { type: \"ICON\" }) => {\r\n if (p.layer_colors?.length === 1) return p.layer_colors[0];\r\n return p.color ?? null;\r\n })\r\n .filter((color: string | null): color is string => Boolean(color));\r\n const uniformProps = computeUniformProperties(textPositions, {\r\n additionalColorValues: iconColorValues,\r\n });\r\n const hasMultipleTextPositions = textPositions.length > 1;\r\n const hasSharedIconColor = iconColorValues.length > 0;\r\n const shouldRenderSharedColorLabel =\r\n !hasMultipleTextPositions &&\r\n hasSharedIconColor &&\r\n uniformProps.isUniform.color &&\r\n Boolean(uniformProps.values.color);\r\n const shouldShowUniformLabels =\r\n hasMultipleTextPositions || shouldRenderSharedColorLabel;\r\n const uniformLabelFields = hasMultipleTextPositions\r\n ? undefined\r\n : { color: true as const };\r\n\r\n // Render uniform labels (when applicable)\r\n if (shouldShowUniformLabels) {\r\n currentY += renderUniformLabels(\r\n ctx,\r\n uniformProps,\r\n padding,\r\n currentY,\r\n sideWidth,\r\n scaleFactor,\r\n imageRefs,\r\n textPositions,\r\n uniformLabelFields,\r\n mockupBounds\r\n );\r\n }\r\n\r\n // Group text positions by common properties\r\n const textGroups = groupTextPositions(textPositions);\r\n\r\n // Render text positions (with proper spacing between groups)\r\n let textCounter = 1;\r\n textGroups.forEach((group, groupIndex) => {\r\n group.forEach((position, index) => {\r\n // Add extra spacing between different groups\r\n if (index === 0 && groupIndex !== 0) {\r\n currentY += LAYOUT.SECTION_SPACING * scaleFactor;\r\n }\r\n\r\n // If only 1 TEXT position, show all labels (no uniform labels rendered)\r\n const showLabels =\r\n textPositions.length === 1\r\n ? {\r\n font: true,\r\n shape: true,\r\n floral: true,\r\n color: !shouldRenderSharedColorLabel,\r\n }\r\n : {\r\n font: !uniformProps.isUniform.font,\r\n shape: !uniformProps.isUniform.shape,\r\n floral: !uniformProps.isUniform.floral,\r\n color: !uniformProps.isUniform.color,\r\n };\r\n const height = renderTextPosition(\r\n ctx,\r\n position as any,\r\n padding,\r\n currentY,\r\n sideWidth,\r\n textCounter,\r\n showLabels,\r\n scaleFactor,\r\n imageRefs,\r\n mockupBounds\r\n );\r\n if (height > 0) {\r\n currentY += height + LAYOUT.PADDING * scaleFactor;\r\n textCounter++;\r\n }\r\n });\r\n });\r\n\r\n // Render icon positions\r\n currentY += LAYOUT.LINE_GAP * scaleFactor;\r\n side.positions.forEach((position: Position) => {\r\n if (position.type === \"ICON\") {\r\n const layerCount = position.layer_colors?.length ?? 0;\r\n const iconUsesSingleColor =\r\n layerCount === 0 || layerCount === 1;\r\n const iconColorValue =\r\n layerCount === 1\r\n ? position.layer_colors?.[0] ?? null\r\n : position.color ?? null;\r\n const hideColor =\r\n shouldShowUniformLabels &&\r\n uniformProps.isUniform.color &&\r\n iconColorValue !== null &&\r\n uniformProps.values.color === iconColorValue &&\r\n iconUsesSingleColor;\r\n currentY += renderIconPosition(\r\n ctx,\r\n position as any,\r\n padding,\r\n currentY,\r\n sideWidth,\r\n scaleFactor,\r\n imageRefs,\r\n { hideColor },\r\n mockupBounds\r\n );\r\n currentY += (LAYOUT.LINE_GAP / 3) * scaleFactor;\r\n }\r\n });\r\n\r\n return currentY - startY;\r\n};\r\n\r\nconst groupTextPositions = (\r\n textPositions: Array<Position & { type: \"TEXT\" }>\r\n): Array<Array<Position & { type: \"TEXT\" }>> => {\r\n const groups: Array<Array<Position & { type: \"TEXT\" }>> = [];\r\n let currentGroup: Array<Position & { type: \"TEXT\" }> | null = null;\r\n let currentProps: any = null;\r\n\r\n textPositions.forEach((position) => {\r\n const posProps = {\r\n font: position.font,\r\n text_shape: position.text_shape,\r\n color: position.color,\r\n character_colors: position.character_colors?.join(\",\"),\r\n };\r\n\r\n if (\r\n !currentGroup ||\r\n currentProps.font !== posProps.font ||\r\n currentProps.text_shape !== posProps.text_shape ||\r\n currentProps.color !== posProps.color ||\r\n currentProps.character_colors !== posProps.character_colors\r\n ) {\r\n if (currentGroup) {\r\n groups.push(currentGroup);\r\n }\r\n currentGroup = [position];\r\n currentProps = posProps;\r\n } else {\r\n currentGroup.push(position);\r\n }\r\n });\r\n\r\n if (currentGroup) {\r\n groups.push(currentGroup);\r\n }\r\n\r\n return groups;\r\n};\r\n\r\nconst computeUniformProperties = (\r\n textPositions: Array<Position & { type: \"TEXT\" }>,\r\n options?: { additionalColorValues?: string[] }\r\n) => {\r\n const defaults = {\r\n values: { font: null, shape: null, floral: null, color: null },\r\n isUniform: { font: false, shape: false, floral: false, color: false },\r\n };\r\n\r\n const fonts = new Set(textPositions.map((p) => p.font));\r\n const shapes = new Set(textPositions.map((p) => p.text_shape));\r\n const florals = new Set(textPositions.map((p) => p.floral_pattern ?? \"None\"));\r\n const colorSources = [\r\n ...textPositions.map((p) =>\r\n p.character_colors?.length\r\n ? p.character_colors.join(\",\")\r\n : p.color ?? \"None\"\r\n ),\r\n ...(options?.additionalColorValues?.map((color) => color ?? \"None\") ?? []),\r\n ];\r\n\r\n if (\r\n textPositions.length === 0 &&\r\n (!options?.additionalColorValues || options.additionalColorValues.length === 0)\r\n ) {\r\n return defaults;\r\n }\r\n\r\n const colors = new Set(colorSources);\r\n\r\n return {\r\n values: {\r\n font: fonts.size === 1 ? [...fonts][0] : null,\r\n shape: shapes.size === 1 ? [...shapes][0] : null,\r\n floral: florals.size === 1 ? [...florals][0] : null,\r\n color: colorSources.length > 0 && colors.size === 1 ? [...colors][0] : null,\r\n },\r\n isUniform: {\r\n font: fonts.size === 1,\r\n shape: shapes.size === 1,\r\n floral: florals.size === 1,\r\n color: colorSources.length > 0 && colors.size === 1,\r\n },\r\n };\r\n};\r\n\r\nconst renderUniformLabels = (\r\n ctx: CanvasRenderingContext2D,\r\n uniformProps: ReturnType<typeof computeUniformProperties>,\r\n x: number,\r\n y: number,\r\n maxWidth: number,\r\n scaleFactor: number,\r\n imageRefs: ImageMapRef,\r\n textPositions: Array<Position & { type: \"TEXT\" }>,\r\n fields?: { font?: boolean; shape?: boolean; floral?: boolean; color?: boolean },\r\n mockupBounds: { x: number; y: number; width: number; height: number } | null = null\r\n): number => {\r\n const { values } = uniformProps;\r\n const fontSize = LAYOUT.OTHER_FONT_SIZE * scaleFactor;\r\n const lineGap = LAYOUT.LINE_GAP * scaleFactor;\r\n\r\n const shouldRenderField = (field: keyof NonNullable<typeof fields>) => {\r\n if (!fields) return true;\r\n return fields[field] === true;\r\n };\r\n\r\n ctx.save();\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n\r\n let cursorY = y;\r\n let rendered = 0;\r\n\r\n if (values.font && shouldRenderField(\"font\")) {\r\n const allDefault = textPositions.every((p) => p.is_font_default === true);\r\n // Render \"Font: \" với font mặc định\r\n const prefix = \"Font: \";\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const prefixWidth = ctx.measureText(prefix).width;\r\n let currentX = x + prefixWidth;\r\n ctx.fillText(prefix, x, cursorY);\r\n \r\n // Render tên font với font từ config\r\n ctx.font = `${fontSize}px ${values.font}`;\r\n const fontNameWidth = ctx.measureText(values.font).width;\r\n ctx.fillText(values.font, currentX, cursorY);\r\n currentX += fontNameWidth;\r\n \r\n // Render \"(Mặc định)\" hoặc \"(Custom)\" với font mặc định\r\n const suffix = allDefault ? \" (Mặc định)\" : \" (Custom)\";\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const suffixWidth = ctx.measureText(suffix).width;\r\n ctx.fillText(suffix, currentX, cursorY);\r\n \r\n // Tính toán height và di chuyển cursorY\r\n const lineHeight = fontSize + lineGap;\r\n cursorY += lineHeight;\r\n rendered++;\r\n }\r\n\r\n if (values.shape && values.shape !== \"None\" && shouldRenderField(\"shape\")) {\r\n const result = wrapText(\r\n ctx,\r\n `Kiểu chữ: ${values.shape}`,\r\n x,\r\n cursorY,\r\n maxWidth,\r\n fontSize + lineGap,\r\n mockupBounds\r\n );\r\n cursorY += result.height;\r\n rendered++;\r\n }\r\n\r\n if (values.color && values.color !== \"None\" && shouldRenderField(\"color\")) {\r\n const colors = values.color.includes(\",\")\r\n ? values.color.split(\",\").map((s) => s.trim())\r\n : [values.color];\r\n \r\n const swatchH = Math.floor(fontSize * LAYOUT.SWATCH_HEIGHT_RATIO);\r\n const totalSwatchWidth = calculateSwatchesWidth(colors, swatchH, scaleFactor, imageRefs);\r\n \r\n // Tính effectiveMaxWidth cho dòng này để tránh mockup\r\n const lineHeight = fontSize + lineGap;\r\n const effectiveMaxWidth = mockupBounds \r\n ? getEffectiveMaxWidth(x, cursorY, lineHeight, maxWidth, mockupBounds)\r\n : maxWidth;\r\n \r\n // Vẽ text với effectiveMaxWidth\r\n const result = wrapText(\r\n ctx,\r\n `Màu chỉ: ${values.color}`,\r\n x,\r\n cursorY,\r\n effectiveMaxWidth,\r\n lineHeight,\r\n mockupBounds\r\n );\r\n\r\n // Kiểm tra xem có đủ chỗ cho swatches trên cùng dòng không\r\n // Sử dụng effectiveMaxWidth thay vì maxWidth\r\n const textEndX = x + Math.ceil(result.lastLineWidth);\r\n const spacing = LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n const swatchesStartX = textEndX + spacing;\r\n const swatchesEndX = swatchesStartX + totalSwatchWidth;\r\n const shouldWrapSwatches = swatchesEndX > x + effectiveMaxWidth;\r\n\r\n let swatchX: number;\r\n let swatchY: number;\r\n \r\n if (shouldWrapSwatches) {\r\n // Không đủ chỗ, cho TẤT CẢ swatches xuống dòng mới\r\n swatchX = x;\r\n swatchY = result.lastLineY + fontSize + lineGap;\r\n cursorY += result.height + fontSize + lineGap;\r\n } else {\r\n // Đủ chỗ, vẽ swatches ngay sau text trên cùng dòng\r\n swatchX = swatchesStartX;\r\n swatchY = result.lastLineY + Math.floor(fontSize / 2 - swatchH / 2);\r\n cursorY += result.height;\r\n }\r\n\r\n drawSwatches(\r\n ctx,\r\n colors,\r\n swatchX,\r\n swatchY,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\r\n \r\n if (shouldWrapSwatches) {\r\n cursorY += swatchH;\r\n }\r\n \r\n rendered++;\r\n }\r\n\r\n if (values.floral && values.floral !== \"None\" && shouldRenderField(\"floral\")) {\r\n const floralUrl = getImageUrl(\"floral\", values.floral);\r\n const floralImg = imageRefs.current.get(floralUrl);\r\n \r\n // Tính kích thước ảnh floral (thêm 50% = 2.5x fontSize)\r\n const floralH = fontSize * 2.5;\r\n let totalFloralWidth = 0;\r\n if (floralImg?.complete && floralImg.naturalHeight > 0) {\r\n const ratio = floralImg.naturalWidth / floralImg.naturalHeight;\r\n totalFloralWidth = Math.max(1, Math.floor(floralH * ratio));\r\n }\r\n \r\n // Line height giống icon_image: floralH + lineGap\r\n const floralLineHeight = floralH + lineGap;\r\n \r\n // Text align center: căn giữa theo chiều dọc trong block\r\n const textCenterY = cursorY + floralH / 2;\r\n \r\n // Đo width trước khi vẽ\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const labelText = `Mẫu hoa: ${values.floral}`;\r\n const labelWidth = ctx.measureText(labelText).width;\r\n \r\n // Vẽ text với textBaseline = middle để align center\r\n ctx.textBaseline = \"middle\";\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n ctx.fillText(labelText, x, textCenterY);\r\n \r\n // Reset textBaseline về top cho các phần tiếp theo\r\n ctx.textBaseline = LAYOUT.TEXT_BASELINE;\r\n\r\n // Kiểm tra xem có đủ chỗ cho ảnh floral trên cùng dòng không\r\n const textEndX = x + labelWidth;\r\n const spacing = LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n const floralStartX = textEndX + spacing;\r\n const floralEndX = floralStartX + totalFloralWidth;\r\n const shouldWrapFloral = floralEndX > x + maxWidth;\r\n\r\n let floralX: number;\r\n let floralY: number;\r\n \r\n if (shouldWrapFloral) {\r\n // Không đủ chỗ, cho ảnh floral xuống dòng mới\r\n floralX = x;\r\n floralY = cursorY + floralH + lineGap;\r\n cursorY += floralLineHeight;\r\n } else {\r\n // Đủ chỗ, vẽ ảnh floral ngay sau text trên cùng dòng, align center\r\n floralX = floralStartX;\r\n floralY = textCenterY - floralH / 2; // Align center với text\r\n cursorY += floralLineHeight;\r\n }\r\n\r\n // Vẽ ảnh floral\r\n if (floralImg?.complete && floralImg.naturalHeight > 0) {\r\n ctx.drawImage(floralImg, floralX, floralY, totalFloralWidth, floralH);\r\n }\r\n \r\n rendered++;\r\n }\r\n\r\n if (rendered > 0) cursorY += LAYOUT.SECTION_SPACING * scaleFactor;\r\n\r\n ctx.restore();\r\n return cursorY - y;\r\n};\r\n\r\nconst renderTextPosition = (\r\n ctx: CanvasRenderingContext2D,\r\n position: Position & { type: \"TEXT\" },\r\n x: number,\r\n y: number,\r\n maxWidth: number, // tổng chiều rộng usable (không tính padding ngoài)\r\n displayIndex: number,\r\n showLabels: {\r\n font: boolean;\r\n shape: boolean;\r\n floral: boolean;\r\n color: boolean;\r\n },\r\n scaleFactor: number,\r\n imageRefs: ImageMapRef,\r\n mockupBounds: { x: number; y: number; width: number; height: number } | null = null\r\n): number => {\r\n ctx.save();\r\n\r\n const textFontSize = LAYOUT.TEXT_FONT_SIZE * scaleFactor;\r\n const otherFontSize = LAYOUT.OTHER_FONT_SIZE * scaleFactor;\r\n const lineGap = LAYOUT.LINE_GAP * scaleFactor;\r\n\r\n let currentY = y;\r\n\r\n // Chuẩn hóa xuống dòng:\r\n // - Hỗ trợ cả newline thật (\\n) và chuỗi literal \"\\\\n\" từ JSON\r\n const normalizeNewlines = (text: string) =>\r\n text\r\n .replace(/\\r\\n/g, \"\\n\")\r\n .replace(/\\r/g, \"\\n\");\r\n\r\n // Get display text (handle empty/null/undefined) sau khi normalize\r\n const rawOriginalText = position.text ?? \"\";\r\n const normalizedText = normalizeNewlines(rawOriginalText);\r\n const isEmptyText = normalizedText.trim() === \"\";\r\n\r\n // ===========================================================================\r\n // PHẦN TEXT CHÍNH\r\n // - Giữ nguyên format: chỉ xuống dòng khi có '\\n'\r\n // - Không tự wrap theo maxWidth\r\n // - Nếu tổng chiều ngang > maxWidth, tự động giảm font-size để vừa\r\n // ===========================================================================\r\n\r\n // Label \"Text N: \" luôn là font mặc định (không bị co theo nội dung)\r\n const textLabel = `Text ${displayIndex}: `;\r\n ctx.font = `bold ${textFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n const labelWidth = ctx.measureText(textLabel).width;\r\n ctx.fillText(textLabel, x, currentY);\r\n\r\n // Phần text value bắt đầu sau label\r\n const valueStartX = x + labelWidth;\r\n const availableWidth = Math.max(1, maxWidth - labelWidth);\r\n\r\n // Chuẩn hóa nội dung text để render\r\n const rawText = isEmptyText ? \"(không có text)\" : normalizedText;\r\n const lines = rawText.split(\"\\n\");\r\n\r\n // Tính font-size hiệu dụng cho phần value sao cho:\r\n // - Không vượt quá availableWidth\r\n // - Tính đến mockup bounds cho từng dòng\r\n // - Có thể thu nhỏ tùy ý (theo yêu cầu, không giới hạn tối thiểu)\r\n let effectiveTextFontSize = textFontSize;\r\n if (!isEmptyText) {\r\n // Tính vị trí Y của từng dòng (textCenterY và lineY)\r\n const valueLineHeight = textFontSize;\r\n const textBlockHeight = lines.length * valueLineHeight;\r\n const textCenterY = currentY + textBlockHeight / 2;\r\n \r\n // Tính font size cần thiết cho từng dòng dựa trên effectiveMaxWidth của nó\r\n let minShrinkRatio = 1;\r\n \r\n ctx.font = `${textFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n lines.forEach((line, idx) => {\r\n const lineY = textCenterY - (lines.length - 1) / 2 * valueLineHeight + idx * valueLineHeight;\r\n // Tính effectiveMaxWidth cho dòng này\r\n const effectiveMaxWidth = mockupBounds \r\n ? getEffectiveMaxWidth(valueStartX, lineY, valueLineHeight, availableWidth, mockupBounds)\r\n : availableWidth;\r\n \r\n const lineWidth = ctx.measureText(line).width;\r\n if (lineWidth > effectiveMaxWidth) {\r\n // Cần thu nhỏ font cho dòng này\r\n const shrinkRatio = effectiveMaxWidth / lineWidth;\r\n if (shrinkRatio < minShrinkRatio) {\r\n minShrinkRatio = shrinkRatio;\r\n }\r\n }\r\n });\r\n \r\n effectiveTextFontSize = textFontSize * minShrinkRatio;\r\n }\r\n\r\n // Line height luôn theo Text label (textFontSize), không theo effectiveTextFontSize\r\n const valueLineHeight = textFontSize;\r\n const textBlockHeight = lines.length * valueLineHeight;\r\n \r\n // Text align center: căn giữa theo chiều dọc trong block\r\n const textCenterY = currentY + textBlockHeight / 2;\r\n \r\n // Vẽ phần value với font hiệu dụng, màu đỏ, align center\r\n ctx.textBaseline = \"middle\";\r\n ctx.font = `${effectiveTextFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = DEFAULT_ERROR_COLOR;\r\n\r\n // Vẽ từ trên xuống: căn giữa mỗi dòng\r\n // Font size đã được tính để vừa với effectiveMaxWidth của từng dòng, nên không cần cắt text\r\n lines.forEach((line, idx) => {\r\n const lineY = textCenterY - (lines.length - 1) / 2 * valueLineHeight + idx * valueLineHeight;\r\n ctx.fillText(line, valueStartX, lineY);\r\n });\r\n \r\n // Reset textBaseline về top cho các phần tiếp theo\r\n ctx.textBaseline = LAYOUT.TEXT_BASELINE;\r\n \r\n currentY += textBlockHeight;\r\n\r\n // Draw additional labels (skip when text is empty)\r\n if (!isEmptyText) {\r\n currentY += lineGap;\r\n ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n\r\n // Lưu ý: phần dưới này vẫn có thể wrap theo maxWidth vì đây chỉ là label mô tả,\r\n // không phải nội dung Text chính cần giữ nguyên format.\r\n\r\n if (showLabels.shape && position.text_shape) {\r\n const result = wrapText(\r\n ctx,\r\n `Kiểu chữ: ${position.text_shape}`,\r\n x,\r\n currentY,\r\n maxWidth,\r\n otherFontSize + lineGap,\r\n mockupBounds\r\n );\r\n currentY += result.height;\r\n }\r\n\r\n if (showLabels.font && position.font) {\r\n // Render \"Font: \" với font mặc định\r\n const prefix = \"Font: \";\r\n ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const prefixWidth = ctx.measureText(prefix).width;\r\n let currentX = x + prefixWidth;\r\n ctx.fillText(prefix, x, currentY);\r\n \r\n // Render tên font với font từ config\r\n ctx.font = `${otherFontSize}px ${position.font}`;\r\n const fontNameWidth = ctx.measureText(position.font).width;\r\n ctx.fillText(position.font, currentX, currentY);\r\n currentX += fontNameWidth;\r\n \r\n // Render \"(Mặc định)\" hoặc \"(Custom)\" với font mặc định\r\n const suffix = position.is_font_default === true ? \" (Mặc định)\" : \" (Custom)\";\r\n ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const suffixWidth = ctx.measureText(suffix).width;\r\n ctx.fillText(suffix, currentX, currentY);\r\n \r\n // Tính toán height và di chuyển cursorY\r\n const lineHeight = otherFontSize + lineGap;\r\n currentY += lineHeight;\r\n }\r\n\r\n if (showLabels.color) {\r\n const colorValue = position.character_colors?.join(\", \") || position.color;\r\n if (colorValue) {\r\n const colors = position.character_colors || [position.color!];\r\n const swatchH = Math.floor(otherFontSize * LAYOUT.SWATCH_HEIGHT_RATIO);\r\n const totalSwatchWidth = calculateSwatchesWidth(colors, swatchH, scaleFactor, imageRefs);\r\n \r\n // Tính effectiveMaxWidth cho dòng này để tránh mockup\r\n const lineHeight = otherFontSize + lineGap;\r\n const effectiveMaxWidth = mockupBounds \r\n ? getEffectiveMaxWidth(x, currentY, lineHeight, maxWidth, mockupBounds)\r\n : maxWidth;\r\n \r\n // Vẽ text với effectiveMaxWidth\r\n const result = wrapText(\r\n ctx,\r\n `Màu chỉ: ${colorValue}`,\r\n x,\r\n currentY,\r\n effectiveMaxWidth,\r\n lineHeight,\r\n mockupBounds\r\n );\r\n\r\n // Kiểm tra xem có đủ chỗ cho swatches trên cùng dòng không\r\n // Sử dụng effectiveMaxWidth thay vì maxWidth\r\n const textEndX = x + Math.ceil(result.lastLineWidth);\r\n const spacing = LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n const swatchesStartX = textEndX + spacing;\r\n const swatchesEndX = swatchesStartX + totalSwatchWidth;\r\n const shouldWrapSwatches = swatchesEndX > x + effectiveMaxWidth;\r\n\r\n let swatchX: number;\r\n let swatchY: number;\r\n \r\n if (shouldWrapSwatches) {\r\n // Không đủ chỗ, cho TẤT CẢ swatches xuống dòng mới\r\n swatchX = x;\r\n swatchY = result.lastLineY + otherFontSize + lineGap;\r\n currentY += result.height + otherFontSize + lineGap;\r\n } else {\r\n // Đủ chỗ, vẽ swatches ngay sau text trên cùng dòng\r\n swatchX = swatchesStartX;\r\n swatchY = result.lastLineY + Math.floor(otherFontSize / 2 - swatchH / 2);\r\n currentY += result.height;\r\n }\r\n\r\n drawSwatches(\r\n ctx,\r\n colors,\r\n swatchX,\r\n swatchY,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\r\n \r\n if (shouldWrapSwatches) {\r\n currentY += swatchH;\r\n }\r\n }\r\n }\r\n\r\n if (showLabels.floral && position.floral_pattern) {\r\n const floralUrl = getImageUrl(\"floral\", position.floral_pattern);\r\n const floralImg = imageRefs.current.get(floralUrl);\r\n \r\n // Tính kích thước ảnh floral (thêm 50% = 2.5x otherFontSize)\r\n const floralH = otherFontSize * 2.5;\r\n let totalFloralWidth = 0;\r\n if (floralImg?.complete && floralImg.naturalHeight > 0) {\r\n const ratio = floralImg.naturalWidth / floralImg.naturalHeight;\r\n totalFloralWidth = Math.max(1, Math.floor(floralH * ratio));\r\n }\r\n \r\n // Line height giống icon_image: floralH + lineGap\r\n const floralLineHeight = floralH + lineGap;\r\n \r\n // Text align center: căn giữa theo chiều dọc trong block\r\n const textCenterY = currentY + floralH / 2;\r\n \r\n // Đo width trước khi vẽ\r\n ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const labelText = `Mẫu hoa: ${position.floral_pattern}`;\r\n const labelWidth = ctx.measureText(labelText).width;\r\n \r\n // Vẽ text với textBaseline = middle để align center\r\n ctx.textBaseline = \"middle\";\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n ctx.fillText(labelText, x, textCenterY);\r\n \r\n // Reset textBaseline về top cho các phần tiếp theo\r\n ctx.textBaseline = LAYOUT.TEXT_BASELINE;\r\n\r\n // Kiểm tra xem có đủ chỗ cho ảnh floral trên cùng dòng không\r\n const textEndX = x + labelWidth;\r\n const spacing = LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n const floralStartX = textEndX + spacing;\r\n const floralEndX = floralStartX + totalFloralWidth;\r\n const shouldWrapFloral = floralEndX > x + maxWidth;\r\n\r\n let floralX: number;\r\n let floralY: number;\r\n \r\n if (shouldWrapFloral) {\r\n // Không đủ chỗ, cho ảnh floral xuống dòng mới\r\n floralX = x;\r\n floralY = currentY + floralH + lineGap;\r\n currentY += floralLineHeight;\r\n } else {\r\n // Đủ chỗ, vẽ ảnh floral ngay sau text trên cùng dòng, align center\r\n floralX = floralStartX;\r\n floralY = textCenterY - floralH / 2; // Align center với text\r\n currentY += floralLineHeight;\r\n }\r\n\r\n // Vẽ ảnh floral\r\n if (floralImg?.complete && floralImg.naturalHeight > 0) {\r\n ctx.drawImage(floralImg, floralX, floralY, totalFloralWidth, floralH);\r\n }\r\n }\r\n }\r\n\r\n ctx.restore();\r\n // Trả về toàn bộ chiều cao đã sử dụng trong block này\r\n return currentY - y;\r\n};\r\n\r\nconst renderIconPosition = (\r\n ctx: CanvasRenderingContext2D,\r\n position: Position & { type: \"ICON\" },\r\n x: number,\r\n y: number,\r\n maxWidth: number,\r\n scaleFactor: number,\r\n imageRefs: ImageMapRef,\r\n options?: { hideColor?: boolean },\r\n mockupBounds: { x: number; y: number; width: number; height: number } | null = null\r\n): number => {\r\n // Dùng cùng font size với Text cho label và value icon\r\n const iconFontSize = LAYOUT.TEXT_FONT_SIZE * scaleFactor;\r\n const lineGap = LAYOUT.LINE_GAP * scaleFactor;\r\n\r\n ctx.save();\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n\r\n let cursorY = y;\r\n\r\n // Tách label \"Icon:\" (in đậm) và phần value (thường)\r\n const iconLabel = \"Icon:\";\r\n let iconValue: string;\r\n if (position.is_delete_icon) {\r\n // Ưu tiên hiển thị không có icon nếu được đánh dấu xóa\r\n iconValue = \"(không có icon)\";\r\n } else if (position.note) {\r\n iconValue = position.note;\r\n } else if (position.icon_name && position.icon_name.trim().length > 0) {\r\n // Nếu có icon_name thì hiển thị tên đó\r\n iconValue = position.icon_name;\r\n } else if (position.icon === 0) {\r\n // Icon mặc định theo file thêu\r\n iconValue = \"(icon mặc định theo file thêu)\";\r\n } else {\r\n // Fallback: hiển thị mã icon (ép sang string)\r\n iconValue = String(position.icon);\r\n }\r\n\r\n // Kiểm tra xem có icon_image không để tính height phù hợp\r\n const hasIconImage = position.icon_image && position.icon_image.trim().length > 0;\r\n const iconImageHeight = hasIconImage ? iconFontSize * 2 : iconFontSize;\r\n \r\n // Text align bottom: đặt text ở dưới cùng của dòng\r\n const textBottomY = cursorY + iconImageHeight;\r\n \r\n // Đo width của label\r\n ctx.font = `bold ${iconFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const labelWidth = ctx.measureText(iconLabel).width;\r\n \r\n // Icon value không cần chuẩn hóa xuống dòng, xử lý như một dòng text đơn giản\r\n // Tính kích thước icon_image nếu có để chừa khoảng trống\r\n let iconImageReservedWidth = 0;\r\n if (hasIconImage) {\r\n const iconUrl = getIconImageUrl(position);\r\n if (iconUrl) {\r\n const img = imageRefs.current.get(iconUrl);\r\n if (img?.complete && img.naturalHeight > 0) {\r\n const ratio = img.naturalWidth / img.naturalHeight;\r\n const iconHeight = iconFontSize * 2;\r\n const iconWidth = Math.max(1, Math.floor(iconHeight * ratio));\r\n iconImageReservedWidth = iconWidth + LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n }\r\n }\r\n }\r\n \r\n // Tính available width cho icon value (trừ đi khoảng trống cho icon_image)\r\n const availableWidth = Math.max(1, maxWidth - labelWidth - iconImageReservedWidth);\r\n \r\n // Tính font-size hiệu dụng cho icon value\r\n // Giới hạn thu nhỏ tối đa 50% (tối thiểu = iconFontSize * 0.5)\r\n const MIN_ICON_VALUE_FONT_SIZE = iconFontSize * 0.5;\r\n \r\n const measureIconValueWidth = (fontSize: number) => {\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n return ctx.measureText(` ${iconValue}`).width;\r\n };\r\n \r\n let effectiveIconValueFontSize = iconFontSize;\r\n const baseMaxWidth = measureIconValueWidth(iconFontSize);\r\n let needsWrap = false;\r\n \r\n if (baseMaxWidth > availableWidth) {\r\n const shrinkRatio = availableWidth / baseMaxWidth;\r\n effectiveIconValueFontSize = Math.max(MIN_ICON_VALUE_FONT_SIZE, iconFontSize * shrinkRatio);\r\n \r\n // Kiểm tra xem sau khi thu nhỏ đến 50% có vẫn overflow không\r\n const minMaxWidth = measureIconValueWidth(MIN_ICON_VALUE_FONT_SIZE);\r\n if (minMaxWidth > availableWidth) {\r\n // Vẫn overflow, cần dùng wrap text\r\n needsWrap = true;\r\n effectiveIconValueFontSize = MIN_ICON_VALUE_FONT_SIZE;\r\n }\r\n }\r\n \r\n // Tính line height và block height cho icon value\r\n const valueLineHeight = effectiveIconValueFontSize;\r\n let iconValueBlockHeight = 0;\r\n let allWrappedLines: string[] = [];\r\n \r\n // Text align center: căn giữa theo chiều dọc trong block\r\n const textCenterY = cursorY + iconImageHeight / 2;\r\n const valueStartX = x + labelWidth;\r\n \r\n if (needsWrap) {\r\n // Dùng wrap text logic\r\n const wrappedLines = buildWrappedLines(\r\n ctx,\r\n iconValue,\r\n availableWidth,\r\n valueStartX,\r\n textCenterY,\r\n valueLineHeight,\r\n mockupBounds\r\n );\r\n allWrappedLines = wrappedLines;\r\n iconValueBlockHeight = wrappedLines.length * valueLineHeight;\r\n } else {\r\n // Không cần wrap, chỉ một dòng\r\n allWrappedLines = [iconValue];\r\n iconValueBlockHeight = valueLineHeight;\r\n }\r\n \r\n // Vẽ label với textBaseline = middle để align center với value\r\n ctx.textBaseline = \"middle\";\r\n ctx.font = `bold ${iconFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n ctx.fillText(iconLabel, x, textCenterY);\r\n \r\n // Vẽ icon value với align center\r\n ctx.font = `${effectiveIconValueFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = DEFAULT_ERROR_COLOR;\r\n \r\n let maxValueLineWidth = 0;\r\n \r\n // Vẽ icon value, căn giữa theo chiều dọc\r\n if (needsWrap) {\r\n // Có nhiều dòng sau khi wrap\r\n allWrappedLines.forEach((line, index) => {\r\n const lineY = textCenterY - (allWrappedLines.length - 1) / 2 * valueLineHeight + index * valueLineHeight;\r\n \r\n // Kiểm tra overlap với mockup và điều chỉnh text nếu cần\r\n if (mockupBounds) {\r\n const effectiveMaxWidth = getEffectiveMaxWidth(valueStartX, lineY, valueLineHeight, availableWidth, mockupBounds);\r\n const lineWidth = ctx.measureText(line).width;\r\n \r\n if (lineWidth > effectiveMaxWidth) {\r\n // Cắt text cho đến khi vừa với effectiveMaxWidth\r\n let truncatedLine = line;\r\n while (ctx.measureText(truncatedLine).width > effectiveMaxWidth && truncatedLine.length > 0) {\r\n truncatedLine = truncatedLine.slice(0, -1);\r\n }\r\n ctx.fillText(truncatedLine, valueStartX, lineY);\r\n const w = ctx.measureText(truncatedLine).width;\r\n if (w > maxValueLineWidth) maxValueLineWidth = w;\r\n } else {\r\n ctx.fillText(line, valueStartX, lineY);\r\n const w = ctx.measureText(line).width;\r\n if (w > maxValueLineWidth) maxValueLineWidth = w;\r\n }\r\n } else {\r\n ctx.fillText(line, valueStartX, lineY);\r\n const w = ctx.measureText(line).width;\r\n if (w > maxValueLineWidth) maxValueLineWidth = w;\r\n }\r\n });\r\n } else {\r\n // Chỉ một dòng, căn giữa\r\n const lineText = ` ${iconValue}`;\r\n \r\n // Kiểm tra overlap với mockup và điều chỉnh text nếu cần\r\n if (mockupBounds) {\r\n const effectiveMaxWidth = getEffectiveMaxWidth(valueStartX, textCenterY, valueLineHeight, availableWidth, mockupBounds);\r\n const lineWidth = ctx.measureText(lineText).width;\r\n \r\n if (lineWidth > effectiveMaxWidth) {\r\n // Cắt text cho đến khi vừa với effectiveMaxWidth\r\n let truncatedLine = lineText;\r\n while (ctx.measureText(truncatedLine).width > effectiveMaxWidth && truncatedLine.length > 0) {\r\n truncatedLine = truncatedLine.slice(0, -1);\r\n }\r\n ctx.fillText(truncatedLine, valueStartX, textCenterY);\r\n const w = ctx.measureText(truncatedLine).width;\r\n if (w > maxValueLineWidth) maxValueLineWidth = w;\r\n } else {\r\n ctx.fillText(lineText, valueStartX, textCenterY);\r\n const w = ctx.measureText(lineText).width;\r\n if (w > maxValueLineWidth) maxValueLineWidth = w;\r\n }\r\n } else {\r\n ctx.fillText(lineText, valueStartX, textCenterY);\r\n const w = ctx.measureText(lineText).width;\r\n if (w > maxValueLineWidth) maxValueLineWidth = w;\r\n }\r\n }\r\n \r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n \r\n // Reset textBaseline về top cho các phần tiếp theo\r\n ctx.textBaseline = LAYOUT.TEXT_BASELINE;\r\n \r\n const iconResult = {\r\n height: iconImageHeight + lineGap,\r\n // tổng width của cả label + value, dùng để canh icon image lệch sang phải\r\n lastLineWidth: labelWidth + maxValueLineWidth,\r\n lastLineY: textCenterY, // Dùng textCenterY thay vì textBottomY\r\n };\r\n\r\n // Kiểm tra xem phần icon image có vượt quá canvas không trước khi render\r\n // Draw icon image (không tự cắt theo canvasHeight, việc đảm bảo fit do scaleFactor xử lý)\r\n const iconUrl = getIconImageUrl(position);\r\n\r\n if (iconUrl) {\r\n const img = imageRefs.current.get(iconUrl);\r\n if (img?.complete && img.naturalHeight > 0) {\r\n const ratio = img.naturalWidth / img.naturalHeight;\r\n // Nếu có icon_image thì hiển thị to gấp đôi\r\n const iconHeight = hasIconImage ? iconFontSize * 2 : iconFontSize;\r\n const swatchW = Math.max(1, Math.floor(iconHeight * ratio));\r\n const iconX =\r\n x +\r\n Math.ceil(iconResult.lastLineWidth) +\r\n LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n const iconY =\r\n textCenterY - iconHeight / 2; // Align center với text\r\n ctx.drawImage(img, iconX, iconY, swatchW, iconHeight);\r\n }\r\n }\r\n \r\n cursorY += iconResult.height;\r\n\r\n // Draw color swatches (prefer layer_colors, fallback to single color)\r\n // Nếu icon đã bị xóa thì không cần hiển thị màu chỉ nữa\r\n const iconColors = position.is_delete_icon\r\n ? null\r\n : position.layer_colors?.length\r\n ? position.layer_colors\r\n : position.color\r\n ? [position.color]\r\n : null;\r\n const layerCount = position.layer_colors?.length ?? 0;\r\n const hasMultiLayerColors = layerCount > 1;\r\n const shouldSkipColorSection = options?.hideColor && !hasMultiLayerColors;\r\n\r\n if (iconColors?.length && !shouldSkipColorSection) {\r\n // Dòng \"Màu chỉ:\" của icon dùng OTHER_FONT_SIZE, không dùng iconFontSize\r\n const otherFontSize = LAYOUT.OTHER_FONT_SIZE * scaleFactor;\r\n const swatchH = Math.floor(otherFontSize * LAYOUT.SWATCH_HEIGHT_RATIO);\r\n const totalSwatchWidth = calculateSwatchesWidth(iconColors, swatchH, scaleFactor, imageRefs);\r\n \r\n // Tính effectiveMaxWidth cho dòng này để tránh mockup\r\n const lineHeight = otherFontSize + lineGap;\r\n const effectiveMaxWidth = mockupBounds \r\n ? getEffectiveMaxWidth(x, cursorY, lineHeight, maxWidth, mockupBounds)\r\n : maxWidth;\r\n \r\n // Tính toán trước để kiểm tra xem có đủ chỗ không\r\n // Đo chiều cao của text \"Màu chỉ:\" trước\r\n ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const testText = `Màu chỉ: ${iconColors.join(\", \")}`;\r\n const testLines = buildWrappedLines(\r\n ctx,\r\n testText,\r\n effectiveMaxWidth,\r\n x,\r\n cursorY,\r\n lineHeight,\r\n mockupBounds\r\n );\r\n const estimatedTextHeight = testLines.length * lineHeight;\r\n \r\n // Kiểm tra xem có đủ chỗ cho swatches trên cùng dòng không\r\n const testTextWidth = Math.max(...testLines.map(line => ctx.measureText(line).width));\r\n const textEndX = x + testTextWidth;\r\n const spacing = LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n const swatchesStartX = textEndX + spacing;\r\n const swatchesEndX = swatchesStartX + totalSwatchWidth;\r\n const shouldWrapSwatches = swatchesEndX > x + effectiveMaxWidth;\r\n \r\n // Tính vị trí Y dự kiến của swatches\r\n let expectedSwatchY: number;\r\n if (shouldWrapSwatches) {\r\n // Swatches xuống dòng mới\r\n expectedSwatchY = cursorY + estimatedTextHeight;\r\n } else {\r\n // Swatches trên cùng dòng với text\r\n const lastLineY = cursorY + (testLines.length - 1) * lineHeight;\r\n expectedSwatchY = lastLineY + Math.floor(otherFontSize / 2 - swatchH / 2);\r\n }\r\n \r\n // Luôn render text và swatches; đảm bảo fit bằng scaleFactor ở tầng trên\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n const colorResult = wrapText(\r\n ctx,\r\n testText,\r\n x,\r\n cursorY,\r\n effectiveMaxWidth,\r\n lineHeight,\r\n mockupBounds\r\n );\r\n\r\n // Cập nhật cursorY sau khi render text\r\n cursorY += colorResult.height;\r\n \r\n let swatchX: number;\r\n let swatchY: number;\r\n \r\n if (shouldWrapSwatches) {\r\n // Không đủ chỗ, cho TẤT CẢ swatches xuống dòng mới\r\n swatchX = x;\r\n swatchY = cursorY;\r\n \r\n // Render swatches (đã kiểm tra overflow ở trên)\r\n drawSwatches(ctx, iconColors, swatchX, swatchY, swatchH, scaleFactor, imageRefs);\r\n cursorY = swatchY + swatchH;\r\n } else {\r\n // Đủ chỗ, vẽ swatches ngay sau text trên cùng dòng\r\n swatchX = swatchesStartX;\r\n swatchY = colorResult.lastLineY + Math.floor(otherFontSize / 2 - swatchH / 2);\r\n \r\n // Render swatches (đã kiểm tra overflow ở trên)\r\n drawSwatches(ctx, iconColors, swatchX, swatchY, swatchH, scaleFactor, imageRefs);\r\n // cursorY đã được cập nhật ở trên\r\n }\r\n }\r\n\r\n ctx.restore();\r\n return cursorY - y;\r\n};\r\n\r\nconst prepareExportCanvas = async (\r\n config: EmbroideryQCConfig,\r\n options: EmbroideryQCImageRenderOptions = {}\r\n): Promise<HTMLCanvasElement | null> => {\r\n const { width = 4200, height = 4800 } = options;\r\n\r\n const canvas = document.createElement(\"canvas\");\r\n const imageRefs: ImageMapRef = {\r\n current: new Map<string, HTMLImageElement>(),\r\n };\r\n\r\n // Load fonts and images in parallel\r\n await Promise.all([\r\n preloadFonts(config),\r\n preloadImages(config, imageRefs)\r\n ]);\r\n\r\n renderEmbroideryCanvas(canvas, config, { width, height }, imageRefs);\r\n\r\n if (!canvas.width || !canvas.height) {\r\n return null;\r\n }\r\n\r\n return canvas;\r\n};\r\n\r\nexport const generateEmbroideryQCImageBlob = async (\r\n config: EmbroideryQCConfig,\r\n options: EmbroideryQCImageRenderOptions = {}\r\n): Promise<Blob | null> => {\r\n if (typeof document === \"undefined\") {\r\n throw new Error(\r\n \"generateEmbroideryQCImageBlob requires a browser environment.\"\r\n );\r\n }\r\n\r\n if (!config) {\r\n throw new Error(\"config is required\");\r\n }\r\n\r\n const { mimeType = \"image/png\", quality } = options;\r\n\r\n const canvas = await prepareExportCanvas(config, options);\r\n if (!canvas || typeof canvas.toBlob !== \"function\") {\r\n return null;\r\n }\r\n\r\n const blob = await new Promise<Blob | null>((resolve) => {\r\n canvas.toBlob((result) => resolve(result), mimeType, quality);\r\n });\r\n\r\n return blob;\r\n};\r\n\r\nexport const generateEmbroideryQCImageData = async (\r\n config: EmbroideryQCConfig,\r\n options: EmbroideryQCImageRenderOptions = {}\r\n): Promise<string | null> => {\r\n if (typeof document === \"undefined\") {\r\n throw new Error(\r\n \"generateEmbroideryQCImageData requires a browser environment.\"\r\n );\r\n }\r\n\r\n if (!config) {\r\n throw new Error(\"config is required\");\r\n };\r\n\r\n const { mimeType = \"image/png\", quality } = options;\r\n\r\n const canvas = await prepareExportCanvas(config, options);\r\n if (!canvas) {\r\n return null;\r\n }\r\n\r\n if (mimeType === \"image/png\" || typeof quality === \"undefined\") {\r\n return canvas.toDataURL(mimeType);\r\n }\r\n\r\n return canvas.toDataURL(mimeType, quality);\r\n};\r\n\r\nexport default EmbroideryQCImage;\r\n"],"names":["_jsx"],"mappings":"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","x_google_ignoreList":[0]}