func arc(w io.Writer, c *Canvas, comp *vg.PathComp) (x, y float64) {
	r := comp.Radius.Points()
	sin, cos := math.Sincos(comp.Start + comp.Angle)
	x = comp.Pos.X.Points() + r*cos
	y = comp.Pos.Y.Points() + r*sin
	fmt.Fprintf(w, "A%.*g,%.*g 0 %d %d %.*g,%.*g", pr, r, pr, r,
		large(comp.Angle), sweep(comp.Angle), pr, x, pr, y)
	return
}
arc adds arc path data to the given writer.
Arc can only be used if the arc's angle is
less than a full circle, if it is greater then
circle should be used instead.
package vgsvg  
import (
	"bufio"
	"bytes"
	"encoding/base64"
	"fmt"
	"html"
	"image"
	"image/color"
	"image/png"
	"io"
	"math"
	"strings"
	svgo "github.com/ajstarks/svgo"
	xfnt "golang.org/x/image/font"
	"golang.org/x/image/font/sfnt"
	"gonum.org/v1/plot/font"
	"gonum.org/v1/plot/vg"
	"gonum.org/v1/plot/vg/draw"
)
func init() {
	draw.RegisterFormat("svg", func(w, h vg.Length) vg.CanvasWriterTo {
		return New(w, h)
	})
}
const pr = 5
const (
	DefaultWidth  = 4 * vg.Inch
	DefaultHeight = 4 * vg.Inch
)
type Canvas struct {
	svg  *svgo.SVG
	w, h vg.Length
	hdr   *bytes.Buffer  
	buf   *bytes.Buffer  
	stack []context
	embed bool
	fonts map[string]struct{}  
}
type context struct {
	color      color.Color
	dashArray  []vg.Length
	dashOffset vg.Length
	lineWidth  vg.Length
	gEnds      int
}
type option func(*Canvas)
func UseWH(w, h vg.Length) option {
	return func(c *Canvas) {
		if w <= 0 || h <= 0 {
			panic("vgsvg: w and h must both be > 0")
		}
		c.w = w
		c.h = h
	}
}
func EmbedFonts(v bool) option {
	return func(c *Canvas) {
		c.embed = v
	}
}
func New(w, h vg.Length) *Canvas {
	return NewWith(UseWH(w, h))
}
func NewWith(opts ...option) *Canvas {
	buf := new(bytes.Buffer)
	c := &Canvas{
		svg:   svgo.New(buf),
		w:     DefaultWidth,
		h:     DefaultHeight,
		hdr:   new(bytes.Buffer),
		buf:   buf,
		stack: []context{{}},
		embed: false,
		fonts: make(map[string]struct{}),
	}
	for _, opt := range opts {
		opt(c)
	}
	fmt.Fprintf(c.hdr, `<?xml version="1.0"?>
<!-- Generated by SVGo and Plotinum VG -->
<svg width="%.*gpt" height="%.*gpt" viewBox="0 0 %.*g %.*g"
	xmlns="http://www.w3.org/2000/svg"
	xmlns:xlink="http://www.w3.org/1999/xlink">`+"\n",
		pr, c.w,
		pr, c.h,
		pr, c.w,
		pr, c.h,
	)
	if c.embed {
		fmt.Fprintf(c.hdr, "<defs>\n\t<style>\n")
	}
	c.svg.Gtransform(fmt.Sprintf("scale(1, -1) translate(0, -%.*g)", pr, c.h.Points()))
	vg.Initialize(c)
	return c
}
func (c *Canvas) Size() (w, h vg.Length) {
	return c.w, c.h
}
func (c *Canvas) context() *context {
	return &c.stack[len(c.stack)-1]
}
func (c *Canvas) SetLineWidth(w vg.Length) {
	c.context().lineWidth = w
}
func (c *Canvas) SetLineDash(dashes []vg.Length, offs vg.Length) {
	c.context().dashArray = dashes
	c.context().dashOffset = offs
}
func (c *Canvas) SetColor(clr color.Color) {
	c.context().color = clr
}
func (c *Canvas) Rotate(rot float64) {
	rot = rot * 180 / math.Pi
	c.svg.Rotate(rot)
	c.context().gEnds++
}
func (c *Canvas) Translate(pt vg.Point) {
	c.svg.Gtransform(fmt.Sprintf("translate(%.*g, %.*g)", pr, pt.X.Points(), pr, pt.Y.Points()))
	c.context().gEnds++
}
func (c *Canvas) Scale(x, y float64) {
	c.svg.ScaleXY(x, y)
	c.context().gEnds++
}
func (c *Canvas) Push() {
	top := *c.context()
	top.gEnds = 0
	c.stack = append(c.stack, top)
}
func (c *Canvas) Pop() {
	for i := 0; i < c.context().gEnds; i++ {
		c.svg.Gend()
	}
	c.stack = c.stack[:len(c.stack)-1]
}
func (c *Canvas) Stroke(path vg.Path) {
	if c.context().lineWidth.Points() <= 0 {
		return
	}
	c.svg.Path(c.pathData(path),
		style(elm("fill", "#000000", "none"),
			elm("stroke", "none", colorString(c.context().color)),
			elm("stroke-opacity", "1", opacityString(c.context().color)),
			elm("stroke-width", "1", "%.*g", pr, c.context().lineWidth.Points()),
			elm("stroke-dasharray", "none", dashArrayString(c)),
			elm("stroke-dashoffset", "0", "%.*g", pr, c.context().dashOffset.Points())))
}
func (c *Canvas) Fill(path vg.Path) {
	c.svg.Path(c.pathData(path),
		style(elm("fill", "#000000", colorString(c.context().color)),
			elm("fill-opacity", "1", opacityString(c.context().color))))
}
func (c *Canvas) pathData(path vg.Path) string {
	buf := new(bytes.Buffer)
	var x, y float64
	for _, comp := range path {
		switch comp.Type {
		case vg.MoveComp:
			fmt.Fprintf(buf, "M%.*g,%.*g", pr, comp.Pos.X.Points(), pr, comp.Pos.Y.Points())
			x = comp.Pos.X.Points()
			y = comp.Pos.Y.Points()
		case vg.LineComp:
			fmt.Fprintf(buf, "L%.*g,%.*g", pr, comp.Pos.X.Points(), pr, comp.Pos.Y.Points())
			x = comp.Pos.X.Points()
			y = comp.Pos.Y.Points()
		case vg.ArcComp:
			r := comp.Radius.Points()
			sin, cos := math.Sincos(comp.Start)
			x0 := comp.Pos.X.Points() + r*cos
			y0 := comp.Pos.Y.Points() + r*sin
			if x0 != x || y0 != y {
				fmt.Fprintf(buf, "L%.*g,%.*g", pr, x0, pr, y0)
			}
			if math.Abs(comp.Angle) >= 2*math.Pi {
				x, y = circle(buf, c, &comp)
			} else {
				x, y = arc(buf, c, &comp)
			}
		case vg.CurveComp:
			switch len(comp.Control) {
			case 1:
				fmt.Fprintf(buf, "Q%.*g,%.*g,%.*g,%.*g",
					pr, comp.Control[0].X.Points(), pr, comp.Control[0].Y.Points(),
					pr, comp.Pos.X.Points(), pr, comp.Pos.Y.Points())
			case 2:
				fmt.Fprintf(buf, "C%.*g,%.*g,%.*g,%.*g,%.*g,%.*g",
					pr, comp.Control[0].X.Points(), pr, comp.Control[0].Y.Points(),
					pr, comp.Control[1].X.Points(), pr, comp.Control[1].Y.Points(),
					pr, comp.Pos.X.Points(), pr, comp.Pos.Y.Points())
			default:
				panic("vgsvg: invalid number of control points")
			}
			x = comp.Pos.X.Points()
			y = comp.Pos.Y.Points()
		case vg.CloseComp:
			buf.WriteString("Z")
		default:
			panic(fmt.Sprintf("vgsvg: unknown path component type: %d", comp.Type))
		}
	}
	return buf.String()
}
func circle(w io.Writer, c *Canvas, comp *vg.PathComp) (x, y float64) {
	angle := 2 * math.Pi
	if comp.Angle < 0 {
		angle = -2 * math.Pi
	}
	angle += remainder(comp.Angle, 2*math.Pi)
	if angle >= 4*math.Pi {
		panic("Impossible angle")
	}
	s0, c0 := math.Sincos(comp.Start + 0.5*angle)
	s1, c1 := math.Sincos(comp.Start + angle)
	r := comp.Radius.Points()
	x0 := comp.Pos.X.Points() + r*c0
	y0 := comp.Pos.Y.Points() + r*s0
	x = comp.Pos.X.Points() + r*c1
	y = comp.Pos.Y.Points() + r*s1
	fmt.Fprintf(w, "A%.*g,%.*g 0 %d %d %.*g,%.*g", pr, r, pr, r,
		large(angle/2), sweep(angle/2), pr, x0, pr, y0)  
	fmt.Fprintf(w, "A%.*g,%.*g 0 %d %d %.*g,%.*g", pr, r, pr, r,
		large(angle/2), sweep(angle/2), pr, x, pr, y)
	return
}
func remainder(x, y float64) float64 {
	return (x/y - math.Trunc(x/y)) * y
}