cache.go (1994B)
1 // Copyright 2020 The Ebiten Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package colormcache 16 17 import ( 18 "image/color" 19 "math" 20 21 "github.com/hajimehoshi/ebiten/v2" 22 ) 23 24 var ( 25 monotonicClock int64 26 ) 27 28 func now() int64 { 29 monotonicClock++ 30 return monotonicClock 31 } 32 33 const ( 34 cacheLimit = 512 // This is an arbitrary number. 35 ) 36 37 type colorMCacheKey uint32 38 39 type colorMCacheEntry struct { 40 m ebiten.ColorM 41 atime int64 42 } 43 44 var ( 45 colorMCache = map[colorMCacheKey]*colorMCacheEntry{} 46 emptyColorM ebiten.ColorM 47 ) 48 49 func init() { 50 emptyColorM.Scale(0, 0, 0, 0) 51 } 52 53 func ColorToColorM(clr color.Color) ebiten.ColorM { 54 // RGBA() is in [0 - 0xffff]. Adjust them in [0 - 0xff]. 55 cr, cg, cb, ca := clr.RGBA() 56 cr /= 0x101 57 cg /= 0x101 58 cb /= 0x101 59 ca /= 0x101 60 if ca == 0 { 61 return emptyColorM 62 } 63 64 key := colorMCacheKey(uint32(cr) | (uint32(cg) << 8) | (uint32(cb) << 16) | (uint32(ca) << 24)) 65 e, ok := colorMCache[key] 66 if ok { 67 e.atime = now() 68 return e.m 69 } 70 71 if len(colorMCache) > cacheLimit { 72 oldest := int64(math.MaxInt64) 73 oldestKey := colorMCacheKey(0) 74 for key, c := range colorMCache { 75 if c.atime < oldest { 76 oldestKey = key 77 oldest = c.atime 78 } 79 } 80 delete(colorMCache, oldestKey) 81 } 82 83 cm := ebiten.ColorM{} 84 rf := float64(cr) / float64(ca) 85 gf := float64(cg) / float64(ca) 86 bf := float64(cb) / float64(ca) 87 af := float64(ca) / 0xff 88 cm.Scale(rf, gf, bf, af) 89 e = &colorMCacheEntry{ 90 m: cm, 91 atime: now(), 92 } 93 colorMCache[key] = e 94 95 return e.m 96 }