Files
dygou_go/font.go
T
2026-06-19 12:10:55 +08:00

94 lines
2.6 KiB
Go

package main
import (
"errors"
"os"
"runtime"
"github.com/golang/freetype"
"github.com/golang/freetype/truetype"
"golang.org/x/image/font/gofont/goregular"
)
// collectFontCandidates 收集常见中文字体路径,允许用 DOUYU_FONT 指定自定义字体。
func collectFontCandidates() []string {
candidates := []string{}
if custom := os.Getenv("DOUYU_FONT"); custom != "" {
candidates = append(candidates, custom)
}
candidates = append(candidates,
"Microsoft Yahei.ttf",
"Microsoft YaHei.ttf",
"NotoSansCJKsc-Regular.otf",
"NotoSansCJK-Regular.ttc",
)
switch runtime.GOOS {
case "darwin":
candidates = append(candidates,
"/System/Library/Fonts/PingFang.ttc",
"/System/Library/Fonts/Supplemental/Arial Unicode.ttf",
"/System/Library/Fonts/Supplemental/Songti.ttc",
)
case "windows":
candidates = append(candidates,
`C:\Windows\Fonts\msyh.ttc`,
`C:\Windows\Fonts\simhei.ttf`,
`C:\Windows\Fonts\simsun.ttc`,
)
default:
candidates = append(candidates,
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.otf",
"/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc",
"/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
)
}
return candidates
}
// loadFont 预加载字体,优先使用本地或系统中文字体,缺失时使用内置字体兜底。
func (s *appState) loadFont() {
s.fontMu.Lock()
defer s.fontMu.Unlock()
source, font, err := parseFirstFont(s.paths.FontFiles)
if err != nil {
source = "内置 Go Regular 字体"
font, err = freetype.ParseFont(goregular.TTF)
if err != nil {
logEvent("字体", "error", "内置字体解析失败,成功图片功能将跳过: %v", err)
return
}
logEvent("字体", "warn", "未找到可用系统字体,使用内置字体兜底,中文可能显示不完整")
}
s.font = font
logEvent("字体", "success", "字体加载完成: %s", source)
}
func parseFirstFont(candidates []string) (string, *truetype.Font, error) {
for _, path := range candidates {
if path == "" {
continue
}
fontBytes, err := os.ReadFile(path)
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
logEvent("字体", "warn", "字体读取失败,已跳过: %s: %v", path, err)
}
continue
}
if len(fontBytes) == 0 {
continue
}
font, err := freetype.ParseFont(fontBytes)
if err != nil {
logEvent("字体", "warn", "字体解析失败,已跳过: %s: %v", path, err)
continue
}
return path, font, nil
}
return "", nil, errors.New("没有可用字体")
}