func (c *Canvas) Comment(text string) {
	c.append(&Comment{Text: text})
}
Comment adds a comment to a list of Actions..
package recorder  
import (
	"bytes"
	"encoding/base64"
	"fmt"
	"image"
	"image/color"
	"image/png"
	"runtime"
	"gonum.org/v1/plot/font"
	"gonum.org/v1/plot/font/liberation"
	"gonum.org/v1/plot/vg"
)
var _ vg.Canvas = (*Canvas)(nil)
type Canvas struct {
	Actions []Action
	KeepCaller bool
	c vg.Canvas
	fonts map[fontID]font.Face
	cache *font.Cache
}
type fontID struct {
	name string
	size vg.Length
}
type Action interface {
	Call() string
	ApplyTo(vg.Canvas)
	callerLocation() *callerLocation
}
type callerLocation struct {
	haveCaller bool
	file       string
	line       int
}
func (l *callerLocation) set() {
	_, l.file, l.line, l.haveCaller = runtime.Caller(3)
}
func (l callerLocation) String() string {
	if !l.haveCaller {
		return ""
	}
	return fmt.Sprintf("%s:%d ", l.file, l.line)
}
func (c *Canvas) Reset() {
	c.Actions = c.Actions[:0]
}
func (c *Canvas) ReplayOn(dst vg.Canvas) error {
	if c.fonts == nil {
		c.fonts = make(map[fontID]font.Face)
	}
	if c.cache == nil {
		c.cache = font.NewCache(liberation.Collection())
	}
	for _, a := range c.Actions {
		fa, ok := a.(*FillString)
		if !ok {
			continue
		}
		f := fontID{name: fa.Font.Name(), size: fa.Size}
		if _, exists := c.fonts[f]; !exists {
			if !c.cache.Has(fa.Font) {
				return fmt.Errorf("Unknown font: %s.", fa.Font.Typeface)
			}
			face := c.cache.Lookup(
				fa.Font,
				fa.Size,
			)
			c.fonts[f] = face
		}
		fa.fonts = c.fonts
	}
	for _, a := range c.Actions {
		a.ApplyTo(dst)
	}
	return nil
}
func (c *Canvas) append(a Action) {
	if c.c != nil {
		a.ApplyTo(c)
	}
	if c.KeepCaller {
		a.callerLocation().set()
	}
	c.Actions = append(c.Actions, a)
}
type SetLineWidth struct {
	Width vg.Length
	l callerLocation
}
func (c *Canvas) SetLineWidth(w vg.Length) {
	c.append(&SetLineWidth{Width: w})
}
func (a *SetLineWidth) Call() string {
	return fmt.Sprintf("%sSetLineWidth(%v)", a.l, a.Width)
}
func (a *SetLineWidth) ApplyTo(c vg.Canvas) {
	c.SetLineWidth(a.Width)
}
func (a *SetLineWidth) callerLocation() *callerLocation {
	return &a.l
}
type SetLineDash struct {
	Dashes  []vg.Length
	Offsets vg.Length
	l callerLocation
}
func (c *Canvas) SetLineDash(dashes []vg.Length, offs vg.Length) {
	c.append(&SetLineDash{
		Dashes:  append([]vg.Length(nil), dashes...),
		Offsets: offs,
	})
}
func (a *SetLineDash) Call() string {
	return fmt.Sprintf("%sSetLineDash(%#v, %v)", a.l, a.Dashes, a.Offsets)
}
func (a *SetLineDash) ApplyTo(c vg.Canvas) {
	c.SetLineDash(a.Dashes, a.Offsets)
}
func (a *SetLineDash) callerLocation() *callerLocation {
	return &a.l
}
type SetColor struct {
	Color color.Color
	l callerLocation
}
func (c *Canvas) SetColor(col color.Color) {
	c.append(&SetColor{Color: col})
}
func (a *SetColor) Call() string {
	return fmt.Sprintf("%sSetColor(%#v)", a.l, a.Color)
}
func (a *SetColor) ApplyTo(c vg.Canvas) {
	c.SetColor(a.Color)
}
func (a *SetColor) callerLocation() *callerLocation {
	return &a.l
}
type Rotate struct {
	Angle float64
	l callerLocation
}
func (c *Canvas) Rotate(a float64) {
	c.append(&Rotate{Angle: a})
}
func (a *Rotate) Call() string {
	return fmt.Sprintf("%sRotate(%v)", a.l, a.Angle)
}
func (a *Rotate) ApplyTo(c vg.Canvas) {
	c.Rotate(a.Angle)
}
func (a *Rotate) callerLocation() *callerLocation {
	return &a.l
}
type Translate struct {
	Point vg.Point
	l callerLocation
}
func (c *Canvas) Translate(pt vg.Point) {
	c.append(&Translate{Point: pt})
}
func (a *Translate) Call() string {
	return fmt.Sprintf("%sTranslate(%v, %v)", a.l, a.Point.X, a.Point.Y)
}
func (a *Translate) ApplyTo(c vg.Canvas) {
	c.Translate(a.Point)
}
func (a *Translate) callerLocation() *callerLocation {
	return &a.l
}
type Scale struct {
	X, Y float64
	l callerLocation
}
func (c *Canvas) Scale(x, y float64) {
	c.append(&Scale{X: x, Y: y})
}
func (a *Scale) Call() string {
	return fmt.Sprintf("%sScale(%v, %v)", a.l, a.X, a.Y)
}
func (a *Scale) ApplyTo(c vg.Canvas) {
	c.Scale(a.X, a.Y)
}
func (a *Scale) callerLocation() *callerLocation {
	return &a.l
}
type Push struct {
	l callerLocation
}
func (c *Canvas) Push() {
	c.append(&Push{})
}
func (a *Push) Call() string {
	return fmt.Sprintf("%sPush()", a.l)
}
func (a *Push) ApplyTo(c vg.Canvas) {
	c.Push()
}
func (a *Push) callerLocation() *callerLocation {
	return &a.l
}
type Pop struct {
	l callerLocation
}
func (c *Canvas) Pop() {
	c.append(&Pop{})
}
func (a *Pop) Call() string {
	return fmt.Sprintf("%sPop()", a.l)
}
func (a *Pop) ApplyTo(c vg.Canvas) {
	c.Pop()
}
func (a *Pop) callerLocation() *callerLocation {
	return &a.l
}
type Stroke struct {
	Path vg.Path
	l callerLocation
}
func (c *Canvas) Stroke(path vg.Path) {
	c.append(&Stroke{Path: append(vg.Path(nil), path...)})
}
func (a *Stroke) Call() string {
	return fmt.Sprintf("%sStroke(%#v)", a.l, a.Path)
}
func (a *Stroke) ApplyTo(c vg.Canvas) {
	c.Stroke(a.Path)
}
func (a *Stroke) callerLocation() *callerLocation {
	return &a.l
}
type Fill struct {
	Path vg.Path
	l callerLocation
}
func (c *Canvas) Fill(path vg.Path) {
	c.append(&Fill{Path: append(vg.Path(nil), path...)})
}
func (a *Fill) Call() string {
	return fmt.Sprintf("%sFill(%#v)", a.l, a.Path)
}
func (a *Fill) ApplyTo(c vg.Canvas) {
	c.Fill(a.Path)
}
func (a *Fill) callerLocation() *callerLocation {
	return &a.l
}
type FillString struct {
	Font   font.Font
	Size   vg.Length
	Point  vg.Point
	String string
	l callerLocation
	fonts map[fontID]font.Face
}
func (c *Canvas) FillString(font font.Face, pt vg.Point, str string) {
	c.append(&FillString{
		Font:   font.Font,
		Size:   font.Font.Size,
		Point:  pt,
		String: str,
	})
}
func (a *FillString) ApplyTo(c vg.Canvas) {
	c.FillString(a.fonts[fontID{name: a.Font.Name(), size: a.Size}], a.Point, a.String)
}
func (a *FillString) Call() string {
	return fmt.Sprintf("%sFillString(%q, %v, %v, %v, %q)", a.l, a.Font.Name(), a.Size, a.Point.X, a.Point.Y, a.String)
}
func (a *FillString) callerLocation() *callerLocation {
	return &a.l
}
type DrawImage struct {
	Rectangle vg.Rectangle
	Image     image.Image
	l callerLocation
}
func (c *Canvas) DrawImage(rect vg.Rectangle, img image.Image) {
	c.append(&DrawImage{
		Rectangle: rect,
		Image:     img,
	})
}
func (a *DrawImage) ApplyTo(c vg.Canvas) {
	c.DrawImage(a.Rectangle, a.Image)
}
func (a *DrawImage) Call() string {
	var buf bytes.Buffer
	err := png.Encode(&buf, a.Image)
	if err != nil {
		panic(fmt.Errorf("recorder: error encoding image to PNG: %v", err))
	}
	b64 := base64.StdEncoding.EncodeToString(buf.Bytes())
	return fmt.Sprintf("%sDrawImage(%#v, {%#v, IMAGE:%s})", a.l, a.Rectangle, a.Image.Bounds(), b64)
}
func (a *DrawImage) callerLocation() *callerLocation {
	return &a.l
}
type Commenter interface {
	Comment(string)
}
var _ Commenter = (*Canvas)(nil)
type Comment struct {
	Text string
	l callerLocation
}