func (a *Rotate) ApplyTo(c vg.Canvas) {
	c.Rotate(a.Angle)
}
ApplyTo applies the action to the given vg.Canvas.
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)
}