1package layout
2
3import (
4 "fmt"
5 "testing"
6
7 "github.com/bnema/nefergui/internal/css"
8 "github.com/bnema/nefergui/internal/text"
9)
10
11// paintFixture is a product-like tree: cards with background, border, shadows,
12// a clip and shaped text children.
13func paintFixture(tb testing.TB, cards int) (*Node, Options) {
14 tb.Helper()
15 catalog, err := text.Load(text.DirectorySource("../../testdata/fonts"))
16 if err != nil {
17 tb.Fatal(err)
18 }
19 engine := text.NewEngine(catalog)
20 card := css.Style{
21 Display: css.KeywordBlock, Height: px(60), Padding: css.LengthSides{Top: px(4), Left: px(4)},
22 BackgroundColor: css.Color{B: 1, A: 1}, BorderWidth: css.LengthSides{Top: px(1), Right: px(1), Bottom: px(1), Left: px(1)},
23 BorderStyle: css.KeywordSides{Top: css.KeywordSolid, Right: css.KeywordSolid, Bottom: css.KeywordSolid, Left: css.KeywordSolid},
24 OverflowX: css.KeywordHidden, OverflowY: css.KeywordHidden,
25 BoxShadow: []css.Shadow{{Y: px(2), Blur: px(4), Color: css.Color{A: .3}}, {Inset: true, Blur: px(2), Color: css.Color{A: .2}}},
26 }
27 label := css.Style{Display: css.KeywordBlock, FontSize: px(14), Color: css.Color{A: 1}}
28 children := make([]*Node, cards)
29 for i := range children {
30 t1 := node("t", Text, label)
31 t1.Content = fmt.Sprintf("Élément %d — une interface native écrite en Go", i)
32 children[i] = node("card", Box, card, t1)
33 }
34 return node("root", Column, css.Style{Display: css.KeywordBlock}, children...), Options{Width: 400, Height: 3000, TextEngine: engine}
35}
36
37// BenchmarkPaint measures only context.paint on an already placed tree.
38func BenchmarkPaint(b *testing.B) {
39 root, opts := paintFixture(b, 100)
40 ctx := newContext(opts)
41 tree, err := ctx.place(root, 0, 0, opts.Width, opts.Height, nil, nil, 0)
42 if err != nil {
43 b.Fatal(err)
44 }
45 b.ReportAllocs()
46 b.ResetTimer()
47 for i := 0; i < b.N; i++ {
48 if display := ctx.display(root, tree); len(display) == 0 {
49 b.Fatal("empty")
50 }
51 }
52}
53
54func BenchmarkLayoutPaintTree(b *testing.B) {
55 root, opts := paintFixture(b, 100)
56 opts.Arena = new(Arena) // as the runtime does: storage is reused per frame
57 if _, err := Layout(root, opts); err != nil {
58 b.Fatal(err)
59 }
60 b.ReportAllocs()
61 b.ResetTimer()
62 for i := 0; i < b.N; i++ {
63 if _, err := Layout(root, opts); err != nil {
64 b.Fatal(err)
65 }
66 }
67}