mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
text: Refactoring
This commit is contained in:
parent
cc423c276d
commit
31ae457a8c
78
text/text.go
78
text/text.go
@ -40,28 +40,15 @@ func now() int64 {
|
|||||||
return monotonicClock
|
return monotonicClock
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
type cacheEntry struct {
|
||||||
faces = map[font.Face]struct{}{}
|
// Use pointers to avoid copying on browsers.
|
||||||
)
|
bounds map[rune]*fixed.Rectangle26_6
|
||||||
|
|
||||||
func fontFaceToFace(f font.Face) font.Face {
|
atlases map[int]*atlas
|
||||||
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 (
|
var (
|
||||||
// Use pointers to avoid copying on browsers.
|
cache = map[font.Face]*cacheEntry{}
|
||||||
charBounds = map[font.Face]map[rune]*fixed.Rectangle26_6{}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type char struct {
|
type char struct {
|
||||||
@ -71,15 +58,12 @@ type char struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *char) bounds() *fixed.Rectangle26_6 {
|
func (c *char) bounds() *fixed.Rectangle26_6 {
|
||||||
if m, ok := charBounds[c.face]; ok {
|
e := cache[c.face]
|
||||||
if b, ok := m[c.rune]; ok {
|
if b, ok := e.bounds[c.rune]; ok {
|
||||||
return b
|
return b
|
||||||
}
|
|
||||||
} else {
|
|
||||||
charBounds[c.face] = map[rune]*fixed.Rectangle26_6{}
|
|
||||||
}
|
}
|
||||||
b, _, _ := c.face.GlyphBounds(c.rune)
|
b, _, _ := c.face.GlyphBounds(c.rune)
|
||||||
charBounds[c.face][c.rune] = &b
|
e.bounds[c.rune] = &b
|
||||||
return &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
|
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)
|
sx, sy := a.at(g)
|
||||||
r := image.Rect(sx, sy, sx+a.glyphSize, sy+a.glyphSize)
|
r := image.Rect(sx, sy, sx+a.glyphSize, sy+a.glyphSize)
|
||||||
op.SourceRect = &r
|
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)
|
dst.DrawImage(a.image, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
atlases = map[font.Face]map[int]*atlas{}
|
|
||||||
)
|
|
||||||
|
|
||||||
type atlas struct {
|
type atlas struct {
|
||||||
// image is the back-end image to hold glyph cache.
|
// image is the back-end image to hold glyph cache.
|
||||||
image *ebiten.Image
|
image *ebiten.Image
|
||||||
@ -282,19 +262,13 @@ func getGlyphFromCache(face font.Face, r rune, now int64) *glyph {
|
|||||||
face: face,
|
face: face,
|
||||||
rune: r,
|
rune: r,
|
||||||
}
|
}
|
||||||
var at *atlas
|
at, ok := cache[face].atlases[ch.atlasGroup()]
|
||||||
if m, ok := atlases[face]; ok {
|
if ok {
|
||||||
a, ok := m[ch.atlasGroup()]
|
g, ok := at.runeToGlyph[r]
|
||||||
if ok {
|
if ok {
|
||||||
g, ok := a.runeToGlyph[r]
|
g.atime = now
|
||||||
if ok {
|
return g
|
||||||
g.atime = now
|
|
||||||
return g
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
at = a
|
|
||||||
} else {
|
|
||||||
atlases[face] = map[int]*atlas{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ch.empty() {
|
if ch.empty() {
|
||||||
@ -324,12 +298,30 @@ func getGlyphFromCache(face font.Face, r rune, now int64) *glyph {
|
|||||||
glyphSize: ch.atlasGroup(),
|
glyphSize: ch.atlasGroup(),
|
||||||
runeToGlyph: map[rune]*glyph{},
|
runeToGlyph: map[rune]*glyph{},
|
||||||
}
|
}
|
||||||
atlases[face][ch.atlasGroup()] = at
|
cache[face].atlases[ch.atlasGroup()] = at
|
||||||
}
|
}
|
||||||
|
|
||||||
return at.appendGlyph(ch, now)
|
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
|
var textM sync.Mutex
|
||||||
|
|
||||||
// Draw draws a given text on a given destination image dst.
|
// 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 {
|
if prevC >= 0 {
|
||||||
fx += face.Kern(prevC, c)
|
fx += face.Kern(prevC, c)
|
||||||
}
|
}
|
||||||
fa := fontFaceToFace(face)
|
fa := uniqFace(face)
|
||||||
if g := getGlyphFromCache(fa, c, n); g != nil {
|
if g := getGlyphFromCache(fa, c, n); g != nil {
|
||||||
if !g.char.empty() {
|
if !g.char.empty() {
|
||||||
g.draw(dst, fx, fixed.I(y), clr)
|
g.draw(dst, fx, fixed.I(y), clr)
|
||||||
|
Loading…
Reference in New Issue
Block a user