94 lines
2.6 KiB
Go
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("没有可用字体")
|
|
}
|