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:
parent
3522bcc2e0
commit
8de8fcfbf7
187
app/debug/fps.go
187
app/debug/fps.go
@ -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 ",
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user