Beispiel #1
0
func (p *Canvas) Save() {
	fmt.Println(p.FileName)
	err := dwg.SaveToPngFile(p.FileName, p.Dest)
	if err != nil {
		fmt.Println(err)
	}
}
Beispiel #2
0
func TestParseSVG(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping lengthier tests during short test run.")
	}

	var tests = []string{
		"rectfull",
		"rectfullwithtext",
		"tworects",
		"threerects",
	}

	for _, tt := range tests {
		f, err := os.Open("testsvgs/" + tt + ".svg")
		if err != nil {
			t.Errorf("Failed to open %s.svg for reading: %s", tt, err)
			continue
		}
		defer f.Close()

		p := ssvgc.NewParser(f)
		svg, err := p.ParseSVG()
		if err != nil {
			t.Errorf("ParseSVG(%s.svg) failed => %s", tt, err)
			continue
		}

		img := svg.Draw()
		draw2dimg.SaveToPngFile("output/"+tt+".png", img)
	}
}
Beispiel #3
0
func TestImageRendering(t *testing.T) {
	var tests = []StringMap{
		{
			"name": "tuxcentered",
			"xml": `<svg width="200" height="200" fill="white">
<image href="testimages/tux-construction.png" width="150" x="25" y="25" />
</svg>`,
		},
		{
			"name": "tuxbottomright",
			"xml": `<svg width="200" height="200" fill="white">
<image href="testimages/tux-construction.png" width="150" x="50" y="50" />
</svg>`,
		},
		{
			"name": "tuxfullsize",
			"xml": `<svg width="200" height="200" fill="white">
<image href="testimages/tux-construction.png" />
</svg>`,
		},
	}

	for _, tt := range tests {
		r := strings.NewReader(tt["xml"])
		p := ssvgc.NewParser(r)
		svg, err := p.ParseSVG()
		if err != nil {
			t.Errorf("ParseSVG() failed => %s", err)
			continue
		}

		draw2dimg.SaveToPngFile("output/"+tt["name"]+".png", svg.Draw())
	}
}
Beispiel #4
0
// DrawClosedLine draws the line represented by the Points and closes it.
func DrawClosedLine(p Points, width, height float64, name string) {
	// Initialize the graphic context on an RGBA image
	dest := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
	gc := draw2dimg.NewGraphicContext(dest)

	// Set some properties
	gc.SetStrokeColor(color.RGBA{0x44, 0x44, 0x44, 0xff})
	gc.SetLineWidth(5)

	paths := []*draw2d.Path{}

	// Draw a path
	for idx, point := range p[:len(p)] {
		path := new(draw2d.Path)
		path.MoveTo(float64(point.X), height-float64(point.Y))
		if idx < len(p)-1 {
			path.LineTo(float64(p[idx+1].X), height-float64(p[idx+1].Y))
		} else {
			path.LineTo(float64(p[0].X), height-float64(p[0].Y))
		}
		paths = append(paths, path)
	}
	gc.Stroke(paths...)
	gc.FillStroke()

	// Save to file
	draw2dimg.SaveToPngFile(name, dest)
}
Beispiel #5
0
func TestFreetypeRasterizerNonZeroWinding(t *testing.T) {
	var p Path
	p.LineTo(10, 190)
	draw2dbase.TraceCubic(&p, []float64{10, 190, 10, 10, 190, 10, 190, 190}, 0.5)
	poly := Polygon(p.points)
	color := color.RGBA{0, 0, 0, 0xff}

	img := image.NewRGBA(image.Rect(0, 0, 200, 200))
	rasterizer := raster.NewRasterizer(200, 200)
	rasterizer.UseNonZeroWinding = true
	rasterizer.Start(raster.Point{
		X: raster.Fix32(10 * 256),
		Y: raster.Fix32(190 * 256)})
	for j := 0; j < len(poly); j = j + 2 {
		rasterizer.Add1(raster.Point{
			X: raster.Fix32(poly[j] * 256),
			Y: raster.Fix32(poly[j+1] * 256)})
	}
	painter := raster.NewRGBAPainter(img)
	painter.SetColor(color)
	rasterizer.Rasterize(painter)

	err := draw2dimg.SaveToPngFile("output/TestFreetypeRasterizerNonZeroWinding.png", img)
	if err != nil {
		fmt.Println(err)
	}
}
Beispiel #6
0
func (r *Renderer) DrawAdjustedToFile(filename string) error {
	dest := r.Draw()
	if subimage, ok := dest.(SubImage); ok {
		bb := r.bbox
		x0, y0, x1, y1 := int(bb[0]), int(bb[1]), int(bb[2]), int(bb[3])
		dest = subimage.SubImage(image.Rect(x0, y0, x1, y1))
	}
	return draw2dimg.SaveToPngFile(filename, dest)
}
Beispiel #7
0
func mainDrawOne(filename string, space hilbert.SpaceFilling) error {
	log.Printf("Drawing one image %q", filename)

	img, err := createSpaceFillingImage(space, 64, 64).Draw()
	if err != nil {
		return err
	}
	return draw2dimg.SaveToPngFile(filename, img)
}
Beispiel #8
0
Datei: dr.go Projekt: taysom/va
func main() {

	pl := NewPlotter(200, 1000)

	pl.Plot([]Point{{1, 2}, {2, 4}, {3, 2}, {4, 3}})
	pl.Plot([]Point{{10, 40}, {20, 10}, {30, 20}, {40, 30}})
	pl.Plot(Sine(20))

	// Save to file
	draw2dimg.SaveToPngFile("hello.png", pl.image)
}
Beispiel #9
0
func main() {
	i := image.NewRGBA(image.Rect(0, 0, 200, 200))
	gc := draw2dimg.NewGraphicContext(i)
	gc.Save()
	gc.SetStrokeColor(color.Black)
	gc.SetFillColor(color.Black)
	draw2d.Rect(gc, 10, 10, 100, 100)
	gc.FillStroke()
	gc.Restore()

	draw2dimg.SaveToPngFile("yay-rectangle.png", i)
}
Beispiel #10
0
func DrawTest() {
	// Initialize the graphic context on an RGBA image
	dest := image.NewRGBA(image.Rect(0, 0, 297, 210.0))
	gc := draw2dimg.NewGraphicContext(dest)

	DrawHello(gc, "Hello World")

	// Save to png
	err := draw2dimg.SaveToPngFile("_testHello.png", dest)
	if err != nil {
		log.Fatalln("Saving failed:", err)
	}
}
Beispiel #11
0
Datei: test.go Projekt: truyet/go
func Test(t *testing.T) {
	dest := image.NewRGBA(image.Rect(0, 0, 300, 300))
	renderer := NewImageRenderer(dest)
	hash := string(md5.New().Sum([]byte("Jeremiah")))
	config := Config{}
	identicon, err := NewIconGenerator(renderer, hash, 0, 0, 300, 8, config)
	if err != nil {
		t.Error(err)
	}
	identicon.Generator()
	draw2dimg.SaveToPngFile("./test.png", dest)

}
Beispiel #12
0
func TestRectangleDrawing(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping lengthier tests during short test run.")
	}

	var tests = []StringMap{
		{
			"name":   "solidblue",
			"fill":   "blue",
			"width":  "400",
			"height": "400",
		},
		{
			"name":         "redinsetwithblue",
			"fill":         "blue",
			"stroke":       "red",
			"stroke-width": "30",
			"width":        "400",
			"height":       "400",
		},
		{
			"name":         "redinsetwithblue2",
			"fill":         "blue",
			"stroke":       "red",
			"stroke-width": "1",
			"width":        "400",
			"height":       "400",
		},
		{
			"name":         "solidredstrokedgreen",
			"fill":         "red",
			"width":        "100",
			"height":       "100",
			"x":            "50",
			"y":            "50",
			"stroke":       "green",
			"stroke-width": "15",
		},
	}

	for _, tt := range tests {
		r := ssvgc.NewRectangle()
		for name, value := range tt {
			r.SetAttribute(name, value)
		}

		draw2dimg.SaveToPngFile("output/"+tt["name"]+".png", r.Draw())
	}
}
Beispiel #13
0
func TestRasterizerNonZeroWinding(t *testing.T) {
	img := image.NewRGBA(image.Rect(0, 0, 200, 200))
	var p Path
	p.LineTo(10, 190)
	draw2dbase.TraceCubic(&p, []float64{10, 190, 10, 10, 190, 10, 190, 190}, 0.5)

	poly := Polygon(p.points)
	color := color.RGBA{0, 0, 0, 0xff}
	tr := [6]float64{1, 0, 0, 1, 0, 0}
	r := NewRasterizer8BitsSample(200, 200)
	//PolylineBresenham(img, image.Black, poly...)

	r.RenderNonZeroWinding(img, &color, &poly, tr)
	draw2dimg.SaveToPngFile("../output/raster/TestRasterizerNonZeroWinding.png", img)
}
func compile(frdat string, fnum int) error {
	r := strings.NewReader(frdat)

	fr, rerr := ani.ReadFrame(r)
	if rerr != nil {
		return fmt.Errorf("Error reading frame %v: %v\nFrame follows\n%v\n",
			fnum, rerr, frdat)
	}

	img := render(fr, fnum)

	fname := fmt.Sprintf("%06d.png", fnum)
	err := dimg.SaveToPngFile(fname, img)

	return err
}
Beispiel #15
0
func test(t *testing.T, draw sample) {
	// Initialize the graphic context on an RGBA image
	dest := image.NewRGBA(image.Rect(0, 0, 297, 210.0))
	gc := draw2dimg.NewGraphicContext(dest)
	// Draw Android logo
	output, err := draw(gc, "png")
	if err != nil {
		t.Errorf("Drawing %q failed: %v", output, err)
		return
	}
	// Save to png
	err = draw2dimg.SaveToPngFile(output, dest)
	if err != nil {
		t.Errorf("Saving %q failed: %v", output, err)
	}
}
Beispiel #16
0
Datei: 2d.go Projekt: taysom/va
func main() {
	// Initialize the graphic context on an RGBA image
	dest := image.NewRGBA(image.Rect(0, 0, 1300, 1200))
	gc := draw2dimg.NewGraphicContext(dest)
	gb := draw2dimg.NewGraphicContext(dest)

	n := draw2d.NewRotationMatrix(math.Pi / 2)
	n.Translate(100, -100)
	gb.SetMatrixTransform(n)
	Draw(gb, "My Text")
	// Set some properties
	gc.SetFillColor(color.RGBA{0x44, 0xff, 0x44, 0xff})
	gc.SetStrokeColor(color.RGBA{0x00, 0x00, 0x00, 0xff})
	gc.SetLineWidth(3)

	m := draw2d.NewRotationMatrix(-0.3)
	//	m.TransformRectangle(40, 40, 100, 500)
	m.Translate(75, 75)
	gc.SetMatrixTransform(m)

	// Draw a closed shape
	gc.MoveTo(39, 39) // should always be called first for a new path
	gc.LineTo(39, 512)
	gc.LineTo(512, 512)
	gc.LineTo(512, 39)
	gc.LineTo(39, 39)
	//gc.LineTo(100, 50)
	//gc.QuadCurveTo(100, 10, 10, 10)
	gc.Close()
	gc.FillStroke()

	gc.SetFillColor(color.RGBA{0xff, 0xff, 0x44, 0x77})
	gc.SetMatrixTransform(draw2d.NewRotationMatrix(0))
	gc.MoveTo(47, 47) // should always be called first for a new path
	gc.LineTo(47, 617)
	gc.LineTo(617, 617)
	gc.LineTo(617, 47)
	gc.LineTo(47, 47)
	gc.Close()
	gc.FillStroke()

	g1 := []Point{{1, 2}, {2, 3}, {3, 4}, {4, 3}}
	Plot(gb, g1)

	// Save to file
	draw2dimg.SaveToPngFile("hello.png", dest)
}
Beispiel #17
0
func TestRasterizerNonZeroWinding(t *testing.T) {
	bounds := image.Rect(0, 0, 200, 200)
	img := image.NewRGBA(bounds)
	mask := image.NewAlpha(bounds)
	var p Path
	p.LineTo(10, 190)
	draw2dbase.TraceCubic(&p, []float64{10, 190, 10, 10, 190, 10, 190, 190}, 0.5)
	poly := Polygon(p.points)
	rgba := color.RGBA{0, 0, 0, 0xff}
	r := NewRasterizer()
	r.Fill(mask, poly, true)
	DrawSolidRGBA(img, mask, rgba)
	err := draw2dimg.SaveToPngFile("output/TestRasterizerNonZeroWinding.png", img)
	if err != nil {
		fmt.Println(err)
	}
}
Beispiel #18
0
func TestCircle(t *testing.T) {
	width := 200
	height := 200
	img := image.NewRGBA(image.Rect(0, 0, width, height))
	gc := draw2dimg.NewGraphicContext(img)

	gc.SetStrokeColor(color.NRGBA{255, 255, 255, 255})
	gc.SetFillColor(color.NRGBA{255, 255, 255, 255})
	gc.Clear()

	gc.SetStrokeColor(color.NRGBA{255, 0, 0, 255})
	gc.SetLineWidth(1)

	// Draw a circle
	Circle(gc, 100, 100, 50)
	gc.Stroke()

	draw2dimg.SaveToPngFile("../output/draw2dkit/TestCircle.png", img)
}
Beispiel #19
0
func main() {

	file, err := os.Open("img/test.svg")

	check(err)

	defer file.Close()

	size := image.Point{1000, 1000}

	dest, err := svg.Render(file, size)

	check(err)

	err = draw2dimg.SaveToPngFile("/home/test.png", dest)

	check(err)

	fmt.Println("done")
}
Beispiel #20
0
// DrawPolygon draws the polygon represented by Points on the canvas
func DrawPolygon(p Points, width, height float64, name string) {
	// Initialize the graphic context on an RGBA image
	dest := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
	gc := draw2dimg.NewGraphicContext(dest)

	// Set some properties
	gc.SetFillColor(color.RGBA{0x44, 0xff, 0x44, 0xff})
	gc.SetStrokeColor(color.RGBA{0x44, 0x44, 0x44, 0xff})
	gc.SetLineWidth(5)

	// Draw a closed shape
	gc.MoveTo(float64(p[0].X), height-float64(p[0].Y))
	for _, point := range p[1:] {
		gc.LineTo(float64(point.X), height-float64(point.Y))
		gc.MoveTo(float64(point.X), height-float64(point.Y))
	}
	gc.Close()
	gc.FillStroke()

	// Save to file
	draw2dimg.SaveToPngFile(name, dest)
}
func snowflake() {

	// Create the L System
	sys := "F--F--F"
	for i := 0; i < iter; i++ {
		sys = iteration(sys)
	}

	// Create graphic context for drawing
	dest := image.NewRGBA(image.Rect(0, 0, 2000, 2000))
	gc := draw2dimg.NewGraphicContext(dest)

	gc.SetFillColor(color.RGBA{0x00, 0x00, 0x00, 0xFF})
	gc.SetStrokeColor(color.RGBA{0x00, 0x00, 0x00, 0xFF})
	gc.SetLineWidth(5)

	//Draw the image
	drawSnowflake(sys, gc)
	//gc.Close()
	gc.Stroke()

	//Save image
	draw2dimg.SaveToPngFile("test.png", dest)
}
Beispiel #22
0
func DrawGrid(v *Viewport, fileName string) {
	log.Println("DRAWING GRID FOR", v.ULCorner, v.LRCorner)
	draw2d.SetFontFolder("")
	dest := image.NewRGBA(image.Rect(0, 0, 400, 400))
	white := color.RGBA{0xff, 0xff, 0xff, 255}
	draw.Draw(dest, dest.Bounds(), &image.Uniform{white}, image.ZP, draw.Src)
	gc := draw2dimg.NewGraphicContext(dest)
	gc.SetFontData(draw2d.FontData{Name: "DroidSansMono", Family: draw2d.FontFamilyMono})
	gc.SetFillColor(image.Black)
	gc.SetFontSize(8)
	for x := 0; x < 400; x++ {
		for y := 0; y < 400; y++ {
			p := Pixel{float64(x), float64(y)}
			hex := v.HexContaining(p)
			var clr color.RGBA
			clN := (hex[0] - hex[1]) % 4
			for clN < 0 {
				clN += 4
			}
			switch clN {
			case 0: // blue
				clr = color.RGBA{0x33, 0x66, 0xcc, 255}
			case 1: // green
				clr = color.RGBA{0x00, 0xAA, 0x33, 255}
			case 2: // red
				clr = color.RGBA{0xAA, 0x33, 0x33, 255}
			default: // white
				clr = white
			}
			dest.Set(x, y, clr)
			/*if (x+60)%60 == 0 && y%15 == 0 {
				gc.FillStringAt(fmt.Sprintf("(%d,%d)", hex[0], hex[1]), p[0], p[1])
			}*/
		}
	}
	for _, h := range v.VisList() {
		corners := v.CornersOf(h)
		gc.MoveTo(corners[0][0], corners[0][1])
		for i, _ := range corners {
			var px, py float64
			if i == 5 {
				px, py = corners[0][0], corners[0][1]
			} else {
				px, py = corners[i+1][0], corners[i+1][1]
			}
			gc.LineTo(px, py)
		}
		gc.Close()
		gc.Stroke()
		c := v.CenterOf(h)
		gc.FillStringAt(fmt.Sprintf("(%d,%d)", h[0], h[1]), c[0], c[1])
	}
	gc.SetLineWidth(2)
	gc.MoveTo(v.ULCorner[0], v.ULCorner[1])
	gc.LineTo(v.LRCorner[0], v.ULCorner[1])
	gc.LineTo(v.LRCorner[0], v.LRCorner[1])
	gc.LineTo(v.ULCorner[0], v.LRCorner[1])
	gc.Close()
	gc.Stroke()

	//}

	draw2dimg.SaveToPngFile(fileName, dest)
}
Beispiel #23
0
func main() {

	// Command-line input
	var in string
	var height int
	var col1 string
	var col2 string

	flag.StringVar(&in, "f", "", `File to be parsed. The file has to
        have a certain format. Every line should be "a>b>amount".`)
	flag.IntVar(&height, "h", 1980, `Height of the output image. The width
        is deduced from the height.`)
	flag.StringVar(&col1, "c1", "#eeef61", "Start color of the gradient.")
	flag.StringVar(&col2, "c2", "#1e3140", "End color of the gradient.")

	flag.Parse()

	// Parse the arcgo file
	names, counter := OpenArcgoFile(in)

	// Comoute width
	width := float64(height) * math.Phi * 1.2
	// Where the first name is located
	top := float64(height) / 10
	// Where the last name is located
	bottom := float64(height) - top

	// Rescale the counter based on the maximal value
	counter = AssignWidths(counter, 1.0, 20.0)
	// Assign linearly separated coordinates to each name
	coordinates := AssignCoordinates(names, top, bottom)
	// Assign "linearly separated" colors to each name
	colors := AssignColors(names, col1, col2)

	// Initialize the image
	img := image.NewRGBA(image.Rect(0, 0, int(width), height))
	gc := draw2dimg.NewGraphicContext(img)

	// Define the x coordinates for the arcs
	xRight := float64(width) * 1.7 / 3.0
	xLeft := float64(width) * 1.3 / 3.0
	// Graph the arcs
	for a := range counter {
		// Get the color of the name
		gc.SetStrokeColor(colors[a])
		for b := range counter[a] {
			// Set where the arc begins
			y1 := coordinates[a]
			// Set where the arc ends
			y2 := coordinates[b]
			// Set the width of the arc
			z := counter[a][b]
			gc.SetLineWidth(2 * z)
			// Define on what side the arc is
			if y1 < y2 {
				// Right side arc
				Arc(gc, xRight, y1, y2)
			} else {
				// Left side arc
				Arc(gc, xLeft, y1, y2)
			}
		}
	}

	// Set the font for writing the names
	draw2d.SetFontFolder("")
	gc.SetFontData(draw2d.FontData{Name: "coolvetica"})
	gc.SetFillColor(image.Black)
	fontSize := float64(height / (3 * len(names)))
	gc.SetFontSize(fontSize)

	// Write the names
	for _, name := range names {
		x := width/2.0 - (float64(len(name))*fontSize)/3.8
		y := coordinates[name] + fontSize/2 - 2
		gc.FillStringAt(name, x, y)
	}
	// Save to file
	path := strings.Split(in, "/")
	out := strings.Join([]string{strings.Split(path[len(path)-1], ".")[0], "png"}, ".")
	draw2dimg.SaveToPngFile(out, img)

}
Beispiel #24
0
func TestSVGDrawing(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping lengthier tests during short test run.")
	}

	var rectangleDefinitions = []StringMap{
		{
			"name":   "solidblue",
			"fill":   "blue",
			"width":  "200",
			"height": "200",
			"x":      "0",
			"y":      "0",
		},
		{
			"name":   "solidred",
			"fill":   "red",
			"width":  "100",
			"height": "100",
			"x":      "50",
			"y":      "50",
		},
		{
			"name":         "solidredstrokedgreen",
			"fill":         "red",
			"width":        "100",
			"height":       "100",
			"x":            "50",
			"y":            "50",
			"stroke":       "green",
			"stroke-width": "15",
		},
	}

	var tests = []StringMap{
		{
			"name":       "solidbluesvg",
			"rectangles": "solidblue",
			"width":      "200",
			"height":     "200",
			"fill":       "none",
		},
		{
			"name":       "bluewithredsvg",
			"rectangles": "solidblue,solidred",
			"width":      "200",
			"height":     "200",
			"fill":       "none",
		},
		{
			"name":       "bluewithredstrokedgreensvg",
			"rectangles": "solidblue,solidredstrokedgreen",
			"width":      "200",
			"height":     "200",
			"fill":       "none",
		},
	}

	rectangles := make(map[string]*ssvgc.Rectangle)

	for _, def := range rectangleDefinitions {
		r := ssvgc.NewRectangle()
		for name, value := range def {
			r.SetAttribute(name, value)
		}

		rectangles[def["name"]] = r
	}

	for _, tt := range tests {
		s := &ssvgc.SVG{}
		for name, value := range tt {
			s.SetAttribute(name, value)
		}

		for _, rect := range strings.Split(tt["rectangles"], ",") {
			s.AddElement(rectangles[rect])
		}

		draw2dimg.SaveToPngFile("output/"+tt["name"]+".png", s.Draw())
	}
}
Beispiel #25
0
func (r *Renderer) DrawToFile(filename string) error {
	dest := r.Draw()
	return draw2dimg.SaveToPngFile(filename, dest)
}
Beispiel #26
0
func TestTextRendering(t *testing.T) {
	var tests = []StringMap{
		{
			"name": "textredbanana",
			"text-value": `<svg width="200" height="200" fill="white">
<text ttf-font="/tmp/DejaVuSans.ttf" x="15" y="30">You are
    <tspan fill="red">not</tspan>
    a banana
</text>
</svg>`,
		},
		{
			"name": "textbananashiftedright",
			"text-value": `<svg width="200" height="200" fill="white">
<text ttf-font="/tmp/DejaVuSans.ttf" x="45" y="30">You are
    <tspan>not</tspan>
    a banana
</text>
</svg>`,
		},
		{
			"name": "textbananashifteddown",
			"text-value": `<svg width="200" height="200" fill="white">
<text ttf-font="/tmp/DejaVuSans.ttf" font-size="18" x="1" y="70">You are
    <tspan>not</tspan>
    a banana
</text>
</svg>`,
		},
		{
			"name": "textbananaanchormiddle",
			"text-value": `<svg width="500" height="200" fill="white">
<text ttf-font="/tmp/DejaVuSans.ttf" font-size="18" x="250" y="70" text-anchor="middle">You are
    <tspan>not</tspan>
    a banana
</text>
</svg>`,
		},
		{
			"name": "textbananaanchorend",
			"text-value": `<svg width="500" height="200" fill="white">
<text ttf-font="/tmp/DejaVuSans.ttf" font-size="18" x="250" y="70" text-anchor="end">You are
    <tspan>not</tspan>
    a banana
</text>
</svg>`,
		},
	}

	for _, tt := range tests {
		r := strings.NewReader(tt["text-value"])
		p := ssvgc.NewParser(r)
		svg, err := p.ParseSVG()
		if err != nil {
			t.Errorf("ParseSVG() failed => %s", err)
			continue
		}

		draw2dimg.SaveToPngFile("output/"+tt["name"]+".png", svg.Draw())
	}
}
Beispiel #27
0
//
// Histograms Charts
//
func dailyWordHistChart(filename string, width, height int, days []*stat.DailyUserStat, dateLine []time.Time) {

	dest := image.NewRGBA(image.Rect(0, 0, width, height))
	gc := draw2dimg.NewGraphicContext(dest)

	var minVal, maxVal float64 = 0, 0
	dayLen := len(days)
	xStep := float64(width) / float64(dayLen)
	baseLineY := float64(50)

	dayAdd := make([]float64, dayLen)
	daySub := make([]float64, dayLen)

	for i := 0; i < dayLen; i += 1 {
		if days[i] == nil {
			dayAdd[i] = 0
			daySub[i] = 0
		} else {
			dayAdd[i] = float64(days[i].WordAdd)
			daySub[i] = float64(0 - days[i].WordSub)

			if dayAdd[i] > maxVal {
				maxVal = dayAdd[i]
			}
			if daySub[i] > minVal {
				minVal = daySub[i]
			}
		}
	}

	hf := float64(height)
	wf := float64(width)

	for i := 0; i < dayLen; i += 1 {
		dayAdd[i] = (hf - baseLineY) * dayAdd[i] / maxVal
		daySub[i] = (baseLineY) * daySub[i] / minVal
	}

	// Draw Grid Lines
	{
		gc.SetFillColor(color.RGBA{0x44, 0x44, 0x44, 0xff})
		gc.SetStrokeColor(color.RGBA{0x00, 0x00, 0x00, 0xff})
		gc.SetLineWidth(0.2)

		yStep := 100.0
		if maxVal > 10000 {
			yStep = 1000.0
		} else if maxVal > 1000 {
			yStep = 250.0
		}

		gc.SetFontData(draw2d.FontData{Name: "Roboto", Family: draw2d.FontFamilySans})
		for y := yStep; y < maxVal; y += yStep {
			yf := (hf - baseLineY) - (hf-baseLineY)*y/maxVal
			gc.MoveTo(0, yf)
			gc.LineTo(wf, yf)
			gc.Stroke()

			gc.FillStringAt(fmt.Sprintf("%.0f", y), 10, yf)
		}

		yStep = 100.0
		if minVal > 10000 {
			yStep = 1000.0
		} else if minVal > 1000 {
			yStep = 250.0
		}

		for y := yStep; y < minVal; y += yStep {
			yf := (hf - baseLineY) + baseLineY*y/minVal
			gc.MoveTo(0, yf)
			gc.LineTo(wf, yf)
		}

		gc.Stroke()
	}

	// Add
	gc.SetFillColor(color.RGBA{0x44, 0xff, 0x44, 0xff})
	for i := 0; i < dayLen; i += 1 {
		x := float64(i) * xStep
		draw2dkit.Rectangle(gc, x, hf-baseLineY, x+xStep, hf-baseLineY-dayAdd[i])
	}
	gc.Fill()

	// Sub
	gc.SetFillColor(color.RGBA{0xff, 0x44, 0x44, 0xff})
	for i := 0; i < dayLen; i += 1 {
		x := float64(i) * xStep
		draw2dkit.Rectangle(gc, x, hf-baseLineY, x+xStep, hf-baseLineY+daySub[i])
	}
	gc.Fill()

	// Draw Base Line
	{
		gc.SetStrokeColor(color.RGBA{0x00, 0x00, 0x00, 0xff})
		gc.SetLineWidth(1)
		gc.MoveTo(0, 0)
		gc.LineTo(0, hf)
		gc.MoveTo(0, hf-baseLineY)
		gc.LineTo(wf, hf-baseLineY)
		gc.MoveTo(wf, 0)
		gc.LineTo(wf, hf)

		for i := 0; i < dayLen; i += 1 {
			if dateLine[i].Weekday() == time.Monday {
				x := float64(i) * xStep
				gc.MoveTo(x, hf-baseLineY-10)
				gc.LineTo(x, hf-baseLineY+10)
			}
		}

		gc.Stroke()
	}

	draw2dimg.SaveToPngFile(filename, dest)
}