embroidery-qc-image 1.0.33 → 1.0.35

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 = (\r\n position: Position & { type: \"ICON\" }\r\n): 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\r\n ? getProxyUrl(getResizeUrl(url))\r\n : 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 // Load layer_colors for TEXT (used in stroke_patches and template_custom_text_patches)\r\n position.layer_colors?.forEach((color) => {\r\n const layerColorUrl = getImageUrl(\"threadColor\", color);\r\n if (!seen.has(layerColorUrl)) {\r\n entries.push({ url: layerColorUrl });\r\n seen.add(layerColorUrl);\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: {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n } | 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(\r\n x,\r\n currentY,\r\n lineHeight,\r\n maxWidth,\r\n mockupBounds\r\n );\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(\r\n x,\r\n currentY,\r\n lineHeight,\r\n maxWidth,\r\n mockupBounds\r\n );\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 (\r\n ctx.measureText(lineToRender).width > effectiveMaxWidth &&\r\n lineToRender.length > 0\r\n ) {\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: {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n } | 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 =\r\n lineHeight > 0\r\n ? getEffectiveMaxWidth(\r\n startX,\r\n currentY,\r\n lineHeight,\r\n maxWidth,\r\n mockupBounds\r\n )\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 // Load layer_colors for TEXT (used in stroke_patches and template_custom_text_patches)\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 });\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 renderStrokePatchesCanvas = (\r\n ctx: CanvasRenderingContext2D,\r\n canvas: HTMLCanvasElement,\r\n config: EmbroideryQCConfig,\r\n imageRefs: ImageMapRef\r\n) => {\r\n // Clear canvas\r\n ctx.fillStyle = \"#e7e7e7\";\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n const padding = LAYOUT.PADDING * 6;\r\n const usableWidth = canvas.width - padding * 2;\r\n const usableHeight = canvas.height - padding * 2;\r\n\r\n // Calculate sections\r\n const topSectionHeight = Math.floor(usableHeight * (2 / 3)); // 2/3 top\r\n const bottomSectionHeight = usableHeight - topSectionHeight; // 1/3 bottom\r\n\r\n const topSectionY = padding;\r\n const bottomSectionY = topSectionY + topSectionHeight;\r\n\r\n // Get first side (stroke_patches should have only one side)\r\n const side = config.sides[0];\r\n if (!side || !side.positions.length) {\r\n renderErrorState(ctx, canvas, \"Không có dữ liệu positions\");\r\n return;\r\n }\r\n\r\n const position = side.positions[0];\r\n if (position.type !== \"TEXT\") {\r\n renderErrorState(ctx, canvas, \"Position phải là TEXT\");\r\n return;\r\n }\r\n\r\n if (!position.layer_colors || position.layer_colors.length < 3) {\r\n renderErrorState(ctx, canvas, \"Không có đủ màu cho stroke patches\");\r\n return;\r\n }\r\n\r\n // Get layer colors with empty check (don't use fallback)\r\n const textColor = position.layer_colors[0];\r\n const borderColor = position.layer_colors[1];\r\n const backgroundColor = position.layer_colors[2];\r\n const fabricColor = position.layer_colors?.[3]; // Màu vải\r\n\r\n // For rendering, use fallback colors (fabricColor không cần fallback vì chỉ hiển thị)\r\n const textColorForRender = textColor;\r\n const borderColorForRender = borderColor;\r\n const backgroundColorForRender = backgroundColor;\r\n\r\n // Check if font is missing (but continue rendering)\r\n const isFontMissing = !position.font || position.font.trim() === \"\";\r\n\r\n // ============================================================================\r\n // TOP SECTION (2/3): Hiển thị mẫu preview\r\n // ============================================================================\r\n ctx.save();\r\n\r\n // Draw \"Hình mẫu:\" label at the top\r\n const titleFontSize = LAYOUT.HEADER_FONT_SIZE * 0.8;\r\n ctx.font = `bold ${titleFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = \"#CC0000\"; // Red color\r\n ctx.fillText(\"Hình mẫu:\", padding, topSectionY);\r\n\r\n // Adjust top section Y to account for title + extra spacing (40px)\r\n const extraSpacing = 40;\r\n const actualTopSectionY =\r\n topSectionY + titleFontSize + LAYOUT.LINE_GAP + extraSpacing;\r\n const actualTopSectionHeight =\r\n topSectionHeight - titleFontSize - LAYOUT.LINE_GAP - extraSpacing;\r\n\r\n // Calculate text size to fit top section\r\n let previewFontSize = LAYOUT.HEADER_FONT_SIZE * 3; // Start with large size\r\n const fontToUse = isFontMissing ? LAYOUT.FONT_FAMILY : position.font;\r\n ctx.font = `${previewFontSize}px ${fontToUse}`;\r\n\r\n const text = position.text || \"\";\r\n const maxTextWidth = usableWidth * 0.9; // Use 75% of width for better padding\r\n const maxTextHeight = actualTopSectionHeight; // Use 60% of height\r\n\r\n // Scale down font size to fit\r\n let textWidth = ctx.measureText(text).width;\r\n while (textWidth > maxTextWidth && previewFontSize > 50) {\r\n previewFontSize *= 0.95;\r\n ctx.font = `${previewFontSize}px ${fontToUse}`;\r\n textWidth = ctx.measureText(text).width;\r\n }\r\n\r\n // Ensure text height also fits\r\n while (previewFontSize > maxTextHeight && previewFontSize > 50) {\r\n previewFontSize *= 0.95;\r\n ctx.font = `${previewFontSize}px ${fontToUse}`;\r\n }\r\n\r\n // Update textWidth after final scaling\r\n textWidth = ctx.measureText(text).width;\r\n\r\n // Center the text in top section\r\n const textX = padding + usableWidth / 2 - textWidth / 2;\r\n const textY =\r\n actualTopSectionY + actualTopSectionHeight / 2 - previewFontSize / 2;\r\n\r\n // Get color hex values (use render colors with fallback)\r\n const textColorHex = COLOR_MAP[textColorForRender] || LAYOUT.LABEL_COLOR;\r\n const borderColorHex = COLOR_MAP[borderColorForRender] || LAYOUT.LABEL_COLOR;\r\n const bgColorHex = COLOR_MAP[backgroundColorForRender] || \"#FFFFFF\";\r\n\r\n // Calculate stroke widths\r\n // Background needs to be MUCH thicker to create spacing from text\r\n // Border needs to be even thicker to wrap around background\r\n const bgWidth = Math.max(80, previewFontSize / 2); // Background - rất dày để tạo khoảng cách lớn\r\n const borderWidth = Math.max(100, previewFontSize / 1.58); // Border - dày hơn để bọc background\r\n\r\n // Layer 1: Draw border stroke (outermost)\r\n ctx.strokeStyle = borderColorHex;\r\n ctx.lineWidth = borderWidth;\r\n ctx.lineJoin = \"round\";\r\n ctx.lineCap = \"round\";\r\n ctx.strokeText(text, textX, textY);\r\n\r\n // Layer 2: Draw background color stroke (middle - creates spacing from text)\r\n ctx.strokeStyle = bgColorHex;\r\n ctx.lineWidth = bgWidth;\r\n ctx.lineJoin = \"round\";\r\n ctx.lineCap = \"round\";\r\n ctx.strokeText(text, textX, textY);\r\n\r\n // Layer 3: Draw text fill ONLY (no stroke on text itself)\r\n ctx.fillStyle = textColorHex;\r\n ctx.fillText(text, textX, textY);\r\n\r\n ctx.restore();\r\n\r\n // ============================================================================\r\n // BOTTOM SECTION (1/3): Flex layout with info (left) and image (right)\r\n // ============================================================================\r\n ctx.save();\r\n\r\n // Draw border around bottom section for debugging\r\n // ctx.strokeStyle = \"#ccc\";\r\n // ctx.lineWidth = 2;\r\n // ctx.strokeRect(padding, bottomSectionY, usableWidth, bottomSectionHeight);\r\n\r\n const bottomPadding = 0; // Không padding ngang, sát lề\r\n const bottomUsableWidth = usableWidth; // Sử dụng toàn bộ width\r\n const bottomUsableHeight = bottomSectionHeight - LAYOUT.PADDING * 2; // Chỉ padding dọc\r\n\r\n // Split bottom section: 60% left for info, 40% right for image\r\n const infoSectionWidth = Math.floor(bottomUsableWidth * 0.6);\r\n const imageSectionWidth = bottomUsableWidth - infoSectionWidth;\r\n const imageSectionX = padding + infoSectionWidth;\r\n\r\n // Left side: Info list\r\n const infoFontSize = LAYOUT.OTHER_FONT_SIZE * 0.9; // Giảm từ 1.2 xuống 0.9\r\n const infoLineHeight = infoFontSize * 1.4; // Giảm từ 1.5 xuống 1.4\r\n let infoY = bottomSectionY + LAYOUT.PADDING;\r\n\r\n ctx.font = `${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n ctx.textAlign = \"left\";\r\n ctx.textBaseline = \"top\";\r\n\r\n // Asterisk prefix style\r\n const drawAsterisk = (x: number, y: number) => {\r\n ctx.save();\r\n ctx.fillStyle = \"#CC0000\"; // Red asterisk\r\n ctx.font = `bold ${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillText(\"*\", x, y);\r\n ctx.restore();\r\n };\r\n\r\n const asteriskWidth = ctx.measureText(\"*\").width + 5;\r\n const startX = padding + asteriskWidth;\r\n\r\n // Font - render \"Font: \" với font mặc định, tên font với font đó\r\n drawAsterisk(padding, infoY);\r\n const fontPrefix = \"Font: \";\r\n ctx.font = `${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillText(fontPrefix, startX, infoY);\r\n\r\n if (isFontMissing) {\r\n // Hiển thị warning màu đỏ nếu thiếu font\r\n ctx.fillStyle = \"#CC0000\"; // Red color\r\n ctx.fillText(\r\n \"(Đang thiếu font chữ)\",\r\n startX + ctx.measureText(fontPrefix).width,\r\n infoY\r\n );\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Render font name với chính font đó\r\n const prefixWidth = ctx.measureText(fontPrefix).width;\r\n const fontName = position.font || LAYOUT.FONT_FAMILY;\r\n ctx.font = `${infoFontSize}px ${fontName}`;\r\n ctx.fillText(fontName, startX + prefixWidth, infoY);\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Reset font về mặc định cho các dòng tiếp theo\r\n ctx.font = `${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n\r\n // Màu chữ (Text Color) - layer_colors[0]\r\n drawAsterisk(padding, infoY);\r\n const textColorPrefix = \"Màu chữ: \";\r\n ctx.fillText(textColorPrefix, startX, infoY);\r\n\r\n if (!textColor || textColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(textColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(textColorPrefix).width;\r\n ctx.fillText(textColor, startX + prefixWidth, infoY);\r\n\r\n // Draw text color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const swatchX =\r\n startX +\r\n ctx.measureText(textColorPrefix + textColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const swatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const textColorSwatchUrl = getImageUrl(\"threadColor\", textColor);\r\n const textColorSwatchImg = imageRefs.current.get(textColorSwatchUrl);\r\n if (textColorSwatchImg?.complete && textColorSwatchImg.naturalHeight > 0) {\r\n const ratio =\r\n textColorSwatchImg.naturalWidth / textColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(textColorSwatchImg, swatchX, swatchY, swatchW, swatchSize);\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Màu nền (Background Color) - layer_colors[2]\r\n drawAsterisk(padding, infoY);\r\n const bgColorPrefix = \"Màu nền: \";\r\n ctx.fillText(bgColorPrefix, startX, infoY);\r\n\r\n if (!backgroundColor || backgroundColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(bgColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(bgColorPrefix).width;\r\n ctx.fillText(backgroundColor, startX + prefixWidth, infoY);\r\n\r\n // Draw background color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const bgSwatchX =\r\n startX +\r\n ctx.measureText(bgColorPrefix + backgroundColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const bgSwatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const bgColorSwatchUrl = getImageUrl(\"threadColor\", backgroundColor);\r\n const bgColorSwatchImg = imageRefs.current.get(bgColorSwatchUrl);\r\n if (bgColorSwatchImg?.complete && bgColorSwatchImg.naturalHeight > 0) {\r\n const ratio =\r\n bgColorSwatchImg.naturalWidth / bgColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(\r\n bgColorSwatchImg,\r\n bgSwatchX,\r\n bgSwatchY,\r\n swatchW,\r\n swatchSize\r\n );\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Màu viền (Border Color) - layer_colors[1]\r\n drawAsterisk(padding, infoY);\r\n const borderColorPrefix = \"Màu viền: \";\r\n ctx.fillText(borderColorPrefix, startX, infoY);\r\n\r\n if (!borderColor || borderColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(borderColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(borderColorPrefix).width;\r\n ctx.fillText(borderColor, startX + prefixWidth, infoY);\r\n\r\n // Draw border color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const borderSwatchX =\r\n startX +\r\n ctx.measureText(borderColorPrefix + borderColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const borderSwatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const borderColorSwatchUrl = getImageUrl(\"threadColor\", borderColor);\r\n const borderColorSwatchImg = imageRefs.current.get(borderColorSwatchUrl);\r\n if (\r\n borderColorSwatchImg?.complete &&\r\n borderColorSwatchImg.naturalHeight > 0\r\n ) {\r\n const ratio =\r\n borderColorSwatchImg.naturalWidth / borderColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(\r\n borderColorSwatchImg,\r\n borderSwatchX,\r\n borderSwatchY,\r\n swatchW,\r\n swatchSize\r\n );\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Màu vải (Fabric Color) - layer_colors[3]\r\n drawAsterisk(padding, infoY);\r\n const fabricColorPrefix = \"Màu vải: \";\r\n ctx.fillText(fabricColorPrefix, startX, infoY);\r\n\r\n if (!fabricColor || fabricColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(fabricColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(fabricColorPrefix).width;\r\n ctx.fillText(fabricColor, startX + prefixWidth, infoY);\r\n\r\n // Draw fabric color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const fabricSwatchX =\r\n startX +\r\n ctx.measureText(fabricColorPrefix + fabricColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const fabricSwatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const fabricColorSwatchUrl = getImageUrl(\"threadColor\", fabricColor);\r\n const fabricColorSwatchImg = imageRefs.current.get(fabricColorSwatchUrl);\r\n if (\r\n fabricColorSwatchImg?.complete &&\r\n fabricColorSwatchImg.naturalHeight > 0\r\n ) {\r\n const ratio =\r\n fabricColorSwatchImg.naturalWidth / fabricColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(\r\n fabricColorSwatchImg,\r\n fabricSwatchX,\r\n fabricSwatchY,\r\n swatchW,\r\n swatchSize\r\n );\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Attachment\r\n if (position.attachment) {\r\n drawAsterisk(padding + bottomPadding, infoY);\r\n const attachmentLabel = `Attachment: ${position.attachment}`;\r\n ctx.fillText(attachmentLabel, startX, infoY);\r\n infoY += infoLineHeight;\r\n }\r\n\r\n // Size\r\n if (side.size) {\r\n drawAsterisk(padding + bottomPadding, infoY);\r\n const sizeLabel = `Size: ${side.size}`;\r\n ctx.fillText(sizeLabel, startX, infoY);\r\n infoY += infoLineHeight;\r\n }\r\n\r\n // Right side: Image from config.image_url\r\n if (config.image_url) {\r\n // Draw \"Mockup\" label\r\n ctx.font = `bold ${infoFontSize * 1.2}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = \"#000000\";\r\n const mockupLabel = \"Mockup\";\r\n const mockupLabelWidth = ctx.measureText(mockupLabel).width;\r\n const mockupLabelX =\r\n imageSectionX + (imageSectionWidth - mockupLabelWidth) / 1.2;\r\n ctx.fillText(mockupLabel, mockupLabelX, bottomSectionY + LAYOUT.PADDING);\r\n\r\n const mockupLabelHeight = infoFontSize * 1.2 + LAYOUT.LINE_GAP * 0.5;\r\n\r\n const img =\r\n imageRefs.current.get(config.image_url) ??\r\n imageRefs.current.get(\"mockup\");\r\n if (img?.complete && img.naturalWidth > 0) {\r\n const maxImgWidth = imageSectionWidth; // Sử dụng toàn bộ width, sát lề phải\r\n const maxImgHeight = bottomUsableHeight - mockupLabelHeight;\r\n\r\n const imgAspectRatio = img.naturalWidth / img.naturalHeight;\r\n let drawWidth = maxImgWidth;\r\n let drawHeight = drawWidth / imgAspectRatio;\r\n\r\n if (drawHeight > maxImgHeight) {\r\n drawHeight = maxImgHeight;\r\n drawWidth = drawHeight * imgAspectRatio;\r\n }\r\n\r\n const imgX = imageSectionX + (imageSectionWidth - drawWidth) / 0.8;\r\n const imgY =\r\n bottomSectionY +\r\n LAYOUT.PADDING +\r\n mockupLabelHeight +\r\n (bottomUsableHeight - mockupLabelHeight - drawHeight) / 2;\r\n\r\n ctx.drawImage(img, imgX, imgY, drawWidth, drawHeight);\r\n }\r\n }\r\n\r\n ctx.restore();\r\n};\r\n\r\n// Helper function để parse size từ string như \"3 X 3 INCHES\"\r\nconst parseSize = (sizeStr: string): { width: number; height: number } | null => {\r\n if (!sizeStr || typeof sizeStr !== \"string\") return null;\r\n \r\n // Pattern để match \"3 X 3 INCHES\" hoặc \"3x3\" hoặc \"3 X 3\"\r\n const match = sizeStr.match(/(\\d+(?:\\.\\d+)?)\\s*[xX]\\s*(\\d+(?:\\.\\d+)?)/i);\r\n if (!match) return null;\r\n \r\n const width = parseFloat(match[1]);\r\n const height = parseFloat(match[2]);\r\n \r\n if (isNaN(width) || isNaN(height) || width <= 0 || height <= 0) return null;\r\n \r\n return { width, height };\r\n};\r\n\r\nconst renderTemplateCustomTextPatchesCanvas = (\r\n ctx: CanvasRenderingContext2D,\r\n canvas: HTMLCanvasElement,\r\n config: EmbroideryQCConfig,\r\n imageRefs: ImageMapRef\r\n) => {\r\n // Clear canvas\r\n ctx.fillStyle = \"#e7e7e7\";\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n const padding = LAYOUT.PADDING * 6;\r\n const usableWidth = canvas.width - padding * 2;\r\n const usableHeight = canvas.height - padding * 2;\r\n\r\n // Calculate sections\r\n const topSectionHeight = Math.floor(usableHeight * (2 / 3)); // 2/3 top\r\n const bottomSectionHeight = usableHeight - topSectionHeight; // 1/3 bottom\r\n\r\n const topSectionY = padding;\r\n const bottomSectionY = topSectionY + topSectionHeight;\r\n\r\n // Get first side (template_custom_text_patches should have only one side)\r\n const side = config.sides[0];\r\n if (!side || !side.positions.length) {\r\n renderErrorState(ctx, canvas, \"Không có dữ liệu positions\");\r\n return;\r\n }\r\n\r\n const position = side.positions[0];\r\n if (position.type !== \"TEXT\") {\r\n renderErrorState(ctx, canvas, \"Position phải là TEXT\");\r\n return;\r\n }\r\n\r\n if (!position.layer_colors || position.layer_colors.length < 3) {\r\n renderErrorState(ctx, canvas, \"Không có đủ màu cho template custom text patches\");\r\n return;\r\n }\r\n\r\n // Parse size từ side.size\r\n const parsedSize = side.size ? parseSize(side.size) : null;\r\n if (!parsedSize) {\r\n renderErrorState(ctx, canvas, \"Không thể parse size từ dữ liệu\");\r\n return;\r\n }\r\n\r\n // Get layer colors\r\n const textColor = position.layer_colors[0];\r\n const borderColor = position.layer_colors[1];\r\n const backgroundColor = position.layer_colors[2];\r\n const fabricColor = position.layer_colors?.[3]; // Màu vải\r\n\r\n // Check if font is missing (but continue rendering)\r\n const isFontMissing = !position.font || position.font.trim() === \"\";\r\n\r\n // ============================================================================\r\n // TOP SECTION (2/3): Hiển thị mẫu preview với khung hình chữ nhật\r\n // ============================================================================\r\n ctx.save();\r\n\r\n // Draw \"Hình mẫu:\" label at the top\r\n const titleFontSize = LAYOUT.HEADER_FONT_SIZE * 0.8;\r\n ctx.font = `bold ${titleFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = \"#CC0000\"; // Red color\r\n ctx.fillText(\"Hình mẫu:\", padding, topSectionY);\r\n\r\n // Adjust top section Y to account for title + extra spacing (40px)\r\n const extraSpacing = 40;\r\n const actualTopSectionY =\r\n topSectionY + titleFontSize + LAYOUT.LINE_GAP + extraSpacing;\r\n const actualTopSectionHeight =\r\n topSectionHeight - titleFontSize - LAYOUT.LINE_GAP - extraSpacing;\r\n\r\n // Tính kích thước khung hình chữ nhật dựa trên tỉ lệ size\r\n // Sử dụng tỉ lệ width/height từ parsedSize để giữ đúng aspect ratio\r\n const sizeAspectRatio = parsedSize.width / parsedSize.height;\r\n \r\n // Tính kích thước khung để fit trong top section\r\n let rectWidth = Math.min(usableWidth * 0.9, actualTopSectionHeight * sizeAspectRatio);\r\n let rectHeight = rectWidth / sizeAspectRatio;\r\n \r\n if (rectHeight > actualTopSectionHeight * 0.9) {\r\n rectHeight = actualTopSectionHeight * 0.9;\r\n rectWidth = rectHeight * sizeAspectRatio;\r\n }\r\n\r\n // Center the rectangle in top section\r\n const rectX = padding + usableWidth / 2 - rectWidth / 2;\r\n const rectY = actualTopSectionY + actualTopSectionHeight / 2 - rectHeight / 2;\r\n\r\n // Get color hex values\r\n const textColorHex = COLOR_MAP[textColor] || LAYOUT.LABEL_COLOR;\r\n const borderColorHex = COLOR_MAP[borderColor] || LAYOUT.LABEL_COLOR;\r\n const bgColorHex = COLOR_MAP[backgroundColor] || \"#FFFFFF\";\r\n\r\n // Border width gấp đôi: 4% của rectWidth, tối thiểu 40px\r\n const borderWidth = Math.max(40, rectWidth * 0.04);\r\n \r\n // Border radius để bo tròn góc\r\n const borderRadius = Math.min(rectWidth, rectHeight) * 0.08; // 8% của cạnh nhỏ hơn\r\n\r\n // Draw rectangle background với border radius\r\n ctx.fillStyle = bgColorHex;\r\n ctx.beginPath();\r\n ctx.roundRect(rectX, rectY, rectWidth, rectHeight, borderRadius);\r\n ctx.fill();\r\n\r\n // Draw rectangle border với border radius\r\n ctx.strokeStyle = borderColorHex;\r\n ctx.lineWidth = borderWidth;\r\n ctx.beginPath();\r\n ctx.roundRect(rectX, rectY, rectWidth, rectHeight, borderRadius);\r\n ctx.stroke();\r\n\r\n // Calculate text size to fit inside rectangle (với padding rất nhỏ)\r\n // Padding chỉ chừa một chút để tránh text chạm border\r\n const textPadding = Math.max(30, rectWidth * 0.03); // 3% padding, tối thiểu 30px\r\n const maxTextWidth = rectWidth - textPadding * 2 - borderWidth;\r\n const maxTextHeight = rectHeight - textPadding * 2 - borderWidth;\r\n\r\n const text = position.text || \"\";\r\n const textLines = text.split(\"\\n\");\r\n const fontToUse = isFontMissing ? LAYOUT.FONT_FAMILY : position.font;\r\n\r\n // Tìm font size tối đa để text vừa trong khung\r\n // Bắt đầu với kích thước lớn và giảm dần\r\n let previewFontSize = Math.min(rectWidth, rectHeight) * 0.8; // Start với 80% của cạnh nhỏ hơn\r\n let bestFontSize = 30; // Minimum font size\r\n \r\n // Binary search để tìm font size tối đa\r\n let low = 30;\r\n let high = previewFontSize;\r\n \r\n while (high - low > 1) {\r\n const mid = (low + high) / 2;\r\n ctx.font = `${mid}px ${fontToUse}`;\r\n \r\n // Kiểm tra width của tất cả các dòng\r\n const maxLineWidth = Math.max(...textLines.map(line => ctx.measureText(line).width));\r\n \r\n // Kiểm tra height với line height = 1.1 (giảm từ 1.2 để text to hơn)\r\n const lineHeight = mid * 1.1;\r\n const totalTextHeight = textLines.length * lineHeight;\r\n \r\n if (maxLineWidth <= maxTextWidth && totalTextHeight <= maxTextHeight) {\r\n // Font size này vừa, thử tăng lên\r\n bestFontSize = mid;\r\n low = mid;\r\n } else {\r\n // Font size này quá lớn, giảm xuống\r\n high = mid;\r\n }\r\n }\r\n \r\n previewFontSize = bestFontSize;\r\n ctx.font = `${previewFontSize}px ${fontToUse}`;\r\n\r\n // Center the text inside rectangle\r\n const finalLineHeight = previewFontSize * 1.1;\r\n const totalTextHeightFinal = textLines.length * finalLineHeight;\r\n const textStartY = rectY + rectHeight / 2 - totalTextHeightFinal / 2;\r\n\r\n // Draw text inside rectangle\r\n ctx.fillStyle = textColorHex;\r\n ctx.textAlign = \"center\";\r\n ctx.textBaseline = \"top\";\r\n textLines.forEach((line, index) => {\r\n const lineY = textStartY + index * finalLineHeight;\r\n ctx.fillText(line, rectX + rectWidth / 2, lineY);\r\n });\r\n\r\n ctx.restore();\r\n\r\n // ============================================================================\r\n // BOTTOM SECTION (1/3): Flex layout with info (left) and image (right)\r\n // ============================================================================\r\n ctx.save();\r\n\r\n const bottomPadding = 0; // Không padding ngang, sát lề\r\n const bottomUsableWidth = usableWidth; // Sử dụng toàn bộ width\r\n const bottomUsableHeight = bottomSectionHeight - LAYOUT.PADDING * 2; // Chỉ padding dọc\r\n\r\n // Split bottom section: 60% left for info, 40% right for image\r\n const infoSectionWidth = Math.floor(bottomUsableWidth * 0.6);\r\n const imageSectionWidth = bottomUsableWidth - infoSectionWidth;\r\n const imageSectionX = padding + infoSectionWidth;\r\n\r\n // Left side: Info list\r\n const infoFontSize = LAYOUT.OTHER_FONT_SIZE * 0.9;\r\n const infoLineHeight = infoFontSize * 1.4;\r\n let infoY = bottomSectionY + LAYOUT.PADDING;\r\n\r\n ctx.font = `${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n ctx.textAlign = \"left\";\r\n ctx.textBaseline = \"top\";\r\n\r\n // Asterisk prefix style\r\n const drawAsterisk = (x: number, y: number) => {\r\n ctx.save();\r\n ctx.fillStyle = \"#CC0000\"; // Red asterisk\r\n ctx.font = `bold ${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillText(\"*\", x, y);\r\n ctx.restore();\r\n };\r\n\r\n const asteriskWidth = ctx.measureText(\"*\").width + 5;\r\n const startX = padding + asteriskWidth;\r\n\r\n // Font - render \"Font: \" với font mặc định, tên font với font đó\r\n drawAsterisk(padding, infoY);\r\n const fontPrefix = \"Font: \";\r\n ctx.font = `${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillText(fontPrefix, startX, infoY);\r\n\r\n if (isFontMissing) {\r\n // Hiển thị warning màu đỏ nếu thiếu font\r\n ctx.fillStyle = \"#CC0000\"; // Red color\r\n ctx.fillText(\r\n \"(Đang thiếu font chữ)\",\r\n startX + ctx.measureText(fontPrefix).width,\r\n infoY\r\n );\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Render font name với chính font đó\r\n const prefixWidth = ctx.measureText(fontPrefix).width;\r\n const fontName = position.font || LAYOUT.FONT_FAMILY;\r\n ctx.font = `${infoFontSize}px ${fontName}`;\r\n ctx.fillText(fontName, startX + prefixWidth, infoY);\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Reset font về mặc định cho các dòng tiếp theo\r\n ctx.font = `${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n\r\n // Màu chữ (Text Color) - layer_colors[0]\r\n drawAsterisk(padding, infoY);\r\n const textColorPrefix = \"Màu chữ: \";\r\n ctx.fillText(textColorPrefix, startX, infoY);\r\n\r\n if (!textColor || textColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(textColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(textColorPrefix).width;\r\n ctx.fillText(textColor, startX + prefixWidth, infoY);\r\n\r\n // Draw text color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const swatchX =\r\n startX +\r\n ctx.measureText(textColorPrefix + textColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const swatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const textColorSwatchUrl = getImageUrl(\"threadColor\", textColor);\r\n const textColorSwatchImg = imageRefs.current.get(textColorSwatchUrl);\r\n if (textColorSwatchImg?.complete && textColorSwatchImg.naturalHeight > 0) {\r\n const ratio =\r\n textColorSwatchImg.naturalWidth / textColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(textColorSwatchImg, swatchX, swatchY, swatchW, swatchSize);\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Màu nền (Background Color) - layer_colors[2]\r\n drawAsterisk(padding, infoY);\r\n const bgColorPrefix = \"Màu nền: \";\r\n ctx.fillText(bgColorPrefix, startX, infoY);\r\n\r\n if (!backgroundColor || backgroundColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(bgColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(bgColorPrefix).width;\r\n ctx.fillText(backgroundColor, startX + prefixWidth, infoY);\r\n\r\n // Draw background color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const bgSwatchX =\r\n startX +\r\n ctx.measureText(bgColorPrefix + backgroundColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const bgSwatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const bgColorSwatchUrl = getImageUrl(\"threadColor\", backgroundColor);\r\n const bgColorSwatchImg = imageRefs.current.get(bgColorSwatchUrl);\r\n if (bgColorSwatchImg?.complete && bgColorSwatchImg.naturalHeight > 0) {\r\n const ratio =\r\n bgColorSwatchImg.naturalWidth / bgColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(\r\n bgColorSwatchImg,\r\n bgSwatchX,\r\n bgSwatchY,\r\n swatchW,\r\n swatchSize\r\n );\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Màu viền (Border Color) - layer_colors[1]\r\n drawAsterisk(padding, infoY);\r\n const borderColorPrefix = \"Màu viền: \";\r\n ctx.fillText(borderColorPrefix, startX, infoY);\r\n\r\n if (!borderColor || borderColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(borderColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(borderColorPrefix).width;\r\n ctx.fillText(borderColor, startX + prefixWidth, infoY);\r\n\r\n // Draw border color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const borderSwatchX =\r\n startX +\r\n ctx.measureText(borderColorPrefix + borderColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const borderSwatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const borderColorSwatchUrl = getImageUrl(\"threadColor\", borderColor);\r\n const borderColorSwatchImg = imageRefs.current.get(borderColorSwatchUrl);\r\n if (\r\n borderColorSwatchImg?.complete &&\r\n borderColorSwatchImg.naturalHeight > 0\r\n ) {\r\n const ratio =\r\n borderColorSwatchImg.naturalWidth / borderColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(\r\n borderColorSwatchImg,\r\n borderSwatchX,\r\n borderSwatchY,\r\n swatchW,\r\n swatchSize\r\n );\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Màu vải (Fabric Color) - layer_colors[3]\r\n drawAsterisk(padding, infoY);\r\n const fabricColorPrefix = \"Màu vải: \";\r\n ctx.fillText(fabricColorPrefix, startX, infoY);\r\n\r\n if (!fabricColor || fabricColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(fabricColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(fabricColorPrefix).width;\r\n ctx.fillText(fabricColor, startX + prefixWidth, infoY);\r\n\r\n // Draw fabric color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const fabricSwatchX =\r\n startX +\r\n ctx.measureText(fabricColorPrefix + fabricColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const fabricSwatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const fabricColorSwatchUrl = getImageUrl(\"threadColor\", fabricColor);\r\n const fabricColorSwatchImg = imageRefs.current.get(fabricColorSwatchUrl);\r\n if (\r\n fabricColorSwatchImg?.complete &&\r\n fabricColorSwatchImg.naturalHeight > 0\r\n ) {\r\n const ratio =\r\n fabricColorSwatchImg.naturalWidth / fabricColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(\r\n fabricColorSwatchImg,\r\n fabricSwatchX,\r\n fabricSwatchY,\r\n swatchW,\r\n swatchSize\r\n );\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Attachment\r\n if (position.attachment) {\r\n drawAsterisk(padding + bottomPadding, infoY);\r\n const attachmentLabel = `Attachment: ${position.attachment}`;\r\n ctx.fillText(attachmentLabel, startX, infoY);\r\n infoY += infoLineHeight;\r\n }\r\n\r\n // Size\r\n if (side.size) {\r\n drawAsterisk(padding + bottomPadding, infoY);\r\n const sizeLabel = `Size: ${side.size}`;\r\n ctx.fillText(sizeLabel, startX, infoY);\r\n infoY += infoLineHeight;\r\n }\r\n\r\n // Right side: Image from config.image_url\r\n if (config.image_url) {\r\n // Draw \"Mockup\" label\r\n ctx.font = `bold ${infoFontSize * 1.2}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = \"#000000\";\r\n const mockupLabel = \"Mockup\";\r\n const mockupLabelWidth = ctx.measureText(mockupLabel).width;\r\n const mockupLabelX =\r\n imageSectionX + (imageSectionWidth - mockupLabelWidth) / 1.2;\r\n ctx.fillText(mockupLabel, mockupLabelX, bottomSectionY + LAYOUT.PADDING);\r\n\r\n const mockupLabelHeight = infoFontSize * 1.2 + LAYOUT.LINE_GAP * 0.5;\r\n\r\n const img =\r\n imageRefs.current.get(config.image_url) ??\r\n imageRefs.current.get(\"mockup\");\r\n if (img?.complete && img.naturalWidth > 0) {\r\n const maxImgWidth = imageSectionWidth; // Sử dụng toàn bộ width, sát lề phải\r\n const maxImgHeight = bottomUsableHeight - mockupLabelHeight;\r\n\r\n const imgAspectRatio = img.naturalWidth / img.naturalHeight;\r\n let drawWidth = maxImgWidth;\r\n let drawHeight = drawWidth / imgAspectRatio;\r\n\r\n if (drawHeight > maxImgHeight) {\r\n drawHeight = maxImgHeight;\r\n drawWidth = drawHeight * imgAspectRatio;\r\n }\r\n\r\n const imgX = imageSectionX + (imageSectionWidth - drawWidth) / 0.8;\r\n const imgY =\r\n bottomSectionY +\r\n LAYOUT.PADDING +\r\n mockupLabelHeight +\r\n (bottomUsableHeight - mockupLabelHeight - drawHeight) / 2;\r\n\r\n ctx.drawImage(img, imgX, imgY, drawWidth, drawHeight);\r\n }\r\n }\r\n\r\n ctx.restore();\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 // Check if this is a stroke_patches layout\r\n const hasStrokePatches = config.sides.some(\r\n (side) => side.item_type && side.item_type.includes(\"stroke_patches\")\r\n );\r\n\r\n if (hasStrokePatches) {\r\n renderStrokePatchesCanvas(ctx, canvas, config, imageRefs);\r\n return;\r\n }\r\n\r\n // Check if this is a template_custom_text_patches layout\r\n const hasTemplateCustomTextPatches = config.sides.some(\r\n (side) => side.item_type && side.item_type.includes(\"template_custom_text_patches\")\r\n );\r\n\r\n if (hasTemplateCustomTextPatches) {\r\n renderTemplateCustomTextPatchesCanvas(ctx, canvas, config, imageRefs);\r\n return;\r\n }\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;\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, có bao gồm padding\r\n let testMeasureY = LAYOUT.PADDING;\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 testMeasureY\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 testMeasureY,\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\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 // Calculate currentY: padding top + actual warning & message height (no spacing)\r\n let currentY = LAYOUT.PADDING;\r\n\r\n // Render warning & message with scaleFactor and get actual heights\r\n if (config.warning_message) {\r\n const actualWarningHeight = renderWarning(\r\n ctx,\r\n canvas,\r\n config.warning_message,\r\n scaleFactor,\r\n currentY\r\n );\r\n currentY += actualWarningHeight;\r\n }\r\n if (config.message) {\r\n const actualMessageHeight = renderWarning(\r\n ctx,\r\n canvas,\r\n config.message,\r\n scaleFactor,\r\n currentY,\r\n \"\", // message: không cần prefix \"Note\"\r\n DEFAULT_ERROR_COLOR // message: hiển thị màu đỏ\r\n );\r\n currentY += actualMessageHeight;\r\n }\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 lines.forEach((line, index) => {\r\n const y = offsetY + 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 =\r\n lineTopY < mockupBounds.y + mockupBounds.height &&\r\n 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: {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n } | 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 =\r\n textPositions.length === 0 ||\r\n 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 =\r\n iconPositions.length === 0 ||\r\n 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\" &&\r\n (!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 = 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 ||\r\n 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:\r\n 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?: {\r\n font?: boolean;\r\n shape?: boolean;\r\n floral?: boolean;\r\n color?: boolean;\r\n },\r\n mockupBounds: {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n } | 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(\r\n colors,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\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 (\r\n values.floral &&\r\n values.floral !== \"None\" &&\r\n shouldRenderField(\"floral\")\r\n ) {\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: {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n } | 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.replace(/\\r\\n/g, \"\\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 =\r\n textCenterY -\r\n ((lines.length - 1) / 2) * valueLineHeight +\r\n idx * valueLineHeight;\r\n // Tính effectiveMaxWidth cho dòng này\r\n const effectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n valueStartX,\r\n lineY,\r\n valueLineHeight,\r\n availableWidth,\r\n mockupBounds\r\n )\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 =\r\n textCenterY -\r\n ((lines.length - 1) / 2) * valueLineHeight +\r\n 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 const prefix = \"Font: \";\r\n const suffix =\r\n position.is_font_default === true ? \" (Mặc định)\" : \" (Custom)\";\r\n const fontName = position.font;\r\n const fullText = `${prefix}${fontName}${suffix}`;\r\n\r\n const lineHeight = otherFontSize + lineGap;\r\n const textTopY = currentY;\r\n const effectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(x, textTopY, lineHeight, maxWidth, mockupBounds)\r\n : maxWidth;\r\n\r\n const MIN_FONT_FONT_SIZE = otherFontSize * 0.5;\r\n\r\n const measureFontTextWidth = (fontSize: number) => {\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const prefixWidth = ctx.measureText(prefix).width;\r\n ctx.font = `${fontSize}px ${position.font}`;\r\n const fontNameWidth = ctx.measureText(fontName).width;\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const suffixWidth = ctx.measureText(suffix).width;\r\n return prefixWidth + fontNameWidth + suffixWidth;\r\n };\r\n\r\n const checkFontSizeFits = (fontSize: number): boolean => {\r\n const textTopY = currentY;\r\n const lineHeight = fontSize + lineGap;\r\n const effectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n x,\r\n textTopY,\r\n lineHeight,\r\n maxWidth,\r\n mockupBounds\r\n )\r\n : maxWidth;\r\n const textWidth = measureFontTextWidth(fontSize);\r\n return textWidth <= effectiveMaxWidth;\r\n };\r\n\r\n let effectiveFontSize = otherFontSize;\r\n let needsWrap = false;\r\n\r\n // Bước 1: Thử giảm font size, kiểm tra xem có vừa chiều ngang không\r\n const baseMaxWidth = measureFontTextWidth(otherFontSize);\r\n if (baseMaxWidth > effectiveMaxWidth) {\r\n // Binary search để tìm font size lớn nhất mà vẫn vừa\r\n let left = MIN_FONT_FONT_SIZE;\r\n let right = otherFontSize;\r\n let bestFontSize = MIN_FONT_FONT_SIZE;\r\n\r\n while (right - left > 0.1) {\r\n const mid = (left + right) / 2;\r\n if (checkFontSizeFits(mid)) {\r\n bestFontSize = mid;\r\n left = mid;\r\n } else {\r\n right = mid;\r\n }\r\n }\r\n\r\n if (checkFontSizeFits(bestFontSize)) {\r\n // Bước 1 thành công: font size đã shrink vừa chiều ngang\r\n effectiveFontSize = Math.floor(bestFontSize);\r\n } else {\r\n // Bước 1 thất bại: đã shrink đến MIN nhưng vẫn không vừa, sang bước 2\r\n needsWrap = true;\r\n effectiveFontSize = otherFontSize;\r\n }\r\n }\r\n\r\n if (needsWrap) {\r\n // Bước 2: Xuống dòng với font size gốc\r\n ctx.font = `${effectiveFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const wrappedLines = buildWrappedLines(\r\n ctx,\r\n fullText,\r\n effectiveMaxWidth,\r\n x,\r\n textTopY,\r\n lineHeight,\r\n mockupBounds\r\n );\r\n\r\n wrappedLines.forEach((line, index) => {\r\n const lineY = textTopY + index * lineHeight;\r\n\r\n const lineEffectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(x, lineY, lineHeight, maxWidth, mockupBounds)\r\n : maxWidth;\r\n\r\n let lineToRender = line;\r\n const lineWidth = ctx.measureText(lineToRender).width;\r\n\r\n if (lineWidth > lineEffectiveMaxWidth) {\r\n while (\r\n ctx.measureText(lineToRender).width > lineEffectiveMaxWidth &&\r\n lineToRender.length > 0\r\n ) {\r\n lineToRender = lineToRender.slice(0, -1);\r\n }\r\n }\r\n\r\n ctx.fillText(lineToRender, x, lineY);\r\n });\r\n\r\n currentY += wrappedLines.length * lineHeight;\r\n } else {\r\n // Bước 1 thành công: Render với font size đã shrink (1 dòng)\r\n const shrunkTextTopY = currentY;\r\n const shrunkLineHeight = effectiveFontSize + lineGap;\r\n const shrunkEffectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n x,\r\n shrunkTextTopY,\r\n shrunkLineHeight,\r\n maxWidth,\r\n mockupBounds\r\n )\r\n : maxWidth;\r\n\r\n ctx.font = `${effectiveFontSize}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 ctx.font = `${effectiveFontSize}px ${position.font}`;\r\n const fontNameWidth = ctx.measureText(fontName).width;\r\n const totalWidth = prefixWidth + fontNameWidth;\r\n\r\n if (totalWidth > shrunkEffectiveMaxWidth) {\r\n // Cần cắt font name\r\n let truncatedFontName = fontName;\r\n while (\r\n ctx.measureText(truncatedFontName).width >\r\n shrunkEffectiveMaxWidth - prefixWidth &&\r\n truncatedFontName.length > 0\r\n ) {\r\n truncatedFontName = truncatedFontName.slice(0, -1);\r\n }\r\n ctx.fillText(truncatedFontName, currentX, currentY);\r\n currentX += ctx.measureText(truncatedFontName).width;\r\n } else {\r\n ctx.fillText(fontName, currentX, currentY);\r\n currentX += fontNameWidth;\r\n }\r\n\r\n ctx.font = `${effectiveFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const remainingWidth = shrunkEffectiveMaxWidth - (currentX - x);\r\n if (remainingWidth > 0) {\r\n let truncatedSuffix = suffix;\r\n while (\r\n ctx.measureText(truncatedSuffix).width > remainingWidth &&\r\n truncatedSuffix.length > 0\r\n ) {\r\n truncatedSuffix = truncatedSuffix.slice(0, -1);\r\n }\r\n if (truncatedSuffix.length > 0) {\r\n ctx.fillText(truncatedSuffix, currentX, currentY);\r\n }\r\n }\r\n\r\n currentY += shrunkLineHeight;\r\n }\r\n }\r\n\r\n if (showLabels.color) {\r\n const colorValue =\r\n 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(\r\n colors,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\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(\r\n x,\r\n currentY,\r\n lineHeight,\r\n maxWidth,\r\n mockupBounds\r\n )\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 =\r\n 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: {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n } | 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 =\r\n 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 =\r\n iconWidth + LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n }\r\n }\r\n }\r\n\r\n const availableWidth = Math.max(\r\n 1,\r\n maxWidth - labelWidth - iconImageReservedWidth\r\n );\r\n const textCenterY = cursorY + iconImageHeight / 2;\r\n const valueStartX = x + labelWidth;\r\n\r\n const textTopY = textCenterY - iconFontSize / 2;\r\n const lineHeight = iconFontSize;\r\n const effectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n valueStartX,\r\n textTopY,\r\n lineHeight,\r\n availableWidth,\r\n mockupBounds\r\n )\r\n : availableWidth;\r\n\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 const checkFontSizeFits = (fontSize: number): boolean => {\r\n const textTopY = textCenterY - fontSize / 2;\r\n const lineHeight = fontSize;\r\n const effectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n valueStartX,\r\n textTopY,\r\n lineHeight,\r\n availableWidth,\r\n mockupBounds\r\n )\r\n : availableWidth;\r\n const textWidth = measureIconValueWidth(fontSize);\r\n return textWidth <= effectiveMaxWidth;\r\n };\r\n\r\n let effectiveIconValueFontSize = iconFontSize;\r\n let needsWrap = false;\r\n\r\n // Bước 1: Thử giảm font size, kiểm tra xem có vừa chiều ngang không\r\n const baseMaxWidth = measureIconValueWidth(iconFontSize);\r\n if (baseMaxWidth > effectiveMaxWidth) {\r\n // Binary search để tìm font size lớn nhất mà vẫn vừa\r\n let left = MIN_ICON_VALUE_FONT_SIZE;\r\n let right = iconFontSize;\r\n let bestFontSize = MIN_ICON_VALUE_FONT_SIZE;\r\n\r\n while (right - left > 0.1) {\r\n const mid = (left + right) / 2;\r\n if (checkFontSizeFits(mid)) {\r\n bestFontSize = mid;\r\n left = mid;\r\n } else {\r\n right = mid;\r\n }\r\n }\r\n\r\n if (checkFontSizeFits(bestFontSize)) {\r\n // Bước 1 thành công: font size đã shrink vừa chiều ngang\r\n effectiveIconValueFontSize = Math.floor(bestFontSize);\r\n } else {\r\n // Bước 1 thất bại: đã shrink đến MIN nhưng vẫn không vừa, sang bước 2\r\n needsWrap = true;\r\n effectiveIconValueFontSize = iconFontSize;\r\n }\r\n }\r\n\r\n // Bước 2: Nếu bước 1 thất bại, xuống dòng với font size gốc\r\n\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 ctx.font = `${effectiveIconValueFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = DEFAULT_ERROR_COLOR;\r\n\r\n let maxValueLineWidth = 0;\r\n let totalTextHeight = iconImageHeight;\r\n\r\n if (needsWrap) {\r\n // Bước 2: Xuống dòng với font size gốc\r\n const wrappedLines = buildWrappedLines(\r\n ctx,\r\n iconValue,\r\n effectiveMaxWidth,\r\n valueStartX,\r\n textTopY,\r\n lineHeight,\r\n mockupBounds\r\n );\r\n\r\n // Tính height dựa trên số dòng thực tế\r\n totalTextHeight = Math.max(\r\n iconImageHeight,\r\n wrappedLines.length * lineHeight\r\n );\r\n\r\n wrappedLines.forEach((line, index) => {\r\n const lineTopY = textTopY + index * lineHeight;\r\n const lineCenterY = lineTopY + lineHeight / 2;\r\n\r\n const lineEffectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n valueStartX,\r\n lineTopY,\r\n lineHeight,\r\n availableWidth,\r\n mockupBounds\r\n )\r\n : availableWidth;\r\n\r\n let lineToRender = line;\r\n const lineWidth = ctx.measureText(lineToRender).width;\r\n\r\n if (lineWidth > lineEffectiveMaxWidth) {\r\n while (\r\n ctx.measureText(lineToRender).width > lineEffectiveMaxWidth &&\r\n lineToRender.length > 0\r\n ) {\r\n lineToRender = lineToRender.slice(0, -1);\r\n }\r\n }\r\n\r\n ctx.fillText(lineToRender, valueStartX, lineCenterY);\r\n const w = ctx.measureText(lineToRender).width;\r\n if (w > maxValueLineWidth) maxValueLineWidth = w;\r\n });\r\n } else {\r\n // Bước 1 thành công: Render với font size đã shrink (1 dòng)\r\n const shrunkTextTopY = textCenterY - effectiveIconValueFontSize / 2;\r\n const shrunkLineHeight = effectiveIconValueFontSize;\r\n const shrunkEffectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n valueStartX,\r\n shrunkTextTopY,\r\n shrunkLineHeight,\r\n availableWidth,\r\n mockupBounds\r\n )\r\n : availableWidth;\r\n\r\n const lineText = ` ${iconValue}`;\r\n let lineToRender = lineText;\r\n const lineWidth = ctx.measureText(lineToRender).width;\r\n\r\n if (lineWidth > shrunkEffectiveMaxWidth) {\r\n while (\r\n ctx.measureText(lineToRender).width > shrunkEffectiveMaxWidth &&\r\n lineToRender.length > 0\r\n ) {\r\n lineToRender = lineToRender.slice(0, -1);\r\n }\r\n }\r\n\r\n ctx.fillText(lineToRender, valueStartX, textCenterY);\r\n const w = ctx.measureText(lineToRender).width;\r\n if (w > maxValueLineWidth) maxValueLineWidth = w;\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: totalTextHeight + 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 = 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(\r\n iconColors,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\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(\r\n ...testLines.map((line) => ctx.measureText(line).width)\r\n );\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(\r\n ctx,\r\n iconColors,\r\n swatchX,\r\n swatchY,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\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 =\r\n colorResult.lastLineY + Math.floor(otherFontSize / 2 - swatchH / 2);\r\n\r\n // Render swatches (đã kiểm tra overflow ở trên)\r\n drawSwatches(\r\n ctx,\r\n iconColors,\r\n swatchX,\r\n swatchY,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\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([preloadFonts(config), preloadImages(config, imageRefs)]);\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 fontFormats = ['woff2', 'ttf', 'otf'];\r\n let currentFormatIndex = 0;\r\n\r\n const tryLoadFont = () => {\r\n if (currentFormatIndex >= fontFormats.length) {\r\n console.warn(`Could not load font ${fontName} from CDN (tried all formats)`);\r\n resolve();\r\n return;\r\n }\r\n\r\n const format = fontFormats[currentFormatIndex];\r\n const fontUrl = `${BASE_URLS.FONT}/${encodeURIComponent(fontName)}.${format}`;\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 // Try next format\r\n currentFormatIndex++;\r\n tryLoadFont();\r\n });\r\n };\r\n\r\n tryLoadFont();\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 = (\r\n position: Position & { type: \"ICON\" }\r\n): 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\r\n ? getProxyUrl(getResizeUrl(url))\r\n : 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 // Load layer_colors for TEXT (used in stroke_patches and template_custom_text_patches)\r\n position.layer_colors?.forEach((color) => {\r\n const layerColorUrl = getImageUrl(\"threadColor\", color);\r\n if (!seen.has(layerColorUrl)) {\r\n entries.push({ url: layerColorUrl });\r\n seen.add(layerColorUrl);\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: {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n } | 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(\r\n x,\r\n currentY,\r\n lineHeight,\r\n maxWidth,\r\n mockupBounds\r\n );\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(\r\n x,\r\n currentY,\r\n lineHeight,\r\n maxWidth,\r\n mockupBounds\r\n );\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 (\r\n ctx.measureText(lineToRender).width > effectiveMaxWidth &&\r\n lineToRender.length > 0\r\n ) {\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: {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n } | 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 =\r\n lineHeight > 0\r\n ? getEffectiveMaxWidth(\r\n startX,\r\n currentY,\r\n lineHeight,\r\n maxWidth,\r\n mockupBounds\r\n )\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 // Load layer_colors for TEXT (used in stroke_patches and template_custom_text_patches)\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 });\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 renderStrokePatchesCanvas = (\r\n ctx: CanvasRenderingContext2D,\r\n canvas: HTMLCanvasElement,\r\n config: EmbroideryQCConfig,\r\n imageRefs: ImageMapRef\r\n) => {\r\n // Clear canvas\r\n ctx.fillStyle = \"#e7e7e7\";\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n const padding = LAYOUT.PADDING * 6;\r\n const usableWidth = canvas.width - padding * 2;\r\n const usableHeight = canvas.height - padding * 2;\r\n\r\n // Calculate sections\r\n const topSectionHeight = Math.floor(usableHeight * (2 / 3)); // 2/3 top\r\n const bottomSectionHeight = usableHeight - topSectionHeight; // 1/3 bottom\r\n\r\n const topSectionY = padding;\r\n const bottomSectionY = topSectionY + topSectionHeight;\r\n\r\n // Get first side (stroke_patches should have only one side)\r\n const side = config.sides[0];\r\n if (!side || !side.positions.length) {\r\n renderErrorState(ctx, canvas, \"Không có dữ liệu positions\");\r\n return;\r\n }\r\n\r\n const position = side.positions[0];\r\n if (position.type !== \"TEXT\") {\r\n renderErrorState(ctx, canvas, \"Position phải là TEXT\");\r\n return;\r\n }\r\n\r\n if (!position.layer_colors || position.layer_colors.length < 3) {\r\n renderErrorState(ctx, canvas, \"Không có đủ màu cho stroke patches\");\r\n return;\r\n }\r\n\r\n // Get layer colors with empty check (don't use fallback)\r\n const textColor = position.layer_colors[0];\r\n const borderColor = position.layer_colors[1];\r\n const backgroundColor = position.layer_colors[2];\r\n const fabricColor = position.layer_colors?.[3]; // Màu vải\r\n\r\n // For rendering, use fallback colors (fabricColor không cần fallback vì chỉ hiển thị)\r\n const textColorForRender = textColor;\r\n const borderColorForRender = borderColor;\r\n const backgroundColorForRender = backgroundColor;\r\n\r\n // Check if font is missing (but continue rendering)\r\n const isFontMissing = !position.font || position.font.trim() === \"\";\r\n\r\n // ============================================================================\r\n // TOP SECTION (2/3): Hiển thị mẫu preview\r\n // ============================================================================\r\n ctx.save();\r\n\r\n // Draw \"Hình mẫu:\" label at the top\r\n const titleFontSize = LAYOUT.HEADER_FONT_SIZE * 0.8;\r\n ctx.font = `bold ${titleFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = \"#CC0000\"; // Red color\r\n ctx.fillText(\"Hình mẫu:\", padding, topSectionY);\r\n\r\n // Adjust top section Y to account for title + extra spacing (40px)\r\n const extraSpacing = 40;\r\n const actualTopSectionY =\r\n topSectionY + titleFontSize + LAYOUT.LINE_GAP + extraSpacing;\r\n const actualTopSectionHeight =\r\n topSectionHeight - titleFontSize - LAYOUT.LINE_GAP - extraSpacing;\r\n\r\n // Calculate text size to fit top section\r\n let previewFontSize = LAYOUT.HEADER_FONT_SIZE * 3; // Start with large size\r\n const fontToUse = isFontMissing ? LAYOUT.FONT_FAMILY : position.font;\r\n ctx.font = `${previewFontSize}px \"${fontToUse}\"`;\r\n\r\n const text = position.text || \"\";\r\n const maxTextWidth = usableWidth * 0.9; // Use 75% of width for better padding\r\n const maxTextHeight = actualTopSectionHeight; // Use 60% of height\r\n\r\n // Scale down font size to fit\r\n let textWidth = ctx.measureText(text).width;\r\n while (textWidth > maxTextWidth && previewFontSize > 50) {\r\n previewFontSize *= 0.95;\r\n ctx.font = `${previewFontSize}px \"${fontToUse}\"`;\r\n textWidth = ctx.measureText(text).width;\r\n }\r\n\r\n // Ensure text height also fits\r\n while (previewFontSize > maxTextHeight && previewFontSize > 50) {\r\n previewFontSize *= 0.95;\r\n ctx.font = `${previewFontSize}px \"${fontToUse}\"`;\r\n }\r\n\r\n // Update textWidth after final scaling\r\n textWidth = ctx.measureText(text).width;\r\n\r\n // Center the text in top section\r\n const textX = padding + usableWidth / 2 - textWidth / 2;\r\n const textY =\r\n actualTopSectionY + actualTopSectionHeight / 2 - previewFontSize / 2;\r\n\r\n // Get color hex values (use render colors with fallback)\r\n const textColorHex = COLOR_MAP[textColorForRender] || LAYOUT.LABEL_COLOR;\r\n const borderColorHex = COLOR_MAP[borderColorForRender] || LAYOUT.LABEL_COLOR;\r\n const bgColorHex = COLOR_MAP[backgroundColorForRender] || \"#FFFFFF\";\r\n\r\n // Calculate stroke widths\r\n // Background needs to be MUCH thicker to create spacing from text\r\n // Border needs to be even thicker to wrap around background\r\n const bgWidth = Math.max(80, previewFontSize / 2); // Background - rất dày để tạo khoảng cách lớn\r\n const borderWidth = Math.max(100, previewFontSize / 1.58); // Border - dày hơn để bọc background\r\n\r\n // Layer 1: Draw border stroke (outermost)\r\n ctx.strokeStyle = borderColorHex;\r\n ctx.lineWidth = borderWidth;\r\n ctx.lineJoin = \"round\";\r\n ctx.lineCap = \"round\";\r\n ctx.strokeText(text, textX, textY);\r\n\r\n // Layer 2: Draw background color stroke (middle - creates spacing from text)\r\n ctx.strokeStyle = bgColorHex;\r\n ctx.lineWidth = bgWidth;\r\n ctx.lineJoin = \"round\";\r\n ctx.lineCap = \"round\";\r\n ctx.strokeText(text, textX, textY);\r\n\r\n // Layer 3: Draw text fill ONLY (no stroke on text itself)\r\n ctx.fillStyle = textColorHex;\r\n ctx.fillText(text, textX, textY);\r\n\r\n ctx.restore();\r\n\r\n // ============================================================================\r\n // BOTTOM SECTION (1/3): Flex layout with info (left) and image (right)\r\n // ============================================================================\r\n ctx.save();\r\n\r\n // Draw border around bottom section for debugging\r\n // ctx.strokeStyle = \"#ccc\";\r\n // ctx.lineWidth = 2;\r\n // ctx.strokeRect(padding, bottomSectionY, usableWidth, bottomSectionHeight);\r\n\r\n const bottomPadding = 0; // Không padding ngang, sát lề\r\n const bottomUsableWidth = usableWidth; // Sử dụng toàn bộ width\r\n const bottomUsableHeight = bottomSectionHeight - LAYOUT.PADDING * 2; // Chỉ padding dọc\r\n\r\n // Split bottom section: 60% left for info, 40% right for image\r\n const infoSectionWidth = Math.floor(bottomUsableWidth * 0.6);\r\n const imageSectionWidth = bottomUsableWidth - infoSectionWidth;\r\n const imageSectionX = padding + infoSectionWidth;\r\n\r\n // Left side: Info list\r\n const infoFontSize = LAYOUT.OTHER_FONT_SIZE * 0.9; // Giảm từ 1.2 xuống 0.9\r\n const infoLineHeight = infoFontSize * 1.4; // Giảm từ 1.5 xuống 1.4\r\n let infoY = bottomSectionY + LAYOUT.PADDING;\r\n\r\n ctx.font = `${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n ctx.textAlign = \"left\";\r\n ctx.textBaseline = \"top\";\r\n\r\n // Asterisk prefix style\r\n const drawAsterisk = (x: number, y: number) => {\r\n ctx.save();\r\n ctx.fillStyle = \"#CC0000\"; // Red asterisk\r\n ctx.font = `bold ${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillText(\"*\", x, y);\r\n ctx.restore();\r\n };\r\n\r\n const asteriskWidth = ctx.measureText(\"*\").width + 5;\r\n const startX = padding + asteriskWidth;\r\n\r\n // Font - render \"Font: \" với font mặc định, tên font với font đó\r\n drawAsterisk(padding, infoY);\r\n const fontPrefix = \"Font: \";\r\n ctx.font = `${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillText(fontPrefix, startX, infoY);\r\n\r\n if (isFontMissing) {\r\n // Hiển thị warning màu đỏ nếu thiếu font\r\n ctx.fillStyle = \"#CC0000\"; // Red color\r\n ctx.fillText(\r\n \"(Đang thiếu font chữ)\",\r\n startX + ctx.measureText(fontPrefix).width,\r\n infoY\r\n );\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Render font name với chính font đó\r\n const prefixWidth = ctx.measureText(fontPrefix).width;\r\n const fontName = position.font || LAYOUT.FONT_FAMILY;\r\n ctx.font = `${infoFontSize}px \"${fontName}\"`;\r\n ctx.fillText(fontName, startX + prefixWidth, infoY);\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Reset font về mặc định cho các dòng tiếp theo\r\n ctx.font = `${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n\r\n // Màu chữ (Text Color) - layer_colors[0]\r\n drawAsterisk(padding, infoY);\r\n const textColorPrefix = \"Màu chữ: \";\r\n ctx.fillText(textColorPrefix, startX, infoY);\r\n\r\n if (!textColor || textColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(textColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(textColorPrefix).width;\r\n ctx.fillText(textColor, startX + prefixWidth, infoY);\r\n\r\n // Draw text color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const swatchX =\r\n startX +\r\n ctx.measureText(textColorPrefix + textColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const swatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const textColorSwatchUrl = getImageUrl(\"threadColor\", textColor);\r\n const textColorSwatchImg = imageRefs.current.get(textColorSwatchUrl);\r\n if (textColorSwatchImg?.complete && textColorSwatchImg.naturalHeight > 0) {\r\n const ratio =\r\n textColorSwatchImg.naturalWidth / textColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(textColorSwatchImg, swatchX, swatchY, swatchW, swatchSize);\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Màu nền (Background Color) - layer_colors[2]\r\n drawAsterisk(padding, infoY);\r\n const bgColorPrefix = \"Màu nền: \";\r\n ctx.fillText(bgColorPrefix, startX, infoY);\r\n\r\n if (!backgroundColor || backgroundColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(bgColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(bgColorPrefix).width;\r\n ctx.fillText(backgroundColor, startX + prefixWidth, infoY);\r\n\r\n // Draw background color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const bgSwatchX =\r\n startX +\r\n ctx.measureText(bgColorPrefix + backgroundColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const bgSwatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const bgColorSwatchUrl = getImageUrl(\"threadColor\", backgroundColor);\r\n const bgColorSwatchImg = imageRefs.current.get(bgColorSwatchUrl);\r\n if (bgColorSwatchImg?.complete && bgColorSwatchImg.naturalHeight > 0) {\r\n const ratio =\r\n bgColorSwatchImg.naturalWidth / bgColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(\r\n bgColorSwatchImg,\r\n bgSwatchX,\r\n bgSwatchY,\r\n swatchW,\r\n swatchSize\r\n );\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Màu viền (Border Color) - layer_colors[1]\r\n drawAsterisk(padding, infoY);\r\n const borderColorPrefix = \"Màu viền: \";\r\n ctx.fillText(borderColorPrefix, startX, infoY);\r\n\r\n if (!borderColor || borderColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(borderColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(borderColorPrefix).width;\r\n ctx.fillText(borderColor, startX + prefixWidth, infoY);\r\n\r\n // Draw border color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const borderSwatchX =\r\n startX +\r\n ctx.measureText(borderColorPrefix + borderColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const borderSwatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const borderColorSwatchUrl = getImageUrl(\"threadColor\", borderColor);\r\n const borderColorSwatchImg = imageRefs.current.get(borderColorSwatchUrl);\r\n if (\r\n borderColorSwatchImg?.complete &&\r\n borderColorSwatchImg.naturalHeight > 0\r\n ) {\r\n const ratio =\r\n borderColorSwatchImg.naturalWidth / borderColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(\r\n borderColorSwatchImg,\r\n borderSwatchX,\r\n borderSwatchY,\r\n swatchW,\r\n swatchSize\r\n );\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Màu vải (Fabric Color) - layer_colors[3]\r\n drawAsterisk(padding, infoY);\r\n const fabricColorPrefix = \"Màu vải: \";\r\n ctx.fillText(fabricColorPrefix, startX, infoY);\r\n\r\n if (!fabricColor || fabricColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(fabricColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(fabricColorPrefix).width;\r\n ctx.fillText(fabricColor, startX + prefixWidth, infoY);\r\n\r\n // Draw fabric color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const fabricSwatchX =\r\n startX +\r\n ctx.measureText(fabricColorPrefix + fabricColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const fabricSwatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const fabricColorSwatchUrl = getImageUrl(\"threadColor\", fabricColor);\r\n const fabricColorSwatchImg = imageRefs.current.get(fabricColorSwatchUrl);\r\n if (\r\n fabricColorSwatchImg?.complete &&\r\n fabricColorSwatchImg.naturalHeight > 0\r\n ) {\r\n const ratio =\r\n fabricColorSwatchImg.naturalWidth / fabricColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(\r\n fabricColorSwatchImg,\r\n fabricSwatchX,\r\n fabricSwatchY,\r\n swatchW,\r\n swatchSize\r\n );\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Attachment\r\n if (position.attachment) {\r\n drawAsterisk(padding + bottomPadding, infoY);\r\n const attachmentLabel = `Attachment: ${position.attachment}`;\r\n ctx.fillText(attachmentLabel, startX, infoY);\r\n infoY += infoLineHeight;\r\n }\r\n\r\n // Size\r\n if (side.size) {\r\n drawAsterisk(padding + bottomPadding, infoY);\r\n const sizeLabel = `Size: ${side.size}`;\r\n ctx.fillText(sizeLabel, startX, infoY);\r\n infoY += infoLineHeight;\r\n }\r\n\r\n // Right side: Image from config.image_url\r\n if (config.image_url) {\r\n // Draw \"Mockup\" label\r\n ctx.font = `bold ${infoFontSize * 1.2}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = \"#000000\";\r\n const mockupLabel = \"Mockup\";\r\n const mockupLabelWidth = ctx.measureText(mockupLabel).width;\r\n const mockupLabelX =\r\n imageSectionX + (imageSectionWidth - mockupLabelWidth) / 1.2;\r\n ctx.fillText(mockupLabel, mockupLabelX, bottomSectionY + LAYOUT.PADDING);\r\n\r\n const mockupLabelHeight = infoFontSize * 1.2 + LAYOUT.LINE_GAP * 0.5;\r\n\r\n const img =\r\n imageRefs.current.get(config.image_url) ??\r\n imageRefs.current.get(\"mockup\");\r\n if (img?.complete && img.naturalWidth > 0) {\r\n const maxImgWidth = imageSectionWidth; // Sử dụng toàn bộ width, sát lề phải\r\n const maxImgHeight = bottomUsableHeight - mockupLabelHeight;\r\n\r\n const imgAspectRatio = img.naturalWidth / img.naturalHeight;\r\n let drawWidth = maxImgWidth;\r\n let drawHeight = drawWidth / imgAspectRatio;\r\n\r\n if (drawHeight > maxImgHeight) {\r\n drawHeight = maxImgHeight;\r\n drawWidth = drawHeight * imgAspectRatio;\r\n }\r\n\r\n const imgX = imageSectionX + (imageSectionWidth - drawWidth) / 0.8;\r\n const imgY =\r\n bottomSectionY +\r\n LAYOUT.PADDING +\r\n mockupLabelHeight +\r\n (bottomUsableHeight - mockupLabelHeight - drawHeight) / 2;\r\n\r\n ctx.drawImage(img, imgX, imgY, drawWidth, drawHeight);\r\n }\r\n }\r\n\r\n ctx.restore();\r\n};\r\n\r\n// Helper function để parse size từ string như \"3 X 3 INCHES\"\r\nconst parseSize = (sizeStr: string): { width: number; height: number } | null => {\r\n if (!sizeStr || typeof sizeStr !== \"string\") return null;\r\n \r\n // Pattern để match \"3 X 3 INCHES\" hoặc \"3x3\" hoặc \"3 X 3\"\r\n const match = sizeStr.match(/(\\d+(?:\\.\\d+)?)\\s*[xX]\\s*(\\d+(?:\\.\\d+)?)/i);\r\n if (!match) return null;\r\n \r\n const width = parseFloat(match[1]);\r\n const height = parseFloat(match[2]);\r\n \r\n if (isNaN(width) || isNaN(height) || width <= 0 || height <= 0) return null;\r\n \r\n return { width, height };\r\n};\r\n\r\nconst renderTemplateCustomTextPatchesCanvas = (\r\n ctx: CanvasRenderingContext2D,\r\n canvas: HTMLCanvasElement,\r\n config: EmbroideryQCConfig,\r\n imageRefs: ImageMapRef\r\n) => {\r\n // Clear canvas\r\n ctx.fillStyle = \"#e7e7e7\";\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n const padding = LAYOUT.PADDING * 6;\r\n const usableWidth = canvas.width - padding * 2;\r\n const usableHeight = canvas.height - padding * 2;\r\n\r\n // Calculate sections\r\n const topSectionHeight = Math.floor(usableHeight * (2 / 3)); // 2/3 top\r\n const bottomSectionHeight = usableHeight - topSectionHeight; // 1/3 bottom\r\n\r\n const topSectionY = padding;\r\n const bottomSectionY = topSectionY + topSectionHeight;\r\n\r\n // Get first side (template_custom_text_patches should have only one side)\r\n const side = config.sides[0];\r\n if (!side || !side.positions.length) {\r\n renderErrorState(ctx, canvas, \"Không có dữ liệu positions\");\r\n return;\r\n }\r\n\r\n const position = side.positions[0];\r\n if (position.type !== \"TEXT\") {\r\n renderErrorState(ctx, canvas, \"Position phải là TEXT\");\r\n return;\r\n }\r\n\r\n if (!position.layer_colors || position.layer_colors.length < 3) {\r\n renderErrorState(ctx, canvas, \"Không có đủ màu cho template custom text patches\");\r\n return;\r\n }\r\n\r\n // Parse size từ side.size\r\n const parsedSize = side.size ? parseSize(side.size) : null;\r\n if (!parsedSize) {\r\n renderErrorState(ctx, canvas, \"Không thể parse size từ dữ liệu\");\r\n return;\r\n }\r\n\r\n // Get layer colors\r\n const textColor = position.layer_colors[0];\r\n const borderColor = position.layer_colors[1];\r\n const backgroundColor = position.layer_colors[2];\r\n const fabricColor = position.layer_colors?.[3]; // Màu vải\r\n\r\n // Check if font is missing (but continue rendering)\r\n const isFontMissing = !position.font || position.font.trim() === \"\";\r\n\r\n // ============================================================================\r\n // TOP SECTION (2/3): Hiển thị mẫu preview với khung hình chữ nhật\r\n // ============================================================================\r\n ctx.save();\r\n\r\n // Draw \"Hình mẫu:\" label at the top\r\n const titleFontSize = LAYOUT.HEADER_FONT_SIZE * 0.8;\r\n ctx.font = `bold ${titleFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = \"#CC0000\"; // Red color\r\n ctx.fillText(\"Hình mẫu:\", padding, topSectionY);\r\n\r\n // Adjust top section Y to account for title + extra spacing (40px)\r\n const extraSpacing = 40;\r\n const actualTopSectionY =\r\n topSectionY + titleFontSize + LAYOUT.LINE_GAP + extraSpacing;\r\n const actualTopSectionHeight =\r\n topSectionHeight - titleFontSize - LAYOUT.LINE_GAP - extraSpacing;\r\n\r\n // Tính kích thước khung hình chữ nhật dựa trên tỉ lệ size\r\n // Sử dụng tỉ lệ width/height từ parsedSize để giữ đúng aspect ratio\r\n const sizeAspectRatio = parsedSize.width / parsedSize.height;\r\n \r\n // Tính kích thước khung để fit trong top section\r\n let rectWidth = Math.min(usableWidth * 0.9, actualTopSectionHeight * sizeAspectRatio);\r\n let rectHeight = rectWidth / sizeAspectRatio;\r\n \r\n if (rectHeight > actualTopSectionHeight * 0.9) {\r\n rectHeight = actualTopSectionHeight * 0.9;\r\n rectWidth = rectHeight * sizeAspectRatio;\r\n }\r\n\r\n // Center the rectangle in top section\r\n const rectX = padding + usableWidth / 2 - rectWidth / 2;\r\n const rectY = actualTopSectionY + actualTopSectionHeight / 2 - rectHeight / 2;\r\n\r\n // Get color hex values\r\n const textColorHex = COLOR_MAP[textColor] || LAYOUT.LABEL_COLOR;\r\n const borderColorHex = COLOR_MAP[borderColor] || LAYOUT.LABEL_COLOR;\r\n const bgColorHex = COLOR_MAP[backgroundColor] || \"#FFFFFF\";\r\n\r\n // Border width gấp đôi: 4% của rectWidth, tối thiểu 40px\r\n const borderWidth = Math.max(40, rectWidth * 0.04);\r\n \r\n // Border radius để bo tròn góc\r\n const borderRadius = Math.min(rectWidth, rectHeight) * 0.08; // 8% của cạnh nhỏ hơn\r\n\r\n // Draw rectangle background với border radius\r\n ctx.fillStyle = bgColorHex;\r\n ctx.beginPath();\r\n ctx.roundRect(rectX, rectY, rectWidth, rectHeight, borderRadius);\r\n ctx.fill();\r\n\r\n // Draw rectangle border với border radius\r\n ctx.strokeStyle = borderColorHex;\r\n ctx.lineWidth = borderWidth;\r\n ctx.beginPath();\r\n ctx.roundRect(rectX, rectY, rectWidth, rectHeight, borderRadius);\r\n ctx.stroke();\r\n\r\n // Calculate text size to fit inside rectangle (với padding rất nhỏ)\r\n // Padding chỉ chừa một chút để tránh text chạm border\r\n const textPadding = Math.max(30, rectWidth * 0.03); // 3% padding, tối thiểu 30px\r\n const maxTextWidth = rectWidth - textPadding * 2 - borderWidth;\r\n const maxTextHeight = rectHeight - textPadding * 2 - borderWidth;\r\n\r\n const text = position.text || \"\";\r\n const textLines = text.split(\"\\n\");\r\n const fontToUse = isFontMissing ? LAYOUT.FONT_FAMILY : position.font;\r\n\r\n // Tìm font size tối đa để text vừa trong khung\r\n // Bắt đầu với kích thước lớn và giảm dần\r\n let previewFontSize = Math.min(rectWidth, rectHeight) * 0.8; // Start với 80% của cạnh nhỏ hơn\r\n let bestFontSize = 30; // Minimum font size\r\n \r\n // Binary search để tìm font size tối đa\r\n let low = 30;\r\n let high = previewFontSize;\r\n \r\n while (high - low > 1) {\r\n const mid = (low + high) / 2;\r\n ctx.font = `${mid}px \"${fontToUse}\"`;\r\n \r\n // Kiểm tra width của tất cả các dòng\r\n const maxLineWidth = Math.max(...textLines.map(line => ctx.measureText(line).width));\r\n \r\n // Kiểm tra height với line height = 1.1 (giảm từ 1.2 để text to hơn)\r\n const lineHeight = mid * 1.1;\r\n const totalTextHeight = textLines.length * lineHeight;\r\n \r\n if (maxLineWidth <= maxTextWidth && totalTextHeight <= maxTextHeight) {\r\n // Font size này vừa, thử tăng lên\r\n bestFontSize = mid;\r\n low = mid;\r\n } else {\r\n // Font size này quá lớn, giảm xuống\r\n high = mid;\r\n }\r\n }\r\n \r\n previewFontSize = bestFontSize;\r\n ctx.font = `${previewFontSize}px \"${fontToUse}\"`;\r\n\r\n // Center the text inside rectangle\r\n const finalLineHeight = previewFontSize * 1.1;\r\n const totalTextHeightFinal = textLines.length * finalLineHeight;\r\n const textStartY = rectY + rectHeight / 2 - totalTextHeightFinal / 2;\r\n\r\n // Draw text inside rectangle\r\n ctx.fillStyle = textColorHex;\r\n ctx.textAlign = \"center\";\r\n ctx.textBaseline = \"top\";\r\n textLines.forEach((line, index) => {\r\n const lineY = textStartY + index * finalLineHeight;\r\n ctx.fillText(line, rectX + rectWidth / 2, lineY);\r\n });\r\n\r\n ctx.restore();\r\n\r\n // ============================================================================\r\n // BOTTOM SECTION (1/3): Flex layout with info (left) and image (right)\r\n // ============================================================================\r\n ctx.save();\r\n\r\n const bottomPadding = 0; // Không padding ngang, sát lề\r\n const bottomUsableWidth = usableWidth; // Sử dụng toàn bộ width\r\n const bottomUsableHeight = bottomSectionHeight - LAYOUT.PADDING * 2; // Chỉ padding dọc\r\n\r\n // Split bottom section: 60% left for info, 40% right for image\r\n const infoSectionWidth = Math.floor(bottomUsableWidth * 0.6);\r\n const imageSectionWidth = bottomUsableWidth - infoSectionWidth;\r\n const imageSectionX = padding + infoSectionWidth;\r\n\r\n // Left side: Info list\r\n const infoFontSize = LAYOUT.OTHER_FONT_SIZE * 0.9;\r\n const infoLineHeight = infoFontSize * 1.4;\r\n let infoY = bottomSectionY + LAYOUT.PADDING;\r\n\r\n ctx.font = `${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR;\r\n ctx.textAlign = \"left\";\r\n ctx.textBaseline = \"top\";\r\n\r\n // Asterisk prefix style\r\n const drawAsterisk = (x: number, y: number) => {\r\n ctx.save();\r\n ctx.fillStyle = \"#CC0000\"; // Red asterisk\r\n ctx.font = `bold ${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillText(\"*\", x, y);\r\n ctx.restore();\r\n };\r\n\r\n const asteriskWidth = ctx.measureText(\"*\").width + 5;\r\n const startX = padding + asteriskWidth;\r\n\r\n // Font - render \"Font: \" với font mặc định, tên font với font đó\r\n drawAsterisk(padding, infoY);\r\n const fontPrefix = \"Font: \";\r\n ctx.font = `${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillText(fontPrefix, startX, infoY);\r\n\r\n if (isFontMissing) {\r\n // Hiển thị warning màu đỏ nếu thiếu font\r\n ctx.fillStyle = \"#CC0000\"; // Red color\r\n ctx.fillText(\r\n \"(Đang thiếu font chữ)\",\r\n startX + ctx.measureText(fontPrefix).width,\r\n infoY\r\n );\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Render font name với chính font đó\r\n const prefixWidth = ctx.measureText(fontPrefix).width;\r\n const fontName = position.font || LAYOUT.FONT_FAMILY;\r\n ctx.font = `${infoFontSize}px \"${fontName}\"`;\r\n ctx.fillText(fontName, startX + prefixWidth, infoY);\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Reset font về mặc định cho các dòng tiếp theo\r\n ctx.font = `${infoFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n\r\n // Màu chữ (Text Color) - layer_colors[0]\r\n drawAsterisk(padding, infoY);\r\n const textColorPrefix = \"Màu chữ: \";\r\n ctx.fillText(textColorPrefix, startX, infoY);\r\n\r\n if (!textColor || textColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(textColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(textColorPrefix).width;\r\n ctx.fillText(textColor, startX + prefixWidth, infoY);\r\n\r\n // Draw text color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const swatchX =\r\n startX +\r\n ctx.measureText(textColorPrefix + textColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const swatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const textColorSwatchUrl = getImageUrl(\"threadColor\", textColor);\r\n const textColorSwatchImg = imageRefs.current.get(textColorSwatchUrl);\r\n if (textColorSwatchImg?.complete && textColorSwatchImg.naturalHeight > 0) {\r\n const ratio =\r\n textColorSwatchImg.naturalWidth / textColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(textColorSwatchImg, swatchX, swatchY, swatchW, swatchSize);\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Màu nền (Background Color) - layer_colors[2]\r\n drawAsterisk(padding, infoY);\r\n const bgColorPrefix = \"Màu nền: \";\r\n ctx.fillText(bgColorPrefix, startX, infoY);\r\n\r\n if (!backgroundColor || backgroundColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(bgColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(bgColorPrefix).width;\r\n ctx.fillText(backgroundColor, startX + prefixWidth, infoY);\r\n\r\n // Draw background color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const bgSwatchX =\r\n startX +\r\n ctx.measureText(bgColorPrefix + backgroundColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const bgSwatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const bgColorSwatchUrl = getImageUrl(\"threadColor\", backgroundColor);\r\n const bgColorSwatchImg = imageRefs.current.get(bgColorSwatchUrl);\r\n if (bgColorSwatchImg?.complete && bgColorSwatchImg.naturalHeight > 0) {\r\n const ratio =\r\n bgColorSwatchImg.naturalWidth / bgColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(\r\n bgColorSwatchImg,\r\n bgSwatchX,\r\n bgSwatchY,\r\n swatchW,\r\n swatchSize\r\n );\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Màu viền (Border Color) - layer_colors[1]\r\n drawAsterisk(padding, infoY);\r\n const borderColorPrefix = \"Màu viền: \";\r\n ctx.fillText(borderColorPrefix, startX, infoY);\r\n\r\n if (!borderColor || borderColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(borderColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(borderColorPrefix).width;\r\n ctx.fillText(borderColor, startX + prefixWidth, infoY);\r\n\r\n // Draw border color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const borderSwatchX =\r\n startX +\r\n ctx.measureText(borderColorPrefix + borderColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const borderSwatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const borderColorSwatchUrl = getImageUrl(\"threadColor\", borderColor);\r\n const borderColorSwatchImg = imageRefs.current.get(borderColorSwatchUrl);\r\n if (\r\n borderColorSwatchImg?.complete &&\r\n borderColorSwatchImg.naturalHeight > 0\r\n ) {\r\n const ratio =\r\n borderColorSwatchImg.naturalWidth / borderColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(\r\n borderColorSwatchImg,\r\n borderSwatchX,\r\n borderSwatchY,\r\n swatchW,\r\n swatchSize\r\n );\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Màu vải (Fabric Color) - layer_colors[3]\r\n drawAsterisk(padding, infoY);\r\n const fabricColorPrefix = \"Màu vải: \";\r\n ctx.fillText(fabricColorPrefix, startX, infoY);\r\n\r\n if (!fabricColor || fabricColor.trim() === \"\") {\r\n // Hiển thị warning màu đỏ nếu thiếu màu\r\n const prefixWidth = ctx.measureText(fabricColorPrefix).width;\r\n ctx.fillStyle = \"#CC0000\";\r\n ctx.fillText(\"(Chưa có màu)\", startX + prefixWidth, infoY);\r\n ctx.fillStyle = LAYOUT.LABEL_COLOR; // Reset color\r\n } else {\r\n // Hiển thị tên màu\r\n const prefixWidth = ctx.measureText(fabricColorPrefix).width;\r\n ctx.fillText(fabricColor, startX + prefixWidth, infoY);\r\n\r\n // Draw fabric color swatch\r\n const swatchSize = infoFontSize * 1.3;\r\n const fabricSwatchX =\r\n startX +\r\n ctx.measureText(fabricColorPrefix + fabricColor).width +\r\n LAYOUT.ELEMENT_SPACING * 0.3;\r\n const fabricSwatchY = infoY + infoFontSize / 2 - swatchSize / 2;\r\n\r\n const fabricColorSwatchUrl = getImageUrl(\"threadColor\", fabricColor);\r\n const fabricColorSwatchImg = imageRefs.current.get(fabricColorSwatchUrl);\r\n if (\r\n fabricColorSwatchImg?.complete &&\r\n fabricColorSwatchImg.naturalHeight > 0\r\n ) {\r\n const ratio =\r\n fabricColorSwatchImg.naturalWidth / fabricColorSwatchImg.naturalHeight;\r\n const swatchW = Math.max(1, Math.floor(swatchSize * ratio));\r\n ctx.drawImage(\r\n fabricColorSwatchImg,\r\n fabricSwatchX,\r\n fabricSwatchY,\r\n swatchW,\r\n swatchSize\r\n );\r\n }\r\n }\r\n\r\n infoY += infoLineHeight;\r\n\r\n // Attachment\r\n if (position.attachment) {\r\n drawAsterisk(padding + bottomPadding, infoY);\r\n const attachmentLabel = `Attachment: ${position.attachment}`;\r\n ctx.fillText(attachmentLabel, startX, infoY);\r\n infoY += infoLineHeight;\r\n }\r\n\r\n // Size\r\n if (side.size) {\r\n drawAsterisk(padding + bottomPadding, infoY);\r\n const sizeLabel = `Size: ${side.size}`;\r\n ctx.fillText(sizeLabel, startX, infoY);\r\n infoY += infoLineHeight;\r\n }\r\n\r\n // Right side: Image from config.image_url\r\n if (config.image_url) {\r\n // Draw \"Mockup\" label\r\n ctx.font = `bold ${infoFontSize * 1.2}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = \"#000000\";\r\n const mockupLabel = \"Mockup\";\r\n const mockupLabelWidth = ctx.measureText(mockupLabel).width;\r\n const mockupLabelX =\r\n imageSectionX + (imageSectionWidth - mockupLabelWidth) / 1.2;\r\n ctx.fillText(mockupLabel, mockupLabelX, bottomSectionY + LAYOUT.PADDING);\r\n\r\n const mockupLabelHeight = infoFontSize * 1.2 + LAYOUT.LINE_GAP * 0.5;\r\n\r\n const img =\r\n imageRefs.current.get(config.image_url) ??\r\n imageRefs.current.get(\"mockup\");\r\n if (img?.complete && img.naturalWidth > 0) {\r\n const maxImgWidth = imageSectionWidth; // Sử dụng toàn bộ width, sát lề phải\r\n const maxImgHeight = bottomUsableHeight - mockupLabelHeight;\r\n\r\n const imgAspectRatio = img.naturalWidth / img.naturalHeight;\r\n let drawWidth = maxImgWidth;\r\n let drawHeight = drawWidth / imgAspectRatio;\r\n\r\n if (drawHeight > maxImgHeight) {\r\n drawHeight = maxImgHeight;\r\n drawWidth = drawHeight * imgAspectRatio;\r\n }\r\n\r\n const imgX = imageSectionX + (imageSectionWidth - drawWidth) / 0.8;\r\n const imgY =\r\n bottomSectionY +\r\n LAYOUT.PADDING +\r\n mockupLabelHeight +\r\n (bottomUsableHeight - mockupLabelHeight - drawHeight) / 2;\r\n\r\n ctx.drawImage(img, imgX, imgY, drawWidth, drawHeight);\r\n }\r\n }\r\n\r\n ctx.restore();\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 // Check if this is a stroke_patches layout\r\n const hasStrokePatches = config.sides.some(\r\n (side) => side.item_type && side.item_type.includes(\"stroke_patches\")\r\n );\r\n\r\n if (hasStrokePatches) {\r\n renderStrokePatchesCanvas(ctx, canvas, config, imageRefs);\r\n return;\r\n }\r\n\r\n // Check if this is a template_custom_text_patches layout\r\n const hasTemplateCustomTextPatches = config.sides.some(\r\n (side) => side.item_type && side.item_type.includes(\"template_custom_text_patches\")\r\n );\r\n\r\n if (hasTemplateCustomTextPatches) {\r\n renderTemplateCustomTextPatchesCanvas(ctx, canvas, config, imageRefs);\r\n return;\r\n }\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;\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, có bao gồm padding\r\n let testMeasureY = LAYOUT.PADDING;\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 testMeasureY\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 testMeasureY,\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\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 // Calculate currentY: padding top + actual warning & message height (no spacing)\r\n let currentY = LAYOUT.PADDING;\r\n\r\n // Render warning & message with scaleFactor and get actual heights\r\n if (config.warning_message) {\r\n const actualWarningHeight = renderWarning(\r\n ctx,\r\n canvas,\r\n config.warning_message,\r\n scaleFactor,\r\n currentY\r\n );\r\n currentY += actualWarningHeight;\r\n }\r\n if (config.message) {\r\n const actualMessageHeight = renderWarning(\r\n ctx,\r\n canvas,\r\n config.message,\r\n scaleFactor,\r\n currentY,\r\n \"\", // message: không cần prefix \"Note\"\r\n DEFAULT_ERROR_COLOR // message: hiển thị màu đỏ\r\n );\r\n currentY += actualMessageHeight;\r\n }\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 lines.forEach((line, index) => {\r\n const y = offsetY + 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 =\r\n lineTopY < mockupBounds.y + mockupBounds.height &&\r\n 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: {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n } | 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 =\r\n textPositions.length === 0 ||\r\n 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 =\r\n iconPositions.length === 0 ||\r\n 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\" &&\r\n (!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 = 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 ||\r\n 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:\r\n 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?: {\r\n font?: boolean;\r\n shape?: boolean;\r\n floral?: boolean;\r\n color?: boolean;\r\n },\r\n mockupBounds: {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n } | 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(\r\n colors,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\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 (\r\n values.floral &&\r\n values.floral !== \"None\" &&\r\n shouldRenderField(\"floral\")\r\n ) {\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: {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n } | 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.replace(/\\r\\n/g, \"\\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 =\r\n textCenterY -\r\n ((lines.length - 1) / 2) * valueLineHeight +\r\n idx * valueLineHeight;\r\n // Tính effectiveMaxWidth cho dòng này\r\n const effectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n valueStartX,\r\n lineY,\r\n valueLineHeight,\r\n availableWidth,\r\n mockupBounds\r\n )\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 =\r\n textCenterY -\r\n ((lines.length - 1) / 2) * valueLineHeight +\r\n 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 const prefix = \"Font: \";\r\n const suffix =\r\n position.is_font_default === true ? \" (Mặc định)\" : \" (Custom)\";\r\n const fontName = position.font;\r\n const fullText = `${prefix}${fontName}${suffix}`;\r\n\r\n const lineHeight = otherFontSize + lineGap;\r\n const textTopY = currentY;\r\n const effectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(x, textTopY, lineHeight, maxWidth, mockupBounds)\r\n : maxWidth;\r\n\r\n const MIN_FONT_FONT_SIZE = otherFontSize * 0.5;\r\n\r\n const measureFontTextWidth = (fontSize: number) => {\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const prefixWidth = ctx.measureText(prefix).width;\r\n ctx.font = `${fontSize}px \"${position.font}\"`;\r\n const fontNameWidth = ctx.measureText(fontName).width;\r\n ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const suffixWidth = ctx.measureText(suffix).width;\r\n return prefixWidth + fontNameWidth + suffixWidth;\r\n };\r\n\r\n const checkFontSizeFits = (fontSize: number): boolean => {\r\n const textTopY = currentY;\r\n const lineHeight = fontSize + lineGap;\r\n const effectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n x,\r\n textTopY,\r\n lineHeight,\r\n maxWidth,\r\n mockupBounds\r\n )\r\n : maxWidth;\r\n const textWidth = measureFontTextWidth(fontSize);\r\n return textWidth <= effectiveMaxWidth;\r\n };\r\n\r\n let effectiveFontSize = otherFontSize;\r\n let needsWrap = false;\r\n\r\n // Bước 1: Thử giảm font size, kiểm tra xem có vừa chiều ngang không\r\n const baseMaxWidth = measureFontTextWidth(otherFontSize);\r\n if (baseMaxWidth > effectiveMaxWidth) {\r\n // Binary search để tìm font size lớn nhất mà vẫn vừa\r\n let left = MIN_FONT_FONT_SIZE;\r\n let right = otherFontSize;\r\n let bestFontSize = MIN_FONT_FONT_SIZE;\r\n\r\n while (right - left > 0.1) {\r\n const mid = (left + right) / 2;\r\n if (checkFontSizeFits(mid)) {\r\n bestFontSize = mid;\r\n left = mid;\r\n } else {\r\n right = mid;\r\n }\r\n }\r\n\r\n if (checkFontSizeFits(bestFontSize)) {\r\n // Bước 1 thành công: font size đã shrink vừa chiều ngang\r\n effectiveFontSize = Math.floor(bestFontSize);\r\n } else {\r\n // Bước 1 thất bại: đã shrink đến MIN nhưng vẫn không vừa, sang bước 2\r\n needsWrap = true;\r\n effectiveFontSize = otherFontSize;\r\n }\r\n }\r\n\r\n if (needsWrap) {\r\n // Bước 2: Xuống dòng với font size gốc\r\n ctx.font = `${effectiveFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const wrappedLines = buildWrappedLines(\r\n ctx,\r\n fullText,\r\n effectiveMaxWidth,\r\n x,\r\n textTopY,\r\n lineHeight,\r\n mockupBounds\r\n );\r\n\r\n wrappedLines.forEach((line, index) => {\r\n const lineY = textTopY + index * lineHeight;\r\n\r\n const lineEffectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(x, lineY, lineHeight, maxWidth, mockupBounds)\r\n : maxWidth;\r\n\r\n let lineToRender = line;\r\n const lineWidth = ctx.measureText(lineToRender).width;\r\n\r\n if (lineWidth > lineEffectiveMaxWidth) {\r\n while (\r\n ctx.measureText(lineToRender).width > lineEffectiveMaxWidth &&\r\n lineToRender.length > 0\r\n ) {\r\n lineToRender = lineToRender.slice(0, -1);\r\n }\r\n }\r\n\r\n ctx.fillText(lineToRender, x, lineY);\r\n });\r\n\r\n currentY += wrappedLines.length * lineHeight;\r\n } else {\r\n // Bước 1 thành công: Render với font size đã shrink (1 dòng)\r\n const shrunkTextTopY = currentY;\r\n const shrunkLineHeight = effectiveFontSize + lineGap;\r\n const shrunkEffectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n x,\r\n shrunkTextTopY,\r\n shrunkLineHeight,\r\n maxWidth,\r\n mockupBounds\r\n )\r\n : maxWidth;\r\n\r\n ctx.font = `${effectiveFontSize}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 ctx.font = `${effectiveFontSize}px \"${position.font}\"`;\r\n const fontNameWidth = ctx.measureText(fontName).width;\r\n const totalWidth = prefixWidth + fontNameWidth;\r\n\r\n if (totalWidth > shrunkEffectiveMaxWidth) {\r\n // Cần cắt font name\r\n let truncatedFontName = fontName;\r\n while (\r\n ctx.measureText(truncatedFontName).width >\r\n shrunkEffectiveMaxWidth - prefixWidth &&\r\n truncatedFontName.length > 0\r\n ) {\r\n truncatedFontName = truncatedFontName.slice(0, -1);\r\n }\r\n ctx.fillText(truncatedFontName, currentX, currentY);\r\n currentX += ctx.measureText(truncatedFontName).width;\r\n } else {\r\n ctx.fillText(fontName, currentX, currentY);\r\n currentX += fontNameWidth;\r\n }\r\n\r\n ctx.font = `${effectiveFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n const remainingWidth = shrunkEffectiveMaxWidth - (currentX - x);\r\n if (remainingWidth > 0) {\r\n let truncatedSuffix = suffix;\r\n while (\r\n ctx.measureText(truncatedSuffix).width > remainingWidth &&\r\n truncatedSuffix.length > 0\r\n ) {\r\n truncatedSuffix = truncatedSuffix.slice(0, -1);\r\n }\r\n if (truncatedSuffix.length > 0) {\r\n ctx.fillText(truncatedSuffix, currentX, currentY);\r\n }\r\n }\r\n\r\n currentY += shrunkLineHeight;\r\n }\r\n }\r\n\r\n if (showLabels.color) {\r\n const colorValue =\r\n 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(\r\n colors,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\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(\r\n x,\r\n currentY,\r\n lineHeight,\r\n maxWidth,\r\n mockupBounds\r\n )\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 =\r\n 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: {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n } | 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 =\r\n 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 =\r\n iconWidth + LAYOUT.ELEMENT_SPACING * scaleFactor;\r\n }\r\n }\r\n }\r\n\r\n const availableWidth = Math.max(\r\n 1,\r\n maxWidth - labelWidth - iconImageReservedWidth\r\n );\r\n const textCenterY = cursorY + iconImageHeight / 2;\r\n const valueStartX = x + labelWidth;\r\n\r\n const textTopY = textCenterY - iconFontSize / 2;\r\n const lineHeight = iconFontSize;\r\n const effectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n valueStartX,\r\n textTopY,\r\n lineHeight,\r\n availableWidth,\r\n mockupBounds\r\n )\r\n : availableWidth;\r\n\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 const checkFontSizeFits = (fontSize: number): boolean => {\r\n const textTopY = textCenterY - fontSize / 2;\r\n const lineHeight = fontSize;\r\n const effectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n valueStartX,\r\n textTopY,\r\n lineHeight,\r\n availableWidth,\r\n mockupBounds\r\n )\r\n : availableWidth;\r\n const textWidth = measureIconValueWidth(fontSize);\r\n return textWidth <= effectiveMaxWidth;\r\n };\r\n\r\n let effectiveIconValueFontSize = iconFontSize;\r\n let needsWrap = false;\r\n\r\n // Bước 1: Thử giảm font size, kiểm tra xem có vừa chiều ngang không\r\n const baseMaxWidth = measureIconValueWidth(iconFontSize);\r\n if (baseMaxWidth > effectiveMaxWidth) {\r\n // Binary search để tìm font size lớn nhất mà vẫn vừa\r\n let left = MIN_ICON_VALUE_FONT_SIZE;\r\n let right = iconFontSize;\r\n let bestFontSize = MIN_ICON_VALUE_FONT_SIZE;\r\n\r\n while (right - left > 0.1) {\r\n const mid = (left + right) / 2;\r\n if (checkFontSizeFits(mid)) {\r\n bestFontSize = mid;\r\n left = mid;\r\n } else {\r\n right = mid;\r\n }\r\n }\r\n\r\n if (checkFontSizeFits(bestFontSize)) {\r\n // Bước 1 thành công: font size đã shrink vừa chiều ngang\r\n effectiveIconValueFontSize = Math.floor(bestFontSize);\r\n } else {\r\n // Bước 1 thất bại: đã shrink đến MIN nhưng vẫn không vừa, sang bước 2\r\n needsWrap = true;\r\n effectiveIconValueFontSize = iconFontSize;\r\n }\r\n }\r\n\r\n // Bước 2: Nếu bước 1 thất bại, xuống dòng với font size gốc\r\n\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 ctx.font = `${effectiveIconValueFontSize}px ${LAYOUT.FONT_FAMILY}`;\r\n ctx.fillStyle = DEFAULT_ERROR_COLOR;\r\n\r\n let maxValueLineWidth = 0;\r\n let totalTextHeight = iconImageHeight;\r\n\r\n if (needsWrap) {\r\n // Bước 2: Xuống dòng với font size gốc\r\n const wrappedLines = buildWrappedLines(\r\n ctx,\r\n iconValue,\r\n effectiveMaxWidth,\r\n valueStartX,\r\n textTopY,\r\n lineHeight,\r\n mockupBounds\r\n );\r\n\r\n // Tính height dựa trên số dòng thực tế\r\n totalTextHeight = Math.max(\r\n iconImageHeight,\r\n wrappedLines.length * lineHeight\r\n );\r\n\r\n wrappedLines.forEach((line, index) => {\r\n const lineTopY = textTopY + index * lineHeight;\r\n const lineCenterY = lineTopY + lineHeight / 2;\r\n\r\n const lineEffectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n valueStartX,\r\n lineTopY,\r\n lineHeight,\r\n availableWidth,\r\n mockupBounds\r\n )\r\n : availableWidth;\r\n\r\n let lineToRender = line;\r\n const lineWidth = ctx.measureText(lineToRender).width;\r\n\r\n if (lineWidth > lineEffectiveMaxWidth) {\r\n while (\r\n ctx.measureText(lineToRender).width > lineEffectiveMaxWidth &&\r\n lineToRender.length > 0\r\n ) {\r\n lineToRender = lineToRender.slice(0, -1);\r\n }\r\n }\r\n\r\n ctx.fillText(lineToRender, valueStartX, lineCenterY);\r\n const w = ctx.measureText(lineToRender).width;\r\n if (w > maxValueLineWidth) maxValueLineWidth = w;\r\n });\r\n } else {\r\n // Bước 1 thành công: Render với font size đã shrink (1 dòng)\r\n const shrunkTextTopY = textCenterY - effectiveIconValueFontSize / 2;\r\n const shrunkLineHeight = effectiveIconValueFontSize;\r\n const shrunkEffectiveMaxWidth = mockupBounds\r\n ? getEffectiveMaxWidth(\r\n valueStartX,\r\n shrunkTextTopY,\r\n shrunkLineHeight,\r\n availableWidth,\r\n mockupBounds\r\n )\r\n : availableWidth;\r\n\r\n const lineText = ` ${iconValue}`;\r\n let lineToRender = lineText;\r\n const lineWidth = ctx.measureText(lineToRender).width;\r\n\r\n if (lineWidth > shrunkEffectiveMaxWidth) {\r\n while (\r\n ctx.measureText(lineToRender).width > shrunkEffectiveMaxWidth &&\r\n lineToRender.length > 0\r\n ) {\r\n lineToRender = lineToRender.slice(0, -1);\r\n }\r\n }\r\n\r\n ctx.fillText(lineToRender, valueStartX, textCenterY);\r\n const w = ctx.measureText(lineToRender).width;\r\n if (w > maxValueLineWidth) maxValueLineWidth = w;\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: totalTextHeight + 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 = 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(\r\n iconColors,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\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(\r\n ...testLines.map((line) => ctx.measureText(line).width)\r\n );\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(\r\n ctx,\r\n iconColors,\r\n swatchX,\r\n swatchY,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\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 =\r\n colorResult.lastLineY + Math.floor(otherFontSize / 2 - swatchH / 2);\r\n\r\n // Render swatches (đã kiểm tra overflow ở trên)\r\n drawSwatches(\r\n ctx,\r\n iconColors,\r\n swatchX,\r\n swatchY,\r\n swatchH,\r\n scaleFactor,\r\n imageRefs\r\n );\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([preloadFonts(config), preloadImages(config, imageRefs)]);\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]}