Files
ngzz-mc/internal/textr/text.go

80 lines
1.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package textr 文本光栅化:把字符串用位图字体渲染成 RGBA 图像(CPU 侧,UI还原.md §4)。
//
// 字形来自素材包 8×8 位图字体(internal/font);本包输出可直接上传为 GL 纹理的图像,
// 因此与渲染线程解耦(GL 只负责贴图)。
package textr
import (
"image"
"image/color"
"image/draw"
"mc/internal/font"
)
// Drawer 文本绘制器。
type Drawer struct {
atlas *font.Atlas
}
// New 创建绘制器。
func New(atlas *font.Atlas) *Drawer { return &Drawer{atlas: atlas} }
// Width 计算文本像素宽度(8px/字符)。
func (d *Drawer) Width(s string) int {
w := 0
for _, r := range s {
if g, ok := d.atlas.Glyphs[r]; ok {
w += g.Width
} else {
w += 8 // 缺失字形占位
}
}
return w
}
// Draw 渲染一行文本(白字透明底;shadow 为 true 时附加 1px 黑色阴影,UI还原.md §4)。
// 返回图像与阴影偏移(阴影在图像内左上角,调用方绘制时需偏移 1px)。
func (d *Drawer) Draw(s string, c color.RGBA, shadow bool) image.Image {
w := d.Width(s)
h := 8
if shadow {
w++
h++
}
img := image.NewRGBA(image.Rect(0, 0, w, h))
x := 0
for _, r := range s {
g, ok := d.atlas.Glyphs[r]
if !ok {
g = d.atlas.Missing()
}
d.blit(img, g, x, 0, c)
if shadow {
d.blit(img, g, x+1, 1, color.RGBA{0, 0, 0, 255})
}
x += g.Width
}
return img
}
// blit 把字形像素以指定颜色写入目标(字形位图按 alpha 通道着色)。
func (d *Drawer) blit(dst *image.RGBA, g font.Glyph, dx, dy int, c color.RGBA) {
if d.atlas.Image == nil {
return
}
src := d.atlas.Image
for y := 0; y < g.H; y++ {
for x := 0; x < g.W; x++ {
r, _, _, a := src.At(g.X+x, g.Y+y).RGBA()
if a == 0 {
continue
}
_ = r // 字形颜色以纹理亮度为准,目标色统一用 c
dst.SetRGBA(dx+x, dy+y, c)
}
}
}
var _ = draw.Draw // 保持 image/draw 引用(后续 9-patch 使用)