fix(font): 主位图确定性选择(修复并行测试下 map 随机序 flake)

This commit is contained in:
NianGao Dev
2026-08-15 23:40:56 +08:00
parent 355fa200a6
commit 272f69b6a3
4 changed files with 13 additions and 8 deletions

View File

@@ -34,6 +34,7 @@ func (a *Atlas) Missing() Glyph { return Glyph{X: 0, Y: 0, W: 8, H: 8, Width: 8,
// Build 从资源管理器加载字体name 如 "default"reference provider 已由 assets 展开。
// 每个 bitmap provider 对应一张 8px 网格位图:列数 = 图宽 / 8。
// 主位图Atlas.Image确定性选择优先含 "ascii" 的位图,否则取首个(供 UI 直接采样)。
func Build(m *assets.Manager, name string) (*Atlas, error) {
f, err := m.LoadFont(name)
if err != nil {
@@ -41,6 +42,7 @@ func Build(m *assets.Manager, name string) (*Atlas, error) {
}
at := &Atlas{Glyphs: make(map[rune]Glyph)}
imgCache := make(map[string]image.Image)
var primaryName string
for _, p := range f.Providers {
if p.Type != "bitmap" || p.File == "" {
continue
@@ -59,6 +61,12 @@ func Build(m *assets.Manager, name string) (*Atlas, error) {
return nil, fmt.Errorf("font.Build %s: %w", p.File, err)
}
imgCache[p.File] = img
if primaryName == "" {
primaryName = p.File // 首个位图作为回退主位图
}
if strings.Contains(p.File, "ascii") {
primaryName = p.File // ascii 优先UI 主字体)
}
}
cols := img.Bounds().Dx() / 8
if cols <= 0 {
@@ -90,11 +98,8 @@ func Build(m *assets.Manager, name string) (*Atlas, error) {
}
}
}
if at.Image == nil && len(imgCache) > 0 {
for _, img := range imgCache { // 取第一张作为主位图(测试/调试用)
at.Image = img
break
}
if primaryName != "" {
at.Image = imgCache[primaryName] // 确定性主位图
}
return at, nil
}

View File

@@ -27,7 +27,7 @@ func TestBuild(t *testing.T) {
t.Fatalf("字形 %q 宽度期望 8实际 %d", ch, g.W)
}
}
// 主位图: 12816 列 × 8px高为 8 的整数倍(原版 ascii.png 为 128×536
// 主位图:ascii 位图为 12816 列 × 8px高为 8 的整数倍
if at.Image == nil {
t.Fatal("主位图为空")
}

View File

@@ -237,4 +237,4 @@ void main() {
float b = max(sky, blk * 0.9 + 0.06);
fragColor = vec4(c.rgb * b, c.a);
}
`
`

View File

@@ -306,4 +306,4 @@ func compileShader(kind uint32, src string) (uint32, error) {
return s, nil
}
var _ = textr.New // 保持引用(长文本光栅化路径后置启用)
var _ = textr.New // 保持引用(长文本光栅化路径后置启用)