mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
text: eliminate path cache memory leak
This commit alters the method we use to check for valid cache hits in the text path cache. Previously we stored the entire text.Layout that was provided when the cache entry was set so that we could ensure only identical text.Layouts would produce hits (guarding against hash collisions). This commit instead pulls the glyph IDs for every glyph in the text.Layout and stores them in the cache. This uses far less memory and seems to allow cache entries to be GCed after eviction. Fixes: https://todo.sr.ht/~eliasnaur/gio/418 Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
+20
-3
@@ -5,6 +5,7 @@ package text
|
||||
import (
|
||||
"gioui.org/io/system"
|
||||
"gioui.org/op/clip"
|
||||
"github.com/benoitkugler/textlayout/fonts"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
||||
@@ -28,7 +29,7 @@ type path struct {
|
||||
next, prev *path
|
||||
key pathKey
|
||||
val clip.PathSpec
|
||||
layout Layout
|
||||
gids []fonts.GID
|
||||
}
|
||||
|
||||
type layoutKey struct {
|
||||
@@ -84,8 +85,20 @@ func (l *layoutCache) insert(lt *layoutElem) {
|
||||
lt.next.prev = lt
|
||||
}
|
||||
|
||||
func gidsMatch(gids []fonts.GID, l Layout) bool {
|
||||
if len(gids) != len(l.Glyphs) {
|
||||
return false
|
||||
}
|
||||
for i := range gids {
|
||||
if gids[i] != l.Glyphs[i].ID {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *pathCache) Get(k pathKey, l Layout) (clip.PathSpec, bool) {
|
||||
if v, ok := c.m[k]; ok && l.equals(v.layout) {
|
||||
if v, ok := c.m[k]; ok && gidsMatch(v.gids, l) {
|
||||
c.remove(v)
|
||||
c.insert(v)
|
||||
return v.val, true
|
||||
@@ -101,7 +114,11 @@ func (c *pathCache) Put(k pathKey, l Layout, v clip.PathSpec) {
|
||||
c.head.prev = c.tail
|
||||
c.tail.next = c.head
|
||||
}
|
||||
val := &path{key: k, val: v, layout: l}
|
||||
gids := make([]fonts.GID, len(l.Glyphs))
|
||||
for i := range l.Glyphs {
|
||||
gids[i] = l.Glyphs[i].ID
|
||||
}
|
||||
val := &path{key: k, val: v, gids: gids}
|
||||
c.m[k] = val
|
||||
c.insert(val)
|
||||
if len(c.m) > maxSize {
|
||||
|
||||
Reference in New Issue
Block a user