text/v2: define different key types for StdFace and GoTextFaceSource

This commit is contained in:
Hajime Hoshi 2023-11-19 23:40:47 +09:00
parent 57ae07eb36
commit 03a8aaee5c
4 changed files with 27 additions and 26 deletions

View File

@ -18,8 +18,6 @@ import (
"math"
"sync"
"golang.org/x/image/math/fixed"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/internal/hook"
)
@ -39,27 +37,17 @@ func init() {
})
}
type glyphImageCacheKey struct {
// id is rune for StdFace, and GID for GoTextFace.
id uint32
xoffset fixed.Int26_6
yoffset fixed.Int26_6
variations string
}
type glyphImageCacheEntry struct {
image *ebiten.Image
atime int64
}
type glyphImageCache struct {
cache map[glyphImageCacheKey]*glyphImageCacheEntry
type glyphImageCache[Key comparable] struct {
cache map[Key]*glyphImageCacheEntry
m sync.Mutex
}
func (g *glyphImageCache) getOrCreate(face Face, key glyphImageCacheKey, create func() *ebiten.Image) *ebiten.Image {
func (g *glyphImageCache[Key]) getOrCreate(face Face, key Key, create func() *ebiten.Image) *ebiten.Image {
g.m.Lock()
defer g.m.Unlock()
@ -70,7 +58,7 @@ func (g *glyphImageCache) getOrCreate(face Face, key glyphImageCacheKey, create
}
if g.cache == nil {
g.cache = map[glyphImageCacheKey]*glyphImageCacheEntry{}
g.cache = map[Key]*glyphImageCacheEntry{}
}
img := create()

View File

@ -329,8 +329,8 @@ func (g *GoTextFace) glyphImage(glyph glyph, origin fixed.Point26_6) (*ebiten.Im
X: (origin.X + b.Min.X) & ((1 << 6) - 1),
Y: (origin.Y + b.Min.Y) & ((1 << 6) - 1),
}
key := glyphImageCacheKey{
id: uint32(glyph.shapingGlyph.GlyphID),
key := goTextGlyphImageCacheKey{
gid: glyph.shapingGlyph.GlyphID,
xoffset: subpixelOffset.X,
yoffset: subpixelOffset.Y,
variations: g.ensureVariationsString(),

View File

@ -52,12 +52,19 @@ type goTextOutputCacheValue struct {
atime int64
}
type goTextGlyphImageCacheKey struct {
gid api.GID
xoffset fixed.Int26_6
yoffset fixed.Int26_6
variations string
}
// GoTextFaceSource is a source of a GoTextFace. This can be shared by multiple GoTextFace objects.
type GoTextFaceSource struct {
f font.Face
outputCache map[goTextOutputCacheKey]*goTextOutputCacheValue
glyphImageCache map[float64]*glyphImageCache
glyphImageCache map[float64]*glyphImageCache[goTextGlyphImageCacheKey]
addr *GoTextFaceSource
@ -224,12 +231,12 @@ func (g *GoTextFaceSource) scale(size float64) float64 {
return size / float64(g.f.Upem())
}
func (g *GoTextFaceSource) getOrCreateGlyphImage(goTextFace *GoTextFace, key glyphImageCacheKey, create func() *ebiten.Image) *ebiten.Image {
func (g *GoTextFaceSource) getOrCreateGlyphImage(goTextFace *GoTextFace, key goTextGlyphImageCacheKey, create func() *ebiten.Image) *ebiten.Image {
if g.glyphImageCache == nil {
g.glyphImageCache = map[float64]*glyphImageCache{}
g.glyphImageCache = map[float64]*glyphImageCache[goTextGlyphImageCacheKey]{}
}
if _, ok := g.glyphImageCache[goTextFace.Size]; !ok {
g.glyphImageCache[goTextFace.Size] = &glyphImageCache{}
g.glyphImageCache[goTextFace.Size] = &glyphImageCache[goTextGlyphImageCacheKey]{}
}
return g.glyphImageCache[goTextFace.Size].getOrCreate(goTextFace, key, create)
}

View File

@ -26,13 +26,20 @@ import (
var _ Face = (*StdFace)(nil)
type stdFaceGlyphImageCacheKey struct {
rune rune
xoffset fixed.Int26_6
// yoffset is always the same if the rune is the same, so this doesn't have to be a key.
}
// StdFace is a Face implementation for a semi-standard font.Face (golang.org/x/image/font).
// StdFace is useful to transit from existing codebase with text v1, or to use some bitmap fonts defined as font.Face.
// StdFace must not be copied by value.
type StdFace struct {
f *faceWithCache
glyphImageCache glyphImageCache
glyphImageCache glyphImageCache[stdFaceGlyphImageCacheKey]
addr *StdFace
}
@ -121,10 +128,9 @@ func (s *StdFace) glyphImage(r rune, origin fixed.Point26_6) (*ebiten.Image, int
X: (origin.X + b.Min.X) & ((1 << 6) - 1),
Y: (origin.Y + b.Min.Y) & ((1 << 6) - 1),
}
key := glyphImageCacheKey{
id: uint32(r),
key := stdFaceGlyphImageCacheKey{
rune: r,
xoffset: subpixelOffset.X,
// yoffset is always the same if the rune is the same, so this doesn't have to be a key.
}
img := s.glyphImageCache.getOrCreate(s, key, func() *ebiten.Image {
return s.glyphImageImpl(r, subpixelOffset, b)