From 500caaeda74dd9c660279036293f4b2997cf0b03 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sat, 9 Sep 2017 09:42:37 +0200 Subject: Add vendor --- .../github.com/llgcode/draw2d/draw2dbase/README.md | 7 + .../github.com/llgcode/draw2d/draw2dbase/curve.go | 161 ++++++++++++++++ .../llgcode/draw2d/draw2dbase/curve_test.go | 134 ++++++++++++++ .../github.com/llgcode/draw2d/draw2dbase/dasher.go | 89 +++++++++ .../llgcode/draw2d/draw2dbase/demux_flattener.go | 35 ++++ .../llgcode/draw2d/draw2dbase/flattener.go | 127 +++++++++++++ .../github.com/llgcode/draw2d/draw2dbase/line.go | 58 ++++++ .../llgcode/draw2d/draw2dbase/stack_gc.go | 203 +++++++++++++++++++++ .../llgcode/draw2d/draw2dbase/stroker.go | 90 +++++++++ .../github.com/llgcode/draw2d/draw2dbase/text.go | 68 +++++++ 10 files changed, 972 insertions(+) create mode 100644 vendor/github.com/llgcode/draw2d/draw2dbase/README.md create mode 100644 vendor/github.com/llgcode/draw2d/draw2dbase/curve.go create mode 100644 vendor/github.com/llgcode/draw2d/draw2dbase/curve_test.go create mode 100644 vendor/github.com/llgcode/draw2d/draw2dbase/dasher.go create mode 100644 vendor/github.com/llgcode/draw2d/draw2dbase/demux_flattener.go create mode 100644 vendor/github.com/llgcode/draw2d/draw2dbase/flattener.go create mode 100644 vendor/github.com/llgcode/draw2d/draw2dbase/line.go create mode 100644 vendor/github.com/llgcode/draw2d/draw2dbase/stack_gc.go create mode 100644 vendor/github.com/llgcode/draw2d/draw2dbase/stroker.go create mode 100644 vendor/github.com/llgcode/draw2d/draw2dbase/text.go (limited to 'vendor/github.com/llgcode/draw2d/draw2dbase') diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/README.md b/vendor/github.com/llgcode/draw2d/draw2dbase/README.md new file mode 100644 index 0000000..3296f5e --- /dev/null +++ b/vendor/github.com/llgcode/draw2d/draw2dbase/README.md @@ -0,0 +1,7 @@ +draw2d/draw2dbase +================= + +[![Coverage](http://gocover.io/_badge/github.com/llgcode/draw2d/draw2dbase?0)](http://gocover.io/github.com/llgcode/draw2d/draw2dbase) +[![GoDoc](https://godoc.org/github.com/llgcode/draw2d/draw2dbase?status.svg)](https://godoc.org/github.com/llgcode/draw2d/draw2dbase) + +Base package implementation that is used by pdf, svg, img, gl implementations. diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/curve.go b/vendor/github.com/llgcode/draw2d/draw2dbase/curve.go new file mode 100644 index 0000000..211e107 --- /dev/null +++ b/vendor/github.com/llgcode/draw2d/draw2dbase/curve.go @@ -0,0 +1,161 @@ +// Copyright 2010 The draw2d Authors. All rights reserved. +// created: 17/05/2011 by Laurent Le Goff + +package draw2dbase + +import ( + "math" +) + +const ( + // CurveRecursionLimit represents the maximum recursion that is really necessary to subsivide a curve into straight lines + CurveRecursionLimit = 32 +) + +// Cubic +// x1, y1, cpx1, cpy1, cpx2, cpy2, x2, y2 float64 + +// SubdivideCubic a Bezier cubic curve in 2 equivalents Bezier cubic curves. +// c1 and c2 parameters are the resulting curves +func SubdivideCubic(c, c1, c2 []float64) { + // First point of c is the first point of c1 + c1[0], c1[1] = c[0], c[1] + // Last point of c is the last point of c2 + c2[6], c2[7] = c[6], c[7] + + // Subdivide segment using midpoints + c1[2] = (c[0] + c[2]) / 2 + c1[3] = (c[1] + c[3]) / 2 + + midX := (c[2] + c[4]) / 2 + midY := (c[3] + c[5]) / 2 + + c2[4] = (c[4] + c[6]) / 2 + c2[5] = (c[5] + c[7]) / 2 + + c1[4] = (c1[2] + midX) / 2 + c1[5] = (c1[3] + midY) / 2 + + c2[2] = (midX + c2[4]) / 2 + c2[3] = (midY + c2[5]) / 2 + + c1[6] = (c1[4] + c2[2]) / 2 + c1[7] = (c1[5] + c2[3]) / 2 + + // Last Point of c1 is equal to the first point of c2 + c2[0], c2[1] = c1[6], c1[7] +} + +// 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) { + // Allocation curves + var curves [CurveRecursionLimit * 8]float64 + copy(curves[0:8], cubic[0:8]) + i := 0 + + // current curve + var c []float64 + + var dx, dy, d2, d3 float64 + + for i >= 0 { + c = curves[i*8:] + dx = c[6] - c[0] + dy = c[7] - c[1] + + d2 = math.Abs((c[2]-c[6])*dy - (c[3]-c[7])*dx) + 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 { + t.LineTo(c[6], c[7]) + i-- + } else { + // second half of bezier go lower onto the stack + SubdivideCubic(c, curves[(i+1)*8:], curves[i*8:]) + i++ + } + } +} + +// Quad +// x1, y1, cpx1, cpy2, x2, y2 float64 + +// SubdivideQuad a Bezier quad curve in 2 equivalents Bezier quad curves. +// c1 and c2 parameters are the resulting curves +func SubdivideQuad(c, c1, c2 []float64) { + // First point of c is the first point of c1 + c1[0], c1[1] = c[0], c[1] + // Last point of c is the last point of c2 + c2[4], c2[5] = c[4], c[5] + + // Subdivide segment using midpoints + c1[2] = (c[0] + c[2]) / 2 + c1[3] = (c[1] + c[3]) / 2 + c2[2] = (c[2] + c[4]) / 2 + c2[3] = (c[3] + c[5]) / 2 + c1[4] = (c1[2] + c2[2]) / 2 + c1[5] = (c1[3] + c2[3]) / 2 + c2[0], c2[1] = c1[4], c1[5] + return +} + +// 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) { + // Allocates curves stack + var curves [CurveRecursionLimit * 6]float64 + copy(curves[0:6], quad[0:6]) + i := 0 + // current curve + var c []float64 + var dx, dy, d float64 + + for i >= 0 { + c = curves[i*6:] + 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 { + t.LineTo(c[4], c[5]) + i-- + } else { + // second half of bezier go lower onto the stack + SubdivideQuad(c, curves[(i+1)*6:], curves[i*6:]) + i++ + } + } +} + +// TraceArc trace an arc using a Liner +func TraceArc(t Liner, x, y, rx, ry, start, angle, scale float64) (lastX, lastY float64) { + end := start + angle + clockWise := true + if angle < 0 { + clockWise = false + } + ra := (math.Abs(rx) + math.Abs(ry)) / 2 + da := math.Acos(ra/(ra+0.125/scale)) * 2 + //normalize + if !clockWise { + da = -da + } + angle = start + da + var curX, curY float64 + for { + if (angle < end-da/4) != clockWise { + curX = x + math.Cos(end)*rx + curY = y + math.Sin(end)*ry + return curX, curY + } + curX = x + math.Cos(angle)*rx + curY = y + math.Sin(angle)*ry + + angle += da + t.LineTo(curX, curY) + } +} diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/curve_test.go b/vendor/github.com/llgcode/draw2d/draw2dbase/curve_test.go new file mode 100644 index 0000000..fa954df --- /dev/null +++ b/vendor/github.com/llgcode/draw2d/draw2dbase/curve_test.go @@ -0,0 +1,134 @@ +package draw2dbase + +import ( + "bufio" + "fmt" + "image" + "image/color" + "image/draw" + "image/png" + "log" + "os" + "testing" +) + +var ( + flatteningThreshold = 0.5 + testsCubicFloat64 = []float64{ + 100, 100, 200, 100, 100, 200, 200, 200, + 100, 100, 300, 200, 200, 200, 300, 100, + 100, 100, 0, 300, 200, 0, 300, 300, + 150, 290, 10, 10, 290, 10, 150, 290, + 10, 290, 10, 10, 290, 10, 290, 290, + 100, 290, 290, 10, 10, 10, 200, 290, + } + testsQuadFloat64 = []float64{ + 100, 100, 200, 100, 200, 200, + 100, 100, 290, 200, 290, 100, + 100, 100, 0, 290, 200, 290, + 150, 290, 10, 10, 290, 290, + 10, 290, 10, 10, 290, 290, + 100, 290, 290, 10, 120, 290, + } +) + +func init() { + os.Mkdir("test_results", 0666) + f, err := os.Create("../output/curve/_test.html") + if err != nil { + log.Println(err) + os.Exit(1) + } + defer f.Close() + log.Printf("Create html viewer") + f.Write([]byte("")) + for i := 0; i < len(testsCubicFloat64)/8; i++ { + f.Write([]byte(fmt.Sprintf("
\n", i))) + } + for i := 0; i < len(testsQuadFloat64); i++ { + f.Write([]byte(fmt.Sprintf("
\n
\n", i))) + } + f.Write([]byte("")) + +} + +func drawPoints(img draw.Image, c color.Color, s ...float64) image.Image { + for i := 0; i < len(s); i += 2 { + x, y := int(s[i]+0.5), int(s[i+1]+0.5) + img.Set(x, y, c) + img.Set(x, y+1, c) + img.Set(x, y-1, c) + img.Set(x+1, y, c) + img.Set(x+1, y+1, c) + img.Set(x+1, y-1, c) + img.Set(x-1, y, c) + img.Set(x-1, y+1, c) + img.Set(x-1, y-1, c) + + } + return img +} + +func TestCubicCurve(t *testing.T) { + for i := 0; i < len(testsCubicFloat64); i += 8 { + var p SegmentedPath + p.MoveTo(testsCubicFloat64[i], testsCubicFloat64[i+1]) + TraceCubic(&p, testsCubicFloat64[i:], flatteningThreshold) + img := image.NewNRGBA(image.Rect(0, 0, 300, 300)) + PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, testsCubicFloat64[i:i+8]...) + PolylineBresenham(img, image.Black, p.Points...) + //drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...) + drawPoints(img, color.NRGBA{0, 0, 0, 0xff}, p.Points...) + SaveToPngFile(fmt.Sprintf("../output/curve/_test%d.png", i/8), img) + log.Printf("Num of points: %d\n", len(p.Points)) + } + fmt.Println() +} + +func TestQuadCurve(t *testing.T) { + for i := 0; i < len(testsQuadFloat64); i += 6 { + var p SegmentedPath + p.MoveTo(testsQuadFloat64[i], testsQuadFloat64[i+1]) + TraceQuad(&p, testsQuadFloat64[i:], flatteningThreshold) + img := image.NewNRGBA(image.Rect(0, 0, 300, 300)) + PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, testsQuadFloat64[i:i+6]...) + PolylineBresenham(img, image.Black, p.Points...) + //drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...) + drawPoints(img, color.NRGBA{0, 0, 0, 0xff}, p.Points...) + SaveToPngFile(fmt.Sprintf("../output/curve/_testQuad%d.png", i), img) + log.Printf("Num of points: %d\n", len(p.Points)) + } + fmt.Println() +} + +func BenchmarkCubicCurve(b *testing.B) { + for i := 0; i < b.N; i++ { + for i := 0; i < len(testsCubicFloat64); i += 8 { + var p SegmentedPath + p.MoveTo(testsCubicFloat64[i], testsCubicFloat64[i+1]) + TraceCubic(&p, testsCubicFloat64[i:], flatteningThreshold) + } + } +} + +// SaveToPngFile create and save an image to a file using PNG format +func SaveToPngFile(filePath string, m image.Image) error { + // Create the file + f, err := os.Create(filePath) + if err != nil { + return err + } + defer f.Close() + // Create Writer from file + b := bufio.NewWriter(f) + // Write the image into the buffer + err = png.Encode(b, m) + if err != nil { + return err + } + err = b.Flush() + if err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/dasher.go b/vendor/github.com/llgcode/draw2d/draw2dbase/dasher.go new file mode 100644 index 0000000..6f8260c --- /dev/null +++ b/vendor/github.com/llgcode/draw2d/draw2dbase/dasher.go @@ -0,0 +1,89 @@ +// Copyright 2010 The draw2d Authors. All rights reserved. +// created: 13/12/2010 by Laurent Le Goff + +package draw2dbase + +type DashVertexConverter struct { + next Flattener + x, y, distance float64 + dash []float64 + currentDash int + dashOffset float64 +} + +func NewDashConverter(dash []float64, dashOffset float64, flattener Flattener) *DashVertexConverter { + var dasher DashVertexConverter + dasher.dash = dash + dasher.currentDash = 0 + dasher.dashOffset = dashOffset + dasher.next = flattener + return &dasher +} + +func (dasher *DashVertexConverter) LineTo(x, y float64) { + dasher.lineTo(x, y) +} + +func (dasher *DashVertexConverter) MoveTo(x, y float64) { + dasher.next.MoveTo(x, y) + dasher.x, dasher.y = x, y + dasher.distance = dasher.dashOffset + dasher.currentDash = 0 +} + +func (dasher *DashVertexConverter) LineJoin() { + dasher.next.LineJoin() +} + +func (dasher *DashVertexConverter) Close() { + dasher.next.Close() +} + +func (dasher *DashVertexConverter) End() { + dasher.next.End() +} + +func (dasher *DashVertexConverter) lineTo(x, y float64) { + rest := dasher.dash[dasher.currentDash] - dasher.distance + for rest < 0 { + dasher.distance = dasher.distance - dasher.dash[dasher.currentDash] + dasher.currentDash = (dasher.currentDash + 1) % len(dasher.dash) + rest = dasher.dash[dasher.currentDash] - dasher.distance + } + d := distance(dasher.x, dasher.y, x, y) + for d >= rest { + k := rest / d + lx := dasher.x + k*(x-dasher.x) + ly := dasher.y + k*(y-dasher.y) + if dasher.currentDash%2 == 0 { + // line + dasher.next.LineTo(lx, ly) + } else { + // gap + dasher.next.End() + dasher.next.MoveTo(lx, ly) + } + d = d - rest + dasher.x, dasher.y = lx, ly + dasher.currentDash = (dasher.currentDash + 1) % len(dasher.dash) + rest = dasher.dash[dasher.currentDash] + } + dasher.distance = d + if dasher.currentDash%2 == 0 { + // line + dasher.next.LineTo(x, y) + } else { + // gap + dasher.next.End() + dasher.next.MoveTo(x, y) + } + if dasher.distance >= dasher.dash[dasher.currentDash] { + dasher.distance = dasher.distance - dasher.dash[dasher.currentDash] + dasher.currentDash = (dasher.currentDash + 1) % len(dasher.dash) + } + dasher.x, dasher.y = x, y +} + +func distance(x1, y1, x2, y2 float64) float64 { + return vectorDistance(x2-x1, y2-y1) +} diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/demux_flattener.go b/vendor/github.com/llgcode/draw2d/draw2dbase/demux_flattener.go new file mode 100644 index 0000000..13b6c40 --- /dev/null +++ b/vendor/github.com/llgcode/draw2d/draw2dbase/demux_flattener.go @@ -0,0 +1,35 @@ +package draw2dbase + +type DemuxFlattener struct { + Flatteners []Flattener +} + +func (dc DemuxFlattener) MoveTo(x, y float64) { + for _, flattener := range dc.Flatteners { + flattener.MoveTo(x, y) + } +} + +func (dc DemuxFlattener) LineTo(x, y float64) { + for _, flattener := range dc.Flatteners { + flattener.LineTo(x, y) + } +} + +func (dc DemuxFlattener) LineJoin() { + for _, flattener := range dc.Flatteners { + flattener.LineJoin() + } +} + +func (dc DemuxFlattener) Close() { + for _, flattener := range dc.Flatteners { + flattener.Close() + } +} + +func (dc DemuxFlattener) End() { + for _, flattener := range dc.Flatteners { + flattener.End() + } +} diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/flattener.go b/vendor/github.com/llgcode/draw2d/draw2dbase/flattener.go new file mode 100644 index 0000000..c62d1bc --- /dev/null +++ b/vendor/github.com/llgcode/draw2d/draw2dbase/flattener.go @@ -0,0 +1,127 @@ +// Copyright 2010 The draw2d Authors. All rights reserved. +// created: 06/12/2010 by Laurent Le Goff + +package draw2dbase + +import ( + "github.com/llgcode/draw2d" +) + +// Liner receive segment definition +type Liner interface { + // LineTo Draw a line from the current position to the point (x, y) + LineTo(x, y float64) +} + +// Flattener receive segment definition +type Flattener interface { + // MoveTo Start a New line from the point (x, y) + MoveTo(x, y float64) + // LineTo Draw a line from the current position to the point (x, y) + LineTo(x, y float64) + // LineJoin use Round, Bevel or miter to join points + LineJoin() + // Close add the most recent starting point to close the path to create a polygon + Close() + // End mark the current line as finished so we can draw caps + End() +} + +// Flatten convert curves into straight segments keeping join segments info +func Flatten(path *draw2d.Path, flattener Flattener, scale float64) { + // First Point + var startX, startY float64 = 0, 0 + // Current Point + var x, y float64 = 0, 0 + i := 0 + for _, cmp := range path.Components { + switch cmp { + case draw2d.MoveToCmp: + x, y = path.Points[i], path.Points[i+1] + startX, startY = x, y + if i != 0 { + flattener.End() + } + flattener.MoveTo(x, y) + i += 2 + case draw2d.LineToCmp: + x, y = path.Points[i], path.Points[i+1] + flattener.LineTo(x, y) + flattener.LineJoin() + i += 2 + case draw2d.QuadCurveToCmp: + TraceQuad(flattener, path.Points[i-2:], 0.5) + x, y = path.Points[i+2], path.Points[i+3] + flattener.LineTo(x, y) + i += 4 + case draw2d.CubicCurveToCmp: + TraceCubic(flattener, path.Points[i-2:], 0.5) + x, y = path.Points[i+4], path.Points[i+5] + flattener.LineTo(x, y) + i += 6 + case draw2d.ArcToCmp: + x, y = TraceArc(flattener, path.Points[i], path.Points[i+1], path.Points[i+2], path.Points[i+3], path.Points[i+4], path.Points[i+5], scale) + flattener.LineTo(x, y) + i += 6 + case draw2d.CloseCmp: + flattener.LineTo(startX, startY) + flattener.Close() + } + } + flattener.End() +} + +// Transformer apply the Matrix transformation tr +type Transformer struct { + Tr draw2d.Matrix + Flattener Flattener +} + +func (t Transformer) MoveTo(x, y float64) { + u := x*t.Tr[0] + y*t.Tr[2] + t.Tr[4] + v := x*t.Tr[1] + y*t.Tr[3] + t.Tr[5] + t.Flattener.MoveTo(u, v) +} + +func (t Transformer) LineTo(x, y float64) { + u := x*t.Tr[0] + y*t.Tr[2] + t.Tr[4] + v := x*t.Tr[1] + y*t.Tr[3] + t.Tr[5] + t.Flattener.LineTo(u, v) +} + +func (t Transformer) LineJoin() { + t.Flattener.LineJoin() +} + +func (t Transformer) Close() { + t.Flattener.Close() +} + +func (t Transformer) End() { + t.Flattener.End() +} + +type SegmentedPath struct { + Points []float64 +} + +func (p *SegmentedPath) MoveTo(x, y float64) { + p.Points = append(p.Points, x, y) + // TODO need to mark this point as moveto +} + +func (p *SegmentedPath) LineTo(x, y float64) { + p.Points = append(p.Points, x, y) +} + +func (p *SegmentedPath) LineJoin() { + // TODO need to mark the current point as linejoin +} + +func (p *SegmentedPath) Close() { + // TODO Close +} + +func (p *SegmentedPath) End() { + // Nothing to do +} diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/line.go b/vendor/github.com/llgcode/draw2d/draw2dbase/line.go new file mode 100644 index 0000000..a83bbc3 --- /dev/null +++ b/vendor/github.com/llgcode/draw2d/draw2dbase/line.go @@ -0,0 +1,58 @@ +// Copyright 2011 The draw2d Authors. All rights reserved. +// created: 27/05/2011 by Laurent Le Goff + +package draw2dbase + +import ( + "image/color" + "image/draw" +) + +func abs(i int) int { + if i < 0 { + return -i + } + return i +} + +// PolylineBresenham draws a polyline to an image +func PolylineBresenham(img draw.Image, c color.Color, s ...float64) { + for i := 2; i < len(s); i += 2 { + Bresenham(img, c, int(s[i-2]+0.5), int(s[i-1]+0.5), int(s[i]+0.5), int(s[i+1]+0.5)) + } +} + +// Bresenham draws a line between (x0, y0) and (x1, y1) +func Bresenham(img draw.Image, color color.Color, x0, y0, x1, y1 int) { + dx := abs(x1 - x0) + dy := abs(y1 - y0) + var sx, sy int + if x0 < x1 { + sx = 1 + } else { + sx = -1 + } + if y0 < y1 { + sy = 1 + } else { + sy = -1 + } + err := dx - dy + + var e2 int + for { + img.Set(x0, y0, color) + if x0 == x1 && y0 == y1 { + return + } + e2 = 2 * err + if e2 > -dy { + err = err - dy + x0 = x0 + sx + } + if e2 < dx { + err = err + dx + y0 = y0 + sy + } + } +} diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/stack_gc.go b/vendor/github.com/llgcode/draw2d/draw2dbase/stack_gc.go new file mode 100644 index 0000000..77622bb --- /dev/null +++ b/vendor/github.com/llgcode/draw2d/draw2dbase/stack_gc.go @@ -0,0 +1,203 @@ +// Copyright 2010 The draw2d Authors. All rights reserved. +// created: 21/11/2010 by Laurent Le Goff + +package draw2dbase + +import ( + "fmt" + "image" + "image/color" + + "github.com/llgcode/draw2d" + + "github.com/golang/freetype/truetype" +) + +var DefaultFontData = draw2d.FontData{Name: "luxi", Family: draw2d.FontFamilySans, Style: draw2d.FontStyleNormal} + +type StackGraphicContext struct { + Current *ContextStack +} + +type ContextStack struct { + Tr draw2d.Matrix + Path *draw2d.Path + LineWidth float64 + Dash []float64 + DashOffset float64 + StrokeColor color.Color + FillColor color.Color + FillRule draw2d.FillRule + Cap draw2d.LineCap + Join draw2d.LineJoin + FontSize float64 + FontData draw2d.FontData + + Font *truetype.Font + // fontSize and dpi are used to calculate scale. scale is the number of + // 26.6 fixed point units in 1 em. + Scale float64 + + Previous *ContextStack +} + +/** + * Create a new Graphic context from an image + */ +func NewStackGraphicContext() *StackGraphicContext { + gc := &StackGraphicContext{} + gc.Current = new(ContextStack) + gc.Current.Tr = draw2d.NewIdentityMatrix() + gc.Current.Path = new(draw2d.Path) + gc.Current.LineWidth = 1.0 + gc.Current.StrokeColor = image.Black + gc.Current.FillColor = image.White + gc.Current.Cap = draw2d.RoundCap + gc.Current.FillRule = draw2d.FillRuleEvenOdd + gc.Current.Join = draw2d.RoundJoin + gc.Current.FontSize = 10 + gc.Current.FontData = DefaultFontData + return gc +} + +func (gc *StackGraphicContext) GetMatrixTransform() draw2d.Matrix { + return gc.Current.Tr +} + +func (gc *StackGraphicContext) SetMatrixTransform(Tr draw2d.Matrix) { + gc.Current.Tr = Tr +} + +func (gc *StackGraphicContext) ComposeMatrixTransform(Tr draw2d.Matrix) { + gc.Current.Tr.Compose(Tr) +} + +func (gc *StackGraphicContext) Rotate(angle float64) { + gc.Current.Tr.Rotate(angle) +} + +func (gc *StackGraphicContext) Translate(tx, ty float64) { + gc.Current.Tr.Translate(tx, ty) +} + +func (gc *StackGraphicContext) Scale(sx, sy float64) { + gc.Current.Tr.Scale(sx, sy) +} + +func (gc *StackGraphicContext) SetStrokeColor(c color.Color) { + gc.Current.StrokeColor = c +} + +func (gc *StackGraphicContext) SetFillColor(c color.Color) { + gc.Current.FillColor = c +} + +func (gc *StackGraphicContext) SetFillRule(f draw2d.FillRule) { + gc.Current.FillRule = f +} + +func (gc *StackGraphicContext) SetLineWidth(lineWidth float64) { + gc.Current.LineWidth = lineWidth +} + +func (gc *StackGraphicContext) SetLineCap(cap draw2d.LineCap) { + gc.Current.Cap = cap +} + +func (gc *StackGraphicContext) SetLineJoin(join draw2d.LineJoin) { + gc.Current.Join = join +} + +func (gc *StackGraphicContext) SetLineDash(dash []float64, dashOffset float64) { + gc.Current.Dash = dash + gc.Current.DashOffset = dashOffset +} + +func (gc *StackGraphicContext) SetFontSize(fontSize float64) { + gc.Current.FontSize = fontSize +} + +func (gc *StackGraphicContext) GetFontSize() float64 { + return gc.Current.FontSize +} + +func (gc *StackGraphicContext) SetFontData(fontData draw2d.FontData) { + gc.Current.FontData = fontData +} + +func (gc *StackGraphicContext) GetFontData() draw2d.FontData { + return gc.Current.FontData +} + +func (gc *StackGraphicContext) BeginPath() { + gc.Current.Path.Clear() +} + +func (gc *StackGraphicContext) GetPath() draw2d.Path { + return *gc.Current.Path.Copy() +} + +func (gc *StackGraphicContext) IsEmpty() bool { + return gc.Current.Path.IsEmpty() +} + +func (gc *StackGraphicContext) LastPoint() (float64, float64) { + return gc.Current.Path.LastPoint() +} + +func (gc *StackGraphicContext) MoveTo(x, y float64) { + gc.Current.Path.MoveTo(x, y) +} + +func (gc *StackGraphicContext) LineTo(x, y float64) { + gc.Current.Path.LineTo(x, y) +} + +func (gc *StackGraphicContext) QuadCurveTo(cx, cy, x, y float64) { + gc.Current.Path.QuadCurveTo(cx, cy, x, y) +} + +func (gc *StackGraphicContext) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) { + gc.Current.Path.CubicCurveTo(cx1, cy1, cx2, cy2, x, y) +} + +func (gc *StackGraphicContext) ArcTo(cx, cy, rx, ry, startAngle, angle float64) { + gc.Current.Path.ArcTo(cx, cy, rx, ry, startAngle, angle) +} + +func (gc *StackGraphicContext) Close() { + gc.Current.Path.Close() +} + +func (gc *StackGraphicContext) Save() { + context := new(ContextStack) + context.FontSize = gc.Current.FontSize + context.FontData = gc.Current.FontData + context.LineWidth = gc.Current.LineWidth + context.StrokeColor = gc.Current.StrokeColor + context.FillColor = gc.Current.FillColor + context.FillRule = gc.Current.FillRule + context.Dash = gc.Current.Dash + context.DashOffset = gc.Current.DashOffset + context.Cap = gc.Current.Cap + context.Join = gc.Current.Join + context.Path = gc.Current.Path.Copy() + context.Font = gc.Current.Font + context.Scale = gc.Current.Scale + copy(context.Tr[:], gc.Current.Tr[:]) + context.Previous = gc.Current + gc.Current = context +} + +func (gc *StackGraphicContext) Restore() { + if gc.Current.Previous != nil { + oldContext := gc.Current + gc.Current = gc.Current.Previous + oldContext.Previous = nil + } +} + +func (gc *StackGraphicContext) GetFontName() string { + fontData := gc.Current.FontData + return fmt.Sprintf("%s:%d:%d:%d", fontData.Name, fontData.Family, fontData.Style, gc.Current.FontSize) +} diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/stroker.go b/vendor/github.com/llgcode/draw2d/draw2dbase/stroker.go new file mode 100644 index 0000000..640b228 --- /dev/null +++ b/vendor/github.com/llgcode/draw2d/draw2dbase/stroker.go @@ -0,0 +1,90 @@ +// Copyright 2010 The draw2d Authors. All rights reserved. +// created: 13/12/2010 by Laurent Le Goff + +package draw2dbase + +import ( + "math" + + "github.com/llgcode/draw2d" +) + +type LineStroker struct { + Flattener Flattener + HalfLineWidth float64 + Cap draw2d.LineCap + Join draw2d.LineJoin + vertices []float64 + rewind []float64 + x, y, nx, ny float64 +} + +func NewLineStroker(c draw2d.LineCap, j draw2d.LineJoin, flattener Flattener) *LineStroker { + l := new(LineStroker) + l.Flattener = flattener + l.HalfLineWidth = 0.5 + l.Cap = c + l.Join = j + return l +} + +func (l *LineStroker) MoveTo(x, y float64) { + l.x, l.y = x, y +} + +func (l *LineStroker) LineTo(x, y float64) { + l.line(l.x, l.y, x, y) +} + +func (l *LineStroker) LineJoin() { + +} + +func (l *LineStroker) line(x1, y1, x2, y2 float64) { + dx := (x2 - x1) + dy := (y2 - y1) + d := vectorDistance(dx, dy) + if d != 0 { + nx := dy * l.HalfLineWidth / d + ny := -(dx * l.HalfLineWidth / d) + l.appendVertex(x1+nx, y1+ny, x2+nx, y2+ny, x1-nx, y1-ny, x2-nx, y2-ny) + l.x, l.y, l.nx, l.ny = x2, y2, nx, ny + } +} + +func (l *LineStroker) Close() { + if len(l.vertices) > 1 { + l.appendVertex(l.vertices[0], l.vertices[1], l.rewind[0], l.rewind[1]) + } +} + +func (l *LineStroker) End() { + if len(l.vertices) > 1 { + l.Flattener.MoveTo(l.vertices[0], l.vertices[1]) + for i, j := 2, 3; j < len(l.vertices); i, j = i+2, j+2 { + l.Flattener.LineTo(l.vertices[i], l.vertices[j]) + } + } + for i, j := len(l.rewind)-2, len(l.rewind)-1; j > 0; i, j = i-2, j-2 { + l.Flattener.LineTo(l.rewind[i], l.rewind[j]) + } + if len(l.vertices) > 1 { + l.Flattener.LineTo(l.vertices[0], l.vertices[1]) + } + l.Flattener.End() + // reinit vertices + l.vertices = l.vertices[0:0] + l.rewind = l.rewind[0:0] + l.x, l.y, l.nx, l.ny = 0, 0, 0, 0 + +} + +func (l *LineStroker) appendVertex(vertices ...float64) { + s := len(vertices) / 2 + l.vertices = append(l.vertices, vertices[:s]...) + l.rewind = append(l.rewind, vertices[s:]...) +} + +func vectorDistance(dx, dy float64) float64 { + return float64(math.Sqrt(dx*dx + dy*dy)) +} diff --git a/vendor/github.com/llgcode/draw2d/draw2dbase/text.go b/vendor/github.com/llgcode/draw2d/draw2dbase/text.go new file mode 100644 index 0000000..4283bad --- /dev/null +++ b/vendor/github.com/llgcode/draw2d/draw2dbase/text.go @@ -0,0 +1,68 @@ +package draw2dbase + +import "github.com/llgcode/draw2d" + +var glyphCache map[string]map[rune]*Glyph + +func init() { + glyphCache = make(map[string]map[rune]*Glyph) +} + +// 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) + } + if glyphCache[fontName][chr] == nil { + glyphCache[fontName][chr] = renderGlyph(gc, fontName, chr) + } + return glyphCache[fontName][chr].Copy() +} + +// renderGlyph renders a glyph then caches and returns it +func renderGlyph(gc draw2d.GraphicContext, fontName string, chr rune) *Glyph { + gc.Save() + defer gc.Restore() + gc.BeginPath() + width := gc.CreateStringPath(string(chr), 0, 0) + path := gc.GetPath() + return &Glyph{ + path: &path, + Width: width, + } +} + +// 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 +} + +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 +} -- cgit v1.2.3