Beispiel #1
0
// NewImage returns a new image canvas
// that draws to the given image.  The
// minimum point of the given image
// should probably be 0,0.
func NewImage(img draw.Image, name string) (*Canvas, error) {
	w := float64(img.Bounds().Max.X - img.Bounds().Min.X)
	h := float64(img.Bounds().Max.Y - img.Bounds().Min.Y)

	X, err := xgbutil.NewConn()
	if err != nil {
		return nil, err
	}
	keybind.Initialize(X)
	ximg := xgraphics.New(X, image.Rect(0, 0, int(w), int(h)))
	err = ximg.CreatePixmap()
	if err != nil {
		return nil, err
	}
	painter := NewPainter(ximg)
	gc := draw2d.NewGraphicContextWithPainter(ximg, painter)
	gc.SetDPI(dpi)
	gc.Scale(1, -1)
	gc.Translate(0, -h)

	wid := ximg.XShowExtra(name, true)
	go func() {
		xevent.Main(X)
	}()

	c := &Canvas{
		Canvas: vgimg.NewWith(vgimg.UseImageWithContext(img, gc)),
		x:      X,
		ximg:   ximg,
		wid:    wid,
	}
	vg.Initialize(c)
	return c, nil
}
Beispiel #2
0
func New(w, h vg.Length) *Canvas {
	buf := new(bytes.Buffer)
	c := &Canvas{
		svg: svgo.New(buf),
		w:   w,
		h:   h,
		buf: buf,
		ht:  w.Points(),
		stk: []context{context{}},
	}

	// This is like svg.Start, except it uses floats
	// and specifies the units.
	fmt.Fprintf(buf, `<?xml version="1.0"?>
<!-- Generated by SVGo and Plotinum VG -->
<svg width="%.*gin" height="%.*gin"
	xmlns="http://www.w3.org/2000/svg"
	xmlns:xlink="http://www.w3.org/1999/xlink">`+"\n",
		pr, w/vg.Inch,
		pr, h/vg.Inch,
	)

	// Swap the origin to the bottom left.
	// This must be matched with a </g> when saving,
	// before the closing </svg>.
	c.svg.Gtransform(fmt.Sprintf("scale(1, -1) translate(0, -%.*g)", pr, h.Dots(c)))

	vg.Initialize(c)
	return c
}
Beispiel #3
0
func TestTextGrobs(t *testing.T) {
	// Output
	file, err := os.Create("text.png")
	if err != nil {
		t.Fatalf("%", err)
	}

	pngCanvas := vgimg.PngCanvas{Canvas: vgimg.New(10*vg.Inch, 8*vg.Inch)}
	vg.Initialize(pngCanvas)

	allVP := Viewport{
		X0:     0,
		Y0:     0,
		Width:  10 * vg.Inch,
		Height: 8 * vg.Inch,
		Canvas: pngCanvas,
	}
	bg := GrobRect{xmin: 0, ymin: 0, xmax: 1, ymax: 1, fill: BuiltinColors["gray60"]}
	bg.Draw(allVP)

	gridVP := allVP.Sub(0.1, 0.1, 0.35, 0.35)
	drawTextGrid(gridVP, 0)
	gridVP = allVP.Sub(0.55, 0.1, 0.35, 0.35)
	drawTextGrid(gridVP, 45./180*math.Pi)
	gridVP = allVP.Sub(0.1, 0.55, 0.35, 0.35)
	drawTextGrid(gridVP, 135./180*math.Pi)
	gridVP = allVP.Sub(0.55, 0.55, 0.35, 0.35)
	drawTextGrid(gridVP, 90./180*math.Pi)

	pngCanvas.WriteTo(file)
	file.Close()
}
Beispiel #4
0
// New creates a new PDF Canvas.
func New(w, h vg.Length) *Canvas {
	c := &Canvas{
		doc:         pdf.New(),
		w:           w,
		h:           h,
		lineVisible: true,
	}
	c.page = c.doc.NewPage(unit(w), unit(h))
	vg.Initialize(c)
	return c
}
Beispiel #5
0
// NewTitle returns a new Canvas with the given title string.
func NewTitle(w, h vg.Length, title string) *Canvas {
	c := &Canvas{
		stk: []ctx{ctx{}},
		w:   w,
		h:   h,
		buf: new(bytes.Buffer),
	}
	c.buf.WriteString("%%!PS-Adobe-3.0 EPSF-3.0\n")
	c.buf.WriteString("%%Creator github.com/gonum/plot/vg/vgeps\n")
	c.buf.WriteString("%%Title: " + title + "\n")
	c.buf.WriteString(fmt.Sprintf("%%%%BoundingBox: 0 0 %.*g %.*g\n",
		pr, w.Dots(DPI),
		pr, h.Dots(DPI)))
	c.buf.WriteString(fmt.Sprintf("%%%%CreationDate: %s\n", time.Now()))
	c.buf.WriteString("%%Orientation: Portrait\n")
	c.buf.WriteString("%%EndComments\n")
	c.buf.WriteString("\n")
	vg.Initialize(c)
	return c
}
Beispiel #6
0
// NewWith returns a new image canvas created according to the specified
// options. The currently accepted options are UseWH,
// UseDPI, UseImage, and UseImageWithContext.
// Each of the options specifies the size of the canvas (UseWH, UseImage),
// the resolution of the canvas (UseDPI), or both (useImageWithContext).
// If size or resolution are not specified, defaults are used.
// It panics if size and resolution are overspecified (i.e., too many options are
// passed).
func NewWith(o ...option) *Canvas {
	c := new(Canvas)
	var g uint32
	for _, opt := range o {
		f := opt(c)
		if g&f != 0 {
			panic("incompatible options")
		}
		g |= f
	}
	if c.dpi == 0 {
		c.dpi = DefaultDPI
	}
	if c.w == 0 { // h should also == 0.
		if c.img == nil {
			c.w = DefaultWidth
			c.h = DefaultHeight
		} else {
			w := float64(c.img.Bounds().Max.X - c.img.Bounds().Min.X)
			h := float64(c.img.Bounds().Max.Y - c.img.Bounds().Min.Y)
			c.w = vg.Length(w/float64(c.dpi)) * vg.Inch
			c.h = vg.Length(h/float64(c.dpi)) * vg.Inch
		}
	}
	if c.img == nil {
		w := c.w / vg.Inch * vg.Length(c.dpi)
		h := c.h / vg.Inch * vg.Length(c.dpi)
		c.img = draw.Image(image.NewRGBA(image.Rect(0, 0, int(w+0.5), int(h+0.5))))
	}
	if c.gc == nil {
		h := float64(c.img.Bounds().Max.Y - c.img.Bounds().Min.Y)
		c.gc = draw2dimg.NewGraphicContext(c.img)
		c.gc.SetDPI(c.dpi)
		c.gc.Scale(1, -1)
		c.gc.Translate(0, -h)
	}
	draw.Draw(c.img, c.img.Bounds(), image.White, image.ZP, draw.Src)
	c.color = []color.Color{color.Black}
	vg.Initialize(c)
	return c
}
Beispiel #7
0
func TestGraphicGrobs(t *testing.T) {
	// Output
	file, err := os.Create("grobs.png")
	if err != nil {
		t.Fatalf("%", err)
	}

	pngCanvas := vgimg.PngCanvas{Canvas: vgimg.New(10*vg.Inch, 8*vg.Inch)}
	vg.Initialize(pngCanvas)
	pngCanvas.Translate(-5*vg.Inch, -4*vg.Inch)
	dot := func(x, y float64) {
		pngCanvas.Push()
		pngCanvas.SetColor(BuiltinColors["red"])
		pngCanvas.SetLineWidth(5)
		var p vg.Path
		xr := vg.Length(x) * vg.Inch
		yr := vg.Length(y) * vg.Inch
		p.Move(xr-5, yr-5)
		p.Line(xr-5, yr+5)
		p.Line(xr+5, yr+5)
		p.Line(xr+5, yr-5)
		p.Close()
		pngCanvas.Fill(p)
		pngCanvas.Pop()
	}

	dot(0, 0)
	dot(5, 0)
	dot(0, 4)

	allVP := Viewport{
		X0:     0,
		Y0:     0,
		Width:  10 * vg.Inch,
		Height: 8 * vg.Inch,
		Canvas: pngCanvas,
	}
	innerVP := allVP.Sub(0.05, 0.05, 0.9, 0.9)
	bg := GrobRect{xmin: 0, ymin: 0, xmax: 1, ymax: 1, fill: BuiltinColors["gray80"]}
	bg.Draw(innerVP)

	cols := []string{"red", "green", "blue", "cyan", "magenta", "yellow",
		"white", "gray", "black"}

	// Draw points in all shapes, three sizes and all builtin colors.
	points := []Grob{}
	x, y := 0.1, 0.1
	for shape := DotPoint; shape <= StarPoint; shape++ {
		for size := 2; size < 7; size += 2 {
			y = 0.05
			for _, col := range cols {
				g := GrobPoint{
					x:     x,
					y:     y,
					size:  float64(size),
					shape: shape,
					color: BuiltinColors[col],
				}
				points = append(points, g)
				y += 0.035
			}
			x += 0.021
		}
	}
	x, y = 0.02, 0.05
	for _, col := range cols {
		g := GrobText{
			x:     x,
			y:     y,
			text:  col,
			size:  10,
			color: BuiltinColors[col],
			vjust: 0.5,
			hjust: 0,
		}
		points = append(points, g)
		y += 0.035
	}
	x, y = 0.121, 0.36
	for shape := DotPoint; shape <= StarPoint; shape++ {
		dy := float64(shape%2) * 0.015
		g := GrobText{
			x:     x,
			y:     y + dy,
			text:  shape.String(),
			size:  10,
			color: BuiltinColors["black"],
			vjust: 0.5,
			hjust: 0.5,
		}
		points = append(points, g)
		x += 3 * 0.021
	}
	for _, grob := range points {
		grob.Draw(innerVP)
	}

	// Draw lines with different styles and widths.
	lines := []Grob{}
	x, y = 0.1, 0.45
	for lt := SolidLine; lt <= TwodashLine; lt++ {
		x = 0.1
		for size := 1; size < 8; size += 2 {
			g := GrobLine{
				x0:       x,
				y0:       y,
				x1:       x + 0.18,
				y1:       y,
				size:     float64(size),
				linetype: lt,
				color:    BuiltinColors["black"],
			}
			lines = append(lines, g)
			x += 0.22
		}
		y += 0.04
	}
	for _, grob := range lines {
		grob.Draw(innerVP)
	}

	// Draw rectangles
	rectVP := innerVP.Sub(0.1, 0.7, 0.4, 0.3)
	rect := []Grob{}
	bgr := GrobRect{xmin: 0, ymin: 0, xmax: 1, ymax: 1, fill: BuiltinColors["gray40"]}
	bgr.Draw(rectVP)
	x, y = 0.0, 0.0
	w, h := 0.5, 0.5
	for _, col := range cols {
		g := GrobRect{
			xmin: x,
			ymin: y,
			xmax: x + w,
			ymax: y + h,
			fill: BuiltinColors[col],
		}
		rect = append(rect, g)
		x += w
		y += h
		w /= 2
		h /= 2
	}
	for _, grob := range rect {
		grob.Draw(rectVP)
	}

	// Draw path
	pathVP := innerVP.Sub(0.55, 0.7, 0.4, 0.3)
	bgp := GrobRect{xmin: 0, ymin: 0, xmax: 1, ymax: 1, fill: BuiltinColors["gray"]}
	bgp.Draw(pathVP)
	sin := make([]struct{ x, y float64 }, 50)
	for i := range sin {
		k := float64(i) / float64(len(sin)-1)
		x = k * 2 * math.Pi
		println(float64(i)/float64(len(sin)), x, math.Sin(x))
		y = 0.4 * math.Sin(x)
		sin[i].x = k
		sin[i].y = 0.55 + y
	}
	g := GrobPath{
		points:   sin,
		size:     4,
		linetype: SolidLine,
		color:    BuiltinColors["white"],
	}
	g.Draw(pathVP)
	cos := make([]struct{ x, y float64 }, 25)
	for i := range cos {
		k := float64(i) / float64(len(cos)-1)
		x = k * 4 * math.Pi
		y = 0.3 * math.Cos(x)
		cos[i].x = k
		cos[i].y = 0.45 + y
	}
	g = GrobPath{
		points:   cos,
		size:     2,
		linetype: DottedLine,
		color:    BuiltinColors["green"],
	}
	g.Draw(pathVP)

	pngCanvas.WriteTo(file)
	file.Close()
}