/
svg_cache.go
114 lines (97 loc) · 2.05 KB
/
svg_cache.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package painter
import (
"image"
"os"
"sync"
"time"
"fyne.io/fyne"
"fyne.io/fyne/canvas"
)
type rasterInfo struct {
pix *image.NRGBA
w, h int
expires time.Time
}
var cacheDuration = time.Minute * 5
var rasters = make(map[string]*rasterInfo)
var aspects = make(map[interface{}]float32, 16)
var rasterMutex sync.RWMutex
var janitorOnce sync.Once
func init() {
if t, err := time.ParseDuration(os.Getenv("FYNE_CACHE")); err == nil {
cacheDuration = t
}
svgCacheJanitor()
}
// GetAspect looks up an aspect ratio of an image
func GetAspect(img *canvas.Image) float32 {
aspect := float32(0.0)
if img.Resource != nil {
aspect = aspects[img.Resource.Name()]
} else if img.File != "" {
aspect = aspects[img.File]
}
if aspect == 0 {
aspect = aspects[img]
}
return aspect
}
func svgCacheJanitor() {
delay := cacheDuration / 2
if delay < time.Second {
delay = time.Second
}
go janitorOnce.Do(func() {
for {
time.Sleep(delay)
now := time.Now()
rasterMutex.Lock()
for k, v := range rasters {
if v.expires.Before(now) {
delete(rasters, k)
}
}
rasterMutex.Unlock()
}
})
}
func svgCacheGet(name string, w int, h int) *image.NRGBA {
rasterMutex.RLock()
defer rasterMutex.RUnlock()
v, ok := rasters[name]
if !ok || v == nil || v.w != w || v.h != h {
return nil
}
v.expires = time.Now().Add(cacheDuration)
return v.pix
}
func svgCachePut(name string, pix *image.NRGBA, w int, h int) {
rasterMutex.Lock()
defer rasterMutex.Unlock()
defer func() {
recover()
}()
rasters[name] = &rasterInfo{
pix: pix,
w: w,
h: h,
expires: time.Now().Add(cacheDuration),
}
}
// SvgCacheReset clears the SVG cache.
func SvgCacheReset() {
rasterMutex.Lock()
rasters = make(map[string]*rasterInfo)
rasterMutex.Unlock()
}
// SvgCacheMonitorTheme hooks up the SVG cache to listen for theme changes and resets the cache
func SvgCacheMonitorTheme() {
listener := make(chan fyne.Settings)
fyne.CurrentApp().Settings().AddChangeListener(listener)
go func() {
for {
<-listener
SvgCacheReset()
}
}()
}