fix #131
This commit is contained in:
parent
8167230c09
commit
a5f7ac8ebe
4 changed files with 53 additions and 29 deletions
|
@ -2,21 +2,29 @@ package draw2dbase
|
||||||
|
|
||||||
import "github.com/llgcode/draw2d"
|
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
|
// 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 {
|
func (glyphCache *GlyphCache) FetchGlyph(gc draw2d.GraphicContext, fontName string, chr rune) *Glyph {
|
||||||
if glyphCache[fontName] == nil {
|
if glyphCache.glyphs[fontName] == nil {
|
||||||
glyphCache[fontName] = make(map[rune]*Glyph, 60)
|
glyphCache.glyphs[fontName] = make(map[rune]*Glyph, 60)
|
||||||
}
|
}
|
||||||
if glyphCache[fontName][chr] == nil {
|
if glyphCache.glyphs[fontName][chr] == nil {
|
||||||
glyphCache[fontName][chr] = renderGlyph(gc, fontName, chr)
|
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
|
// renderGlyph renders a glyph then caches and returns it
|
||||||
|
@ -40,6 +48,7 @@ type Glyph struct {
|
||||||
Width float64
|
Width float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a copy of a Glyph
|
||||||
func (g *Glyph) Copy() *Glyph {
|
func (g *Glyph) Copy() *Glyph {
|
||||||
return &Glyph{
|
return &Glyph{
|
||||||
path: g.path.Copy(),
|
path: g.path.Copy(),
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
package draw2dimg
|
package draw2dimg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"log"
|
"log"
|
||||||
|
@ -35,6 +34,8 @@ type GraphicContext struct {
|
||||||
painter Painter
|
painter Painter
|
||||||
fillRasterizer *raster.Rasterizer
|
fillRasterizer *raster.Rasterizer
|
||||||
strokeRasterizer *raster.Rasterizer
|
strokeRasterizer *raster.Rasterizer
|
||||||
|
FontCache draw2d.FontCache
|
||||||
|
glyphCache *draw2dbase.GlyphCache
|
||||||
glyphBuf *truetype.GlyphBuf
|
glyphBuf *truetype.GlyphBuf
|
||||||
DPI int
|
DPI int
|
||||||
}
|
}
|
||||||
|
@ -74,6 +75,8 @@ func NewGraphicContextWithPainter(img draw.Image, painter Painter) *GraphicConte
|
||||||
painter,
|
painter,
|
||||||
raster.NewRasterizer(width, height),
|
raster.NewRasterizer(width, height),
|
||||||
raster.NewRasterizer(width, height),
|
raster.NewRasterizer(width, height),
|
||||||
|
draw2d.GetGlobalFontCache(),
|
||||||
|
draw2dbase.NewGlyphCache(),
|
||||||
&truetype.GlyphBuf{},
|
&truetype.GlyphBuf{},
|
||||||
dpi,
|
dpi,
|
||||||
}
|
}
|
||||||
|
@ -136,7 +139,7 @@ func (gc *GraphicContext) FillStringAt(text string, x, y float64) (width float64
|
||||||
if hasPrev {
|
if hasPrev {
|
||||||
x += fUnitsToFloat64(f.Kern(fixed.Int26_6(gc.Current.Scale), prev, index))
|
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)
|
x += glyph.Fill(gc, x, y)
|
||||||
prev, hasPrev = index, true
|
prev, hasPrev = index, true
|
||||||
}
|
}
|
||||||
|
@ -163,7 +166,7 @@ func (gc *GraphicContext) StrokeStringAt(text string, x, y float64) (width float
|
||||||
if hasPrev {
|
if hasPrev {
|
||||||
x += fUnitsToFloat64(f.Kern(fixed.Int26_6(gc.Current.Scale), prev, index))
|
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)
|
x += glyph.Stroke(gc, x, y)
|
||||||
prev, hasPrev = index, true
|
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) {
|
func (gc *GraphicContext) loadCurrentFont() (*truetype.Font, error) {
|
||||||
font := draw2d.GetFont(gc.Current.FontData)
|
font, err := gc.FontCache.Load(gc.Current.FontData)
|
||||||
if font == nil {
|
if err != nil {
|
||||||
font = draw2d.GetFont(draw2dbase.DefaultFontData)
|
font, err = gc.FontCache.Load(draw2dbase.DefaultFontData)
|
||||||
}
|
}
|
||||||
if font == nil {
|
if font != nil {
|
||||||
return nil, errors.New("No font set, and no default font available.")
|
gc.SetFont(font)
|
||||||
|
gc.SetFontSize(gc.Current.FontSize)
|
||||||
}
|
}
|
||||||
gc.SetFont(font)
|
return font, err
|
||||||
gc.SetFontSize(gc.Current.FontSize)
|
|
||||||
return font, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// p is a truetype.Point measured in FUnits and positive Y going upwards.
|
// p is a truetype.Point measured in FUnits and positive Y going upwards.
|
||||||
|
|
28
font.go
28
font.go
|
@ -79,6 +79,10 @@ func GetFontFolder() string {
|
||||||
return defaultFonts.folder
|
return defaultFonts.folder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetGlobalFontCache() FontCache {
|
||||||
|
return defaultFonts
|
||||||
|
}
|
||||||
|
|
||||||
func SetFontFolder(folder string) {
|
func SetFontFolder(folder string) {
|
||||||
defaultFonts.folder = filepath.Clean(folder)
|
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
|
fonts map[string]*truetype.Font
|
||||||
folder string
|
folder string
|
||||||
namer FontFileNamer
|
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 {
|
if font = cache.fonts[cache.namer(fontData)]; font != nil {
|
||||||
return font, nil
|
return font, nil
|
||||||
}
|
}
|
||||||
|
@ -139,16 +154,13 @@ func (cache *defaultFontCache) Load(fontData FontData) (font *truetype.Font, err
|
||||||
return
|
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
|
cache.fonts[cache.namer(fontData)] = font
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaultFonts = &defaultFontCache{
|
defaultFonts = NewFolderFontCache("../resource/font")
|
||||||
fonts: make(map[string]*truetype.Font),
|
|
||||||
folder: "../resource/font",
|
|
||||||
namer: FontFileName,
|
|
||||||
}
|
|
||||||
|
|
||||||
fontCache FontCache = defaultFonts
|
fontCache FontCache = defaultFonts
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
package draw2d_test
|
package draw2d_test
|
||||||
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/llgcode/draw2d"
|
"github.com/llgcode/draw2d"
|
||||||
|
@ -25,10 +26,10 @@ func TestSync(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Draw(i int, ch chan<- int) {
|
func Draw(i int, ch chan<- int) {
|
||||||
draw2d.SetFontFolder("./resource/font")
|
|
||||||
// Draw a rounded rectangle using default colors
|
// Draw a rounded rectangle using default colors
|
||||||
dest := image.NewRGBA(image.Rect(0, 0, 297, 210.0))
|
dest := image.NewRGBA(image.Rect(0, 0, 297, 210.0))
|
||||||
gc := draw2dimg.NewGraphicContext(dest)
|
gc := draw2dimg.NewGraphicContext(dest)
|
||||||
|
gc.FontCache = draw2d.NewFolderFontCache("./resource/font")
|
||||||
|
|
||||||
draw2dkit.RoundedRectangle(gc, 5, 5, 135, 95, 10, 10)
|
draw2dkit.RoundedRectangle(gc, 5, 5, 135, 95, 10, 10)
|
||||||
gc.FillStroke()
|
gc.FillStroke()
|
||||||
|
|
Loading…
Reference in a new issue