fix: improve psd template text rendering
This commit is contained in:
parent
bc8c3084fe
commit
71997086e1
@ -70,6 +70,7 @@ import {
|
||||
isAgentPsdImageLayerSlot,
|
||||
isAgentPsdTextLayerSlot,
|
||||
parseAgentPsdTemplates,
|
||||
resolveAgentPsdTextLayerEffectiveAlign,
|
||||
} from "@/lib/agents/psd-template-config";
|
||||
import {
|
||||
defaultAgentPsdTemplateSecondaryCategoryConfig,
|
||||
@ -992,9 +993,11 @@ function getLayerFrameStyle(
|
||||
|
||||
function getResolvedTextPreview(
|
||||
layer: AgentPsdTemplateTextLayerSlot,
|
||||
value: string
|
||||
value?: string
|
||||
) {
|
||||
return value || layer.placeholder || layer.layerName;
|
||||
return typeof value === "string"
|
||||
? value
|
||||
: layer.placeholder || layer.layerName;
|
||||
}
|
||||
|
||||
function getResolvedTextLayerColor(
|
||||
@ -1023,10 +1026,11 @@ function getTextLayerRenderFrame(
|
||||
});
|
||||
const width = Math.max(layer.width, resolvedLayout.contentWidth);
|
||||
const height = Math.max(layer.height, resolvedLayout.contentHeight);
|
||||
const textAlign = resolveAgentPsdTextLayerEffectiveAlign(layer);
|
||||
const offsetX =
|
||||
layer.textAlign === "right"
|
||||
textAlign === "right"
|
||||
? layer.width - width
|
||||
: layer.textAlign === "center"
|
||||
: textAlign === "center"
|
||||
? (layer.width - width) / 2
|
||||
: 0;
|
||||
|
||||
@ -1046,16 +1050,17 @@ function renderTextLayerPreviewContent(
|
||||
) {
|
||||
const resolvedText = getResolvedTextPreview(layer, value);
|
||||
const resolvedLayout = getTextLayerRenderFrame(layer, resolvedText);
|
||||
const textAlign = resolveAgentPsdTextLayerEffectiveAlign(layer);
|
||||
const textAnchor =
|
||||
layer.textAlign === "center"
|
||||
textAlign === "center"
|
||||
? "middle"
|
||||
: layer.textAlign === "right"
|
||||
: textAlign === "right"
|
||||
? "end"
|
||||
: "start";
|
||||
const textX =
|
||||
layer.textAlign === "center"
|
||||
textAlign === "center"
|
||||
? resolvedLayout.width / 2
|
||||
: layer.textAlign === "right"
|
||||
: textAlign === "right"
|
||||
? resolvedLayout.width - layer.paddingX
|
||||
: layer.paddingX;
|
||||
|
||||
@ -3043,7 +3048,7 @@ export function AgentPsdTemplateEditorDialog({
|
||||
}
|
||||
|
||||
const value =
|
||||
effectiveTextAssignments[layer.id] || "";
|
||||
effectiveTextAssignments[layer.id] ?? "";
|
||||
const resolvedTextColor =
|
||||
effectiveTextColorAssignments[layer.id] ||
|
||||
layer.textColor;
|
||||
@ -3076,7 +3081,7 @@ export function AgentPsdTemplateEditorDialog({
|
||||
|
||||
const textFrame = getTextLayerRenderFrame(
|
||||
layer,
|
||||
value || layer.placeholder || layer.layerName
|
||||
value
|
||||
);
|
||||
|
||||
return (
|
||||
@ -3092,7 +3097,7 @@ export function AgentPsdTemplateEditorDialog({
|
||||
>
|
||||
{renderTextLayerPreviewContent(
|
||||
layer,
|
||||
value || layer.placeholder || layer.layerName,
|
||||
value,
|
||||
resolvedTextColor
|
||||
)}
|
||||
</div>
|
||||
@ -3243,7 +3248,7 @@ export function AgentPsdTemplateEditorDialog({
|
||||
isSelected
|
||||
);
|
||||
const currentValue =
|
||||
effectiveTextAssignments[layer.id] || "";
|
||||
effectiveTextAssignments[layer.id] ?? "";
|
||||
const resolvedTextColor =
|
||||
effectiveTextColorAssignments[layer.id] ||
|
||||
layer.textColor;
|
||||
@ -3496,7 +3501,7 @@ export function AgentPsdTemplateEditorDialog({
|
||||
}
|
||||
rows={4}
|
||||
value={
|
||||
effectiveTextAssignments[selectedTextLayer.id] || ""
|
||||
effectiveTextAssignments[selectedTextLayer.id] ?? ""
|
||||
}
|
||||
/>
|
||||
<div className="flex flex-wrap gap-x-4 gap-y-2 rounded-xl bg-white/[0.02] px-4 py-3 text-white/60 text-xs shadow-inner">
|
||||
|
||||
@ -171,8 +171,7 @@ export function AgentWorkflowMaterialPicker({
|
||||
recommendedImageIds.every((id) => selectedSet.has(id));
|
||||
const isAutoSelectedResult =
|
||||
Boolean(hasSystemRecommendedSelection) && !hasManualSelectionInteraction;
|
||||
const canTogglePreviewMode =
|
||||
totalImageCount > 0 && selectedGalleryCount > 0 && selectedGalleryCount < totalImageCount;
|
||||
const canTogglePreviewMode = totalImageCount > 0;
|
||||
const visibleImages = useMemo(() => {
|
||||
if (!galleryImages.length) {
|
||||
return [];
|
||||
@ -201,8 +200,8 @@ export function AgentWorkflowMaterialPicker({
|
||||
if (hasManualSelectionInteraction) {
|
||||
return;
|
||||
}
|
||||
setPreviewDisplayMode(hasSystemRecommendedSelection ? "selected" : "all");
|
||||
}, [hasManualSelectionInteraction, hasSystemRecommendedSelection, previewResetKey]);
|
||||
setPreviewDisplayMode("all");
|
||||
}, [hasManualSelectionInteraction, previewResetKey]);
|
||||
|
||||
const hasFetchSuccess = !disabled && !isLoading && !errorText && Boolean(result);
|
||||
|
||||
|
||||
@ -95,9 +95,12 @@ export async function executeAgentPsdTemplateRenderRequest(
|
||||
}
|
||||
|
||||
if (isAgentPsdTextLayerSlot(layer)) {
|
||||
const nextText = String(body.textAssignments[layer.id] || layer.defaultText || "").trim();
|
||||
if (nextText) {
|
||||
textAssignments[layer.id] = nextText;
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(body.textAssignments, layer.id)
|
||||
) {
|
||||
textAssignments[layer.id] = String(
|
||||
body.textAssignments[layer.id] ?? ""
|
||||
).trim();
|
||||
}
|
||||
textColorAssignments[layer.id] = normalizeHexColor(
|
||||
body.textColorAssignments[layer.id] || layer.textColor,
|
||||
@ -112,7 +115,8 @@ export async function executeAgentPsdTemplateRenderRequest(
|
||||
layer.isRequired &&
|
||||
(isAgentPsdImageLayerSlot(layer)
|
||||
? !imageAssignments[layer.id]
|
||||
: !textAssignments[layer.id])
|
||||
: !Object.prototype.hasOwnProperty.call(textAssignments, layer.id) &&
|
||||
!String(layer.defaultText || "").trim())
|
||||
);
|
||||
if (missingRequiredLayer) {
|
||||
throw new Error(`缺少必传素材:${missingRequiredLayer.layerName}`);
|
||||
|
||||
@ -289,6 +289,27 @@ export function normalizeAgentPsdTextAlign(value: unknown): AgentPsdTextAlign {
|
||||
return "left";
|
||||
}
|
||||
|
||||
export function resolveAgentPsdTextLayerEffectiveAlign(
|
||||
layer: Pick<
|
||||
AgentPsdTemplateTextLayerSlot,
|
||||
"paddingX" | "styleSource" | "textAlign" | "width"
|
||||
>
|
||||
): AgentPsdTextAlign {
|
||||
const textAlign = normalizeAgentPsdTextAlign(layer.textAlign);
|
||||
const paddingX = normalizePositiveInteger(layer.paddingX);
|
||||
const width = normalizePositiveInteger(layer.width);
|
||||
|
||||
if (
|
||||
layer.styleSource !== "custom" &&
|
||||
textAlign === "center" &&
|
||||
paddingX <= Math.max(2, Math.round(width * 0.02))
|
||||
) {
|
||||
return "left";
|
||||
}
|
||||
|
||||
return textAlign;
|
||||
}
|
||||
|
||||
export function normalizeAgentPsdTextStyleSource(value: unknown): AgentPsdTextStyleSource {
|
||||
return normalizeText(value) === "custom" ? "custom" : "auto";
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
hasAgentPsdTemplateStoredLayerSource,
|
||||
isAgentPsdImageLayerSlot,
|
||||
isAgentPsdTextLayerSlot,
|
||||
resolveAgentPsdTextLayerEffectiveAlign,
|
||||
type AgentPsdTemplate,
|
||||
} from "@/lib/agents/psd-template-config";
|
||||
import type { AgentPsdFont } from "@/lib/agents/psd-font-config";
|
||||
@ -527,17 +528,30 @@ export async function renderAgentPsdTemplate(params: {
|
||||
}
|
||||
|
||||
if (isAgentPsdTextLayerSlot(layer)) {
|
||||
const text = String(textAssignments[layer.id] || layer.defaultText || "").trim();
|
||||
const hasTextAssignment = Object.prototype.hasOwnProperty.call(
|
||||
textAssignments,
|
||||
layer.id
|
||||
);
|
||||
const defaultText = String(layer.defaultText || "").trim();
|
||||
const text = String(
|
||||
hasTextAssignment ? textAssignments[layer.id] ?? "" : defaultText
|
||||
).trim();
|
||||
const textColor = normalizeHexColor(
|
||||
textColorAssignments[layer.id] || layer.textColor,
|
||||
layer.textColor
|
||||
);
|
||||
const hasColorChange = normalizeHexColor(textColor, layer.textColor) !== normalizeHexColor(layer.textColor);
|
||||
if (!text || (text === defaultText && !hasColorChange)) {
|
||||
if (!text) {
|
||||
if (!hasTextAssignment) {
|
||||
await appendStoredLayer(layer);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (text === defaultText && !hasColorChange) {
|
||||
await appendStoredLayer(layer);
|
||||
continue;
|
||||
}
|
||||
const textAlign = resolveAgentPsdTextLayerEffectiveAlign(layer);
|
||||
|
||||
const font = layer.fontId ? fontMap.get(layer.fontId) : undefined;
|
||||
const fontBuffer = font?.fileUrl
|
||||
@ -587,7 +601,7 @@ export async function renderAgentPsdTemplate(params: {
|
||||
lineHeight: layer.lineHeight,
|
||||
letterSpacing: layer.letterSpacing,
|
||||
textColor,
|
||||
textAlign: layer.textAlign,
|
||||
textAlign,
|
||||
paddingX: layer.paddingX,
|
||||
paddingY: layer.paddingY,
|
||||
maxLines: layer.maxLines,
|
||||
@ -612,7 +626,7 @@ export async function renderAgentPsdTemplate(params: {
|
||||
layerHeight: layer.height,
|
||||
contentWidth: overlayLayout.contentWidth,
|
||||
contentHeight: overlayLayout.contentHeight,
|
||||
textAlign: layer.textAlign,
|
||||
textAlign,
|
||||
topOffset: -overlayLayout.visualOffsetY,
|
||||
});
|
||||
|
||||
|
||||
@ -272,9 +272,12 @@ export function analyzeTextLayerPixels(params: {
|
||||
const rightGap = Math.max(0, width - maxX - 1);
|
||||
const centerTolerance = Math.max(4, width * 0.06);
|
||||
const edgeTolerance = Math.max(6, width * 0.08);
|
||||
const hasReliableCenterPadding =
|
||||
leftGap >= edgeTolerance && rightGap >= edgeTolerance;
|
||||
const contentCenterX = (minX + maxX) / 2;
|
||||
const stageCenterX = (width - 1) / 2;
|
||||
const inferredTextAlign: AgentPsdTextAlign =
|
||||
hasReliableCenterPadding &&
|
||||
Math.abs(contentCenterX - stageCenterX) <= centerTolerance &&
|
||||
Math.abs(leftGap - rightGap) <= edgeTolerance
|
||||
? "center"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user