aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/llgcode
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2018-01-01 22:45:26 +0100
committerDimitri Sokolyuk <demon@dim13.org>2018-01-01 22:45:26 +0100
commit16df0bea5fe8ce0a4ea871d409f589b298567a97 (patch)
treef2f18a2c6773d86a895d075bf8f1a374d48406c4 /vendor/github.com/llgcode
parent500caaeda74dd9c660279036293f4b2997cf0b03 (diff)
Update vendor
Diffstat (limited to 'vendor/github.com/llgcode')
-rw-r--r--vendor/github.com/llgcode/draw2d/draw2dbase/curve.go35
-rw-r--r--vendor/github.com/llgcode/draw2d/draw2dbase/curve_test.go42
-rw-r--r--vendor/github.com/llgcode/draw2d/draw2dbase/text.go45
-rw-r--r--vendor/github.com/llgcode/draw2d/draw2dgl/gc.go26
-rw-r--r--vendor/github.com/llgcode/draw2d/draw2dimg/curve_limit_test.go189
-rw-r--r--vendor/github.com/llgcode/draw2d/draw2dimg/ftgc.go24
-rw-r--r--vendor/github.com/llgcode/draw2d/font.go93
-rw-r--r--vendor/github.com/llgcode/draw2d/output/samples/geometry.pngbin24841 -> 23028 bytes
-rw-r--r--vendor/github.com/llgcode/draw2d/output/samples/postscript.pngbin41596 -> 43560 bytes
-rw-r--r--vendor/github.com/llgcode/draw2d/sync_test.go46
10 files changed, 442 insertions, 58 deletions
diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/curve.go b/vendor/github.com/llgcode/draw2d/draw2dbase/curve.go
index 211e107..05a9ede 100644
--- a/vendor/github.com/llgcode/draw2d/draw2dbase/curve.go
+++ b/vendor/github.com/llgcode/draw2d/draw2dbase/curve.go
@@ -4,6 +4,7 @@
package draw2dbase
import (
+ "errors"
"math"
)
@@ -17,6 +18,7 @@ const (
// SubdivideCubic a Bezier cubic curve in 2 equivalents Bezier cubic curves.
// c1 and c2 parameters are the resulting curves
+// length of c, c1 and c2 must be 8 otherwise it panics.
func SubdivideCubic(c, c1, c2 []float64) {
// First point of c is the first point of c1
c1[0], c1[1] = c[0], c[1]
@@ -48,7 +50,10 @@ func SubdivideCubic(c, c1, c2 []float64) {
// TraceCubic generate lines subdividing the cubic curve using a Liner
// flattening_threshold helps determines the flattening expectation of the curve
-func TraceCubic(t Liner, cubic []float64, flatteningThreshold float64) {
+func TraceCubic(t Liner, cubic []float64, flatteningThreshold float64) error {
+ if len(cubic) < 8 {
+ return errors.New("cubic length must be >= 8")
+ }
// Allocation curves
var curves [CurveRecursionLimit * 8]float64
copy(curves[0:8], cubic[0:8])
@@ -60,7 +65,7 @@ func TraceCubic(t Liner, cubic []float64, flatteningThreshold float64) {
var dx, dy, d2, d3 float64
for i >= 0 {
- c = curves[i*8:]
+ c = curves[i:]
dx = c[6] - c[0]
dy = c[7] - c[1]
@@ -68,15 +73,16 @@ func TraceCubic(t Liner, cubic []float64, flatteningThreshold float64) {
d3 = math.Abs((c[4]-c[6])*dy - (c[5]-c[7])*dx)
// if it's flat then trace a line
- if (d2+d3)*(d2+d3) < flatteningThreshold*(dx*dx+dy*dy) || i == len(curves)-1 {
+ if (d2+d3)*(d2+d3) <= flatteningThreshold*(dx*dx+dy*dy) || i == len(curves)-8 {
t.LineTo(c[6], c[7])
- i--
+ i -= 8
} else {
// second half of bezier go lower onto the stack
- SubdivideCubic(c, curves[(i+1)*8:], curves[i*8:])
- i++
+ SubdivideCubic(c, curves[i+8:], curves[i:])
+ i += 8
}
}
+ return nil
}
// Quad
@@ -84,6 +90,7 @@ func TraceCubic(t Liner, cubic []float64, flatteningThreshold float64) {
// SubdivideQuad a Bezier quad curve in 2 equivalents Bezier quad curves.
// c1 and c2 parameters are the resulting curves
+// length of c, c1 and c2 must be 6 otherwise it panics.
func SubdivideQuad(c, c1, c2 []float64) {
// First point of c is the first point of c1
c1[0], c1[1] = c[0], c[1]
@@ -103,7 +110,10 @@ func SubdivideQuad(c, c1, c2 []float64) {
// TraceQuad generate lines subdividing the curve using a Liner
// flattening_threshold helps determines the flattening expectation of the curve
-func TraceQuad(t Liner, quad []float64, flatteningThreshold float64) {
+func TraceQuad(t Liner, quad []float64, flatteningThreshold float64) error {
+ if len(quad) < 6 {
+ return errors.New("quad length must be >= 6")
+ }
// Allocates curves stack
var curves [CurveRecursionLimit * 6]float64
copy(curves[0:6], quad[0:6])
@@ -113,22 +123,23 @@ func TraceQuad(t Liner, quad []float64, flatteningThreshold float64) {
var dx, dy, d float64
for i >= 0 {
- c = curves[i*6:]
+ c = curves[i:]
dx = c[4] - c[0]
dy = c[5] - c[1]
d = math.Abs(((c[2]-c[4])*dy - (c[3]-c[5])*dx))
// if it's flat then trace a line
- if (d*d) < flatteningThreshold*(dx*dx+dy*dy) || i == len(curves)-1 {
+ if (d*d) <= flatteningThreshold*(dx*dx+dy*dy) || i == len(curves)-6 {
t.LineTo(c[4], c[5])
- i--
+ i -= 6
} else {
// second half of bezier go lower onto the stack
- SubdivideQuad(c, curves[(i+1)*6:], curves[i*6:])
- i++
+ SubdivideQuad(c, curves[i+6:], curves[i:])
+ i += 6
}
}
+ return nil
}
// TraceArc trace an arc using a Liner
diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/curve_test.go b/vendor/github.com/llgcode/draw2d/draw2dbase/curve_test.go
index fa954df..fc4efc8 100644
--- a/vendor/github.com/llgcode/draw2d/draw2dbase/curve_test.go
+++ b/vendor/github.com/llgcode/draw2d/draw2dbase/curve_test.go
@@ -101,6 +101,32 @@ func TestQuadCurve(t *testing.T) {
fmt.Println()
}
+func TestQuadCurveCombinedPoint(t *testing.T) {
+ var p1 SegmentedPath
+ TraceQuad(&p1, []float64{0, 0, 0, 0, 0, 0}, flatteningThreshold)
+ if len(p1.Points) != 2 {
+ t.Error("It must have one point for this curve", len(p1.Points))
+ }
+ var p2 SegmentedPath
+ TraceQuad(&p2, []float64{0, 0, 100, 100, 0, 0}, flatteningThreshold)
+ if len(p2.Points) != 2 {
+ t.Error("It must have one point for this curve", len(p2.Points))
+ }
+}
+
+func TestCubicCurveCombinedPoint(t *testing.T) {
+ var p1 SegmentedPath
+ TraceCubic(&p1, []float64{0, 0, 0, 0, 0, 0, 0, 0}, flatteningThreshold)
+ if len(p1.Points) != 2 {
+ t.Error("It must have one point for this curve", len(p1.Points))
+ }
+ var p2 SegmentedPath
+ TraceCubic(&p2, []float64{0, 0, 100, 100, 200, 200, 0, 0}, flatteningThreshold)
+ if len(p2.Points) != 2 {
+ t.Error("It must have one point for this curve", len(p2.Points))
+ }
+}
+
func BenchmarkCubicCurve(b *testing.B) {
for i := 0; i < b.N; i++ {
for i := 0; i < len(testsCubicFloat64); i += 8 {
@@ -132,3 +158,19 @@ func SaveToPngFile(filePath string, m image.Image) error {
}
return nil
}
+
+func TestOutOfRangeTraceCurve(t *testing.T) {
+ c := []float64{
+ 100, 100, 200, 100, 100, 200,
+ }
+ var p SegmentedPath
+ TraceCubic(&p, c, flatteningThreshold)
+}
+
+func TestOutOfRangeTraceQuad(t *testing.T) {
+ c := []float64{
+ 100, 100, 200, 100,
+ }
+ var p SegmentedPath
+ TraceQuad(&p, c, flatteningThreshold)
+}
diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/text.go b/vendor/github.com/llgcode/draw2d/draw2dbase/text.go
index 4283bad..22b7acf 100644
--- a/vendor/github.com/llgcode/draw2d/draw2dbase/text.go
+++ b/vendor/github.com/llgcode/draw2d/draw2dbase/text.go
@@ -2,21 +2,35 @@ package draw2dbase
import "github.com/llgcode/draw2d"
-var glyphCache map[string]map[rune]*Glyph
+// GlyphCache manage a cache of glyphs
+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
+}
+
+// GlyphCacheImp manage a map of glyphs without sync mecanism, not thread safe
+type GlyphCacheImp struct {
+ glyphs map[string]map[rune]*Glyph
+}
-func init() {
- glyphCache = make(map[string]map[rune]*Glyph)
+
+// NewGlyphCache initializes a GlyphCache
+func NewGlyphCache() *GlyphCacheImp {
+ glyphs := make(map[string]map[rune]*Glyph)
+ return &GlyphCacheImp {
+ 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)
+// Fetch fetches a glyph from the cache, calling renderGlyph first if it doesn't already exist
+func (glyphCache *GlyphCacheImp) Fetch(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
@@ -27,7 +41,7 @@ func renderGlyph(gc draw2d.GraphicContext, fontName string, chr rune) *Glyph {
width := gc.CreateStringPath(string(chr), 0, 0)
path := gc.GetPath()
return &Glyph{
- path: &path,
+ Path: &path,
Width: width,
}
}
@@ -35,14 +49,15 @@ func renderGlyph(gc draw2d.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 *draw2d.Path
+ Path *draw2d.Path
// Width of the glyph
Width float64
}
+// Copy Returns a copy of a Glyph
func (g *Glyph) Copy() *Glyph {
return &Glyph{
- path: g.path.Copy(),
+ Path: g.Path.Copy(),
Width: g.Width,
}
}
@@ -52,7 +67,7 @@ func (g *Glyph) Fill(gc draw2d.GraphicContext, x, y float64) float64 {
gc.Save()
gc.BeginPath()
gc.Translate(x, y)
- gc.Fill(g.path)
+ gc.Fill(g.Path)
gc.Restore()
return g.Width
}
@@ -62,7 +77,7 @@ func (g *Glyph) Stroke(gc draw2d.GraphicContext, x, y float64) float64 {
gc.Save()
gc.BeginPath()
gc.Translate(x, y)
- gc.Stroke(g.path)
+ gc.Stroke(g.Path)
gc.Restore()
return g.Width
}
diff --git a/vendor/github.com/llgcode/draw2d/draw2dgl/gc.go b/vendor/github.com/llgcode/draw2d/draw2dgl/gc.go
index d512ccc..7253170 100644
--- a/vendor/github.com/llgcode/draw2d/draw2dgl/gc.go
+++ b/vendor/github.com/llgcode/draw2d/draw2dgl/gc.go
@@ -1,7 +1,6 @@
package draw2dgl
import (
- "errors"
"image"
"image/color"
"image/draw"
@@ -125,8 +124,10 @@ type GraphicContext struct {
painter *Painter
fillRasterizer *raster.Rasterizer
strokeRasterizer *raster.Rasterizer
+ FontCache draw2d.FontCache
+ glyphCache draw2dbase.GlyphCache
glyphBuf *truetype.GlyphBuf
- DPI int
+ DPI int
}
// NewGraphicContext creates a new Graphic context from an image.
@@ -136,6 +137,8 @@ func NewGraphicContext(width, height int) *GraphicContext {
NewPainter(),
raster.NewRasterizer(width, height),
raster.NewRasterizer(width, height),
+ draw2d.GetGlobalFontCache(),
+ draw2dbase.NewGlyphCache(),
&truetype.GlyphBuf{},
92,
}
@@ -143,16 +146,15 @@ func NewGraphicContext(width, height int) *GraphicContext {
}
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
}
func (gc *GraphicContext) drawGlyph(glyph truetype.Index, dx, dy float64) error {
@@ -217,7 +219,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.Fetch(gc, fontName, r)
x += glyph.Fill(gc, x, y)
prev, hasPrev = index, true
}
@@ -283,7 +285,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.Fetch(gc, fontName, r)
x += glyph.Stroke(gc, x, y)
prev, hasPrev = index, true
}
diff --git a/vendor/github.com/llgcode/draw2d/draw2dimg/curve_limit_test.go b/vendor/github.com/llgcode/draw2d/draw2dimg/curve_limit_test.go
new file mode 100644
index 0000000..26ecdb0
--- /dev/null
+++ b/vendor/github.com/llgcode/draw2d/draw2dimg/curve_limit_test.go
@@ -0,0 +1,189 @@
+package draw2dimg
+
+import (
+ "fmt"
+ "github.com/golang/freetype/truetype"
+ "github.com/llgcode/draw2d"
+ "github.com/llgcode/draw2d/draw2dkit"
+ "golang.org/x/image/font/gofont/goregular"
+ "image"
+ "image/color"
+ "testing"
+)
+
+// font generated from icomoon.io and converted to go byte slice
+// contains only two glyphs
+// \u2716 - which should look like a cross
+// \u25cb - which should look like an empty circle
+var icoTTF = []byte{
+ 0, 1, 0, 0, 0, 12, 0, 128, 0, 3, 0, 64, 71, 83, 85, 66, 219, 7, 221, 185,
+ 0, 0, 0, 204, 0, 0, 0, 188, 79, 83, 47, 50, 175, 17, 51, 150, 0, 0, 1, 136,
+ 0, 0, 0, 96, 99, 109, 97, 112, 37, 204, 43, 67, 0, 0, 1, 232, 0, 0, 0, 148,
+ 103, 97, 115, 112, 0, 0, 0, 16, 0, 0, 2, 124, 0, 0, 0, 8, 103, 108, 121, 102,
+ 163, 112, 233, 32, 0, 0, 2, 132, 0, 0, 3, 64, 104, 101, 97, 100, 15, 49, 194, 135,
+ 0, 0, 5, 196, 0, 0, 0, 54, 104, 104, 101, 97, 7, 194, 3, 217, 0, 0, 5, 252,
+ 0, 0, 0, 36, 104, 109, 116, 120, 14, 0, 0, 2, 0, 0, 6, 32, 0, 0, 0, 96,
+ 108, 111, 99, 97, 6, 168, 5, 226, 0, 0, 6, 128, 0, 0, 0, 50, 109, 97, 120, 112,
+ 0, 27, 0, 86, 0, 0, 6, 180, 0, 0, 0, 32, 110, 97, 109, 101, 108, 36, 213, 69,
+ 0, 0, 6, 212, 0, 0, 1, 170, 112, 111, 115, 116, 0, 3, 0, 0, 0, 0, 8, 128,
+ 0, 0, 0, 32, 0, 1, 0, 0, 0, 10, 0, 30, 0, 44, 0, 1, 108, 97, 116, 110,
+ 0, 8, 0, 4, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 108, 105, 103, 97,
+ 0, 8, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 0, 4, 0, 0, 0, 1, 0, 10,
+ 0, 0, 0, 1, 0, 12, 0, 3, 0, 22, 0, 54, 0, 120, 0, 1, 0, 3, 0, 8,
+ 0, 17, 0, 23, 0, 2, 0, 6, 0, 18, 0, 22, 0, 5, 0, 17, 0, 16, 0, 18,
+ 0, 18, 0, 22, 0, 6, 0, 6, 0, 15, 0, 8, 0, 10, 0, 14, 0, 2, 0, 6,
+ 0, 38, 0, 21, 0, 15, 0, 6, 0, 9, 0, 12, 0, 16, 0, 4, 0, 20, 0, 15,
+ 0, 8, 0, 11, 0, 10, 0, 8, 0, 13, 0, 10, 0, 9, 0, 21, 0, 13, 0, 6,
+ 0, 9, 0, 12, 0, 16, 0, 4, 0, 7, 0, 20, 0, 19, 0, 19, 0, 16, 0, 15,
+ 0, 5, 0, 1, 0, 4, 0, 22, 0, 2, 0, 23, 0, 3, 3, 85, 1, 144, 0, 5,
+ 0, 0, 2, 153, 2, 204, 0, 0, 0, 143, 2, 153, 2, 204, 0, 0, 1, 235, 0, 51,
+ 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 39, 23,
+ 3, 192, 255, 192, 0, 64, 3, 192, 0, 64, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 28,
+ 0, 1, 0, 3, 0, 0, 0, 28, 0, 3, 0, 1, 0, 0, 0, 28, 0, 4, 0, 120,
+ 0, 0, 0, 26, 0, 16, 0, 3, 0, 10, 0, 1, 0, 32, 0, 45, 0, 51, 0, 101,
+ 0, 105, 0, 108, 0, 111, 0, 117, 37, 203, 39, 23, 255, 253, 255, 255, 0, 0, 0, 0,
+ 0, 32, 0, 45, 0, 51, 0, 97, 0, 104, 0, 107, 0, 110, 0, 114, 37, 203, 39, 22,
+ 255, 253, 255, 255, 0, 1, 255, 227, 255, 215, 255, 210, 255, 165, 255, 163, 255, 162, 255, 161,
+ 255, 159, 218, 74, 217, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
+ 255, 255, 0, 15, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57,
+ 1, 0, 0, 0, 0, 2, 0, 0, 255, 192, 4, 0, 3, 192, 0, 27, 0, 55, 0, 0,
+ 1, 34, 7, 14, 1, 7, 6, 21, 20, 23, 30, 1, 23, 22, 51, 50, 55, 62, 1, 55,
+ 54, 53, 52, 39, 46, 1, 39, 38, 3, 34, 39, 46, 1, 39, 38, 53, 52, 55, 62, 1,
+ 55, 54, 51, 50, 23, 30, 1, 23, 22, 21, 20, 7, 14, 1, 7, 6, 2, 0, 106, 93,
+ 94, 139, 40, 40, 40, 40, 139, 94, 93, 106, 106, 93, 94, 139, 40, 40, 40, 40, 139, 94,
+ 93, 106, 80, 69, 70, 105, 30, 30, 30, 30, 105, 70, 69, 80, 80, 69, 70, 105, 30, 30,
+ 30, 30, 105, 70, 69, 3, 192, 40, 40, 139, 94, 93, 106, 106, 93, 94, 139, 40, 40, 40,
+ 40, 139, 94, 93, 106, 106, 93, 94, 139, 40, 40, 252, 128, 30, 30, 105, 70, 69, 80, 80,
+ 69, 70, 105, 30, 30, 30, 30, 105, 70, 69, 80, 80, 69, 70, 105, 30, 30, 0, 0, 0,
+ 0, 1, 0, 2, 255, 194, 3, 254, 3, 190, 0, 83, 0, 0, 37, 56, 1, 49, 9, 1,
+ 56, 1, 49, 62, 1, 55, 54, 38, 47, 1, 46, 1, 7, 14, 1, 7, 56, 1, 49, 9,
+ 1, 56, 1, 49, 46, 1, 39, 38, 6, 15, 1, 14, 1, 23, 30, 1, 23, 56, 1, 49,
+ 9, 1, 56, 1, 49, 14, 1, 7, 6, 22, 31, 1, 30, 1, 55, 62, 1, 55, 56, 1,
+ 49, 9, 1, 56, 1, 49, 30, 1, 23, 22, 54, 63, 1, 62, 1, 39, 46, 1, 3, 247,
+ 254, 201, 1, 55, 2, 4, 1, 3, 3, 7, 147, 7, 18, 9, 3, 6, 2, 254, 201, 254,
+ 201, 2, 6, 3, 9, 18, 7, 147, 7, 3, 3, 1, 4, 2, 1, 55, 254, 201, 2, 4,
+ 1, 3, 3, 7, 147, 7, 18, 9, 3, 6, 2, 1, 55, 1, 55, 2, 6, 3, 9, 18,
+ 7, 147, 7, 3, 3, 1, 4, 137, 1, 55, 1, 55, 2, 6, 3, 9, 18, 7, 147, 7,
+ 3, 3, 1, 4, 2, 254, 201, 1, 55, 2, 4, 1, 3, 3, 7, 147, 7, 18, 9, 3,
+ 6, 2, 254, 201, 254, 201, 2, 6, 3, 9, 18, 7, 147, 7, 3, 3, 1, 4, 2, 1,
+ 55, 254, 201, 2, 4, 1, 3, 3, 7, 147, 7, 18, 9, 3, 6, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 55, 57, 1, 0, 0, 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 32, 120, 21, 165, 95, 15, 60, 245, 0, 11, 4, 0, 0, 0, 0, 0,
+ 214, 9, 63, 5, 0, 0, 0, 0, 214, 9, 63, 5, 0, 0, 255, 192, 4, 0, 3, 192,
+ 0, 0, 0, 8, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 3, 192, 255, 192,
+ 0, 0, 4, 0, 0, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 20, 0, 30, 0, 40, 0, 50, 0, 60,
+ 0, 70, 0, 80, 0, 90, 0, 100, 0, 110, 0, 120, 0, 130, 0, 140, 0, 150, 0, 160,
+ 0, 170, 0, 180, 0, 190, 0, 200, 1, 32, 1, 150, 1, 160, 0, 0, 0, 1, 0, 0,
+ 0, 24, 0, 84, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 174, 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 7, 0, 123, 0, 1,
+ 0, 0, 0, 0, 0, 3, 0, 10, 0, 63, 0, 1, 0, 0, 0, 0, 0, 4, 0, 10,
+ 0, 144, 0, 1, 0, 0, 0, 0, 0, 5, 0, 11, 0, 30, 0, 1, 0, 0, 0, 0,
+ 0, 6, 0, 10, 0, 93, 0, 1, 0, 0, 0, 0, 0, 10, 0, 26, 0, 174, 0, 3,
+ 0, 1, 4, 9, 0, 1, 0, 20, 0, 10, 0, 3, 0, 1, 4, 9, 0, 2, 0, 14,
+ 0, 130, 0, 3, 0, 1, 4, 9, 0, 3, 0, 20, 0, 73, 0, 3, 0, 1, 4, 9,
+ 0, 4, 0, 20, 0, 154, 0, 3, 0, 1, 4, 9, 0, 5, 0, 22, 0, 41, 0, 3,
+ 0, 1, 4, 9, 0, 6, 0, 20, 0, 103, 0, 3, 0, 1, 4, 9, 0, 10, 0, 52,
+ 0, 200, 105, 99, 111, 45, 112, 101, 110, 101, 103, 111, 0, 105, 0, 99, 0, 111, 0, 45,
+ 0, 112, 0, 101, 0, 110, 0, 101, 0, 103, 0, 111, 86, 101, 114, 115, 105, 111, 110, 32,
+ 49, 46, 48, 0, 86, 0, 101, 0, 114, 0, 115, 0, 105, 0, 111, 0, 110, 0, 32, 0,
+ 49, 0, 46, 0, 48, 105, 99, 111, 45, 112, 101, 110, 101, 103, 111, 0, 105, 0, 99, 0,
+ 111, 0, 45, 0, 112, 0, 101, 0, 110, 0, 101, 0, 103, 0, 111, 105, 99, 111, 45, 112,
+ 101, 110, 101, 103, 111, 0, 105, 0, 99, 0, 111, 0, 45, 0, 112, 0, 101, 0, 110, 0,
+ 101, 0, 103, 0, 111, 82, 101, 103, 117, 108, 97, 114, 0, 82, 0, 101, 0, 103, 0, 117,
+ 0, 108, 0, 97, 0, 114, 105, 99, 111, 45, 112, 101, 110, 101, 103, 111, 0, 105, 0, 99,
+ 0, 111, 0, 45, 0, 112, 0, 101, 0, 110, 0, 101, 0, 103, 0, 111, 70, 111, 110, 116,
+ 32, 103, 101, 110, 101, 114, 97, 116, 101, 100, 32, 98, 121, 32, 73, 99, 111, 77, 111, 111,
+ 110, 46, 0, 70, 0, 111, 0, 110, 0, 116, 0, 32, 0, 103, 0, 101, 0, 110, 0, 101,
+ 0, 114, 0, 97, 0, 116, 0, 101, 0, 100, 0, 32, 0, 98, 0, 121, 0, 32, 0, 73,
+ 0, 99, 0, 111, 0, 77, 0, 111, 0, 111, 0, 110, 0, 46, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+}
+
+type customFontCache map[string]*truetype.Font
+
+func (fc customFontCache) Store(fd draw2d.FontData, font *truetype.Font) {
+ fc[fd.Name] = font
+}
+
+func (fc customFontCache) Load(fd draw2d.FontData) (*truetype.Font, error) {
+ font, stored := fc[fd.Name]
+ if !stored {
+ return nil, fmt.Errorf("font %s is not stored in font cache", fd.Name)
+ }
+ return font, nil
+}
+
+func initFontCache() { // init font cache
+ fontCache := customFontCache{}
+ // add gofont to cache
+ gofont, err := truetype.Parse(goregular.TTF)
+ if err != nil {
+ panic(err)
+ }
+ fontCache.Store(draw2d.FontData{Name: "goregular"}, gofont)
+ // add icofont to cache
+ icofont, err := truetype.Parse(icoTTF)
+ if err != nil {
+ panic(err)
+ }
+ fontCache.Store(draw2d.FontData{Name: "ico"}, icofont)
+
+ draw2d.SetFontCache(fontCache)
+}
+
+func TestCurveIndexOutOfRange(t *testing.T) {
+
+ initFontCache()
+
+ // Initialize the graphic context on an RGBA image
+ dest := image.NewRGBA(image.Rect(0, 0, 512, 512))
+ gc := NewGraphicContext(dest)
+
+ // background
+ gc.SetFillColor(color.RGBA{0xef, 0xef, 0xef, 0xff})
+ draw2dkit.Rectangle(gc, 0, 0, 512, 512)
+ gc.Fill()
+
+ // text
+ gc.SetFontSize(20)
+ gc.SetFillColor(color.RGBA{0x10, 0x10, 0x10, 0xff})
+ gc.SetFontData(draw2d.FontData{Name: "goregular"})
+
+ // gc.FillStringAt("Hello", 128, 120) // this works well
+
+ gc.SetFontData(draw2d.FontData{Name: "ico"})
+ gc.FillStringAt("\u25cb", 128, 150) // this also works
+ gc.FillStringAt("\u2716", 128, 170) // Works now
+
+ SaveToPngFile("_test_hello.png", dest)
+}
diff --git a/vendor/github.com/llgcode/draw2d/draw2dimg/ftgc.go b/vendor/github.com/llgcode/draw2d/draw2dimg/ftgc.go
index abaf7e5..c07e1da 100644
--- a/vendor/github.com/llgcode/draw2d/draw2dimg/ftgc.go
+++ b/vendor/github.com/llgcode/draw2d/draw2dimg/ftgc.go
@@ -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.Fetch(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.Fetch(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.
diff --git a/vendor/github.com/llgcode/draw2d/font.go b/vendor/github.com/llgcode/draw2d/font.go
index cd0ec1b..90ef9a1 100644
--- a/vendor/github.com/llgcode/draw2d/font.go
+++ b/vendor/github.com/llgcode/draw2d/font.go
@@ -8,6 +8,7 @@ import (
"log"
"path/filepath"
+ "sync"
"github.com/golang/freetype/truetype"
)
@@ -80,11 +81,15 @@ func GetFontFolder() string {
}
func SetFontFolder(folder string) {
- defaultFonts.folder = filepath.Clean(folder)
+ defaultFonts.setFolder(filepath.Clean(folder))
+}
+
+func GetGlobalFontCache() FontCache {
+ return fontCache
}
func SetFontNamer(fn FontFileNamer) {
- defaultFonts.namer = fn
+ defaultFonts.setNamer(fn)
}
// Types implementing this interface can be passed to SetFontCache to change the
@@ -113,13 +118,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 +155,77 @@ 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{
+// 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: "../resource/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 = NewSyncFolderFontCache("../resource/font")
fontCache FontCache = defaultFonts
)
diff --git a/vendor/github.com/llgcode/draw2d/output/samples/geometry.png b/vendor/github.com/llgcode/draw2d/output/samples/geometry.png
index a2c966e..b68bb32 100644
--- a/vendor/github.com/llgcode/draw2d/output/samples/geometry.png
+++ b/vendor/github.com/llgcode/draw2d/output/samples/geometry.png
Binary files differ
diff --git a/vendor/github.com/llgcode/draw2d/output/samples/postscript.png b/vendor/github.com/llgcode/draw2d/output/samples/postscript.png
index 53e1a63..05e1107 100644
--- a/vendor/github.com/llgcode/draw2d/output/samples/postscript.png
+++ b/vendor/github.com/llgcode/draw2d/output/samples/postscript.png
Binary files differ
diff --git a/vendor/github.com/llgcode/draw2d/sync_test.go b/vendor/github.com/llgcode/draw2d/sync_test.go
new file mode 100644
index 0000000..6c5afd8
--- /dev/null
+++ b/vendor/github.com/llgcode/draw2d/sync_test.go
@@ -0,0 +1,46 @@
+// go test -race -test.v sync_test.go
+
+package draw2d_test
+
+
+import (
+ "fmt"
+ "github.com/llgcode/draw2d"
+ "github.com/llgcode/draw2d/draw2dimg"
+ "github.com/llgcode/draw2d/draw2dkit"
+ "image"
+ "testing"
+)
+
+func TestSync(t *testing.T) {
+ ch := make(chan int)
+ limit := 2
+ for i := 0; i < limit; i++ {
+ go Draw(i, ch)
+ }
+
+ for i := 0; i < limit; i++ {
+ counter := <-ch
+ t.Logf("Goroutine %d returned\n", counter)
+ }
+}
+
+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)
+
+ draw2dkit.RoundedRectangle(gc, 5, 5, 135, 95, 10, 10)
+ gc.FillStroke()
+
+ // Set the fill text color to black
+ gc.SetFillColor(image.Black)
+ gc.SetFontSize(14)
+
+ // Display Hello World dimensions
+ x1, y1, x2, y2 := gc.GetStringBounds("Hello world")
+ gc.FillStringAt(fmt.Sprintf("%.2f %.2f %.2f %.2f", x1, y1, x2, y2), 0, 0)
+
+ ch <- i
+}