package shaping

import (
	
	
)

// adjust the cache size of the zero value, used by default
// in [HarfbuzzShaper]
const defaultFontCacheSize = 32

// fontEntry holds a single key-value pair for an LRU cache.
type fontEntry struct {
	next, prev *fontEntry
	key        *font.Font
	v          *harfbuzz.Font
}

// fontLRU is a least-recently-used cache for harfbuzz fonts built from
// font.Fonts. It uses a doubly-linked list to track how recently elements have
// been used and a map to store element data for quick access.
type fontLRU struct {
	// This implementation is derived from the one here under the terms of the UNLICENSE:
	//
	// https://git.sr.ht/~eliasnaur/gio/tree/e768fe347a732056031100f2c66987d6db258ea4/item/text/lru.go
	m          map[*font.Font]*fontEntry
	head, tail *fontEntry

	// the actual cache size is [maxSizeOffset] + [defaultFontCacheSize]
	maxSizeOffset int
}

// Get fetches the value associated with the given key, if any.
func ( *fontLRU) ( *font.Font) (*harfbuzz.Font, bool) {
	if ,  := .m[];  {
		.remove()
		.insert()
		return .v, true
	}
	return nil, false
}

// Put inserts the given value with the given key, evicting old
// cache entries if necessary.
func ( *fontLRU) ( *font.Font,  *harfbuzz.Font) {
	if .m == nil {
		.m = make(map[*font.Font]*fontEntry)
		.head = new(fontEntry)
		.tail = new(fontEntry)
		.head.prev = .tail
		.tail.next = .head
	}
	 := &fontEntry{key: , v: }
	.m[] = 
	.insert()
	if len(.m) > (defaultFontCacheSize + .maxSizeOffset) {
		 := .tail.next
		.remove()
		delete(.m, .key)
	}
}

// remove cuts e out of the lru linked list.
func ( *fontLRU) ( *fontEntry) {
	.next.prev = .prev
	.prev.next = .next
}

// insert adds e to the lru linked list.
func ( *fontLRU) ( *fontEntry) {
	.next = .head
	.prev = .head.prev
	.prev.next = 
	.next.prev = 
}