github.com/jmigpin/editor@v1.6.0/util/fontutil/facecachel2.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 FaceCacheL but with sync.map.
    12  type FaceCacheL2 struct {
    13  	font.Face
    14  	mu  sync.RWMutex
    15  	gc  sync.Map
    16  	gac sync.Map
    17  	gbc sync.Map
    18  	kc  sync.Map // kern cache
    19  }
    20  
    21  func NewFaceCacheL2(face font.Face) *FaceCacheL2 {
    22  	fc := &FaceCacheL2{Face: face}
    23  	return fc
    24  }
    25  func (fc *FaceCacheL2) Glyph(dot fixed.Point26_6, ru rune) (
    26  	dr image.Rectangle,
    27  	mask image.Image,
    28  	maskp image.Point,
    29  	advance fixed.Int26_6,
    30  	ok bool,
    31  ) {
    32  	v, ok := fc.gc.Load(ru)
    33  	var gc *GlyphCache
    34  	if ok {
    35  		gc = v.(*GlyphCache)
    36  	} else {
    37  		fc.mu.Lock()
    38  		gc = NewGlyphCache(fc.Face, ru)
    39  		fc.gc.Store(ru, gc)
    40  		fc.mu.Unlock()
    41  	}
    42  	p := image.Point{dot.X.Floor(), dot.Y.Floor()}
    43  	dr2 := gc.dr.Add(p)
    44  	return dr2, gc.mask, gc.maskp, gc.advance, gc.ok
    45  }
    46  func (fc *FaceCacheL2) GlyphAdvance(ru rune) (advance fixed.Int26_6, ok bool) {
    47  	v, ok := fc.gac.Load(ru)
    48  	var gac *GlyphAdvanceCache
    49  	if ok {
    50  		gac = v.(*GlyphAdvanceCache)
    51  	} else {
    52  		fc.mu.Lock()
    53  		gac = NewGlyphAdvanceCache(fc.Face, ru)
    54  		fc.gac.Store(ru, gac)
    55  		fc.mu.Unlock()
    56  	}
    57  	return gac.advance, gac.ok
    58  }
    59  func (fc *FaceCacheL2) GlyphBounds(ru rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
    60  	v, ok := fc.gbc.Load(ru)
    61  	var gbc *GlyphBoundsCache
    62  	if ok {
    63  		gbc = v.(*GlyphBoundsCache)
    64  	} else {
    65  		fc.mu.Lock()
    66  		gbc = NewGlyphBoundsCache(fc.Face, ru)
    67  		fc.gbc.Store(ru, gbc)
    68  		fc.mu.Unlock()
    69  	}
    70  	return gbc.bounds, gbc.advance, gbc.ok
    71  }
    72  func (fc *FaceCacheL2) Kern(r0, r1 rune) fixed.Int26_6 {
    73  	i := kernIndex(r0, r1)
    74  	v, ok := fc.kc.Load(i)
    75  	var k fixed.Int26_6
    76  	if ok {
    77  		k = v.(fixed.Int26_6)
    78  	} else {
    79  		fc.mu.Lock()
    80  		k = NewKernCache(fc.Face, r0, r1)
    81  		fc.kc.Store(i, k)
    82  		fc.mu.Unlock()
    83  	}
    84  	return k
    85  }