text: Refactoring

This commit is contained in:
Hajime Hoshi 2018-02-12 22:02:05 +09:00
parent cc423c276d
commit 31ae457a8c

View File

@ -40,28 +40,15 @@ func now() int64 {
return monotonicClock
}
var (
faces = map[font.Face]struct{}{}
)
func fontFaceToFace(f font.Face) font.Face {
if _, ok := faces[f]; ok {
return f
}
// If the (DeepEqual-ly) same font exists,
// reuse this to avoid to consume a lot of cache (#498).
for key := range faces {
if reflect.DeepEqual(key, f) {
return key
}
}
faces[f] = struct{}{}
return f
}
var (
type cacheEntry struct {
// Use pointers to avoid copying on browsers.
charBounds = map[font.Face]map[rune]*fixed.Rectangle26_6{}
bounds map[rune]*fixed.Rectangle26_6
atlases map[int]*atlas
}
var (
cache = map[font.Face]*cacheEntry{}
)
type char struct {
@ -71,15 +58,12 @@ type char struct {
}
func (c *char) bounds() *fixed.Rectangle26_6 {
if m, ok := charBounds[c.face]; ok {
if b, ok := m[c.rune]; ok {
e := cache[c.face]
if b, ok := e.bounds[c.rune]; ok {
return b
}
} else {
charBounds[c.face] = map[rune]*fixed.Rectangle26_6{}
}
b, _, _ := c.face.GlyphBounds(c.rune)
charBounds[c.face][c.rune] = &b
e.bounds[c.rune] = &b
return &b
}
@ -180,7 +164,7 @@ func (g *glyph) draw(dst *ebiten.Image, x, y fixed.Int26_6, clr color.Color) {
}
op.ColorM = e.m
a := atlases[g.char.face][g.char.atlasGroup()]
a := cache[g.char.face].atlases[g.char.atlasGroup()]
sx, sy := a.at(g)
r := image.Rect(sx, sy, sx+a.glyphSize, sy+a.glyphSize)
op.SourceRect = &r
@ -188,10 +172,6 @@ func (g *glyph) draw(dst *ebiten.Image, x, y fixed.Int26_6, clr color.Color) {
dst.DrawImage(a.image, op)
}
var (
atlases = map[font.Face]map[int]*atlas{}
)
type atlas struct {
// image is the back-end image to hold glyph cache.
image *ebiten.Image
@ -282,20 +262,14 @@ func getGlyphFromCache(face font.Face, r rune, now int64) *glyph {
face: face,
rune: r,
}
var at *atlas
if m, ok := atlases[face]; ok {
a, ok := m[ch.atlasGroup()]
at, ok := cache[face].atlases[ch.atlasGroup()]
if ok {
g, ok := a.runeToGlyph[r]
g, ok := at.runeToGlyph[r]
if ok {
g.atime = now
return g
}
}
at = a
} else {
atlases[face] = map[int]*atlas{}
}
if ch.empty() {
// The glyph doesn't have its size but might have valid 'advance' parameter
@ -324,12 +298,30 @@ func getGlyphFromCache(face font.Face, r rune, now int64) *glyph {
glyphSize: ch.atlasGroup(),
runeToGlyph: map[rune]*glyph{},
}
atlases[face][ch.atlasGroup()] = at
cache[face].atlases[ch.atlasGroup()] = at
}
return at.appendGlyph(ch, now)
}
func uniqFace(f font.Face) font.Face {
if _, ok := cache[f]; ok {
return f
}
// If the (DeepEqual-ly) same font exists,
// reuse this to avoid to consume a lot of cache (#498).
for key := range cache {
if reflect.DeepEqual(key, f) {
return key
}
}
cache[f] = &cacheEntry{
bounds: map[rune]*fixed.Rectangle26_6{},
atlases: map[int]*atlas{},
}
return f
}
var textM sync.Mutex
// Draw draws a given text on a given destination image dst.
@ -355,7 +347,7 @@ func Draw(dst *ebiten.Image, text string, face font.Face, x, y int, clr color.Co
if prevC >= 0 {
fx += face.Kern(prevC, c)
}
fa := fontFaceToFace(face)
fa := uniqFace(face)
if g := getGlyphFromCache(fa, c, n); g != nil {
if !g.char.empty() {
g.draw(dst, fx, fixed.I(y), clr)