// NewLabels returns a new Labels using the DefaultFont and // the DefaultFontSize. func NewLabels(d interface { XYer Labeller }) (*Labels, error) { xys, err := CopyXYs(d) if err != nil { return nil, err } if d.Len() != len(xys) { return nil, errors.New("Number of points does not match the number of labels") } strs := make([]string, d.Len()) for i := range strs { strs[i] = d.Label(i) } fnt, err := vg.MakeFont(DefaultFont, DefaultFontSize) if err != nil { return nil, err } return &Labels{ XYs: xys, Labels: strs, TextStyle: draw.TextStyle{Font: fnt}, }, nil }
// New returns a new plot with some reasonable // default settings. func New() (*Plot, error) { titleFont, err := vg.MakeFont(DefaultFont, 12) if err != nil { return nil, err } x, err := makeAxis() if err != nil { return nil, err } y, err := makeAxis() if err != nil { return nil, err } legend, err := makeLegend() if err != nil { return nil, err } p := &Plot{ BackgroundColor: color.White, X: x, Y: y, Legend: legend, } p.Title.TextStyle = draw.TextStyle{ Color: color.Black, Font: titleFont, } return p, nil }
// makeLegend returns a legend with the default // parameter settings. func makeLegend() (Legend, error) { font, err := vg.MakeFont(DefaultFont, vg.Points(12)) if err != nil { return Legend{}, err } return Legend{ ThumbnailWidth: vg.Points(20), TextStyle: draw.TextStyle{Font: font}, }, nil }
// makeAxis returns a default Axis. // // The default range is (∞, ∞), and thus any finite // value is less than Min and greater than Max. func makeAxis() (Axis, error) { labelFont, err := vg.MakeFont(DefaultFont, vg.Points(12)) if err != nil { return Axis{}, err } tickFont, err := vg.MakeFont(DefaultFont, vg.Points(10)) if err != nil { return Axis{}, err } a := Axis{ Min: math.Inf(1), Max: math.Inf(-1), LineStyle: draw.LineStyle{ Color: color.Black, Width: vg.Points(0.5), }, Padding: vg.Points(5), Scale: LinearScale{}, } a.Label.TextStyle = draw.TextStyle{ Color: color.Black, Font: labelFont, } a.Tick.Label = draw.TextStyle{ Color: color.Black, Font: tickFont, } a.Tick.LineStyle = draw.LineStyle{ Color: color.Black, Width: vg.Points(0.5), } a.Tick.Length = vg.Points(8) a.Tick.Marker = DefaultTicks{} return a, nil }
// ReplayOn applies the set of Actions recorded by the Recorder onto // the destination Canvas. func (c *Canvas) ReplayOn(dst vg.Canvas) error { if c.fonts == nil { c.fonts = make(map[fontID]vg.Font) } for _, a := range c.Actions { fa, ok := a.(*FillString) if !ok { continue } f := fontID{name: fa.Font, size: fa.Size} if _, exists := c.fonts[f]; !exists { var err error c.fonts[f], err = vg.MakeFont(fa.Font, fa.Size) if err != nil { return err } } fa.fonts = c.fonts } for _, a := range c.Actions { a.ApplyTo(dst) } return nil }
func TestLegendAlignment(t *testing.T) { font, err := vg.MakeFont(plot.DefaultFont, 10.822510822510822) // This font size gives an entry height of 10. if err != nil { t.Fatalf("failed to create font: %v", err) } l := plot.Legend{ ThumbnailWidth: vg.Points(20), TextStyle: draw.TextStyle{Font: font}, } for _, n := range []string{"A", "B", "C", "D"} { b, err := plotter.NewBarChart(plotter.Values{0}, 1) if err != nil { t.Fatalf("failed to create bar chart %q: %v", n, err) } l.Add(n, b) } r := recorder.New(100) c := draw.NewCanvas(r, 100, 100) l.Draw(draw.Canvas{ Canvas: c.Canvas, Rectangle: draw.Rectangle{ Min: draw.Point{0, 0}, Max: draw.Point{100, 100}, }, }) got := r.Actions // want is a snapshot of the actions for the code above when the // graphical output has been visually confirmed to be correct for // the bar charts example show in gonum/plot#25. want := []recorder.Action{ &recorder.SetColor{ Color: color.Gray16{}, }, &recorder.Fill{ Path: vg.Path{ {Type: vg.MoveComp, X: 80, Y: 30}, {Type: vg.LineComp, X: 80, Y: 40}, {Type: vg.LineComp, X: 100, Y: 40}, {Type: vg.LineComp, X: 100, Y: 30}, {Type: vg.CloseComp}, }, }, &recorder.SetColor{ Color: color.Gray16{}, }, &recorder.SetLineWidth{ Width: 1, }, &recorder.SetLineDash{}, &recorder.Stroke{ Path: vg.Path{ {Type: vg.MoveComp, X: 80, Y: 30}, {Type: vg.LineComp, X: 80, Y: 40}, {Type: vg.LineComp, X: 100, Y: 40}, {Type: vg.LineComp, X: 100, Y: 30}, {Type: vg.LineComp, X: 80, Y: 30}, }, }, &recorder.SetColor{}, &recorder.FillString{ Font: string("Times-Roman"), Size: 10.822510822510822, X: 69.48051948051948, Y: 30.82251082251082, String: "A", }, &recorder.SetColor{ Color: color.Gray16{}, }, &recorder.Fill{ Path: vg.Path{ {Type: vg.MoveComp, X: 80, Y: 20}, {Type: vg.LineComp, X: 80, Y: 30}, {Type: vg.LineComp, X: 100, Y: 30}, {Type: vg.LineComp, X: 100, Y: 20}, {Type: vg.CloseComp}, }, }, &recorder.SetColor{ Color: color.Gray16{}, }, &recorder.SetLineWidth{ Width: 1, }, &recorder.SetLineDash{}, &recorder.Stroke{ Path: vg.Path{ {Type: vg.MoveComp, X: 80, Y: 20}, {Type: vg.LineComp, X: 80, Y: 30}, {Type: vg.LineComp, X: 100, Y: 30}, {Type: vg.LineComp, X: 100, Y: 20}, {Type: vg.LineComp, X: 80, Y: 20}, }, }, &recorder.SetColor{}, &recorder.FillString{ Font: string("Times-Roman"), Size: 10.822510822510822, X: 70.07575757575758, Y: 20.82251082251082, String: "B", }, &recorder.SetColor{ Color: color.Gray16{ Y: uint16(0), }, }, &recorder.Fill{ Path: vg.Path{ {Type: vg.MoveComp, X: 80, Y: 10}, {Type: vg.LineComp, X: 80, Y: 20}, {Type: vg.LineComp, X: 100, Y: 20}, {Type: vg.LineComp, X: 100, Y: 10}, {Type: vg.CloseComp}, }, }, &recorder.SetColor{ Color: color.Gray16{}, }, &recorder.SetLineWidth{ Width: 1, }, &recorder.SetLineDash{}, &recorder.Stroke{ Path: vg.Path{ {Type: vg.MoveComp, X: 80, Y: 10}, {Type: vg.LineComp, X: 80, Y: 20}, {Type: vg.LineComp, X: 100, Y: 20}, {Type: vg.LineComp, X: 100, Y: 10}, {Type: vg.LineComp, X: 80, Y: 10}, }, }, &recorder.SetColor{}, &recorder.FillString{ Font: string("Times-Roman"), Size: 10.822510822510822, X: 70.07575757575758, Y: 10.822510822510822, String: "C", }, &recorder.SetColor{ Color: color.Gray16{}, }, &recorder.Fill{ Path: vg.Path{ {Type: vg.MoveComp, X: 80, Y: 0}, {Type: vg.LineComp, X: 80, Y: 10}, {Type: vg.LineComp, X: 100, Y: 10}, {Type: vg.LineComp, X: 100, Y: 0}, {Type: vg.CloseComp}, }, }, &recorder.SetColor{ Color: color.Gray16{}, }, &recorder.SetLineWidth{ Width: 1, }, &recorder.SetLineDash{}, &recorder.Stroke{ Path: vg.Path{ {Type: vg.MoveComp, X: 80, Y: 0}, {Type: vg.LineComp, X: 80, Y: 10}, {Type: vg.LineComp, X: 100, Y: 10}, {Type: vg.LineComp, X: 100, Y: 0}, {Type: vg.LineComp, X: 80, Y: 0}, }, }, &recorder.SetColor{}, &recorder.FillString{ Font: string("Times-Roman"), Size: 10.822510822510822, X: 69.48051948051948, Y: 0.8225108225108215, String: "D", }, } if !reflect.DeepEqual(got, want) { t.Errorf("unexpected legend actions:\ngot:\n%s\nwant:\n%s", formatActions(got), formatActions(want)) } }