twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

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 }