embroidery-qc-image 1.0.34 → 1.0.36

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.
package/dist/index.js CHANGED
@@ -681,7 +681,7 @@ const renderStrokePatchesCanvas = (ctx, canvas, config, imageRefs) => {
681
681
  // Calculate text size to fit top section
682
682
  let previewFontSize = LAYOUT.HEADER_FONT_SIZE * 3; // Start with large size
683
683
  const fontToUse = isFontMissing ? LAYOUT.FONT_FAMILY : position.font;
684
- ctx.font = `${previewFontSize}px ${fontToUse}`;
684
+ ctx.font = `${previewFontSize}px "${fontToUse}"`;
685
685
  const text = position.text || "";
686
686
  const maxTextWidth = usableWidth * 0.9; // Use 75% of width for better padding
687
687
  const maxTextHeight = actualTopSectionHeight; // Use 60% of height
@@ -689,13 +689,13 @@ const renderStrokePatchesCanvas = (ctx, canvas, config, imageRefs) => {
689
689
  let textWidth = ctx.measureText(text).width;
690
690
  while (textWidth > maxTextWidth && previewFontSize > 50) {
691
691
  previewFontSize *= 0.95;
692
- ctx.font = `${previewFontSize}px ${fontToUse}`;
692
+ ctx.font = `${previewFontSize}px "${fontToUse}"`;
693
693
  textWidth = ctx.measureText(text).width;
694
694
  }
695
695
  // Ensure text height also fits
696
696
  while (previewFontSize > maxTextHeight && previewFontSize > 50) {
697
697
  previewFontSize *= 0.95;
698
- ctx.font = `${previewFontSize}px ${fontToUse}`;
698
+ ctx.font = `${previewFontSize}px "${fontToUse}"`;
699
699
  }
700
700
  // Update textWidth after final scaling
701
701
  textWidth = ctx.measureText(text).width;
@@ -775,7 +775,7 @@ const renderStrokePatchesCanvas = (ctx, canvas, config, imageRefs) => {
775
775
  // Render font name với chính font đó
776
776
  const prefixWidth = ctx.measureText(fontPrefix).width;
777
777
  const fontName = position.font || LAYOUT.FONT_FAMILY;
778
- ctx.font = `${infoFontSize}px ${fontName}`;
778
+ ctx.font = `${infoFontSize}px "${fontName}"`;
779
779
  ctx.fillText(fontName, startX + prefixWidth, infoY);
780
780
  }
781
781
  infoY += infoLineHeight;
@@ -1065,7 +1065,7 @@ const renderTemplateCustomTextPatchesCanvas = (ctx, canvas, config, imageRefs) =
1065
1065
  let high = previewFontSize;
1066
1066
  while (high - low > 1) {
1067
1067
  const mid = (low + high) / 2;
1068
- ctx.font = `${mid}px ${fontToUse}`;
1068
+ ctx.font = `${mid}px "${fontToUse}"`;
1069
1069
  // Kiểm tra width của tất cả các dòng
1070
1070
  const maxLineWidth = Math.max(...textLines.map(line => ctx.measureText(line).width));
1071
1071
  // Kiểm tra height với line height = 1.1 (giảm từ 1.2 để text to hơn)
@@ -1082,7 +1082,7 @@ const renderTemplateCustomTextPatchesCanvas = (ctx, canvas, config, imageRefs) =
1082
1082
  }
1083
1083
  }
1084
1084
  previewFontSize = bestFontSize;
1085
- ctx.font = `${previewFontSize}px ${fontToUse}`;
1085
+ ctx.font = `${previewFontSize}px "${fontToUse}"`;
1086
1086
  // Center the text inside rectangle
1087
1087
  const finalLineHeight = previewFontSize * 1.1;
1088
1088
  const totalTextHeightFinal = textLines.length * finalLineHeight;
@@ -1140,7 +1140,7 @@ const renderTemplateCustomTextPatchesCanvas = (ctx, canvas, config, imageRefs) =
1140
1140
  // Render font name với chính font đó
1141
1141
  const prefixWidth = ctx.measureText(fontPrefix).width;
1142
1142
  const fontName = position.font || LAYOUT.FONT_FAMILY;
1143
- ctx.font = `${infoFontSize}px ${fontName}`;
1143
+ ctx.font = `${infoFontSize}px "${fontName}"`;
1144
1144
  ctx.fillText(fontName, startX + prefixWidth, infoY);
1145
1145
  }
1146
1146
  infoY += infoLineHeight;
@@ -1584,13 +1584,13 @@ const renderSide = (ctx, side, startY, width, height, scaleFactor, imageRefs, mo
1584
1584
  return currentY - startY;
1585
1585
  }
1586
1586
  // Compute uniform properties
