1package text
2
3import (
4 "bytes"
5 "image"
6 "image/color"
7 "image/draw"
8 "image/png"
9 "math"
10 "os"
11 "path/filepath"
12 "testing"
13)
14
15func goldenPNG(t *testing.T, scale float64) []byte {
16 t.Helper()
17 c := fixture(t)
18 l, err := NewEngine(c).Measure("office fi سلام कि 日本語 ★", Request{Families: []string{"Noto Sans"}, Size: 20}, 0)
19 if err != nil {
20 t.Fatal(err)
21 }
22 dst := image.NewRGBA(image.Rect(0, 0, int(math.Ceil(l.Width*scale))+12, int(math.Ceil(l.Height*scale))+12))
23 draw.Draw(dst, dst.Bounds(), image.NewUniform(color.White), image.Point{}, draw.Src)
24 for _, line := range l.Lines {
25 for _, run := range line.Runs {
26 for _, g := range run.Glyphs {
27 x, y := 6+g.X*scale, 6+g.Y*scale
28 k, err := GlyphKey(run.Face, g.ID, 20*scale, x, run.Face.Variations)
29 if err != nil {
30 t.Fatal(err)
31 }
32 mask, err := Rasterize(run.Face, k)
33 if err != nil {
34 t.Fatal(err)
35 }
36 if mask.Alpha.Rect.Empty() {
37 continue
38 }
39 // Phase is already encoded into the mask; the integer dot and glyph origin
40 // determine the destination rectangle, without rounding advance positions.
41 pt := image.Pt(int(math.Floor(x))+mask.Origin.X, int(math.Floor(y))+mask.Origin.Y)
42 draw.DrawMask(dst, mask.Alpha.Bounds().Add(pt), image.NewUniform(color.Black), image.Point{}, mask.Alpha, image.Point{}, draw.Over)
43 }
44 }
45 }
46 var buf bytes.Buffer
47 if err := png.Encode(&buf, dst); err != nil {
48 t.Fatal(err)
49 }
50 return buf.Bytes()
51}
52func TestGoldenPending(t *testing.T) {
53 for _, tc := range []struct {
54 name string
55 scale float64
56 }{{"1", 1}, {"1.25", 1.25}, {"1.5", 1.5}, {"2", 2}} {
57 t.Run(tc.name, func(t *testing.T) {
58 pending := filepath.Join("../../testdata/golden/pending", tc.name+".png")
59 got := goldenPNG(t, tc.scale)
60 want, err := os.ReadFile(pending)
61 if err != nil {
62 t.Fatal(err)
63 }
64 if !bytes.Equal(got, want) {
65 t.Errorf("pending CPU image drift: %s", pending)
66 }
67 approved := filepath.Join("../../testdata/golden/approved", tc.name+".png")
68 if ref, err := os.ReadFile(approved); err == nil && !bytes.Equal(got, ref) {
69 t.Errorf("approved reference mismatch: %s", approved)
70 }
71 })
72 }
73}