1package hdrcursor
2
3import (
4 "bytes"
5 "math"
6 "testing"
7)
8
9// vector is a 5×3 premultiplied BGRA image: alpha ramps up with one fully
10// transparent pixel (index 3).
11func vector() (pixels []byte, w, h int) {
12 w, h = 5, 3
13 pixels = make([]byte, w*h*4)
14 for i := range w * h {
15 a := byte(i * 255 / (w*h - 1))
16 if i == 3 {
17 a = 0
18 }
19 c := func(v int) byte { return byte(v * int(a) / 255) }
20 pixels[i*4], pixels[i*4+1], pixels[i*4+2], pixels[i*4+3] = c(i*37%256), c((i*91+20)%256), c((i*53+200)%256), a
21 }
22 return
23}
24
25// The conversion is byte-identical to the one the Vulkan renderer did
26// before it moved here (203 nits, cropped to 4×4).
27func TestConvertMatchesRecordedVector(t *testing.T) {
28 pixels, w, h := vector()
29 want := []byte{0x0, 0x0, 0x0, 0x0, 0x5, 0x7, 0x9, 0x12, 0xd, 0x13, 0xf, 0x24, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x31, 0x31, 0x5b, 0x3a, 0x1f, 0x20, 0x6d, 0x20, 0x39, 0x30, 0x7f, 0x33, 0x51, 0x46, 0x91, 0x4c, 0x58, 0x5f, 0xb6, 0x5f, 0x72, 0x5e, 0xc8, 0x6d, 0x4e, 0x4c, 0xda, 0x81, 0x75, 0x6c, 0xec}
30 var c Cache
31 if got := c.Convert(pixels, w, h, 4, 203); !bytes.Equal(got, want) {
32 t.Fatalf("converted\n got %#v\nwant %#v", got, want)
33 }
34}
35
36func TestPixelWhite(t *testing.T) {
37 p := []byte{255, 255, 255, 255}
38 Pixel(p, 203)
39 if p[3] != 255 || math.Abs(float64(p[0])-148) > 1 || p[0] != p[1] || p[1] != p[2] {
40 t.Fatalf("cursor white: %v", p)
41 }
42 if PQEncode(0) != 0 || math.Abs(PQEncode(10000)-1) > 1e-9 {
43 t.Fatal("PQ endpoints")
44 }
45}
46
47func TestCacheKeepsLastConversion(t *testing.T) {
48 var c Cache
49 px := []byte{255, 255, 255, 255}
50 a := c.Convert(px, 1, 1, 64, 203)
51 if c.Len() != 4 || a[0] != 148 {
52 t.Fatalf("len %d pixel %v", c.Len(), a)
53 }
54 first := c.Key()
55 if b := c.Convert(px, 1, 1, 64, 203); &a[0] != &b[0] {
56 t.Fatal("same image converted again")
57 }
58 for i := range 12 {
59 v := byte(i * 18)
60 c.Convert([]byte{v, v, v, 255}, 1, 1, 64, 203)
61 if c.Len() != 4 {
62 t.Fatalf("cache grew after image %d: %d", i, c.Len())
63 }
64 }
65 if c.Key() == first {
66 t.Fatal("conversion not replaced")
67 }
68 c.Convert(px, 1, 1, 64, 100)
69 if c.Key() == first {
70 t.Fatal("nits not part of the key")
71 }
72 c.Reset()
73 if c.Len() != 0 || c.Key() != [32]byte{} {
74 t.Fatal("reset left a conversion")
75 }
76}