mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-26 18:52:44 +01:00
text: Change getGlyphImages to getGlyphImage to avoid allocating slices
This commit is contained in:
parent
f77c514598
commit
927c477d2b
108
text/text.go
108
text/text.go
@ -88,7 +88,7 @@ var (
|
|||||||
emptyGlyphs = map[font.Face]map[rune]struct{}{}
|
emptyGlyphs = map[font.Face]map[rune]struct{}{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func getGlyphImages(face font.Face, runes []rune) []*ebiten.Image {
|
func getGlyphImage(face font.Face, r rune) *ebiten.Image {
|
||||||
if _, ok := emptyGlyphs[face]; !ok {
|
if _, ok := emptyGlyphs[face]; !ok {
|
||||||
emptyGlyphs[face] = map[rune]struct{}{}
|
emptyGlyphs[face] = map[rune]struct{}{}
|
||||||
}
|
}
|
||||||
@ -96,62 +96,49 @@ func getGlyphImages(face font.Face, runes []rune) []*ebiten.Image {
|
|||||||
glyphImageCache[face] = map[rune]*glyphImageCacheEntry{}
|
glyphImageCache[face] = map[rune]*glyphImageCacheEntry{}
|
||||||
}
|
}
|
||||||
|
|
||||||
imgs := make([]*ebiten.Image, len(runes))
|
if _, ok := emptyGlyphs[face][r]; ok {
|
||||||
glyphBounds := map[rune]fixed.Rectangle26_6{}
|
return nil
|
||||||
neededGlyphIndices := map[int]rune{}
|
|
||||||
for i, r := range runes {
|
|
||||||
if _, ok := emptyGlyphs[face][r]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if e, ok := glyphImageCache[face][r]; ok {
|
|
||||||
e.atime = now()
|
|
||||||
imgs[i] = e.image
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
b := getGlyphBounds(face, r)
|
|
||||||
w, h := (b.Max.X - b.Min.X).Ceil(), (b.Max.Y - b.Min.Y).Ceil()
|
|
||||||
if w == 0 || h == 0 {
|
|
||||||
emptyGlyphs[face][r] = struct{}{}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
glyphBounds[r] = b
|
|
||||||
neededGlyphIndices[i] = r
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, r := range neededGlyphIndices {
|
if e, ok := glyphImageCache[face][r]; ok {
|
||||||
b := glyphBounds[r]
|
e.atime = now()
|
||||||
w, h := (b.Max.X - b.Min.X).Ceil(), (b.Max.Y - b.Min.Y).Ceil()
|
return e.image
|
||||||
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
|
|
||||||
|
b := getGlyphBounds(face, r)
|
||||||
|
w, h := (b.Max.X - b.Min.X).Ceil(), (b.Max.Y - b.Min.Y).Ceil()
|
||||||
|
if w == 0 || h == 0 {
|
||||||
|
emptyGlyphs[face][r] = struct{}{}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return img
|
||||||
}
|
}
|
||||||
|
|
||||||
var textM sync.Mutex
|
var textM sync.Mutex
|
||||||
@ -190,11 +177,9 @@ func Draw(dst *ebiten.Image, text string, face font.Face, x, y int, clr color.Co
|
|||||||
|
|
||||||
faceHeight := face.Metrics().Height
|
faceHeight := face.Metrics().Height
|
||||||
|
|
||||||
runes := []rune(text)
|
|
||||||
glyphImgs := getGlyphImages(face, runes)
|
|
||||||
colorm := colormcache.ColorToColorM(clr)
|
colorm := colormcache.ColorToColorM(clr)
|
||||||
|
|
||||||
for i, r := range runes {
|
for _, r := range text {
|
||||||
if prevR >= 0 {
|
if prevR >= 0 {
|
||||||
fx += face.Kern(prevR, r)
|
fx += face.Kern(prevR, r)
|
||||||
}
|
}
|
||||||
@ -205,7 +190,8 @@ func Draw(dst *ebiten.Image, text string, face font.Face, x, y int, clr color.Co
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
drawGlyph(dst, face, r, glyphImgs[i], fx, fy, colorm)
|
img := getGlyphImage(face, r)
|
||||||
|
drawGlyph(dst, face, r, img, fx, fy, colorm)
|
||||||
fx += glyphAdvance(face, r)
|
fx += glyphAdvance(face, r)
|
||||||
|
|
||||||
prevR = r
|
prevR = r
|
||||||
@ -254,7 +240,7 @@ func BoundString(face font.Face, text string) image.Rectangle {
|
|||||||
prevR := rune(-1)
|
prevR := rune(-1)
|
||||||
|
|
||||||
var bounds fixed.Rectangle26_6
|
var bounds fixed.Rectangle26_6
|
||||||
for _, r := range []rune(text) {
|
for _, r := range text {
|
||||||
if prevR >= 0 {
|
if prevR >= 0 {
|
||||||
fx += face.Kern(prevR, r)
|
fx += face.Kern(prevR, r)
|
||||||
}
|
}
|
||||||
@ -297,5 +283,7 @@ func CacheGlyphs(face font.Face, text string) {
|
|||||||
textM.Lock()
|
textM.Lock()
|
||||||
defer textM.Unlock()
|
defer textM.Unlock()
|
||||||
|
|
||||||
getGlyphImages(face, []rune(text))
|
for _, r := range text {
|
||||||
|
getGlyphImage(face, r)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user