2
0
mirror of synced 2025-02-22 06:28:04 +00:00

app/debug, exp/font: remove the freetype dependency.

Change-Id: Id71acfeb605995d8caf947d996a1375335410e08
Reviewed-on: https://go-review.googlesource.com/11668
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
Nigel Tao 2015-06-30 16:59:14 +10:00
parent 3522bcc2e0
commit 8de8fcfbf7
2 changed files with 179 additions and 46 deletions

View File

@ -6,72 +6,61 @@
package debug // import "golang.org/x/mobile/app/debug"
import (
"fmt"
"image"
"image/color"
"image/draw"
"log"
"math"
"sync"
"time"
"code.google.com/p/freetype-go/freetype"
"golang.org/x/mobile/event"
"golang.org/x/mobile/exp/font"
"golang.org/x/mobile/geom"
"golang.org/x/mobile/gl/glutil"
)
var lastDraw = time.Now()
var monofont = freetype.NewContext()
var fps struct {
mu sync.Mutex
c event.Config
m *glutil.Image
}
// TODO(crawshaw): It looks like we need a gl.RegisterInit feature.
// TODO(crawshaw): The gldebug mode needs to complain loudly when GL functions
// are called before init, because often they fail silently.
// TODO(nigeltao): no need to re-load the font on every config change (e.g.
// phone rotation between portrait and landscape).
func fpsInit() {
b := font.Monospace()
f, err := freetype.ParseFont(b)
if err != nil {
panic(err)
}
monofont.SetFont(f)
monofont.SetSrc(image.Black)
monofont.SetHinting(freetype.FullHinting)
toPx := func(x geom.Pt) int { return int(math.Ceil(float64(geom.Pt(x).Px(fps.c.PixelsPerPt)))) }
fps.m = glutil.NewImage(toPx(50), toPx(12))
monofont.SetDst(fps.m.RGBA)
monofont.SetClip(fps.m.Bounds())
monofont.SetDPI(72 * float64(fps.c.PixelsPerPt))
monofont.SetFontSize(12)
}
// DrawFPS draws the per second framerate in the bottom-left of the screen.
func DrawFPS(c event.Config) {
fps.mu.Lock()
if fps.c != c || fps.m == nil {
fps.c = c
fpsInit()
fps.m = glutil.NewImage(7*(fontWidth+1)+1, fontHeight+2)
}
fps.mu.Unlock()
display := [7]byte{
4: 'F',
5: 'P',
6: 'S',
}
now := time.Now()
diff := now.Sub(lastDraw)
str := fmt.Sprintf("%.0f FPS", float32(time.Second)/float32(diff))
draw.Draw(fps.m.RGBA, fps.m.Rect, image.White, image.Point{}, draw.Src)
ftpt12 := freetype.Pt(0, int(12*c.PixelsPerPt))
if _, err := monofont.DrawString(str, ftpt12); err != nil {
log.Printf("DrawFPS: %v", err)
return
f := 0
if dur := now.Sub(lastDraw); dur > 0 {
f = int(time.Second / dur)
}
display[2] = '0' + byte((f/1e0)%10)
display[1] = '0' + byte((f/1e1)%10)
display[0] = '0' + byte((f/1e2)%10)
draw.Draw(fps.m.RGBA, fps.m.RGBA.Bounds(), image.White, image.Point{}, draw.Src)
for i, c := range display {
glyph := glyphs[c]
if len(glyph) != fontWidth*fontHeight {
continue
}
for y := 0; y < fontHeight; y++ {
for x := 0; x < fontWidth; x++ {
if glyph[fontWidth*y+x] == ' ' {
continue
}
fps.m.RGBA.SetRGBA((fontWidth+1)*i+x+1, y+1, color.RGBA{A: 0xff})
}
}
}
fps.m.Upload()
@ -85,3 +74,123 @@ func DrawFPS(c event.Config) {
lastDraw = now
}
const (
fontWidth = 5
fontHeight = 7
)
// glyphs comes from the 6x10 fixed font from the plan9port:
// https://github.com/9fans/plan9port/tree/master/font/fixed
//
// 6x10 becomes 5x7 because each glyph has a 1-pixel margin plus space for
// descenders.
//
// Its README file says that those fonts were converted from XFree86, and are
// in the public domain.
var glyphs = [256]string{
'0': "" +
" X " +
" X X " +
"X X" +
"X X" +
"X X" +
" X X " +
" X ",
'1': "" +
" X " +
" XX " +
"X X " +
" X " +
" X " +
" X " +
"XXXXX",
'2': "" +
" XXX " +
"X X" +
" X" +
" XX " +
" X " +
"X " +
"XXXXX",
'3': "" +
"XXXXX" +
" X" +
" X " +
" XX " +
" X" +
"X X" +
" XXX ",
'4': "" +
" X " +
" XX " +
" X X " +
"X X " +
"XXXXX" +
" X " +
" X ",
'5': "" +
"XXXXX" +
"X " +
"X XX " +
"XX X" +
" X" +
"X X" +
" XXX ",
'6': "" +
" XX " +
" X " +
"X " +
"X XX " +
"XX X" +
"X X" +
" XXX ",
'7': "" +
"XXXXX" +
" X" +
" X " +
" X " +
" X " +
" X " +
" X ",
'8': "" +
" XXX " +
"X X" +
"X X" +
" XXX " +
"X X" +
"X X" +
" XXX ",
'9': "" +
" XXX " +
"X X" +
"X XX" +
" XX X" +
" X" +
" X " +
" XX ",
'F': "" +
"XXXXX" +
"X " +
"X " +
"XXXX " +
"X " +
"X " +
"X ",
'P': "" +
"XXXX " +
"X X" +
"X X" +
"XXXX " +
"X " +
"X " +
"X ",
'S': "" +
" XXX " +
"X X" +
"X " +
" XXX " +
" X" +
"X X" +
" XXX ",
}

View File

@ -7,16 +7,40 @@
package font
import (
"bytes"
"fmt"
"testing"
"code.google.com/p/freetype-go/freetype"
)
func TestLoadFonts(t *testing.T) {
if _, err := freetype.ParseFont(Default()); err != nil {
t.Fatalf("default font: %v", err)
func looksLikeATTF(b []byte) error {
if len(b) < 256 {
return fmt.Errorf("not a TTF: not enough data")
}
if _, err := freetype.ParseFont(Monospace()); err != nil {
t.Fatalf("monospace font: %v", err)
b = b[:256]
// Look for the 4-byte magic header. See
// http://www.microsoft.com/typography/otspec/otff.htm
switch string(b[:4]) {
case "\x00\x01\x00\x00", "ttcf":
// No-op.
default:
return fmt.Errorf("not a TTF: missing magic header")
}
// Look for a glyf table.
if i := bytes.Index(b, []byte("glyf")); i < 0 {
return fmt.Errorf(`not a TTF: missing "glyf" table`)
} else if i%0x10 != 0x0c {
return fmt.Errorf(`not a TTF: invalid "glyf" offset 0x%02x`, i)
}
return nil
}
func TestLoadFonts(t *testing.T) {
if err := looksLikeATTF(Default()); err != nil {
t.Errorf("default font: %v", err)
}
if err := looksLikeATTF(Monospace()); err != nil {
t.Errorf("monospace font: %v", err)
}
}