1587
- const iconColorPositions = side.positions.filter((p) => p.type === "ICON" &&
1588
- (!p.layer_colors?.length || p.layer_colors.length === 1));
1587
+ // Lấy màu từ tất cả ICON positions (sử dụng getIconColors để ưu tiên layer_colors)
1588
+ const iconColorPositions = side.positions.filter((p) => p.type === "ICON");
1589
1589
  const iconColorValues = iconColorPositions
1590
1590
  .map((p) => {
1591
- if (p.layer_colors?.length === 1)
1592
- return p.layer_colors[0];
1593
- return p.color ?? null;
1591
+ const iconColors = getIconColors(p);
1592
+ // Join các màu bằng dấu phẩy giống TEXT để so sánh uniform
1593
+ return iconColors?.length ? iconColors.join(",") : null;
1594
1594
  })
1595
1595
  .filter((color) => Boolean(color));
1596
1596
  const uniformProps = computeUniformProperties(textPositions, {
@@ -1645,38 +1645,62 @@ const renderSide = (ctx, side, startY, width, height, scaleFactor, imageRefs, mo
1645
1645
  currentY += LAYOUT.LINE_GAP * scaleFactor;
1646
1646
  side.positions.forEach((position) => {
1647
1647
  if (position.type === "ICON") {
1648
- const layerCount = position.layer_colors?.length ?? 0;
1649
- const iconUsesSingleColor = layerCount === 0 || layerCount === 1;
1650
- const iconColorValue = layerCount === 1
1651
- ? position.layer_colors?.[0] ?? null
1652
- : position.color ?? null;
1648
+ const iconColors = getIconColors(position);
1649
+ const iconColorValue = iconColors?.length ? iconColors.join(",") : null;
1650
+ // Icon thể hide color nếu uniform với TEXT, bất kể số lượng màu
1651
+ // (vì TEXT với layer_colors nhiều màu cũng có thể uniform)
1653
1652
  const hideColor = shouldShowUniformLabels &&
1654
1653
  uniformProps.isUniform.color &&
1655
1654
  iconColorValue !== null &&
1656
- uniformProps.values.color === iconColorValue &&
1657
- iconUsesSingleColor;
1655
+ uniformProps.values.color === iconColorValue;
1658
1656
  currentY += renderIconPosition(ctx, position, padding, currentY, sideWidth, scaleFactor, imageRefs, { hideColor }, mockupBounds);
1659
1657
  currentY += (LAYOUT.LINE_GAP / 3) * scaleFactor;
1660
1658
  }
1661
1659
  });
1662
1660
  return currentY - startY;
1663
1661
  };
1662
+ // Helper function để lấy màu từ TEXT position (ưu tiên layer_colors, fallback về character_colors hoặc color)
1663
+ const getTextColors = (position) => {
1664
+ if (position.layer_colors?.length) {
1665
+ return position.layer_colors;
1666
+ }
1667
+ if (position.character_colors?.length) {
1668
+ return position.character_colors;
1669
+ }
1670
+ if (position.color) {
1671
+ return [position.color];
1672
+ }
1673
+ return null;
1674
+ };
1675
+ // Helper function để lấy màu từ ICON position (ưu tiên layer_colors, fallback về color)
1676
+ const getIconColors = (position) => {
1677
+ if (position.layer_colors?.length) {
1678
+ return position.layer_colors;
1679
+ }
1680
+ if (position.color) {
1681
+ return [position.color];
1682
+ }
1683
+ return null;
1684
+ };
1664
1685
  const groupTextPositions = (textPositions) => {
1665
1686
  const groups = [];
1666
1687
  let currentGroup = null;
1667
1688
  let currentProps = null;
1668
1689
  textPositions.forEach((position) => {
1690
+ const textColors = getTextColors(position);
1669
1691
  const posProps = {
1670
1692
  font: position.font,
1671
1693
  text_shape: position.text_shape,
1672
1694
  color: position.color,
1673
1695
  character_colors: position.character_colors?.join(","),
1696
+ layer_colors: textColors?.join(","),
1674
1697
  };
1675
1698
  if (!currentGroup ||
1676
1699
  currentProps.font !== posProps.font ||
1677
1700
  currentProps.text_shape !== posProps.text_shape ||
1678
1701
  currentProps.color !== posProps.color ||
1679
- currentProps.character_colors !== posProps.character_colors) {
1702
+ currentProps.character_colors !== posProps.character_colors ||
1703
+ currentProps.layer_colors !== posProps.layer_colors) {
1680
1704
  if (currentGroup) {
1681
1705
  groups.push(currentGroup);
1682
1706
  }
@@ -1701,9 +1725,12 @@ const computeUniformProperties = (textPositions, options) => {
1701
1725
  const shapes = new Set(textPositions.map((p) => p.text_shape));
1702
1726
  const florals = new Set(textPositions.map((p) => p.floral_pattern ?? "None"));
1703
1727
  const colorSources = [
1704
- ...textPositions.map((p) => p.character_colors?.length
1705
- ? p.character_colors.join(",")
1706
- : p.color ?? "None"),
1728
+ ...textPositions.map((p) => {
1729
+ const textColors = getTextColors(p);
1730
+ return textColors?.length
1731
+ ? textColors.join(",")
1732
+ : p.color ?? "None";
1733
+ }),
1707
1734
  ...(options?.additionalColorValues?.map((color) => color ?? "None") ?? []),
1708
1735
  ];
1709
1736
  if (textPositions.length === 0 &&
@@ -1750,7 +1777,7 @@ const renderUniformLabels = (ctx, uniformProps, x, y, maxWidth, scaleFactor, ima
1750
1777
  let currentX = x + prefixWidth;
1751
1778
  ctx.fillText(prefix, x, cursorY);
1752
1779
  // Render tên font với font từ config
1753
- ctx.font = `${fontSize}px ${values.font}`;
1780
+ ctx.font = `${fontSize}px "${values.font}"`;
1754
1781
  const fontNameWidth = ctx.measureText(values.font).width;
1755
1782
  ctx.fillText(values.font, currentX, cursorY);
1756
1783
  currentX += fontNameWidth;
@@ -1975,7 +2002,7 @@ displayIndex, showLabels, scaleFactor, imageRefs, mockupBounds = null) => {
1975
2002
  const measureFontTextWidth = (fontSize) => {
1976
2003
  ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;
1977
2004
  const prefixWidth = ctx.measureText(prefix).width;
1978
- ctx.font = `${fontSize}px ${position.font}`;
2005
+ ctx.font = `${fontSize}px "${position.font}"`;
1979
2006
  const fontNameWidth = ctx.measureText(fontName).width;
1980
2007
  ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;
1981
2008
  const suffixWidth = ctx.measureText(suffix).width;
@@ -2051,7 +2078,7 @@ displayIndex, showLabels, scaleFactor, imageRefs, mockupBounds = null) => {
2051
2078
  const prefixWidth = ctx.measureText(prefix).width;
2052
2079
  let currentX = x + prefixWidth;
2053
2080
  ctx.fillText(prefix, x, currentY);
2054
- ctx.font = `${effectiveFontSize}px ${position.font}`;
2081
+ ctx.font = `${effectiveFontSize}px "${position.font}"`;
2055
2082
  const fontNameWidth = ctx.measureText(fontName).width;
2056
2083
  const totalWidth = prefixWidth + fontNameWidth;
2057
2084
  if (totalWidth > shrunkEffectiveMaxWidth) {
@@ -2085,9 +2112,11 @@ displayIndex, showLabels, scaleFactor, imageRefs, mockupBounds = null) => {
2085
2112
  }
2086
2113
  }
2087
2114
  if (showLabels.color) {
2088
- const colorValue = position.character_colors?.join(", ") || position.color;
2089
- if (colorValue) {
2090
- const colors = position.character_colors || [position.color];
2115
+ // Ưu tiên layer_colors, fallback về character_colors hoặc color (giống ICON)
2116
+ const textColors = getTextColors(position);
2117
+ if (textColors && textColors.length > 0) {
2118
+ const colorValue = textColors.join(", ");
2119
+ const colors = textColors;
2091
2120
  const swatchH = Math.floor(otherFontSize * LAYOUT.SWATCH_HEIGHT_RATIO);
2092
2121
  const totalSwatchWidth = calculateSwatchesWidth(colors, swatchH, scaleFactor, imageRefs);
2093
2122
  // Tính effectiveMaxWidth cho dòng này để tránh mockup
@@ -2363,16 +2392,9 @@ const renderIconPosition = (ctx, position, x, y, maxWidth, scaleFactor, imageRef
2363
2392
  cursorY += iconResult.height;
2364
2393
  // Draw color swatches (prefer layer_colors, fallback to single color)
2365
2394
  // Nếu icon đã bị xóa thì không cần hiển thị màu chỉ nữa
2366
- const iconColors = position.is_delete_icon
2367
- ? null
2368
- : position.layer_colors?.length
2369
- ? position.layer_colors
2370
- : position.color
2371
- ? [position.color]
2372
- : null;
2373
- const layerCount = position.layer_colors?.length ?? 0;
2374
- const hasMultiLayerColors = layerCount > 1;
2375
- const shouldSkipColorSection = options?.hideColor && !hasMultiLayerColors;
2395
+ const iconColors = position.is_delete_icon ? null : getIconColors(position);
2396
+ // Nếu hideColor = true, ẩn màu của ICON (giống TEXT) bất kể số lượng màu
2397
+ const shouldSkipColorSection = options?.hideColor === true;
2376
2398
  if (iconColors?.length && !shouldSkipColorSection) {
2377
2399
  // Dòng "Màu chỉ:" của icon dùng OTHER_FONT_SIZE, không dùng iconFontSize
2378
2400
  const otherFontSize = LAYOUT.OTHER_FONT_SIZE * scaleFactor;