77 lines
2.0 KiB
Go
77 lines
2.0 KiB
Go
// Package cjkfont 中文字体渲染:加载系统 CJK 字体(微软雅黑)光栅化文本(UI还原.md §4 中文回退)。
|
||
//
|
||
// 素材包位图字体只含 ASCII;中文(如「年糕历险记」)用系统字体渲染,
|
||
// 保持像素风(最近邻采样、整数缩放),字形不追求与原版一致。
|
||
package cjkfont
|
||
|
||
import (
|
||
"image"
|
||
"image/color"
|
||
"os"
|
||
|
||
"golang.org/x/image/font"
|
||
"golang.org/x/image/font/opentype"
|
||
"golang.org/x/image/math/fixed"
|
||
)
|
||
|
||
// Renderer CJK 文本渲染器。
|
||
type Renderer struct {
|
||
face font.Face
|
||
}
|
||
|
||
// Load 加载字体文件(如 C:\Windows\Fonts\msyh.ttc)。
|
||
func Load(path string, sizePx float64) (*Renderer, error) {
|
||
data, err := os.ReadFile(path)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
// 兼容 .ttc 字体集合(如 msyh.ttc)与单字体 .ttf/.otf
|
||
var f *opentype.Font
|
||
if col, err := opentype.ParseCollection(data); err == nil && col != nil && col.NumFonts() > 0 {
|
||
f, err = col.Font(0)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
} else {
|
||
f, err = opentype.Parse(data)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
face, err := opentype.NewFace(f, &opentype.FaceOptions{
|
||
Size: sizePx,
|
||
DPI: 72,
|
||
Hinting: font.HintingNone,
|
||
})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return &Renderer{face: face}, nil
|
||
}
|
||
|
||
// Width 文本像素宽度。
|
||
func (r *Renderer) Width(s string) int {
|
||
d := &font.Drawer{Face: r.face}
|
||
return d.MeasureString(s).Ceil()
|
||
}
|
||
|
||
// Draw 渲染文本为 RGBA 图像(含 1px 阴影,UI还原.md §4)。
|
||
func (r *Renderer) Draw(s string, c color.RGBA) image.Image {
|
||
w := r.Width(s) + 1
|
||
h := int(r.face.Metrics().Height.Ceil()) + 1
|
||
img := image.NewRGBA(image.Rect(0, 0, w, h))
|
||
d := &font.Drawer{
|
||
Dst: img,
|
||
Src: image.NewUniform(c),
|
||
Face: r.face,
|
||
}
|
||
// 阴影
|
||
sh := &font.Drawer{Dst: img, Src: image.NewUniform(color.RGBA{10, 10, 10, 220}), Face: r.face}
|
||
sh.Dot = fixed.P(1, int(r.face.Metrics().Ascent.Ceil())+1)
|
||
sh.DrawString(s)
|
||
// 正文
|
||
d.Dot = fixed.P(0, int(r.face.Metrics().Ascent.Ceil()))
|
||
d.DrawString(s)
|
||
return img
|
||
}
|