// 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 使用)