Repository: gonum/plot
Pull request #667 (2021-02-09 13:47:19)

New plot legend
Please take a look.

<!--
Checklist:

- API changes have been discussed
- code is goformated correctly (goimports)
- packages with generated code have had code generation run
- tests pass locally
- linked to relevant issues

Please make sure your commit message summary line and pull request
title match the Go convention; a one-line summary of the change,
prefixed by the primary affected package that should complete the
sentence, "This change modifies Gonum to _____."
-->


codecov-io: # [Codecov](https://codecov.io/gh/gonum/plot/pull/667?src=pr&el=h1) Report
> Merging [#667](https://codecov.io/gh/gonum/plot/pull/667?src=pr&el=desc) (d0ab659) into [master](https://codecov.io/gh/gonum/plot/commit/b77680aef80318563e2e268b9fcc0654f46809a2?el=desc) (b77680a) will **increase** coverage by `0.17%`.
> The diff coverage is `66.66%`.

[![Impacted file tree graph](https://codecov.io/gh/gonum/plot/pull/667/graphs/tree.svg?width=650&height=150&src=pr&token=B6pWWpjnoM)](https://codecov.io/gh/gonum/plot/pull/667?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #667      +/-   ##
==========================================
+ Coverage   70.54%   70.71%   +0.17%     
==========================================
  Files          58       60       +2     
  Lines        5024     5269     +245     
==========================================
+ Hits         3544     3726     +182     
- Misses       1295     1349      +54     
- Partials      185      194       +9     
```


| [Impacted Files](https://codecov.io/gh/gonum/plot/pull/667?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [text/latex.go](https://codecov.io/gh/gonum/plot/pull/667/diff?src=pr&el=tree#diff-dGV4dC9sYXRleC5nbw==) | `90.16% <0.00%> (-0.75%)` | :arrow_down: |
| [text/plain.go](https://codecov.io/gh/gonum/plot/pull/667/diff?src=pr&el=tree#diff-dGV4dC9wbGFpbi5nbw==) | `90.32% <0.00%> (-3.02%)` | :arrow_down: |
| [text/text.go](https://codecov.io/gh/gonum/plot/pull/667/diff?src=pr&el=tree#diff-dGV4dC90ZXh0Lmdv) | `100.00% <ø> (ø)` | |
| [legend.go](https://codecov.io/gh/gonum/plot/pull/667/diff?src=pr&el=tree#diff-bGVnZW5kLmdv) | `96.92% <100.00%> (ø)` | |
| [plot.go](https://codecov.io/gh/gonum/plot/pull/667/diff?src=pr&el=tree#diff-cGxvdC5nbw==) | `70.45% <100.00%> (-0.50%)` | :arrow_down: |
| [vg/vggio/context.go](https://codecov.io/gh/gonum/plot/pull/667/diff?src=pr&el=tree#diff-dmcvdmdnaW8vY29udGV4dC5nbw==) | `100.00% <0.00%> (ø)` | |
| [vg/vggio/vggio.go](https://codecov.io/gh/gonum/plot/pull/667/diff?src=pr&el=tree#diff-dmcvdmdnaW8vdmdnaW8uZ28=) | `72.39% <0.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/gonum/plot/pull/667?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/gonum/plot/pull/667?src=pr&el=footer). Last update [b77680a...d0ab659](https://codecov.io/gh/gonum/plot/pull/667?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/legend.go b/legend.go
index 14487db..9f949c1 100644
--- a/legend.go
+++ b/legend.go
@@ -76,10 +76,9 @@ type Thumbnailer interface {
 	Thumbnail(c *draw.Canvas)
 }
 
-// NewLegend returns a legend with the default
-// parameter settings.
-func NewLegend() (Legend, error) {
-	return newLegend(DefaultTextHandler), nil
+// NewLegend returns a legend with the default parameter settings.
+func NewLegend() Legend {
+	return newLegend(DefaultTextHandler)
 }
 
 func newLegend(hdlr text.Handler) Legend {
diff --git a/plot.go b/plot.go
index 81214cf..09c9ec7 100644
--- a/plot.go
+++ b/plot.go
@@ -58,8 +58,10 @@ type Plot struct {
 	// Legend is the plot's legend.
 	Legend Legend
 
-	// Fonts is the cache of fonts used by this plot.
-	Fonts *font.Cache
+	// TextHandler parses and formats text according to a given
+	// dialect (Markdown, LaTeX, plain, ...)
+	// The default is a plain text handler.
+	TextHandler text.Handler
 
 	// plotters are drawn by calling their Plot method
 	// after the axes are drawn.
@@ -90,20 +92,15 @@ const (
 	vertical
 )
 
-// New returns a new plot with some reasonable
-// default settings.
-func New() (*Plot, error) {
-	var (
-		hdlr  = DefaultTextHandler
-		fonts = font.DefaultCache
-	)
-
+// New returns a new plot with some reasonable default settings.
+func New() *Plot {
+	hdlr := DefaultTextHandler
 	p := &Plot{
 		BackgroundColor: color.White,
 		X:               makeAxis(horizontal),
 		Y:               makeAxis(vertical),
 		Legend:          newLegend(hdlr),
-		Fonts:           fonts,
+		TextHandler:     hdlr,
 	}
 	p.Title.TextStyle = text.Style{
 		Color:   color.Black,
@@ -112,7 +109,7 @@ func New() (*Plot, error) {
 		YAlign:  draw.YTop,
 		Handler: hdlr,
 	}
-	return p, nil
+	return p
 }
 
 // Add adds a Plotters to the plot.
diff --git a/text/latex.go b/text/latex.go
index ed64cf5..6a0ac0f 100644
--- a/text/latex.go
+++ b/text/latex.go
@@ -32,6 +32,11 @@ type Latex struct {
 
 var _ Handler = (*Latex)(nil)
 
+// Cache returns the cache of fonts used by the text handler.
+func (hdlr Latex) Cache() *font.Cache {
+	return hdlr.Fonts
+}
+
 // Extents returns the Extents of a font.
 func (hdlr Latex) Extents(fnt font.Font) font.Extents {
 	face := hdlr.Fonts.Lookup(fnt, fnt.Size)
diff --git a/text/plain.go b/text/plain.go
index 19fca0b..406c7f4 100644
--- a/text/plain.go
+++ b/text/plain.go
@@ -19,6 +19,11 @@ type Plain struct {
 
 var _ Handler = (*Plain)(nil)
 
+// Cache returns the cache of fonts used by the text handler.
+func (hdlr Plain) Cache() *font.Cache {
+	return hdlr.Fonts
+}
+
 // Extents returns the Extents of a font.
 func (hdlr Plain) Extents(fnt font.Font) font.Extents {
 	face := hdlr.Fonts.Lookup(fnt, fnt.Size)
diff --git a/text/text.go b/text/text.go
index fb3a45d..eaed130 100644
--- a/text/text.go
+++ b/text/text.go
@@ -14,6 +14,9 @@ import (
 
 // Handler parses, formats and renders text.
 type Handler interface {
+	// Cache returns the cache of fonts used by the text handler.
+	Cache() *font.Cache
+
 	// Extents returns the Extents of a font.
 	Extents(fnt font.Font) font.Extents
 


Test patch:
diff --git a/align_example_test.go b/align_example_test.go
index 45e742d..85456be 100644
--- a/align_example_test.go
+++ b/align_example_test.go
@@ -26,10 +26,7 @@ func ExampleAlign() {
 				continue
 			}
 
-			p, err := plot.New()
-			if err != nil {
-				panic(err)
-			}
+			p := plot.New()
 
 			if j == 0 && i == 2 {
 				// This shows what happens when the axis padding
@@ -93,11 +90,7 @@ func ExampleAlign() {
 }
 
 func ExampleAxis_labelsPosition() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("could not create plot: %+v", err)
-	}
-
+	p := plot.New()
 	p.Title.Text = "Title"
 	p.X.Label.Text = "X [mm]"
 	p.Y.Label.Text = "Y [A.U.]"
@@ -108,7 +101,7 @@ func ExampleAxis_labelsPosition() {
 	p.Y.Min = -10
 	p.Y.Max = +10
 
-	err = p.Save(10*vg.Centimeter, 10*vg.Centimeter, "testdata/axis_labels.png")
+	err := p.Save(10*vg.Centimeter, 10*vg.Centimeter, "testdata/axis_labels.png")
 	if err != nil {
 		log.Fatalf("could not save plot: %+v", err)
 	}
diff --git a/axis_test.go b/axis_test.go
index fc9e65b..57098ef 100644
--- a/axis_test.go
+++ b/axis_test.go
@@ -156,11 +156,7 @@ func TestAxisPadding(t *testing.T) {
 	for _, padding := range []int{0, 5, 10} {
 		t.Run(fmt.Sprintf("padding-%d", padding), func(t *testing.T) {
 			cmpimg.CheckPlot(func() {
-				p, err := New()
-				if err != nil {
-					t.Fatalf("error: %+v", err)
-				}
-
+				p := New()
 				p.Title.Text = fmt.Sprintf("padding=%d", padding)
 				p.X.Label.Text = "X-Axis"
 				p.X.Label.Padding = vg.Points(float64(padding))
@@ -168,7 +164,7 @@ func TestAxisPadding(t *testing.T) {
 				p.Y.Label.Padding = vg.Points(float64(padding))
 
 				const size = 5 * vg.Centimeter
-				err = p.Save(size, size, fmt.Sprintf("testdata/axis_padding_%02d.png", padding))
+				err := p.Save(size, size, fmt.Sprintf("testdata/axis_padding_%02d.png", padding))
 				if err != nil {
 					t.Fatalf("error: %+v", err)
 				}
diff --git a/gob/gob_test.go b/gob/gob_test.go
index da415fd..21f72fe 100644
--- a/gob/gob_test.go
+++ b/gob/gob_test.go
@@ -33,11 +33,7 @@ func TestPersistency(t *testing.T) {
 	lineData := randomPoints(n, rnd)
 	linePointsData := randomPoints(n, rnd)
 
-	p, err := plot.New()
-	if err != nil {
-		t.Fatalf("error creating plot: %v\n", err)
-	}
-
+	p := plot.New()
 	p.Title.Text = "Plot Example"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
diff --git a/legend_example_test.go b/legend_example_test.go
index 8b57c0b..fefa645 100644
--- a/legend_example_test.go
+++ b/legend_example_test.go
@@ -48,10 +48,7 @@ func ExampleLegend_standalone() {
 	green := exampleThumbnailer{Color: color.NRGBA{G: 255, A: 255}}
 	blue := exampleThumbnailer{Color: color.NRGBA{B: 255, A: 255}}
 
-	l, err := plot.NewLegend()
-	if err != nil {
-		panic(err)
-	}
+	l := plot.NewLegend()
 	l.Add("red", red)
 	l.Add("green", green)
 	l.Add("blue", blue)
@@ -90,6 +87,7 @@ func ExampleLegend_standalone() {
 		panic(err)
 	}
 	defer w.Close()
+
 	png := vgimg.PngCanvas{Canvas: c}
 	if _, err := png.WriteTo(w); err != nil {
 		panic(err)
diff --git a/palette/moreland/example_test.go b/palette/moreland/example_test.go
index b903d9d..f400aa1 100644
--- a/palette/moreland/example_test.go
+++ b/palette/moreland/example_test.go
@@ -119,10 +119,7 @@ func Example() {
 
 		h := plotter.NewHeatMap(m, plte.cmap)
 
-		p, err := plot.New()
-		if err != nil {
-			log.Panic(err)
-		}
+		p := plot.New()
 		p.Title.Text = plte.name
 
 		p.Add(h)
diff --git a/palette/reverse_example_test.go b/palette/reverse_example_test.go
index 810b087..dc1de92 100644
--- a/palette/reverse_example_test.go
+++ b/palette/reverse_example_test.go
@@ -17,10 +17,7 @@ import (
 // This example creates a color bar and a second color bar where the
 // direction of the colors are reversed.
 func ExampleReverse() {
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	l := &plotter.ColorBar{ColorMap: moreland.Kindlmann()}
 	l2 := &plotter.ColorBar{ColorMap: palette.Reverse(moreland.Kindlmann())}
 	l.ColorMap.SetMin(0.5)
@@ -33,17 +30,14 @@ func ExampleReverse() {
 	p.X.Padding = 0
 	p.Title.Text = "A ColorMap and its Reverse"
 
-	if err = p.Save(300, 48, "testdata/reverse.png"); err != nil {
+	if err := p.Save(300, 48, "testdata/reverse.png"); err != nil {
 		log.Panic(err)
 	}
 }
 
 // This example creates a color palette from a reversed ColorMap.
 func ExampleReverse_palette() {
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	thumbs := plotter.PaletteThumbnailers(palette.Reverse(moreland.Kindlmann()).Palette(10))
 	for i, t := range thumbs {
 		p.Legend.Add(fmt.Sprint(i), t)
@@ -52,7 +46,7 @@ func ExampleReverse_palette() {
 	p.X.Padding = 0
 	p.Y.Padding = 0
 
-	if err = p.Save(35, 120, "testdata/reverse_palette.png"); err != nil {
+	if err := p.Save(35, 120, "testdata/reverse_palette.png"); err != nil {
 		log.Panic(err)
 	}
 }
diff --git a/plot_test.go b/plot_test.go
index 3a3286e..1d952e4 100644
--- a/plot_test.go
+++ b/plot_test.go
@@ -88,11 +88,7 @@ func TestIssue514(t *testing.T) {
 			go func() {
 				defer close(done)
 
-				p, err := plot.New()
-				if err != nil {
-					t.Errorf("could not create plot: %v", err)
-					return
-				}
+				p := plot.New()
 
 				var (
 					y1 = 100.0
diff --git a/plotter/barchart_example_test.go b/plotter/barchart_example_test.go
index 828562d..8599686 100644
--- a/plotter/barchart_example_test.go
+++ b/plotter/barchart_example_test.go
@@ -22,10 +22,7 @@ func ExampleBarChart() {
 	horizontalLabels := []string{"Label A", "Label B", "Label C", "Label D"}
 
 	// Create a vertical BarChart
-	p1, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p1 := plot.New()
 	verticalBarChart, err := plotter.NewBarChart(values, 0.5*vg.Centimeter)
 	if err != nil {
 		log.Panic(err)
@@ -38,10 +35,7 @@ func ExampleBarChart() {
 	}
 
 	// Create a horizontal BarChart
-	p2, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p2 := plot.New()
 	horizontalBarChart, err := plotter.NewBarChart(values, 0.5*vg.Centimeter)
 	horizontalBarChart.Horizontal = true // Specify a horizontal BarChart.
 	if err != nil {
@@ -60,10 +54,7 @@ func ExampleBarChart() {
 	groupC := plotter.Values{12, 28, 15, 21, 8}
 	groupD := plotter.Values{30, 42, 6, 9, 12}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Bar chart"
 	p.Y.Label.Text = "Heights"
 
@@ -115,10 +106,7 @@ func ExampleBarChart() {
 	}
 
 	// Now, make a stacked BarChart.
-	p, err = plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p = plot.New()
 	p.Title.Text = "Bar chart"
 	p.Y.Label.Text = "Heights"
 
@@ -243,10 +231,7 @@ func ExampleBarChart_positiveNegative() {
 		log.Panic(err)
 	}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Add(zero, pos1, pos2, neg1, neg2, netDots)
 	p.NominalY("Alpha", "Bravo", "Charlie", "Echo", "Foxtrot", "Golf")
 
diff --git a/plotter/boxplot_example_test.go b/plotter/boxplot_example_test.go
index f5576a0..8f8b271 100644
--- a/plotter/boxplot_example_test.go
+++ b/plotter/boxplot_example_test.go
@@ -60,10 +60,7 @@ func ExampleBoxPlot() {
 		log.Panic(err)
 	}
 
-	p1, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p1 := plot.New()
 	p1.Title.Text = "Vertical Box Plot"
 	p1.Y.Label.Text = "plotter.Values"
 	p1.Y.Max = 6
@@ -97,10 +94,7 @@ func ExampleBoxPlot() {
 		log.Panic(err)
 	}
 
-	p2, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p2 := plot.New()
 	p2.Title.Text = "Horizontal Box Plot"
 	p2.X.Label.Text = "plotter.Values"
 
@@ -117,10 +111,7 @@ func ExampleBoxPlot() {
 	}
 
 	// Now, make a grouped box plot.
-	p3, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p3 := plot.New()
 	p3.Title.Text = "Box Plot"
 	p3.Y.Label.Text = "plotter.Values"
 
diff --git a/plotter/bubbles_example_test.go b/plotter/bubbles_example_test.go
index 62ccd54..ae820c6 100644
--- a/plotter/bubbles_example_test.go
+++ b/plotter/bubbles_example_test.go
@@ -52,10 +52,7 @@ func ExampleScatter_bubbles() {
 		}
 	}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Bubbles"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
diff --git a/plotter/colorbar_example_test.go b/plotter/colorbar_example_test.go
index c9f4c46..d1f908c 100644
--- a/plotter/colorbar_example_test.go
+++ b/plotter/colorbar_example_test.go
@@ -14,29 +14,24 @@ import (
 )
 
 func ExampleColorBar_horizontal() {
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
+	p.HideY()
+	p.X.Padding = 0
+	p.Title.Text = "Title"
+
 	l := &plotter.ColorBar{ColorMap: moreland.ExtendedBlackBody()}
 	l.ColorMap.SetMin(0.5)
 	l.ColorMap.SetMax(1.5)
 	p.Add(l)
-	p.HideY()
-	p.X.Padding = 0
-	p.Title.Text = "Title"
 
-	if err = p.Save(300, 48, "testdata/colorBarHorizontal.png"); err != nil {
+	if err := p.Save(300, 48, "testdata/colorBarHorizontal.png"); err != nil {
 		log.Panic(err)
 	}
 }
 
 // This example shows how to create a ColorBar on a log-transformed axis.
 func ExampleColorBar_horizontal_log() {
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	colorMap, err := moreland.NewLuminance([]color.Color{color.Black, color.White})
 	if err != nil {
 		log.Panic(err)
@@ -57,10 +52,7 @@ func ExampleColorBar_horizontal_log() {
 }
 
 func ExampleColorBar_vertical() {
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	l := &plotter.ColorBar{ColorMap: moreland.ExtendedBlackBody()}
 	l.ColorMap.SetMin(0.5)
 	l.ColorMap.SetMax(1.5)
@@ -70,7 +62,7 @@ func ExampleColorBar_vertical() {
 	p.Y.Padding = 0
 	p.Title.Text = "Title"
 
-	if err = p.Save(40, 300, "testdata/colorBarVertical.png"); err != nil {
+	if err := p.Save(40, 300, "testdata/colorBarVertical.png"); err != nil {
 		log.Panic(err)
 	}
 }
diff --git a/plotter/contour_example_test.go b/plotter/contour_example_test.go
index 412e98f..6425ca8 100644
--- a/plotter/contour_example_test.go
+++ b/plotter/contour_example_test.go
@@ -42,11 +42,7 @@ func ExampleContour() {
 		)
 	)
 
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("could not create plot: %+v", err)
-	}
-
+	p := plot.New()
 	p.Title.Text = "Contour"
 	p.X.Padding = 0
 	p.Y.Padding = 0
@@ -55,7 +51,7 @@ func ExampleContour() {
 
 	p.Add(c)
 
-	err = p.Save(10*vg.Centimeter, 10*vg.Centimeter, "testdata/contour.png")
+	err := p.Save(10*vg.Centimeter, 10*vg.Centimeter, "testdata/contour.png")
 	if err != nil {
 		log.Fatalf("could not save plot: %+v", err)
 	}
diff --git a/plotter/contour_test.go b/plotter/contour_test.go
index bdce8c2..995610e 100644
--- a/plotter/contour_test.go
+++ b/plotter/contour_test.go
@@ -56,11 +56,7 @@ func TestHeatMapWithContour(t *testing.T) {
 	c := NewContour(m, levels, palette.Rainbow(10, palette.Blue, palette.Red, 1, 1, 1))
 	c.LineStyles[0].Width *= 5
 
-	plt, err := plot.New()
-	if err != nil {
-		t.Fatalf("could not create plot: %+v", err)
-	}
-
+	plt := plot.New()
 	plt.Add(h)
 	plt.Add(c)
 	plt.Add(NewGlyphBoxes())
@@ -69,7 +65,8 @@ func TestHeatMapWithContour(t *testing.T) {
 	plt.Y.Padding = 0
 	plt.X.Max = 3.5
 	plt.Y.Max = 2.5
-	err = plt.Save(7, 7, "heat.svg")
+
+	err := plt.Save(7*vg.Centimeter, 7*vg.Centimeter, "heat.svg")
 	if err != nil {
 		t.Fatalf("could not save plot: %+v", err)
 	}
@@ -95,18 +92,15 @@ func TestComplexContours(t *testing.T) {
 		levels := []float64{-1, 3, 7, 9, 13, 15, 19, 23, 27, 31}
 		c := NewContour(m, levels, palette.Rainbow(10, palette.Blue, palette.Red, 1, 1, 1))
 
-		plt, err := plot.New()
-		if err != nil {
-			t.Fatalf("could not create plot: %+v", err)
-		}
-
-		plt.Add(c)
-
+		plt := plot.New()
 		plt.X.Padding = 0
 		plt.Y.Padding = 0
 		plt.X.Max = 79.5
 		plt.Y.Max = 79.5
-		err = plt.Save(7, 7, fmt.Sprintf("complex_contour-%v.svg", n))
+
+		plt.Add(c)
+
+		err := plt.Save(7*vg.Centimeter, 7*vg.Centimeter, fmt.Sprintf("complex_contour-%v.svg", n))
 		if err != nil {
 			t.Fatalf("could not save plot: %+v", err)
 		}
diff --git a/plotter/errbars_example_test.go b/plotter/errbars_example_test.go
index ae676fb..60283e3 100644
--- a/plotter/errbars_example_test.go
+++ b/plotter/errbars_example_test.go
@@ -54,10 +54,7 @@ func ExampleErrors() {
 		XErrors: plotter.XErrors(randomError(n)),
 	}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	scatter, err := plotter.NewScatter(data)
 	if err != nil {
 		log.Panic(err)
diff --git a/plotter/field_example_test.go b/plotter/field_example_test.go
index a5994e8..55d2855 100644
--- a/plotter/field_example_test.go
+++ b/plotter/field_example_test.go
@@ -31,12 +31,8 @@ func ExampleField() {
 	})
 	f.LineStyle.Width = 0.2
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Vector field"
-
 	p.X.Tick.Marker = integerTicks{}
 	p.Y.Tick.Marker = integerTicks{}
 
@@ -99,12 +95,8 @@ func ExampleField_colors() {
 		c.Stroke(pa)
 	}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Vortex"
-
 	p.X.Tick.Marker = integerTicks{}
 	p.Y.Tick.Marker = integerTicks{}
 
@@ -161,12 +153,8 @@ func ExampleField_gophers() {
 		c.DrawImage(vg.Rectangle{Max: vg.Point{X: 2, Y: 2}}, gopher)
 	}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Gopher vortex"
-
 	p.X.Tick.Marker = integerTicks{}
 	p.Y.Tick.Marker = integerTicks{}
 
diff --git a/plotter/field_test.go b/plotter/field_test.go
index eda444d..c392745 100644
--- a/plotter/field_test.go
+++ b/plotter/field_test.go
@@ -73,10 +73,7 @@ func TestFieldDims(t *testing.T) {
 				},
 			})
 
-			p, err := plot.New()
-			if err != nil {
-				t.Errorf("unexpected error: %v", err)
-			}
+			p := plot.New()
 			p.Add(f)
 
 			img := vgimg.New(250, 175)
diff --git a/plotter/filledLine_example_test.go b/plotter/filledLine_example_test.go
index 94258e4..2be2215 100644
--- a/plotter/filledLine_example_test.go
+++ b/plotter/filledLine_example_test.go
@@ -32,10 +32,7 @@ func ExampleLine_filledLine() {
 		return pts
 	}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Filled Line Example"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
diff --git a/plotter/filledLine_test.go b/plotter/filledLine_test.go
index 1c2c486..26430b3 100644
--- a/plotter/filledLine_test.go
+++ b/plotter/filledLine_test.go
@@ -35,10 +35,7 @@ func clippedFilledLine() {
 		return pts
 	}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Filled Line Example"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
diff --git a/plotter/functions_example_test.go b/plotter/functions_example_test.go
index 539a7ef..331bb87 100644
--- a/plotter/functions_example_test.go
+++ b/plotter/functions_example_test.go
@@ -29,11 +29,7 @@ func ExampleFunction() {
 	sin.Width = vg.Points(4)
 	sin.Color = color.RGBA{R: 255, A: 255}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
-
+	p := plot.New()
 	p.Title.Text = "Functions"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
@@ -49,7 +45,7 @@ func ExampleFunction() {
 	p.Y.Min = 0
 	p.Y.Max = 100
 
-	err = p.Save(200, 200, "testdata/functions.png")
+	err := p.Save(200, 200, "testdata/functions.png")
 	if err != nil {
 		log.Panic(err)
 	}
diff --git a/plotter/general_example_test.go b/plotter/general_example_test.go
index e245fa9..22f5e51 100644
--- a/plotter/general_example_test.go
+++ b/plotter/general_example_test.go
@@ -14,10 +14,7 @@ import (
 
 // Draw the plot logo.
 func Example() {
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 
 	plotter.DefaultLineStyle.Width = vg.Points(1)
 	plotter.DefaultGlyphStyle.Radius = vg.Points(3)
diff --git a/plotter/heat_example_test.go b/plotter/heat_example_test.go
index 971ad75..6a4130d 100644
--- a/plotter/heat_example_test.go
+++ b/plotter/heat_example_test.go
@@ -30,10 +30,7 @@ func ExampleHeatMap() {
 	pal := palette.Heat(12, 1)
 	h := plotter.NewHeatMap(m, pal)
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Heat map"
 
 	p.X.Tick.Marker = integerTicks{}
@@ -42,10 +39,7 @@ func ExampleHeatMap() {
 	p.Add(h)
 
 	// Create a legend.
-	l, err := plot.NewLegend()
-	if err != nil {
-		log.Panic(err)
-	}
+	l := plot.NewLegend()
 	thumbs := plotter.PaletteThumbnailers(pal)
 	for i := len(thumbs) - 1; i >= 0; i-- {
 		t := thumbs[i]
diff --git a/plotter/heat_rasterized_example_test.go b/plotter/heat_rasterized_example_test.go
index 3054272..45b8c58 100644
--- a/plotter/heat_rasterized_example_test.go
+++ b/plotter/heat_rasterized_example_test.go
@@ -24,16 +24,13 @@ func ExampleHeatMap_rasterized() {
 		})}
 
 	pal := palette.Heat(12, 1)
-	plt, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	plt := plot.New()
 
 	raster := plotter.NewHeatMap(&m, pal)
 	raster.Rasterized = true
 	plt.Add(raster)
 
-	err = plt.Save(250, 175, "testdata/rasterHeatMap.png")
+	err := plt.Save(250, 175, "testdata/rasterHeatMap.png")
 	if err != nil {
 		log.Panic(err)
 	}
diff --git a/plotter/heat_test.go b/plotter/heat_test.go
index f4e243a..0ae8189 100644
--- a/plotter/heat_test.go
+++ b/plotter/heat_test.go
@@ -77,10 +77,7 @@ func TestHeatMapDims(t *testing.T) {
 			m := offsetUnitGrid{Data: mat.NewDense(test.rows, test.cols, nil)}
 			h := plotter.NewHeatMap(m, pal)
 
-			p, err := plot.New()
-			if err != nil {
-				t.Errorf("unexpected error: %v", err)
-			}
+			p := plot.New()
 			p.Add(h)
 
 			img := vgimg.New(250, 175)
diff --git a/plotter/histogram_example_test.go b/plotter/histogram_example_test.go
index eeec9c9..1e90b00 100644
--- a/plotter/histogram_example_test.go
+++ b/plotter/histogram_example_test.go
@@ -35,10 +35,7 @@ func ExampleHistogram() {
 		vals[i] = rnd.NormFloat64()
 	}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Histogram"
 	h, err := plotter.NewHist(vals, 16)
 	if err != nil {
@@ -60,10 +57,7 @@ func ExampleHistogram() {
 }
 
 func ExampleHistogram_logScaleY() {
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Histogram in log-y"
 	p.Y.Scale = plot.LogScale{}
 	p.Y.Tick.Marker = plot.LogTicks{}
diff --git a/plotter/histogram_test.go b/plotter/histogram_test.go
index c1ccadc..f6a072c 100644
--- a/plotter/histogram_test.go
+++ b/plotter/histogram_test.go
@@ -22,12 +22,7 @@ func TestSingletonHistogram(t *testing.T) {
 	done := make(chan struct{}, 1)
 	go func() {
 		defer close(done)
-		p, err := plot.New()
-		if err != nil {
-			t.Errorf("unexpected error from plot.New: %v", err)
-			return
-		}
-
+		p := plot.New()
 		hist, err := plotter.NewHist(plotter.Values([]float64{1.0}), 60)
 		if err != nil {
 			t.Errorf("unexpected error from NewHist: %v", err)
diff --git a/plotter/image_example_test.go b/plotter/image_example_test.go
index d1cb8b3..802e92f 100644
--- a/plotter/image_example_test.go
+++ b/plotter/image_example_test.go
@@ -16,10 +16,7 @@ import (
 
 // An example of embedding an image in a plot.
 func ExampleImage() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("error: %v\n", err)
-	}
+	p := plot.New()
 	p.Title.Text = "A Logo"
 
 	// load an image
@@ -49,10 +46,7 @@ func ExampleImage() {
 
 // An example of embedding an image in a plot with non-linear axes.
 func ExampleImage_log() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("error: %v\n", err)
-	}
+	p := plot.New()
 	p.Title.Text = "A Logo"
 
 	// load an image
diff --git a/plotter/invertedaxis_example_test.go b/plotter/invertedaxis_example_test.go
index c4b2e6d..5231806 100644
--- a/plotter/invertedaxis_example_test.go
+++ b/plotter/invertedaxis_example_test.go
@@ -18,11 +18,7 @@ func Example_invertedScale() {
 	// This example is nearly identical to the LogScale, other than
 	// both the X and Y axes are inverted. InvertedScale expects to act
 	// on another Normalizer - which should allow for more flexibility
-	p, err := plot.New()
-	if err != nil {
-		log.Fatal(err)
-	}
-
+	p := plot.New()
 	p.Title.Text = "Example of inverted axes"
 	p.Y.Scale = plot.InvertedScale{Normalizer: plot.LogScale{}}
 	p.X.Scale = plot.InvertedScale{Normalizer: plot.LinearScale{}}
@@ -47,7 +43,7 @@ func Example_invertedScale() {
 	p.Y.Min = math.Exp(f.XMin)
 	p.Y.Max = math.Exp(f.XMax)
 
-	err = p.Save(10*vg.Centimeter, 10*vg.Centimeter, "testdata/invertedlogscale.png")
+	err := p.Save(10*vg.Centimeter, 10*vg.Centimeter, "testdata/invertedlogscale.png")
 	if err != nil {
 		log.Panic(err)
 	}
diff --git a/plotter/labels_example_test.go b/plotter/labels_example_test.go
index 018583e..a89cc7e 100644
--- a/plotter/labels_example_test.go
+++ b/plotter/labels_example_test.go
@@ -16,11 +16,7 @@ import (
 )
 
 func ExampleLabels() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("could not create plot: %+v", err)
-	}
-
+	p := plot.New()
 	p.Title.Text = "Labels"
 	p.X.Min = -10
 	p.X.Max = +10
@@ -55,11 +51,7 @@ func ExampleLabels() {
 // always in the same location of a plot, irrespective of the minute
 // details of a particular plot data range.
 func ExampleLabels_inCanvasCoordinates() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("could not create plot: %+v", err)
-	}
-
+	p := plot.New()
 	p.Title.Text = "Labels - X"
 	p.X.Min = -10
 	p.X.Max = +10
@@ -97,7 +89,7 @@ func ExampleLabels_inCanvasCoordinates() {
 
 	// Put an 'X' in the middle of the data-canvas.
 	{
-		fnt := p.Fonts.Lookup(plotter.DefaultFont, vg.Points(12))
+		fnt := p.TextHandler.Cache().Lookup(plotter.DefaultFont, vg.Points(12))
 		da := p.DataCanvas(dc)
 		da.FillString(fnt, vg.Point{X: da.X(0.5), Y: da.Y(0.5)}, "X")
 	}
diff --git a/plotter/labels_test.go b/plotter/labels_test.go
index c4de511..19b4e46 100644
--- a/plotter/labels_test.go
+++ b/plotter/labels_test.go
@@ -28,11 +28,7 @@ func TestLabelsWithGlyphBoxes(t *testing.T) {
 		func() {
 			const fontSize = 24
 
-			p, err := plot.New()
-			if err != nil {
-				t.Fatalf("could not create plot: %+v", err)
-			}
-
+			p := plot.New()
 			p.Title.Text = "Labels"
 			p.X.Min = -1
 			p.X.Max = +1
diff --git a/plotter/logscale_example_test.go b/plotter/logscale_example_test.go
index 5caeb5d..43194b3 100644
--- a/plotter/logscale_example_test.go
+++ b/plotter/logscale_example_test.go
@@ -16,11 +16,7 @@ import (
 
 // Example_logScale shows how to create a plot with a log-scale on the Y-axis.
 func Example_logScale() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatal(err)
-	}
-
+	p := plot.New()
 	p.Title.Text = "My Plot"
 	p.Y.Scale = plot.LogScale{}
 	p.Y.Tick.Marker = plot.LogTicks{}
@@ -40,7 +36,7 @@ func Example_logScale() {
 	p.Y.Min = math.Exp(f.XMin)
 	p.Y.Max = math.Exp(f.XMax)
 
-	err = p.Save(10*vg.Centimeter, 10*vg.Centimeter, "testdata/logscale.png")
+	err := p.Save(10*vg.Centimeter, 10*vg.Centimeter, "testdata/logscale.png")
 	if err != nil {
 		log.Panic(err)
 	}
diff --git a/plotter/polygon_example_test.go b/plotter/polygon_example_test.go
index 18209ba..a6d87bc 100644
--- a/plotter/polygon_example_test.go
+++ b/plotter/polygon_example_test.go
@@ -40,10 +40,7 @@ func ExamplePolygon_holes() {
 	}
 	poly.Color = color.NRGBA{B: 255, A: 255}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Polygon with holes"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
@@ -95,10 +92,8 @@ func ExamplePolygon_hexagons() {
 		return g
 	}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	var err error
+	p := plot.New()
 	p.Title.Text = "Hexagons"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
diff --git a/plotter/polygon_test.go b/plotter/polygon_test.go
index 36cf525..79907c7 100644
--- a/plotter/polygon_test.go
+++ b/plotter/polygon_test.go
@@ -34,11 +34,7 @@ func TestPolygon_clip(t *testing.T) {
 		t.Fatal(err)
 	}
 	poly.Color = color.Black // Give the polygon a color to fill.
-	p, err := plot.New()
-	if err != nil {
-		t.Fatal(err)
-	}
-
+	p := plot.New()
 	// Set the plotting range so that the polygon is outside of it.
 	p.X.Min = 2
 	p.X.Max = 5
diff --git a/plotter/precision_test.go b/plotter/precision_test.go
index 37be0b2..77a47cf 100644
--- a/plotter/precision_test.go
+++ b/plotter/precision_test.go
@@ -17,11 +17,7 @@ func TestFloatPrecision(t *testing.T) {
 	const fname = "precision.png"
 
 	cmpimg.CheckPlot(func() {
-		p, err := plot.New()
-		if err != nil {
-			log.Fatal(err)
-		}
-
+		p := plot.New()
 		p.X.Label.Text = "x"
 		p.Y.Label.Text = "y"
 
diff --git a/plotter/quartile_example_test.go b/plotter/quartile_example_test.go
index 1ba0549..90b62fa 100644
--- a/plotter/quartile_example_test.go
+++ b/plotter/quartile_example_test.go
@@ -43,10 +43,7 @@ func ExampleQuartPlot() {
 	}
 
 	// Create a vertical plot
-	p1, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p1 := plot.New()
 	p1.Title.Text = "Quartile Plot"
 	p1.Y.Label.Text = "plotter.Values"
 	p1.Add(qp1, qp2, qp3)
@@ -66,10 +63,7 @@ func ExampleQuartPlot() {
 	qp2.Horizontal = true
 	qp3.Horizontal = true
 
-	p2, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p2 := plot.New()
 	p2.Title.Text = "Quartile Plot"
 	p2.X.Label.Text = "plotter.Values"
 	p2.Add(qp1, qp2, qp3)
@@ -86,10 +80,7 @@ func ExampleQuartPlot() {
 
 	// Now, create a grouped quartile plot.
 
-	p3, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p3 := plot.New()
 	p3.Title.Text = "Box Plot"
 	p3.Y.Label.Text = "plotter.Values"
 
diff --git a/plotter/rotation_example_test.go b/plotter/rotation_example_test.go
index 9056955..a804677 100644
--- a/plotter/rotation_example_test.go
+++ b/plotter/rotation_example_test.go
@@ -36,10 +36,7 @@ func Example_rotation() {
 	// These points are our label locations.
 	labelPoints := sin(8, xmax)
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Rotation Example"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "100 × Sine X"
diff --git a/plotter/sankey_example_test.go b/plotter/sankey_example_test.go
index 20c6170..9f0a29f 100644
--- a/plotter/sankey_example_test.go
+++ b/plotter/sankey_example_test.go
@@ -21,10 +21,7 @@ import (
 // ExampleSankey_sample creates a simple sankey diagram.
 // The output can be found at https://github.com/gonum/plot/blob/master/plotter/testdata/sankeySimple_golden.png.
 func ExampleSankey_simple() {
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 
 	// Define the stock categories
 	const (
@@ -144,10 +141,7 @@ func ExampleSankey_simple() {
 // ExampleSankey_grouped creates a sankey diagram with grouped flows.
 // The output can be found at https://github.com/gonum/plot/blob/master/plotter/testdata/sankeyGrouped_golden.png.
 func ExampleSankey_grouped() {
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	c := vgimg.New(vg.Points(300), vg.Points(180))
 	dc := draw.New(c)
 
diff --git a/plotter/sankey_test.go b/plotter/sankey_test.go
index 6a5b057..d2d11f4 100644
--- a/plotter/sankey_test.go
+++ b/plotter/sankey_test.go
@@ -46,10 +46,7 @@ func TestSankey_idempotent(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	p, err := plot.New()
-	if err != nil {
-		t.Fatal(err)
-	}
+	p := plot.New()
 	p.Add(s)
 	p.HideAxes()
 
diff --git a/plotter/scatterColor_example_test.go b/plotter/scatterColor_example_test.go
index 41b6c67..982d457 100644
--- a/plotter/scatterColor_example_test.go
+++ b/plotter/scatterColor_example_test.go
@@ -59,10 +59,7 @@ func ExampleScatter_color() {
 	colors.SetMax(maxZ)
 	colors.SetMin(minZ)
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Colored Points Example"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
diff --git a/plotter/scatter_example_test.go b/plotter/scatter_example_test.go
index c3934b6..9d354bc 100644
--- a/plotter/scatter_example_test.go
+++ b/plotter/scatter_example_test.go
@@ -41,10 +41,7 @@ func ExampleScatter() {
 	lineData := randomPoints(n)
 	linePointsData := randomPoints(n)
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Points Example"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
diff --git a/plotter/step_example_test.go b/plotter/step_example_test.go
index cd6822e..8c4a0de 100644
--- a/plotter/step_example_test.go
+++ b/plotter/step_example_test.go
@@ -32,10 +32,7 @@ func ExampleLine_stepLine() {
 
 	n := 4
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Step Example"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
diff --git a/plotter/timeseries_example_test.go b/plotter/timeseries_example_test.go
index f83b93a..1533154 100644
--- a/plotter/timeseries_example_test.go
+++ b/plotter/timeseries_example_test.go
@@ -47,10 +47,7 @@ func Example_timeSeries() {
 	n := 10
 	data := randomPoints(n)
 
-	p, err := plot.New()
-	if err != nil {
-		log.Panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Time Series"
 	p.X.Tick.Marker = xticks
 	p.Y.Label.Text = "Number of Gophers\n(Billions)"
diff --git a/plotter/volcano_example_test.go b/plotter/volcano_example_test.go
index ab6dfaa..3cc7250 100644
--- a/plotter/volcano_example_test.go
+++ b/plotter/volcano_example_test.go
@@ -56,10 +56,7 @@ func Example_volcano() {
 
 	h := plotter.NewHeatMap(volcano, palette.Heat(len(levels)*2, 1))
 
-	p, err := plot.New()
-	if err != nil {
-		panic(err)
-	}
+	p := plot.New()
 	p.Title.Text = "Maunga Whau Volcano"
 
 	p.Add(h)
diff --git a/plotutil/errorpoints_example_test.go b/plotutil/errorpoints_example_test.go
index d3973b3..3b7e7d3 100644
--- a/plotutil/errorpoints_example_test.go
+++ b/plotutil/errorpoints_example_test.go
@@ -28,10 +28,7 @@ func ExampleErrorPoints() {
 		}
 	}
 
-	plt, err := plot.New()
-	if err != nil {
-		panic(err)
-	}
+	plt := plot.New()
 
 	mean95, err := plotutil.NewErrorPoints(plotutil.MeanAndConf95, pts...)
 	if err != nil {
diff --git a/text/latex_example_test.go b/text/latex_example_test.go
index 949c8f4..29dc410 100644
--- a/text/latex_example_test.go
+++ b/text/latex_example_test.go
@@ -26,11 +26,7 @@ func ExampleLatex() {
 		Fonts: fonts,
 	}
 
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("could not create plot: %+v", err)
-	}
-
+	p := plot.New()
 	p.Title.Text = `$f(x) = \sqrt{\alpha x \Gamma}$`
 	p.X.Label.Text = `$\frac{\sqrt{x}}{2\pi\Gamma\gamma}$`
 	p.Y.Label.Text = `$\beta$`
diff --git a/vg/example_test.go b/vg/example_test.go
index 45a623a..6937677 100644
--- a/vg/example_test.go
+++ b/vg/example_test.go
@@ -59,10 +59,7 @@ func Example_addFont() {
 	plot.DefaultFont = mincho
 	plotter.DefaultFont = mincho
 
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("could not create plot: %+v", err)
-	}
+	p := plot.New()
 	p.Title.Text = "Hello, 世界!"
 	p.X.Label.Text = "世"
 	p.Y.Label.Text = "界"
@@ -116,11 +113,7 @@ func untargz(name string, r io.Reader) ([]byte, error) {
 }
 
 func Example_inMemoryCanvas() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("could not create plot: %+v", err)
-	}
-
+	p := plot.New()
 	p.Title.Text = "sin(x)"
 	p.X.Label.Text = "x"
 	p.Y.Label.Text = "f(x)"
@@ -157,11 +150,7 @@ func Example_inMemoryCanvas() {
 }
 
 func Example_writerToCanvas() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("could not create plot: %+v", err)
-	}
-
+	p := plot.New()
 	p.Title.Text = "cos(x)"
 	p.X.Label.Text = "x"
 	p.Y.Label.Text = "f(x)"
diff --git a/vg/tee_test.go b/vg/tee_test.go
index 65dc4fd..bdf09ea 100644
--- a/vg/tee_test.go
+++ b/vg/tee_test.go
@@ -19,11 +19,7 @@ import (
 )
 
 func TestMultiCanvas(t *testing.T) {
-	p, err := plot.New()
-	if err != nil {
-		t.Fatal(err)
-	}
-
+	p := plot.New()
 	p.Title.Text = "Title"
 	p.X.Label.Text = "x"
 	p.Y.Label.Text = "y"
diff --git a/vg/vg_test.go b/vg/vg_test.go
index ecf884b..42f8467 100644
--- a/vg/vg_test.go
+++ b/vg/vg_test.go
@@ -80,20 +80,16 @@ func TestLineWidth(t *testing.T) {
 }
 
 func lines(w vg.Length) (*plot.Plot, error) {
-	p, err := plot.New()
-	if err != nil {
-		return nil, err
-	}
-
+	p := plot.New()
 	pts := plotter.XYs{
 		{X: 0, Y: 0}, {X: 0, Y: 1},
 		{X: 1, Y: 0}, {X: 1, Y: 1},
 	}
 	line, err := plotter.NewLine(pts)
-	line.Width = w
 	if err != nil {
 		return nil, err
 	}
+	line.Width = w
 	p.Add(line)
 	p.X.Label.Text = "X label"
 	p.Y.Label.Text = "Y label"
diff --git a/vg/vggio/vggio_example_test.go b/vg/vggio/vggio_example_test.go
index 677c12f..de8a23a 100644
--- a/vg/vggio/vggio_example_test.go
+++ b/vg/vggio/vggio_example_test.go
@@ -6,7 +6,6 @@ package vggio_test
 
 import (
 	"image/color"
-	"log"
 	"math"
 	"os"
 	"time"
@@ -47,10 +46,7 @@ func ExampleCanvas() {
 		for e := range win.Events() {
 			switch e := e.(type) {
 			case system.FrameEvent:
-				p, err := plot.New()
-				if err != nil {
-					log.Fatalf("could not create plot: %+v", err)
-				}
+				p := plot.New()
 				p.Title.Text = "My title"
 				p.X.Label.Text = "X"
 				p.Y.Label.Text = "Y"
diff --git a/vg/vggio/vggio_test.go b/vg/vggio/vggio_test.go
index 1f23fab..714b151 100644
--- a/vg/vggio/vggio_test.go
+++ b/vg/vggio/vggio_test.go
@@ -8,7 +8,6 @@ import (
 	"image"
 	"image/color"
 	"image/png"
-	"log"
 	"math"
 	"os"
 	"runtime"
@@ -39,10 +38,7 @@ func TestCanvas(t *testing.T) {
 	)
 
 	cmpimg.CheckPlotApprox(func() {
-		p, err := plot.New()
-		if err != nil {
-			log.Fatalf("could not create plot: %+v", err)
-		}
+		p := plot.New()
 		p.Title.Text = "My title"
 		p.X.Label.Text = "X"
 		p.Y.Label.Text = "Y"
@@ -146,11 +142,7 @@ func TestLabels(t *testing.T) {
 	)
 
 	cmpimg.CheckPlotApprox(func() {
-		p, err := plot.New()
-		if err != nil {
-			t.Fatalf("could not create plot: %+v", err)
-		}
-
+		p := plot.New()
 		p.Title.Text = "Labels"
 		p.X.Min = -1
 		p.X.Max = +1
diff --git a/vg/vgimg/vgimg_example_test.go b/vg/vgimg/vgimg_example_test.go
index ff2dfa5..f8f6395 100644
--- a/vg/vgimg/vgimg_example_test.go
+++ b/vg/vgimg/vgimg_example_test.go
@@ -7,7 +7,6 @@ package vgimg_test
 import (
 	"image"
 	"image/color"
-	"log"
 
 	"gonum.org/v1/plot"
 	"gonum.org/v1/plot/vg"
@@ -16,10 +15,7 @@ import (
 )
 
 func ExampleUseDPI() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("%+v", err)
-	}
+	p := plot.New()
 	p.Title.Text = "Title"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
@@ -42,10 +38,7 @@ func ExampleUseDPI() {
 }
 
 func ExampleUseImage() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("%+v", err)
-	}
+	p := plot.New()
 	p.Title.Text = "Title"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
@@ -65,10 +58,7 @@ func ExampleUseImage() {
 }
 
 func ExampleUseBackgroundColor() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("%+v", err)
-	}
+	p := plot.New()
 	p.Title.Text = "Title"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
diff --git a/vg/vgimg/vgimg_test.go b/vg/vgimg/vgimg_test.go
index 07cca0d..88fb368 100644
--- a/vg/vgimg/vgimg_test.go
+++ b/vg/vgimg/vgimg_test.go
@@ -33,10 +33,7 @@ func TestIssue179(t *testing.T) {
 	if err != nil {
 		log.Fatal(err)
 	}
-	p, err := plot.New()
-	if err != nil {
-		log.Fatal(err)
-	}
+	p := plot.New()
 	p.Add(scatter)
 	p.HideAxes()
 
@@ -97,10 +94,7 @@ func TestUseBackgroundColor(t *testing.T) {
 }
 
 func TestIssue540(t *testing.T) {
-	p, err := plot.New()
-	if err != nil {
-		t.Fatal(err)
-	}
+	p := plot.New()
 
 	xys := plotter.XYs{
 		plotter.XY{X: 0, Y: 0},
diff --git a/vg/vgpdf/vgpdf_example_test.go b/vg/vgpdf/vgpdf_example_test.go
index ee79c57..149397a 100644
--- a/vg/vgpdf/vgpdf_example_test.go
+++ b/vg/vgpdf/vgpdf_example_test.go
@@ -20,10 +20,7 @@ import (
 // Example_embedFonts shows how one can embed (or not) fonts inside
 // a PDF plot.
 func Example_embedFonts() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("could not create plot: %v", err)
-	}
+	p := plot.New()
 
 	pts := plotter.XYs{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 0}, {X: 1, Y: 1}}
 	line, err := plotter.NewLine(pts)
@@ -67,10 +64,7 @@ func Example_multipage() {
 			c.NextPage()
 		}
 
-		p, err := plot.New()
-		if err != nil {
-			log.Fatalf("could not create plot: %v", err)
-		}
+		p := plot.New()
 
 		pts := plotter.XYs{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 0}, {X: 1, Y: 1}}
 		line, err := plotter.NewLine(pts)
diff --git a/vg/vgpdf/vgpdf_test.go b/vg/vgpdf/vgpdf_test.go
index 391ebc7..8cf7b1e 100644
--- a/vg/vgpdf/vgpdf_test.go
+++ b/vg/vgpdf/vgpdf_test.go
@@ -35,10 +35,7 @@ func TestEmbedFonts(t *testing.T) {
 		},
 	} {
 		t.Run(fmt.Sprintf("embed=%v", tc.embed), func(t *testing.T) {
-			p, err := plot.New()
-			if err != nil {
-				t.Fatalf("could not create plot: %v", err)
-			}
+			p := plot.New()
 
 			pts := plotter.XYs{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 0}, {X: 1, Y: 1}}
 			line, err := plotter.NewLine(pts)
@@ -93,10 +90,7 @@ func TestArc(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	p, err := plot.New()
-	if err != nil {
-		t.Fatal(err)
-	}
+	p := plot.New()
 	p.Add(scat)
 
 	c := vgpdf.New(100, 100)
@@ -160,10 +154,7 @@ func TestMultipage(t *testing.T) {
 }
 
 func TestIssue540(t *testing.T) {
-	p, err := plot.New()
-	if err != nil {
-		t.Fatal(err)
-	}
+	p := plot.New()
 
 	xys := plotter.XYs{
 		plotter.XY{X: 0, Y: 0},
diff --git a/vg/vgsvg/vgsvg_example_test.go b/vg/vgsvg/vgsvg_example_test.go
index cc7efa1..8e0d629 100644
--- a/vg/vgsvg/vgsvg_example_test.go
+++ b/vg/vgsvg/vgsvg_example_test.go
@@ -13,10 +13,7 @@ import (
 )
 
 func Example() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatalf("could not create plot: %v", err)
-	}
+	p := plot.New()
 	p.Title.Text = "Scatter plot"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
diff --git a/vg/vgsvg/vgsvg_test.go b/vg/vgsvg/vgsvg_test.go
index bd1fd50..96d47dd 100644
--- a/vg/vgsvg/vgsvg_test.go
+++ b/vg/vgsvg/vgsvg_test.go
@@ -22,10 +22,7 @@ func TestSVG(t *testing.T) {
 }
 
 func TestNewWith(t *testing.T) {
-	p, err := plot.New()
-	if err != nil {
-		t.Fatalf("could not create plot: %v", err)
-	}
+	p := plot.New()
 	p.Title.Text = "Scatter plot"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
@@ -59,10 +56,7 @@ func TestNewWith(t *testing.T) {
 }
 
 func TestHtmlEscape(t *testing.T) {
-	p, err := plot.New()
-	if err != nil {
-		t.Fatalf("could not create plot: %v", err)
-	}
+	p := plot.New()
 	p.Title.Text = "Scatter & line plot"
 	p.X.Label.Text = "X"
 	p.Y.Label.Text = "Y"
diff --git a/vg/vgtex/canvas_example_test.go b/vg/vgtex/canvas_example_test.go
index 0554729..9da05ef 100644
--- a/vg/vgtex/canvas_example_test.go
+++ b/vg/vgtex/canvas_example_test.go
@@ -18,10 +18,7 @@ import (
 
 // An example of making a LaTeX plot.
 func Example() {
-	p, err := plot.New()
-	if err != nil {
-		log.Fatal(err)
-	}
+	p := plot.New()
 	// p.HideAxes()
 	p.Title.Text = `A scatter plot: $\sqrt{\frac{e^{3i\pi}}{2\cos 3\pi}}$`
 	p.Title.TextStyle.Font.Size = 16
@@ -44,7 +41,7 @@ func Example() {
 
 	p.Add(scatter1, scatter2)
 
-	txtFont := p.Fonts.Lookup(
+	txtFont := p.TextHandler.Cache().Lookup(
 		p.X.Label.TextStyle.Font,
 		p.X.Label.TextStyle.Font.Size,
 	)
diff --git a/vg/vgtex/canvas_test.go b/vg/vgtex/canvas_test.go
index 6a4c14b..6f19eff 100644
--- a/vg/vgtex/canvas_test.go
+++ b/vg/vgtex/canvas_test.go
@@ -21,10 +21,7 @@ func TestTexCanvas(t *testing.T) {
 func TestLineLatex(t *testing.T) {
 	test := func(fname string) func() {
 		return func() {
-			p, err := plot.New()
-			if err != nil {
-				t.Fatalf("error: %+v", err)
-			}
+			p := plot.New()
 			p.X.Min = -10
 			p.X.Max = +10
 			p.Y.Min = -10
@@ -55,7 +52,7 @@ func TestLineLatex(t *testing.T) {
 			p.Add(plotter.NewGrid())
 
 			const size = 5 * vg.Centimeter
-			err = p.Save(size, size, fname)
+			err := p.Save(size, size, fname)
 			if err != nil {
 				t.Fatalf("error: %+v", err)
 			}
@@ -67,10 +64,7 @@ func TestLineLatex(t *testing.T) {
 
 func TestFillStyle(t *testing.T) {
 	cmpimg.CheckPlot(func() {
-		p, err := plot.New()
-		if err != nil {
-			t.Fatalf("error: %+v", err)
-		}
+		p := plot.New()
 		p.Title.Text = "Fill style"
 		p.Legend.Top = true
 		p.Legend.Left = true