github.com/jmigpin/editor@v1.6.0/util/fontutil/facecachel.go (about)

     1  package fontutil
     2  
     3  import (
     4  	"image"
     5  	"sync"
     6  
     7  	"golang.org/x/image/font"
     8  	"golang.org/x/image/math/fixed"
     9  )
    10  
    11  // Same as FaceCache but with locks.
    12  type FaceCacheL struct {
    13  	font.Face
    14  	mu  sync.RWMutex
    15  	gc  map[rune]*GlyphCache
    16  	gac map[rune]*GlyphAdvanceCache
    17  	gbc map[rune]*GlyphBoundsCache
    18  	kc  map[string]fixed.Int26_6 // kern cache
    19  }
    20  
    21  func NewFaceCacheL(face font.Face) *FaceCacheL {
    22  	fc := &FaceCacheL{Face: face}
    23  	fc.gc = make(map[rune]*GlyphCache)
    24  	fc.gac = make(map[rune]*GlyphAdvanceCache)
    25  	fc.gbc = make(map[rune]*GlyphBoundsCache)
    26  	fc.kc = make(map[string]fixed.Int26_6)
    27  	return fc
    28  }
    29  func (fc *FaceCacheL) Glyph(dot fixed.Point26_6, ru rune) (
    30  	dr image.Rectangle,
    31  	mask image.Image,
    32  	maskp image.Point,
    33  	advance fixed.Int26_6,
    34  	ok bool,
    35  ) {
    36  	fc.mu.RLock()
    37  	gc, ok := fc.gc[ru]
    38  	fc.mu.RUnlock()
    39  	if !ok {
    40  		fc.mu.Lock()
    41  		gc = NewGlyphCache(fc.Face, ru)
    42  		fc.gc[ru] = gc
    43  		fc.mu.Unlock()
    44  	}
    45  	p := image.Point{dot.X.Floor(), dot.Y.Floor()}
    46  	dr2 := gc.dr.Add(p)
    47  	return dr2, gc.mask, gc.maskp, gc.advance, gc.ok
    48  }
    49  func (fc *FaceCacheL) GlyphAdvance(ru rune) (advance fixed.Int26_6, ok bool) {
    50  	fc.mu.RLock()
    51  	gac, ok := fc.gac[ru]
    52  	fc.mu.RUnlock()
    53  	if !ok {
    54  		fc.mu.Lock()
    55  		gac = NewGlyphAdvanceCache(fc.Face, ru)
    56  		fc.gac[ru] = gac
    57  		fc.mu.Unlock()
    58  	}
    59  	return gac.advance, gac.ok
    60  }
    61  func (fc *FaceCacheL) GlyphBounds(ru rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
    62  	fc.mu.RLock()
    63  	gbc, ok := fc.gbc[ru]
    64  	fc.mu.RUnlock()
    65  	if !ok {
    66  		fc.mu.Lock()
    67  		gbc = NewGlyphBoundsCache(fc.Face, ru)
    68  		fc.gbc[ru] = gbc
    69  		fc.mu.Unlock()
    70  	}
    71  	return gbc.bounds, gbc.advance, gbc.ok
    72  }
    73  func (fc *FaceCacheL) Kern(r0, r1 rune) fixed.Int26_6 {
    74  	i := kernIndex(r0, r1)
    75  	fc.mu.RLock()
    76  	k, ok := fc.kc[i]
    77  	fc.mu.RUnlock()
    78  	if !ok {
    79  		fc.mu.Lock()
    80  		k = NewKernCache(fc.Face, r0, r1)
    81  		fc.kc[i] = k
    82  		fc.mu.Unlock()
    83  	}
    84  	return k
    85  }