Skip to content

Commit 00ab59d

Browse files
committed
internal/task: switch to opentype for TTF font rendering
When working on CL 358897, I forgot that there's already an SFNT font parser and glyph rasterizer available in the x/image module. Using it produces an equivalent final image, and allows x/build to depend on 1 less module. Also add a regression test for drawTerminal. Updates golang/go#47403. Change-Id: I77166a2180a7db9c81a30f77b12bb20dcd21bd8b Reviewed-on: https://go-review.googlesource.com/c/build/+/388834 Trust: Dmitri Shuralyov <[email protected]> Run-TryBot: Dmitri Shuralyov <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]>
1 parent 1c23949 commit 00ab59d

File tree

5 files changed

+85
-6
lines changed

5 files changed

+85
-6
lines changed

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ require (
1919
github.com/esimov/stackblur-go v1.0.1
2020
github.com/gliderlabs/ssh v0.3.3
2121
github.com/golang-migrate/migrate/v4 v4.15.0-beta.3
22-
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
2322
github.com/golang/protobuf v1.5.2
2423
github.com/google/go-cmp v0.5.6
2524
github.com/google/go-github v17.0.0+incompatible

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,6 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
272272
github.com/golang-migrate/migrate/v4 v4.15.0-beta.3 h1:tqLMcxs6gB6+b2Jhwao4s2sNMSKku+0rjtBtKucKWkg=
273273
github.com/golang-migrate/migrate/v4 v4.15.0-beta.3/go.mod h1:g9qbiDvB47WyrRnNu2t2gMZFNHKnatsYRxsGZbCi4EM=
274274
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
275-
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
276-
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
277275
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
278276
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
279277
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=

internal/task/testdata/terminal.png

107 KB
Loading

internal/task/tweet.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ import (
2525

2626
"github.com/dghubble/oauth1"
2727
"github.com/esimov/stackblur-go"
28-
"github.com/golang/freetype/truetype"
2928
"golang.org/x/build/internal/secret"
3029
"golang.org/x/build/internal/workflow"
3130
"golang.org/x/image/font"
3231
"golang.org/x/image/font/gofont/gomono"
32+
"golang.org/x/image/font/opentype"
3333
"golang.org/x/image/math/fixed"
3434
)
3535

@@ -496,7 +496,7 @@ func (f golangorgDLFile) GOARCH() string {
496496
// with the given text displayed.
497497
func drawTerminal(text string) (image.Image, error) {
498498
// Load font from TTF data.
499-
f, err := truetype.Parse(gomono.TTF)
499+
f, err := opentype.Parse(gomono.TTF)
500500
if err != nil {
501501
return nil, err
502502
}
@@ -521,7 +521,11 @@ func drawTerminal(text string) (image.Image, error) {
521521
roundedRect(image.Rect(50, 80, width-50, height-80), 10), image.Point{}, draw.Over)
522522

523523
// Text.
524-
d := font.Drawer{Dst: m, Src: image.White, Face: truetype.NewFace(f, &truetype.Options{Size: 24})}
524+
face, err := opentype.NewFace(f, &opentype.FaceOptions{Size: 24, DPI: 72})
525+
if err != nil {
526+
return nil, err
527+
}
528+
d := font.Drawer{Dst: m, Src: image.White, Face: face}
525529
const lineHeight = 32
526530
for n, line := range strings.Split(text, "\n") {
527531
d.Dot = fixed.P(80, 135+n*lineHeight)

internal/task/tweet_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@ package task
77
import (
88
"bytes"
99
"context"
10+
"flag"
1011
"fmt"
12+
"image"
13+
"image/png"
1114
"io"
1215
"net/http"
1316
"net/http/httptest"
17+
"os"
18+
"path/filepath"
1419
"testing"
1520

1621
"golang.org/x/build/internal/workflow"
@@ -175,6 +180,79 @@ func (f fmtWriter) Printf(format string, v ...interface{}) {
175180
fmt.Fprintf(f.w, format, v...)
176181
}
177182

183+
var updateFlag = flag.Bool("update", false, "Update golden files.")
184+
185+
func TestDrawTerminal(t *testing.T) {
186+
got, err := drawTerminal(`$ go install golang.org/dl/go1.18beta1@latest
187+
$ go1.18beta1 download
188+
Downloaded 0.0% ( 0 / 111109966 bytes) ...
189+
Downloaded 50.0% ( 55554983 / 111109966 bytes) ...
190+
Downloaded 100.0% (111109966 / 111109966 bytes)
191+
Unpacking go1.18beta1.linux-s390x.tar.gz ...
192+
Success. You may now run 'go1.18beta1'
193+
$ go1.18beta1 version
194+
go version go1.18beta1 linux/s390x`)
195+
if err != nil {
196+
t.Fatalf("drawTerminal: got error=%v, want nil", err)
197+
}
198+
if *updateFlag {
199+
encodePNG(t, filepath.Join("testdata", "terminal.png"), got)
200+
return
201+
}
202+
want := decodePNG(t, filepath.Join("testdata", "terminal.png"))
203+
if !got.Bounds().Eq(want.Bounds()) {
204+
t.Fatalf("drawTerminal: got image bounds=%v, want %v", got.Bounds(), want.Bounds())
205+
}
206+
diff := func(a, b uint32) uint64 {
207+
if a < b {
208+
return uint64(b - a)
209+
}
210+
return uint64(a - b)
211+
}
212+
var total uint64
213+
for y := 0; y < want.Bounds().Dy(); y++ {
214+
for x := 0; x < want.Bounds().Dx(); x++ {
215+
r0, g0, b0, a0 := got.At(x, y).RGBA()
216+
r1, g1, b1, a1 := want.At(x, y).RGBA()
217+
const D = 0xffff * 20 / 100 // Diff threshold of 20% for RGB color components.
218+
if diff(r0, r1) > D || diff(g0, g1) > D || diff(b0, b1) > D || a0 != a1 {
219+
t.Errorf("at (%d, %d):\n got RGBA %v\nwant RGBA %v", x, y, got.At(x, y), want.At(x, y))
220+
}
221+
total += diff(r0, r1) + diff(g0, g1) + diff(b0, b1)
222+
}
223+
}
224+
if testing.Verbose() {
225+
t.Logf("average pixel color diff: %v%%", 100*float64(total)/float64(0xffff*want.Bounds().Dx()*want.Bounds().Dy()))
226+
}
227+
}
228+
229+
func encodePNG(t *testing.T, name string, m image.Image) {
230+
t.Helper()
231+
var buf bytes.Buffer
232+
err := (&png.Encoder{CompressionLevel: png.BestCompression}).Encode(&buf, m)
233+
if err != nil {
234+
t.Fatal(err)
235+
}
236+
err = os.WriteFile(name, buf.Bytes(), 0644)
237+
if err != nil {
238+
t.Fatal(err)
239+
}
240+
}
241+
242+
func decodePNG(t *testing.T, name string) image.Image {
243+
t.Helper()
244+
f, err := os.Open(name)
245+
if err != nil {
246+
t.Fatal(err)
247+
}
248+
defer f.Close()
249+
m, err := png.Decode(f)
250+
if err != nil {
251+
t.Fatal(err)
252+
}
253+
return m
254+
}
255+
178256
func TestPostTweet(t *testing.T) {
179257
mux := http.NewServeMux()
180258
mux.HandleFunc("upload.twitter.com/1.1/media/upload.json", func(w http.ResponseWriter, req *http.Request) {

0 commit comments

Comments
 (0)