This commit is contained in:
llgcode 2017-12-04 16:29:40 +01:00
parent 8167230c09
commit a5f7ac8ebe
4 changed files with 53 additions and 29 deletions

View File

@ -2,21 +2,29 @@ package draw2dbase
import "github.com/llgcode/draw2d"
var glyphCache map[string]map[rune]*Glyph
// GlyphCache manage a map of glyphs
type GlyphCache struct {
glyphs map[string]map[rune]*Glyph
}
func init() {
glyphCache = make(map[string]map[rune]*Glyph)
// NewGlyphCache initializes a GlyphCache
func NewGlyphCache() *GlyphCache {
glyphs := make(map[string]map[rune]*Glyph)
return &GlyphCache {
glyphs: glyphs,
}
}
// 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 {
if glyphCache[fontName] == nil {
glyphCache[fontName] = make(map[rune]*Glyph, 60)
func (glyphCache *GlyphCache) FetchGlyph(gc draw2d.GraphicContext, fontName string, chr rune) *Glyph {
if glyphCache.glyphs[fontName] == nil {
glyphCache.glyphs[fontName] = make(map[rune]*Glyph, 60)
}
if glyphCache[fontName][chr] == nil {
glyphCache[fontName][chr] = renderGlyph(gc, fontName, chr)
if glyphCache.glyphs[fontName][chr] == nil {
glyphCache.glyphs[fontName][chr] = renderGlyph(gc, fontName, chr)
}
return glyphCache[fontName][chr].Copy()
return glyphCache.glyphs[fontName][chr].Copy()
}
// renderGlyph renders a glyph then caches and returns it
@ -40,6 +48,7 @@ type Glyph struct {
Width float64
}
// Returns a copy of a Glyph
func (g *Glyph) Copy() *Glyph {
return &Glyph{
path: g.path.Copy(),

View File

@ -4,7 +4,6 @@
package draw2dimg
import (
"errors"
"image"
"image/color"
"log"
@ -35,6 +34,8 @@ type GraphicContext struct {
painter Painter
fillRasterizer *raster.Rasterizer
strokeRasterizer *raster.Rasterizer
FontCache draw2d.FontCache
glyphCache *draw2dbase.GlyphCache
glyphBuf *truetype.GlyphBuf
DPI int
}
@ -74,6 +75,8 @@ func NewGraphicContextWithPainter(img draw.Image, painter Painter) *GraphicConte
painter,
raster.NewRasterizer(width, height),
raster.NewRasterizer(width, height),
draw2d.GetGlobalFontCache(),
draw2dbase.NewGlyphCache(),
&truetype.GlyphBuf{},
dpi,
}
@ -136,7 +139,7 @@ func (gc *GraphicContext) FillStringAt(text string, x, y float64) (width float64
if hasPrev {
x += fUnitsToFloat64(f.Kern(fixed.Int26_6(gc.Current.Scale), prev, index))
}
glyph := draw2dbase.FetchGlyph(gc, fontName, r)
glyph := gc.glyphCache.FetchGlyph(gc, fontName, r)
x += glyph.Fill(gc, x, y)
prev, hasPrev = index, true
}
@ -163,7 +166,7 @@ func (gc *GraphicContext) StrokeStringAt(text string, x, y float64) (width float
if hasPrev {
x += fUnitsToFloat64(f.Kern(fixed.Int26_6(gc.Current.Scale), prev, index))
}
glyph := draw2dbase.FetchGlyph(gc, fontName, r)
glyph := gc.glyphCache.FetchGlyph(gc, fontName, r)
x += glyph.Stroke(gc, x, y)
prev, hasPrev = index, true
}
@ -171,16 +174,15 @@ func (gc *GraphicContext) StrokeStringAt(text string, x, y float64) (width float
}
func (gc *GraphicContext) loadCurrentFont() (*truetype.Font, error) {
font := draw2d.GetFont(gc.Current.FontData)
if font == nil {
font = draw2d.GetFont(draw2dbase.DefaultFontData)
font, err := gc.FontCache.Load(gc.Current.FontData)
if err != nil {
font, err = gc.FontCache.Load(draw2dbase.DefaultFontData)
}
if font == nil {
return nil, errors.New("No font set, and no default font available.")
if font != nil {
gc.SetFont(font)
gc.SetFontSize(gc.Current.FontSize)
}
gc.SetFont(font)
gc.SetFontSize(gc.Current.FontSize)
return font, nil
return font, err
}
// p is a truetype.Point measured in FUnits and positive Y going upwards.

28
font.go
View File

@ -79,6 +79,10 @@ func GetFontFolder() string {
return defaultFonts.folder
}
func GetGlobalFontCache() FontCache {
return defaultFonts
}
func SetFontFolder(folder string) {
defaultFonts.folder = filepath.Clean(folder)
}
@ -113,13 +117,24 @@ func SetFontCache(cache FontCache) {
}
}
type defaultFontCache struct {
// FolderFontCache can Load font from folder
type FolderFontCache struct {
fonts map[string]*truetype.Font
folder string
namer FontFileNamer
}
func (cache *defaultFontCache) Load(fontData FontData) (font *truetype.Font, err error) {
// NewFolderFontCache creates FolderFontCache
func NewFolderFontCache(folder string) *FolderFontCache {
return &FolderFontCache{
fonts: make(map[string]*truetype.Font),
folder: folder,
namer: FontFileName,
}
}
// Load a font from cache if exists otherwise it will load the font from file
func (cache *FolderFontCache) Load(fontData FontData) (font *truetype.Font, err error) {
if font = cache.fonts[cache.namer(fontData)]; font != nil {
return font, nil
}
@ -139,16 +154,13 @@ func (cache *defaultFontCache) Load(fontData FontData) (font *truetype.Font, err
return
}
func (cache *defaultFontCache) Store(fontData FontData, font *truetype.Font) {
// Store a font to this cache
func (cache *FolderFontCache) Store(fontData FontData, font *truetype.Font) {
cache.fonts[cache.namer(fontData)] = font
}
var (
defaultFonts = &defaultFontCache{
fonts: make(map[string]*truetype.Font),
folder: "../resource/font",
namer: FontFileName,
}
defaultFonts = NewFolderFontCache("../resource/font")
fontCache FontCache = defaultFonts
)

View File

@ -2,6 +2,7 @@
package draw2d_test
import (
"fmt"
"github.com/llgcode/draw2d"
@ -25,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()