mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
text: Cleaning up the cache after the rendering finishes
Before this fix, cleaning up the cache happens during making glyph images, and this can be problematic when the text includes more glyphs than the cache limit. After this fix, Draw allows to have more glyph cache than the limit temporarily.
This commit is contained in:
parent
9d4b0f3bad
commit
5ec05ed79d
92
text/text.go
92
text/text.go
@ -43,10 +43,6 @@ func fixed26_6ToFloat64(x fixed.Int26_6) float64 {
|
||||
return float64(x>>6) + float64(x&((1<<6)-1))/float64(1<<6)
|
||||
}
|
||||
|
||||
const (
|
||||
cacheLimit = 512 // This is an arbitrary number.
|
||||
)
|
||||
|
||||
func drawGlyph(dst *ebiten.Image, face font.Face, r rune, img *ebiten.Image, x, y fixed.Int26_6, clr ebiten.ColorM) {
|
||||
if img == nil {
|
||||
return
|
||||
@ -85,7 +81,7 @@ var (
|
||||
emptyGlyphs = map[font.Face]map[rune]struct{}{}
|
||||
)
|
||||
|
||||
func getGlyphImages(face font.Face, runes []rune) []*ebiten.Image {
|
||||
func getGlyphImages(face font.Face, runes []rune, cacheLimit int) []*ebiten.Image {
|
||||
if _, ok := emptyGlyphs[face]; !ok {
|
||||
emptyGlyphs[face] = map[rune]struct{}{}
|
||||
}
|
||||
@ -114,54 +110,39 @@ func getGlyphImages(face font.Face, runes []rune) []*ebiten.Image {
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO: What if len(runes) > cacheLimit?
|
||||
if len(glyphImageCache[face]) > cacheLimit {
|
||||
oldest := int64(math.MaxInt64)
|
||||
oldestKey := rune(-1)
|
||||
for r, e := range glyphImageCache[face] {
|
||||
if e.atime < oldest {
|
||||
oldestKey = r
|
||||
oldest = e.atime
|
||||
}
|
||||
}
|
||||
delete(glyphImageCache[face], oldestKey)
|
||||
}
|
||||
|
||||
glyphBounds[r] = b
|
||||
neededGlyphIndices[i] = r
|
||||
}
|
||||
|
||||
if len(neededGlyphIndices) > 0 {
|
||||
for i, r := range neededGlyphIndices {
|
||||
b := glyphBounds[r]
|
||||
w, h := (b.Max.X - b.Min.X).Ceil(), (b.Max.Y - b.Min.Y).Ceil()
|
||||
if b.Min.X&((1<<6)-1) != 0 {
|
||||
w++
|
||||
}
|
||||
if b.Min.Y&((1<<6)-1) != 0 {
|
||||
h++
|
||||
}
|
||||
rgba := image.NewRGBA(image.Rect(0, 0, w, h))
|
||||
|
||||
d := font.Drawer{
|
||||
Dst: rgba,
|
||||
Src: image.White,
|
||||
Face: face,
|
||||
}
|
||||
x, y := -b.Min.X, -b.Min.Y
|
||||
x, y = fixed.I(x.Ceil()), fixed.I(y.Ceil())
|
||||
d.Dot = fixed.Point26_6{X: x, Y: y}
|
||||
d.DrawString(string(r))
|
||||
|
||||
img := ebiten.NewImageFromImage(rgba)
|
||||
if _, ok := glyphImageCache[face][r]; !ok {
|
||||
glyphImageCache[face][r] = &glyphImageCacheEntry{
|
||||
image: img,
|
||||
atime: now(),
|
||||
}
|
||||
}
|
||||
imgs[i] = img
|
||||
for i, r := range neededGlyphIndices {
|
||||
b := glyphBounds[r]
|
||||
w, h := (b.Max.X - b.Min.X).Ceil(), (b.Max.Y - b.Min.Y).Ceil()
|
||||
if b.Min.X&((1<<6)-1) != 0 {
|
||||
w++
|
||||
}
|
||||
if b.Min.Y&((1<<6)-1) != 0 {
|
||||
h++
|
||||
}
|
||||
rgba := image.NewRGBA(image.Rect(0, 0, w, h))
|
||||
|
||||
d := font.Drawer{
|
||||
Dst: rgba,
|
||||
Src: image.White,
|
||||
Face: face,
|
||||
}
|
||||
x, y := -b.Min.X, -b.Min.Y
|
||||
x, y = fixed.I(x.Ceil()), fixed.I(y.Ceil())
|
||||
d.Dot = fixed.Point26_6{X: x, Y: y}
|
||||
d.DrawString(string(r))
|
||||
|
||||
img := ebiten.NewImageFromImage(rgba)
|
||||
if _, ok := glyphImageCache[face][r]; !ok {
|
||||
glyphImageCache[face][r] = &glyphImageCacheEntry{
|
||||
image: img,
|
||||
atime: now(),
|
||||
}
|
||||
}
|
||||
imgs[i] = img
|
||||
}
|
||||
return imgs
|
||||
}
|
||||
@ -202,8 +183,9 @@ func Draw(dst *ebiten.Image, text string, face font.Face, x, y int, clr color.Co
|
||||
|
||||
faceHeight := face.Metrics().Height
|
||||
|
||||
const cacheLimit = 512 // This is an arbitrary number.
|
||||
runes := []rune(text)
|
||||
glyphImgs := getGlyphImages(face, runes)
|
||||
glyphImgs := getGlyphImages(face, runes, cacheLimit)
|
||||
colorm := colormcache.ColorToColorM(clr)
|
||||
|
||||
for i, r := range runes {
|
||||
@ -222,6 +204,18 @@ func Draw(dst *ebiten.Image, text string, face font.Face, x, y int, clr color.Co
|
||||
|
||||
prevR = r
|
||||
}
|
||||
|
||||
for len(glyphImageCache[face]) > cacheLimit {
|
||||
oldest := int64(math.MaxInt64)
|
||||
oldestKey := rune(-1)
|
||||
for r, e := range glyphImageCache[face] {
|
||||
if e.atime < oldest {
|
||||
oldestKey = r
|
||||
oldest = e.atime
|
||||
}
|
||||
}
|
||||
delete(glyphImageCache[face], oldestKey)
|
||||
}
|
||||
}
|
||||
|
||||
// BoundString returns the measured size of a given string using a given font.
|
||||
|
Loading…
Reference in New Issue
Block a user