From f3e35015aa4f1232e03907ee3618af62dbaeab70 Mon Sep 17 00:00:00 2001 From: llgcode Date: Mon, 4 Dec 2017 18:06:33 +0100 Subject: [PATCH] synchronize global font cache fixes #131 --- font.go | 77 ++++++++++++++++++++++++++++++++++++++++++++++++---- sync_test.go | 2 +- 2 files changed, 72 insertions(+), 7 deletions(-) diff --git a/font.go b/font.go index 61c0171..70de72b 100644 --- a/font.go +++ b/font.go @@ -8,6 +8,7 @@ import ( "log" "path/filepath" + "sync" "github.com/golang/freetype/truetype" ) @@ -79,16 +80,16 @@ func GetFontFolder() string { return defaultFonts.folder } +func SetFontFolder(folder string) { + defaultFonts.setFolder(filepath.Clean(folder)) +} + func GetGlobalFontCache() FontCache { return defaultFonts } -func SetFontFolder(folder string) { - defaultFonts.folder = filepath.Clean(folder) -} - func SetFontNamer(fn FontFileNamer) { - defaultFonts.namer = fn + defaultFonts.setNamer(fn) } // Types implementing this interface can be passed to SetFontCache to change the @@ -159,8 +160,72 @@ func (cache *FolderFontCache) Store(fontData FontData, font *truetype.Font) { cache.fonts[cache.namer(fontData)] = font } +// SyncFolderFontCache can Load font from folder +type SyncFolderFontCache struct { + sync.RWMutex + fonts map[string]*truetype.Font + folder string + namer FontFileNamer +} + + + +// NewSyncFolderFontCache creates SyncFolderFontCache +func NewSyncFolderFontCache(folder string) *SyncFolderFontCache { + return &SyncFolderFontCache{ + fonts: make(map[string]*truetype.Font), + folder: folder, + namer: FontFileName, + } +} + +func (cache *SyncFolderFontCache) setFolder(folder string) { + cache.Lock() + cache.folder = folder + cache.Unlock() +} + +func (cache *SyncFolderFontCache) setNamer(namer FontFileNamer) { + cache.Lock() + cache.namer = namer + cache.Unlock() +} + +// Load a font from cache if exists otherwise it will load the font from file +func (cache *SyncFolderFontCache) Load(fontData FontData) (font *truetype.Font, err error) { + cache.RLock() + font = cache.fonts[cache.namer(fontData)] + cache.RUnlock() + + if font != nil { + return font, nil + } + + var data []byte + var file = cache.namer(fontData) + + if data, err = ioutil.ReadFile(filepath.Join(cache.folder, file)); err != nil { + return + } + + if font, err = truetype.Parse(data); err != nil { + return + } + cache.Lock() + cache.fonts[file] = font + cache.Unlock() + return +} + +// Store a font to this cache +func (cache *SyncFolderFontCache) Store(fontData FontData, font *truetype.Font) { + cache.Lock() + cache.fonts[cache.namer(fontData)] = font + cache.Unlock() +} + var ( - defaultFonts = NewFolderFontCache("../resource/font") + defaultFonts = NewSyncFolderFontCache("../resource/font") fontCache FontCache = defaultFonts ) diff --git a/sync_test.go b/sync_test.go index 41eef62..6c5afd8 100644 --- a/sync_test.go +++ b/sync_test.go @@ -26,10 +26,10 @@ func TestSync(t *testing.T) { } func Draw(i int, ch chan<- int) { + draw2d.SetFontFolder("./resource/font") // Draw a rounded rectangle using default colors dest := image.NewRGBA(image.Rect(0, 0, 297, 210.0)) gc := draw2dimg.NewGraphicContext(dest) - gc.FontCache = draw2d.NewFolderFontCache("./resource/font") draw2dkit.RoundedRectangle(gc, 5, 5, 135, 95, 10, 10) gc.FillStroke()