fix: stabilize psd text font rendering
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-10 21:55:26 +08:00
parent e84bfd94ec
commit 10dc87eaf7
2 changed files with 76 additions and 20 deletions

View File

@ -828,39 +828,68 @@ function renderTextLayerPreviewContent(
) {
const resolvedText = getResolvedTextPreview(layer, value);
const resolvedLayout = getTextLayerRenderFrame(layer, resolvedText);
const textAnchor =
layer.textAlign === "center"
? "middle"
: layer.textAlign === "right"
? "end"
: "start";
const textX =
layer.textAlign === "center"
? resolvedLayout.width / 2
: layer.textAlign === "right"
? resolvedLayout.width - layer.paddingX
: layer.paddingX;
return (
<div
className="relative overflow-visible"
<svg
className="block overflow-visible"
height={resolvedLayout.height}
viewBox={`0 0 ${resolvedLayout.width} ${resolvedLayout.height}`}
width={resolvedLayout.width}
style={{
width: resolvedLayout.width,
height: resolvedLayout.height,
}}
xmlns="http://www.w3.org/2000/svg"
>
{resolvedLayout.lines.map((line, index) => (
<text
fill={color}
fontSize={resolvedLayout.fontSize}
fontWeight={layer.fontWeight}
letterSpacing={layer.letterSpacing}
style={{
fontFamily: buildTextLayerFontFamily(layer),
textRendering: "geometricPrecision",
}}
textAnchor={textAnchor}
xmlSpace="preserve"
>
{resolvedLayout.lines.map((line, index) => (
<tspan
key={`${layer.id}-preview-line-${index + 1}`}
x={textX}
y={
layer.paddingY +
resolvedLayout.fontSize +
index * resolvedLayout.lineHeightPx
}
>
{line || "\u00a0"}
</tspan>
))}
</text>
<foreignObject height="0" width="0" x="0" y="0">
<div
className="absolute overflow-visible whitespace-pre"
key={`${layer.id}-preview-line-${index + 1}`}
style={{
top: layer.paddingY + index * resolvedLayout.lineHeightPx,
width: resolvedLayout.width,
paddingLeft: layer.paddingX,
paddingRight: layer.paddingX,
fontFamily: buildTextLayerFontFamily(layer),
fontSize: resolvedLayout.fontSize,
lineHeight: `${resolvedLayout.fontSize}px`,
letterSpacing: `${layer.letterSpacing}px`,
color,
fontWeight: layer.fontWeight,
textAlign: layer.textAlign,
wordBreak: "keep-all",
overflowWrap: "normal",
fontSize: 0,
}}
>
{line || "\u00a0"}
&nbsp;
</div>
))}
</div>
</foreignObject>
</svg>
);
}

View File

@ -136,6 +136,8 @@ export function repairAgentPsdTemplateFontBindings(
...((layer.detectedFontNames || []).filter(Boolean)),
...(layer.detectedFontName ? [layer.detectedFontName] : []),
];
const preferredDetectedFontName =
detectedFontNames.find((entry) => String(entry || "").trim()) || "";
const currentFont = layer.fontId ? fontMap.get(layer.fontId) : undefined;
const currentFontMatches = currentFont
? doesPsdFontMatchDetectedNames({
@ -163,6 +165,31 @@ export function repairAgentPsdTemplateFontBindings(
};
}
if (
!matchedFont &&
!currentFontMatches &&
(
layer.fontId ||
layer.fontFileUrl ||
layer.fontContentType ||
(preferredDetectedFontName &&
(
layer.fontFamily !== preferredDetectedFontName ||
layer.fontLabel !== preferredDetectedFontName
))
)
) {
didChange = true;
return {
...layer,
fontId: undefined,
fontFamily: preferredDetectedFontName || undefined,
fontLabel: preferredDetectedFontName || undefined,
fontFileUrl: undefined,
fontContentType: undefined,
};
}
if (currentFont && (
layer.fontFamily !== currentFont.family ||
layer.fontLabel !== currentFont.name ||