From 138c71d1c059da1a5959f46c8e06d207d9066e4e Mon Sep 17 00:00:00 2001 From: redstarcoder Date: Tue, 20 Dec 2016 18:20:10 -0500 Subject: [PATCH] Made the GlyphCache settable per GraphicContext --- draw2dbase/stack_gc.go | 18 ++++++++++ draw2dbase/text.go | 79 ++++++------------------------------------ gc.go | 4 +++ glyph.go | 47 +++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 68 deletions(-) create mode 100644 glyph.go diff --git a/draw2dbase/stack_gc.go b/draw2dbase/stack_gc.go index 77622bb..af333d9 100644 --- a/draw2dbase/stack_gc.go +++ b/draw2dbase/stack_gc.go @@ -32,6 +32,7 @@ type ContextStack struct { Join draw2d.LineJoin FontSize float64 FontData draw2d.FontData + GlyphCache draw2d.GlyphCache Font *truetype.Font // fontSize and dpi are used to calculate scale. scale is the number of @@ -57,6 +58,7 @@ func NewStackGraphicContext() *StackGraphicContext { gc.Current.Join = draw2d.RoundJoin gc.Current.FontSize = 10 gc.Current.FontData = DefaultFontData + gc.Current.GlyphCache = DefaultGlyphCache return gc } @@ -169,6 +171,21 @@ func (gc *StackGraphicContext) Close() { gc.Current.Path.Close() } +// Changes the glyph cache backend used by the GraphicContext. +// To restore the default glyph cache, call this function passing nil as argument. +func (gc *StackGraphicContext) SetGlyphCache(cache draw2d.GlyphCache) { + if cache == nil { + gc.Current.GlyphCache = DefaultGlyphCache + } else { + gc.Current.GlyphCache = cache + } +} + +// Gets the glyph cache backend used by the GraphicContext. +func (gc *StackGraphicContext) GetGlyphCache() draw2d.GlyphCache { + return gc.Current.GlyphCache +} + func (gc *StackGraphicContext) Save() { context := new(ContextStack) context.FontSize = gc.Current.FontSize @@ -184,6 +201,7 @@ func (gc *StackGraphicContext) Save() { context.Path = gc.Current.Path.Copy() context.Font = gc.Current.Font context.Scale = gc.Current.Scale + context.GlyphCache = gc.Current.GlyphCache copy(context.Tr[:], gc.Current.Tr[:]) context.Previous = gc.Current gc.Current = context diff --git a/draw2dbase/text.go b/draw2dbase/text.go index 093a2a3..6873cad 100644 --- a/draw2dbase/text.go +++ b/draw2dbase/text.go @@ -3,38 +3,17 @@ package draw2dbase import "github.com/llgcode/draw2d" var ( - glyphCacheDefault = &defaultGlyphCache{make(map[string]map[rune]*Glyph)} - glyphCache GlyphCache = glyphCacheDefault + DefaultGlyphCache = &defaultGlyphCache{make(map[string]map[rune]*draw2d.Glyph)} ) -// Types implementing this interface can be passed to SetGlyphCache to change the -// way glyphs are being stored and retrieved. -type GlyphCache interface { - // Fetch fetches a glyph from the cache, storing with Render first if it doesn't already exist - Fetch(gc draw2d.GraphicContext, fontName string, chr rune) *Glyph - - // Render renders a glyph then returns it - Render(gc draw2d.GraphicContext, fontName string, chr rune) *Glyph -} - -// Changes the glyph cache backend used by the package. -// To restore the default glyph cache, call this function passing nil as argument. -func SetGlyphCache(cache GlyphCache) { - if cache == nil { - glyphCache = glyphCacheDefault - } else { - glyphCache = cache - } -} - type defaultGlyphCache struct { - glyphMap map[string]map[rune]*Glyph + glyphMap map[string]map[rune]*draw2d.Glyph } // Fetch fetches a glyph from the cache, storing with Render first if it doesn't already exist -func (cache *defaultGlyphCache) Fetch(gc draw2d.GraphicContext, fontName string, chr rune) *Glyph { +func (cache *defaultGlyphCache) Fetch(gc draw2d.GraphicContext, fontName string, chr rune) *draw2d.Glyph { if cache.glyphMap[fontName] == nil { - cache.glyphMap[fontName] = make(map[rune]*Glyph, 60) + cache.glyphMap[fontName] = make(map[rune]*draw2d.Glyph, 60) } if cache.glyphMap[fontName][chr] == nil { cache.glyphMap[fontName][chr] = cache.Render(gc, fontName, chr) @@ -43,60 +22,24 @@ func (cache *defaultGlyphCache) Fetch(gc draw2d.GraphicContext, fontName string, } // Render renders a glyph then returns it -func (cache *defaultGlyphCache) Render(gc draw2d.GraphicContext, fontName string, chr rune) *Glyph { +func (cache *defaultGlyphCache) Render(gc draw2d.GraphicContext, fontName string, chr rune) *draw2d.Glyph { gc.Save() defer gc.Restore() gc.BeginPath() width := gc.CreateStringPath(string(chr), 0, 0) path := gc.GetPath() - return &Glyph{ - path: &path, + return &draw2d.Glyph{ + Path: &path, Width: width, } } // FetchGlyph fetches a glyph from the cache, calling renderGlyph first if it doesn't already exist -func FetchGlyph(gc draw2d.GraphicContext, fontName string, chr rune) *Glyph { - return glyphCache.Fetch(gc, fontName, chr) +func FetchGlyph(gc draw2d.GraphicContext, fontName string, chr rune) *draw2d.Glyph { + return gc.GetGlyphCache().Fetch(gc, fontName, chr) } // renderGlyph renders a glyph then caches and returns it -func renderGlyph(gc draw2d.GraphicContext, fontName string, chr rune) *Glyph { - return glyphCache.Render(gc, fontName, chr) -} - -// Glyph represents a rune which has been converted to a Path and width -type Glyph struct { - // path represents a glyph, it is always at (0, 0) - path *draw2d.Path - // Width of the glyph - Width float64 -} - -// Copy copys the Glyph, and returns the copy -func (g *Glyph) Copy() *Glyph { - return &Glyph{ - path: g.path.Copy(), - Width: g.Width, - } -} - -// Fill copies a glyph from the cache, and fills it -func (g *Glyph) Fill(gc draw2d.GraphicContext, x, y float64) float64 { - gc.Save() - gc.BeginPath() - gc.Translate(x, y) - gc.Fill(g.path) - gc.Restore() - return g.Width -} - -// Stroke fetches a glyph from the cache, and strokes it -func (g *Glyph) Stroke(gc draw2d.GraphicContext, x, y float64) float64 { - gc.Save() - gc.BeginPath() - gc.Translate(x, y) - gc.Stroke(g.path) - gc.Restore() - return g.Width +func renderGlyph(gc draw2d.GraphicContext, fontName string, chr rune) *draw2d.Glyph { + return gc.GetGlyphCache().Render(gc, fontName, chr) } diff --git a/gc.go b/gc.go index 543359e..ec0023a 100644 --- a/gc.go +++ b/gc.go @@ -52,6 +52,10 @@ type GraphicContext interface { GetFontData() FontData // GetFontName gets the current FontData as a string GetFontName() string + // SetGlyphCache changes the glyph cache backend used by the GraphicContext + SetGlyphCache(cache GlyphCache) + // GetGlyphCache gets the current GlyphCache + GetGlyphCache() GlyphCache // DrawImage draws the raster image in the current canvas DrawImage(image image.Image) // Save the context and push it to the context stack diff --git a/glyph.go b/glyph.go new file mode 100644 index 0000000..9dcb36c --- /dev/null +++ b/glyph.go @@ -0,0 +1,47 @@ +package draw2d + +// Types implementing this interface can be passed to gc.SetGlyphCache to change the +// way glyphs are being stored and retrieved. +type GlyphCache interface { + // Fetch fetches a glyph from the cache, storing with Render first if it doesn't already exist + Fetch(gc GraphicContext, fontName string, chr rune) *Glyph + + // Render renders a glyph then returns it + Render(gc GraphicContext, fontName string, chr rune) *Glyph +} + +// Glyph represents a rune which has been converted to a Path and width +type Glyph struct { + // Path represents a glyph, it is always at (0, 0) + Path *Path + // Width of the glyph + Width float64 +} + +// Copy copys the Glyph, and returns the copy +func (g *Glyph) Copy() *Glyph { + return &Glyph{ + Path: g.Path.Copy(), + Width: g.Width, + } +} + +// Fill fills a Glyph in the specified coordinates +func (g *Glyph) Fill(gc GraphicContext, x, y float64) float64 { + gc.Save() + gc.BeginPath() + gc.Translate(x, y) + gc.Fill(g.Path) + gc.Restore() + return g.Width +} + +// Stroke strokes a Glyph in the specified coordinates +func (g *Glyph) Stroke(gc GraphicContext, x, y float64) float64 { + gc.Save() + gc.BeginPath() + gc.Translate(x, y) + gc.Stroke(g.Path) + gc.Restore() + return g.Width +}