diff --git a/.gitignore b/.gitignore index 5aafa34..3527a30 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,4 @@ _test* **/*.dll **/core*[0-9] .private -output + diff --git a/README.md b/README.md index 958b213..db90f91 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ draw2d ====== -Package draw2d is a pure [go](http://golang.org) 2D vector graphics library with support for multiple output devices such as [images](http://golang.org/pkg/image) (draw2d), pdf documents (draw2dpdf) and opengl (draw2dopengl), which can also be used on the google app engine. It can be used as a pure go [Cairo](http://www.cairographics.org/) alternative. +Package draw2d is a pure [go](http://golang.org) 2D vector graphics library with support for multiple output devices such as [images](http://golang.org/pkg/image) (draw2d), pdf documents (draw2dpdf) and opengl (draw2dopengl), which can also be used on the google app engine. It can be used as a pure go [Cairo](http://www.cairographics.org/) alternative. draw2d is released under the BSD license. See the [documentation](http://godoc.org/github.com/llgcode/draw2d) for more details. Features -------- -Operations in draw2d include stroking and filling polygons, arcs, Bézier curves, drawing images and text rendering with truetype fonts. All drawing operations can be transformed by affine transformations (scale, rotation, translation). draw2d is released under the BSD license. +Operations in draw2d include stroking and filling polygons, arcs, Bézier curves, drawing images and text rendering with truetype fonts. All drawing operations can be transformed by affine transformations (scale, rotation, translation). Package draw2d follows the conventions of the [HTML Canvas 2D Context](http://www.w3.org/TR/2dcontext/) for coordinate system, angles, etc... diff --git a/curve/curve_test.go b/curve/curve_test.go index c101e6a..0978e11 100644 --- a/curve/curve_test.go +++ b/curve/curve_test.go @@ -15,8 +15,8 @@ import ( ) var ( - flattening_threshold float64 = 0.5 - testsCubicFloat64 = []CubicCurveFloat64{ + flatteningThreshold = 0.5 + testsCubicFloat64 = []CubicCurveFloat64{ CubicCurveFloat64{100, 100, 200, 100, 100, 200, 200, 200}, CubicCurveFloat64{100, 100, 300, 200, 200, 200, 300, 100}, CubicCurveFloat64{100, 100, 0, 300, 200, 0, 300, 300}, @@ -51,7 +51,7 @@ func (p *Path) LineTo(x, y float64) { } func init() { - f, err := os.Create("_test.html") + f, err := os.Create("../output/curve/test.html") if err != nil { log.Println(err) os.Exit(1) @@ -60,10 +60,10 @@ func init() { log.Printf("Create html viewer") f.Write([]byte("")) for i := 0; i < len(testsCubicFloat64); i++ { - f.Write([]byte(fmt.Sprintf("
\n\n\n\n\n
\n", i, i, i, i, i))) + f.Write([]byte(fmt.Sprintf("
\n\n\n\n\n
\n", i, i, i, i, i))) } for i := 0; i < len(testsQuadFloat64); i++ { - f.Write([]byte(fmt.Sprintf("
\n
\n", i))) + f.Write([]byte(fmt.Sprintf("
\n
\n", i))) } f.Write([]byte("")) @@ -110,13 +110,13 @@ func TestCubicCurveRec(t *testing.T) { for i, curve := range testsCubicFloat64 { var p Path p.LineTo(curve[0], curve[1]) - curve.SegmentRec(&p, flattening_threshold) + curve.SegmentRec(&p, flatteningThreshold) img := image.NewNRGBA(image.Rect(0, 0, 300, 300)) raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, curve[:]...) raster.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...) - savepng(fmt.Sprintf("_testRec%d.png", i), img) + savepng(fmt.Sprintf("../output/curve/testRec%d.png", i), img) log.Printf("Num of points: %d\n", len(p.points)) } fmt.Println() @@ -126,13 +126,13 @@ func TestCubicCurve(t *testing.T) { for i, curve := range testsCubicFloat64 { var p Path p.LineTo(curve[0], curve[1]) - curve.Segment(&p, flattening_threshold) + curve.Segment(&p, flatteningThreshold) img := image.NewNRGBA(image.Rect(0, 0, 300, 300)) raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, curve[:]...) raster.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...) - savepng(fmt.Sprintf("_test%d.png", i), img) + savepng(fmt.Sprintf("../output/curve/test%d.png", i), img) log.Printf("Num of points: %d\n", len(p.points)) } fmt.Println() @@ -148,7 +148,7 @@ func TestCubicCurveAdaptiveRec(t *testing.T) { raster.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...) - savepng(fmt.Sprintf("_testAdaptiveRec%d.png", i), img) + savepng(fmt.Sprintf("../output/curve/testAdaptiveRec%d.png", i), img) log.Printf("Num of points: %d\n", len(p.points)) } fmt.Println() @@ -164,7 +164,7 @@ func TestCubicCurveAdaptive(t *testing.T) { raster.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...) - savepng(fmt.Sprintf("_testAdaptive%d.png", i), img) + savepng(fmt.Sprintf("../output/curve/testAdaptive%d.png", i), img) log.Printf("Num of points: %d\n", len(p.points)) } fmt.Println() @@ -174,13 +174,13 @@ func TestCubicCurveParabolic(t *testing.T) { for i, curve := range testsCubicFloat64 { var p Path p.LineTo(curve[0], curve[1]) - curve.ParabolicSegment(&p, flattening_threshold) + curve.ParabolicSegment(&p, flatteningThreshold) img := image.NewNRGBA(image.Rect(0, 0, 300, 300)) raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, curve[:]...) raster.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...) - savepng(fmt.Sprintf("_testParabolic%d.png", i), img) + savepng(fmt.Sprintf("../output/curve/testParabolic%d.png", i), img) log.Printf("Num of points: %d\n", len(p.points)) } fmt.Println() @@ -190,13 +190,13 @@ func TestQuadCurve(t *testing.T) { for i, curve := range testsQuadFloat64 { var p Path p.LineTo(curve[0], curve[1]) - curve.Segment(&p, flattening_threshold) + curve.Segment(&p, flatteningThreshold) img := image.NewNRGBA(image.Rect(0, 0, 300, 300)) raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, curve[:]...) raster.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...) - savepng(fmt.Sprintf("_testQuad%d.png", i), img) + savepng(fmt.Sprintf("../output/curve/testQuad%d.png", i), img) log.Printf("Num of points: %d\n", len(p.points)) } fmt.Println() @@ -207,7 +207,7 @@ func BenchmarkCubicCurveRec(b *testing.B) { for _, curve := range testsCubicFloat64 { p := Path{make([]float64, 0, 32)} p.LineTo(curve[0], curve[1]) - curve.SegmentRec(&p, flattening_threshold) + curve.SegmentRec(&p, flatteningThreshold) } } } @@ -217,7 +217,7 @@ func BenchmarkCubicCurve(b *testing.B) { for _, curve := range testsCubicFloat64 { p := Path{make([]float64, 0, 32)} p.LineTo(curve[0], curve[1]) - curve.Segment(&p, flattening_threshold) + curve.Segment(&p, flatteningThreshold) } } } @@ -247,7 +247,7 @@ func BenchmarkCubicCurveParabolic(b *testing.B) { for _, curve := range testsCubicFloat64 { p := Path{make([]float64, 0, 32)} p.LineTo(curve[0], curve[1]) - curve.ParabolicSegment(&p, flattening_threshold) + curve.ParabolicSegment(&p, flatteningThreshold) } } } @@ -257,7 +257,7 @@ func BenchmarkQuadCurve(b *testing.B) { for _, curve := range testsQuadFloat64 { p := Path{make([]float64, 0, 32)} p.LineTo(curve[0], curve[1]) - curve.Segment(&p, flattening_threshold) + curve.Segment(&p, flatteningThreshold) } } } diff --git a/output/.empty b/output/.empty deleted file mode 100644 index e69de29..0000000 diff --git a/output/curve/.gitignore b/output/curve/.gitignore new file mode 100644 index 0000000..86d0cb2 --- /dev/null +++ b/output/curve/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/output/raster/.gitignore b/output/raster/.gitignore new file mode 100644 index 0000000..86d0cb2 --- /dev/null +++ b/output/raster/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/output/samples/.gitignore b/output/samples/.gitignore new file mode 100644 index 0000000..86d0cb2 --- /dev/null +++ b/output/samples/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/raster/raster_test.go b/raster/raster_test.go index 7a70968..e01373e 100644 --- a/raster/raster_test.go +++ b/raster/raster_test.go @@ -13,7 +13,7 @@ import ( "github.com/llgcode/draw2d/curve" ) -var flattening_threshold float64 = 0.5 +var flatteningThreshold = 0.5 func savepng(filePath string, m image.Image) { f, err := os.Create(filePath) @@ -55,7 +55,7 @@ func TestFreetype(t *testing.T) { var p Path p.LineTo(10, 190) c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} - c.Segment(&p, flattening_threshold) + c.Segment(&p, flatteningThreshold) poly := Polygon(p.points) color := color.RGBA{0, 0, 0, 0xff} @@ -74,14 +74,14 @@ func TestFreetype(t *testing.T) { painter.SetColor(color) rasterizer.Rasterize(painter) - savepng("../output/raster_TestFreetype.png", img) + savepng("../output/raster/TestFreetype.png", img) } func TestFreetypeNonZeroWinding(t *testing.T) { var p Path p.LineTo(10, 190) c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} - c.Segment(&p, flattening_threshold) + c.Segment(&p, flatteningThreshold) poly := Polygon(p.points) color := color.RGBA{0, 0, 0, 0xff} @@ -100,7 +100,7 @@ func TestFreetypeNonZeroWinding(t *testing.T) { painter.SetColor(color) rasterizer.Rasterize(painter) - savepng("../output/raster_TestFreetypeNonZeroWinding.png", img) + savepng("../output/raster/TestFreetypeNonZeroWinding.png", img) } func TestRasterizer(t *testing.T) { @@ -108,7 +108,7 @@ func TestRasterizer(t *testing.T) { var p Path p.LineTo(10, 190) c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} - c.Segment(&p, flattening_threshold) + c.Segment(&p, flatteningThreshold) poly := Polygon(p.points) color := color.RGBA{0, 0, 0, 0xff} tr := [6]float64{1, 0, 0, 1, 0, 0} @@ -116,7 +116,7 @@ func TestRasterizer(t *testing.T) { //PolylineBresenham(img, image.Black, poly...) r.RenderEvenOdd(img, &color, &poly, tr) - savepng("../output/raster_TestRasterizer.png", img) + savepng("../output/raster/TestRasterizer.png", img) } func TestRasterizerNonZeroWinding(t *testing.T) { @@ -124,7 +124,7 @@ func TestRasterizerNonZeroWinding(t *testing.T) { var p Path p.LineTo(10, 190) c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} - c.Segment(&p, flattening_threshold) + c.Segment(&p, flatteningThreshold) poly := Polygon(p.points) color := color.RGBA{0, 0, 0, 0xff} tr := [6]float64{1, 0, 0, 1, 0, 0} @@ -132,14 +132,14 @@ func TestRasterizerNonZeroWinding(t *testing.T) { //PolylineBresenham(img, image.Black, poly...) r.RenderNonZeroWinding(img, &color, &poly, tr) - savepng("../output/raster_TestRasterizerNonZeroWinding.png", img) + savepng("../output/raster/TestRasterizerNonZeroWinding.png", img) } func BenchmarkFreetype(b *testing.B) { var p Path p.LineTo(10, 190) c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} - c.Segment(&p, flattening_threshold) + c.Segment(&p, flatteningThreshold) poly := Polygon(p.points) color := color.RGBA{0, 0, 0, 0xff} @@ -165,7 +165,7 @@ func BenchmarkFreetypeNonZeroWinding(b *testing.B) { var p Path p.LineTo(10, 190) c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} - c.Segment(&p, flattening_threshold) + c.Segment(&p, flatteningThreshold) poly := Polygon(p.points) color := color.RGBA{0, 0, 0, 0xff} @@ -191,7 +191,7 @@ func BenchmarkRasterizerNonZeroWinding(b *testing.B) { var p Path p.LineTo(10, 190) c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} - c.Segment(&p, flattening_threshold) + c.Segment(&p, flatteningThreshold) poly := Polygon(p.points) color := color.RGBA{0, 0, 0, 0xff} tr := [6]float64{1, 0, 0, 1, 0, 0} @@ -206,7 +206,7 @@ func BenchmarkRasterizer(b *testing.B) { var p Path p.LineTo(10, 190) c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} - c.Segment(&p, flattening_threshold) + c.Segment(&p, flatteningThreshold) poly := Polygon(p.points) color := color.RGBA{0, 0, 0, 0xff} tr := [6]float64{1, 0, 0, 1, 0, 0} diff --git a/rgba_interpolation.go b/rgba_interpolation.go index 92534e7..1265fe0 100644 --- a/rgba_interpolation.go +++ b/rgba_interpolation.go @@ -11,11 +11,15 @@ import ( "math" ) +// ImageFilter defines sampling filter (linear, bilinear or bicubic) type ImageFilter int const ( + // LinearFilter uses linear interpolation LinearFilter ImageFilter = iota + // BilinearFilter uses bilinear interpolation BilinearFilter + // BicubicFilter uses bicubic interpolation BicubicFilter ) @@ -103,6 +107,7 @@ func cubic(offset, v0, v1, v2, v3 float64) uint32 { (-9*v0+9*v2))*offset + (v0 + 16*v1 + v2)) / 18.0) } +// DrawImage draws a source image on an destination image. func DrawImage(src image.Image, dest draw.Image, tr MatrixTransform, op draw.Op, filter ImageFilter) { bounds := src.Bounds() x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Max.X), float64(bounds.Max.Y) diff --git a/samples/samples.go b/samples/samples.go index ee08db4..ff30559 100644 --- a/samples/samples.go +++ b/samples/samples.go @@ -20,5 +20,5 @@ func Output(name, ext string) string { if ext == "pdf" { root = "../" } - return fmt.Sprintf("%soutput/%s.%s", root, name, ext) + return fmt.Sprintf("%soutput/samples/%s.%s", root, name, ext) } diff --git a/test b/test index f643b46..2a387e6 100755 --- a/test +++ b/test @@ -1,5 +1,5 @@ echo golint -golint ./... | grep "draw2dpdf\|samples" +golint ./... | grep "draw2dpdf\|samples\|^advanced_path\|^arc\|draw2d[.]\|fileutil\|^gc\|math\|^path[.]\|rgba_interpolation\|test\|vertex2d" echo echo go vet go vet ./... diff --git a/vertex2d.go b/vertex2d.go index 4e4d4fd..5bc2f52 100644 --- a/vertex2d.go +++ b/vertex2d.go @@ -3,16 +3,23 @@ package draw2d +// VertexCommand defines different commands to describe the vertex of a path. type VertexCommand byte const ( + // VertexNoCommand does nothing VertexNoCommand VertexCommand = iota + // VertexStartCommand starts a (sub)path VertexStartCommand + // VertexJoinCommand joins the two edges at the vertex VertexJoinCommand + // VertexCloseCommand closes the subpath VertexCloseCommand + // VertexStopCommand is the endpoint of the path. VertexStopCommand ) +// VertexConverter allows to convert vertices. type VertexConverter interface { NextCommand(cmd VertexCommand) Vertex(x, y float64)