fix(platform): require supported surface requests and test empty glyphs
- commit
- 2e4532deb31a22f6cc48af28bff8dfcac2bb814b
- author
- brice · · 2026-09-30 04:36 UTC
- parent
- 9064a73
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +49 -1
M internal/platform/wayland/window.go +1 -1
| @@ -116,7 +116,7 @@ func Connect(name string, width, height int32, transparent bool) (_ *Window, err | |||
| 116 | 116 | return nil | |
| 117 | 117 | } | |
| 118 | 118 | w.Compositor = core.NewCompositor(ctx) | |
| 119 | - | if err = bind(core.CompositorInterface, 6, 1, w.Compositor); err != nil { | |
| 119 | + | if err = bind(core.CompositorInterface, 6, 4, w.Compositor); err != nil { | |
| 120 | 120 | return nil, err | |
| 121 | 121 | } | |
| 122 | 122 | w.Shell = xdgshell.NewXdgWmBase(ctx) | |
| @@ -116,7 +116,7 @@ func Connect(name string, width, height int32, transparent bool) (_ *Window, err | |||||
| 116 | return nil | 116 | return nil | ||
| 117 | } | 117 | } | ||
| 118 | w.Compositor = core.NewCompositor(ctx) | 118 | w.Compositor = core.NewCompositor(ctx) | ||
| 119 | - | if err = bind(core.CompositorInterface, 6, 1, w.Compositor); err != nil { | 119 | + | if err = bind(core.CompositorInterface, 6, 4, w.Compositor); err != nil { |
| 120 | return nil, err | 120 | return nil, err | ||
| 121 | } | 121 | } | ||
| 122 | w.Shell = xdgshell.NewXdgWmBase(ctx) | 122 | w.Shell = xdgshell.NewXdgWmBase(ctx) | ||
A internal/render/empty_glyph_test.go +48 -0
| @@ -0,0 +1,48 @@ | |||
| 1 | + | package render | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "testing" | |
| 5 | + | ||
| 6 | + | "github.com/bnema/nefergui/internal/layout" | |
| 7 | + | "github.com/bnema/nefergui/internal/text" | |
| 8 | + | "github.com/go-text/typesetting/font" | |
| 9 | + | ) | |
| 10 | + | ||
| 11 | + | func TestUncoveredSpaceRemainsInvisible(t *testing.T) { | |
| 12 | + | catalog, err := text.Load(text.DirectorySource("../../testdata/fonts")) | |
| 13 | + | if err != nil { | |
| 14 | + | t.Fatal(err) | |
| 15 | + | } | |
| 16 | + | measured, err := text.NewEngine(catalog).Measure("a\u1680b", text.Request{Families: []string{"Noto Sans"}, Size: 20}, 0) | |
| 17 | + | if err != nil { | |
| 18 | + | t.Fatal(err) | |
| 19 | + | } | |
| 20 | + | cmd := layout.Command{Op: "text", Opacity: 1} | |
| 21 | + | spaces := 0 | |
| 22 | + | for _, line := range measured.Lines { | |
| 23 | + | for _, shaped := range line.Runs { | |
| 24 | + | r := layout.Run{Face: shaped.Face, FaceID: shaped.Face.ID, Size: 20} | |
| 25 | + | for _, g := range shaped.Glyphs { | |
| 26 | + | if g.ID == font.EmptyGlyph { | |
| 27 | + | spaces++ | |
| 28 | + | if g.Missing || g.Advance <= 0 { | |
| 29 | + | t.Fatalf("empty space glyph: %+v", g) | |
| 30 | + | } | |
| 31 | + | } | |
| 32 | + | r.Glyphs = append(r.Glyphs, layout.Glyph{ID: uint32(g.ID), X: 6 + g.X, Y: 30 + g.Y}) | |
| 33 | + | } | |
| 34 | + | cmd.Runs = append(cmd.Runs, r) | |
| 35 | + | } | |
| 36 | + | } | |
| 37 | + | if spaces != 1 { | |
| 38 | + | t.Fatalf("want one uncovered space, got %d", spaces) | |
| 39 | + | } | |
| 40 | + | p, err := NewPreparer(256, 2) | |
| 41 | + | if err != nil { | |
| 42 | + | t.Fatal(err) | |
| 43 | + | } | |
| 44 | + | frame, err := p.Prepare([]layout.Command{cmd}, 1, 200, 100) | |
| 45 | + | if err != nil || len(frame.Quads) != 2 { | |
| 46 | + | t.Fatalf("space must emit no quad: %d quads, error %v", len(frame.Quads), err) | |
| 47 | + | } | |
| 48 | + | } | |
| @@ -0,0 +1,48 @@ | |||||
| 1 | + | package render | |||
| 2 | + | ||||
| 3 | + | import ( | |||
| 4 | + | "testing" | |||
| 5 | + | ||||
| 6 | + | "github.com/bnema/nefergui/internal/layout" | |||
| 7 | + | "github.com/bnema/nefergui/internal/text" | |||
| 8 | + | "github.com/go-text/typesetting/font" | |||
| 9 | + | ) | |||
| 10 | + | ||||
| 11 | + | func TestUncoveredSpaceRemainsInvisible(t *testing.T) { | |||
| 12 | + | catalog, err := text.Load(text.DirectorySource("../../testdata/fonts")) | |||
| 13 | + | if err != nil { | |||
| 14 | + | t.Fatal(err) | |||
| 15 | + | } | |||
| 16 | + | measured, err := text.NewEngine(catalog).Measure("a\u1680b", text.Request{Families: []string{"Noto Sans"}, Size: 20}, 0) | |||
| 17 | + | if err != nil { | |||
| 18 | + | t.Fatal(err) | |||
| 19 | + | } | |||
| 20 | + | cmd := layout.Command{Op: "text", Opacity: 1} | |||
| 21 | + | spaces := 0 | |||
| 22 | + | for _, line := range measured.Lines { | |||
| 23 | + | for _, shaped := range line.Runs { | |||
| 24 | + | r := layout.Run{Face: shaped.Face, FaceID: shaped.Face.ID, Size: 20} | |||
| 25 | + | for _, g := range shaped.Glyphs { | |||
| 26 | + | if g.ID == font.EmptyGlyph { | |||
| 27 | + | spaces++ | |||
| 28 | + | if g.Missing || g.Advance <= 0 { | |||
| 29 | + | t.Fatalf("empty space glyph: %+v", g) | |||
| 30 | + | } | |||
| 31 | + | } | |||
| 32 | + | r.Glyphs = append(r.Glyphs, layout.Glyph{ID: uint32(g.ID), X: 6 + g.X, Y: 30 + g.Y}) | |||
| 33 | + | } | |||
| 34 | + | cmd.Runs = append(cmd.Runs, r) | |||
| 35 | + | } | |||
| 36 | + | } | |||
| 37 | + | if spaces != 1 { | |||
| 38 | + | t.Fatalf("want one uncovered space, got %d", spaces) | |||
| 39 | + | } | |||
| 40 | + | p, err := NewPreparer(256, 2) | |||
| 41 | + | if err != nil { | |||
| 42 | + | t.Fatal(err) | |||
| 43 | + | } | |||
| 44 | + | frame, err := p.Prepare([]layout.Command{cmd}, 1, 200, 100) | |||
| 45 | + | if err != nil || len(frame.Quads) != 2 { | |||
| 46 | + | t.Fatalf("space must emit no quad: %d quads, error %v", len(frame.Quads), err) | |||
| 47 | + | } | |||
| 48 | + | } | |||