fix: add cjk fallback fonts for psd export
This commit is contained in:
parent
cc01b539bc
commit
59e26064e5
@ -136,6 +136,47 @@ function getFontMimeType(font: AgentPsdFont | undefined, fontFamily: string) {
|
||||
return "font/ttf";
|
||||
}
|
||||
|
||||
const GENERIC_FONT_FAMILIES = new Set(["sans-serif", "serif", "monospace", "cursive", "fantasy", "system-ui"]);
|
||||
const CJK_FALLBACK_FONT_FAMILIES = [
|
||||
"Noto Sans CJK SC",
|
||||
"Noto Sans SC",
|
||||
"Source Han Sans SC",
|
||||
"Microsoft YaHei",
|
||||
"PingFang SC",
|
||||
"Hiragino Sans GB",
|
||||
"WenQuanYi Zen Hei",
|
||||
"SimHei",
|
||||
"Arial Unicode MS",
|
||||
"sans-serif",
|
||||
] as const;
|
||||
|
||||
function textContainsCjkGlyphs(value: string) {
|
||||
return /[\u3400-\u9fff\u3040-\u30ff\uac00-\ud7af]/.test(String(value || ""));
|
||||
}
|
||||
|
||||
function buildSvgFontFamilyStack(fontFamily: string, text: string) {
|
||||
const familyTokens = new Set<string>();
|
||||
const primaryFamily = String(fontFamily || "").trim();
|
||||
|
||||
if (primaryFamily) {
|
||||
familyTokens.add(primaryFamily);
|
||||
}
|
||||
|
||||
if (textContainsCjkGlyphs(text)) {
|
||||
for (const fallbackFamily of CJK_FALLBACK_FONT_FAMILIES) {
|
||||
familyTokens.add(fallbackFamily);
|
||||
}
|
||||
} else {
|
||||
familyTokens.add("sans-serif");
|
||||
}
|
||||
|
||||
return Array.from(familyTokens)
|
||||
.map((family) =>
|
||||
GENERIC_FONT_FAMILIES.has(family) ? family : `"${escapeXml(family)}"`
|
||||
)
|
||||
.join(", ");
|
||||
}
|
||||
|
||||
async function createTextOverlayBuffer(params: {
|
||||
width: number;
|
||||
height: number;
|
||||
@ -192,6 +233,7 @@ async function createTextOverlayBuffer(params: {
|
||||
}
|
||||
|
||||
const escapedFamily = escapeXml(fontFamily || "sans-serif");
|
||||
const fontFamilyStack = buildSvgFontFamilyStack(fontFamily, normalizedText);
|
||||
const fontFaceCss = fontBuffer
|
||||
? `@font-face { font-family: "${escapedFamily}"; src: url("data:${getFontMimeType(font, fontFamily)};base64,${fontBuffer.toString("base64")}"); }`
|
||||
: "";
|
||||
@ -217,7 +259,7 @@ async function createTextOverlayBuffer(params: {
|
||||
<defs>
|
||||
<style>
|
||||
${fontFaceCss}
|
||||
.text { font-family: "${escapedFamily}", sans-serif; font-size: ${adjustedFontSize}px; font-weight: ${fontWeight}; fill: ${textColor}; letter-spacing: ${letterSpacing}px; }
|
||||
.text { font-family: ${fontFamilyStack}; font-size: ${adjustedFontSize}px; font-weight: ${fontWeight}; fill: ${textColor}; letter-spacing: ${letterSpacing}px; }
|
||||
</style>
|
||||
<clipPath id="${clipId}">
|
||||
<rect x="0" y="0" width="${width}" height="${height}" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user