Skip to content

Commit

Permalink
hplot: migrate to new gonum/plot font cache
Browse files Browse the repository at this point in the history
  • Loading branch information
sbinet committed Sep 27, 2021
1 parent 8c95ddf commit 64a270d
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 93 deletions.
49 changes: 26 additions & 23 deletions hplot/h1d.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (

"go-hep.org/x/hep/hbook"
"gonum.org/v1/plot"
"gonum.org/v1/plot/font"
"gonum.org/v1/plot/plotter"
"gonum.org/v1/plot/text"
"gonum.org/v1/plot/vg"
"gonum.org/v1/plot/vg/draw"
)
Expand Down Expand Up @@ -319,31 +321,32 @@ func (h *H1D) Plot(c draw.Canvas, p *plot.Plot) {
}

if h.Infos.Style != HInfoNone {
fnt, err := vg.MakeFont(DefaultStyle.Fonts.Name, DefaultStyle.Fonts.Tick.Size)
if err == nil {
sty := draw.TextStyle{Font: fnt}
legend := histLegend{
ColWidth: DefaultStyle.Fonts.Tick.Size,
TextStyle: sty,
}
fnt := font.From(DefaultStyle.Fonts.Tick, DefaultStyle.Fonts.Tick.Size)
sty := text.Style{
Font: fnt,
Handler: p.Title.TextStyle.Handler,
}
legend := histLegend{
ColWidth: DefaultStyle.Fonts.Tick.Size,
TextStyle: sty,
}

for i := uint32(0); i < 32; i++ {
switch h.Infos.Style & (1 << i) {
case HInfoEntries:
legend.Add("Entries", hist.Entries())
case HInfoMean:
legend.Add("Mean", hist.XMean())
case HInfoRMS:
legend.Add("RMS", hist.XRMS())
case HInfoStdDev:
legend.Add("Std Dev", hist.XStdDev())
default:
}
for i := uint32(0); i < 32; i++ {
switch h.Infos.Style & (1 << i) {
case HInfoEntries:
legend.Add("Entries", hist.Entries())
case HInfoMean:
legend.Add("Mean", hist.XMean())
case HInfoRMS:
legend.Add("RMS", hist.XRMS())
case HInfoStdDev:
legend.Add("Std Dev", hist.XStdDev())
default:
}
legend.Top = true

legend.draw(c)
}
legend.Top = true

legend.draw(c)
}
}

Expand Down Expand Up @@ -499,7 +502,7 @@ func newHistFromXYer(xys plotter.XYer, n int) *hbook.H1D {
type histLegend struct {
// TextStyle is the style given to the legend
// entry texts.
draw.TextStyle
TextStyle draw.TextStyle

// Padding is the amount of padding to add
// betweeneach entry of the legend. If Padding
Expand Down
43 changes: 21 additions & 22 deletions hplot/hstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"go-hep.org/x/hep/hbook"
"gonum.org/v1/plot"
"gonum.org/v1/plot/font"
"gonum.org/v1/plot/vg"
"gonum.org/v1/plot/vg/draw"
)
Expand Down Expand Up @@ -284,31 +285,29 @@ func (hs *HStack) hplot(c draw.Canvas, p *plot.Plot, h *H1D, yoffs []float64, hs
}

if h.Infos.Style != HInfoNone {
fnt, err := vg.MakeFont(DefaultStyle.Fonts.Name, DefaultStyle.Fonts.Tick.Size)
if err == nil {
sty := draw.TextStyle{Font: fnt}
legend := histLegend{
ColWidth: DefaultStyle.Fonts.Tick.Size,
TextStyle: sty,
}
fnt := font.From(DefaultStyle.Fonts.Tick, DefaultStyle.Fonts.Tick.Size)
sty := draw.TextStyle{Font: fnt}
legend := histLegend{
ColWidth: DefaultStyle.Fonts.Tick.Size,
TextStyle: sty,
}

for i := uint32(0); i < 32; i++ {
switch h.Infos.Style & (1 << i) {
case HInfoEntries:
legend.Add("Entries", hist.Entries())
case HInfoMean:
legend.Add("Mean", hist.XMean())
case HInfoRMS:
legend.Add("RMS", hist.XRMS())
case HInfoStdDev:
legend.Add("Std Dev", hist.XStdDev())
default:
}
for i := uint32(0); i < 32; i++ {
switch h.Infos.Style & (1 << i) {
case HInfoEntries:
legend.Add("Entries", hist.Entries())
case HInfoMean:
legend.Add("Mean", hist.XMean())
case HInfoRMS:
legend.Add("RMS", hist.XRMS())
case HInfoStdDev:
legend.Add("Std Dev", hist.XStdDev())
default:
}
legend.Top = true

legend.draw(c)
}
legend.Top = true

legend.draw(c)
}

// handle stack, if any.
Expand Down
8 changes: 6 additions & 2 deletions hplot/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ type Label struct {
func NewLabel(x, y float64, txt string, opts ...LabelOption) *Label {

style := draw.TextStyle{
Color: color.Black,
Font: DefaultStyle.Fonts.Tick, // FIXME(sbinet): add a field in Style?
Color: color.Black,
Font: DefaultStyle.Fonts.Tick, // FIXME(sbinet): add a field in Style?
Handler: DefaultStyle.TextHandler,
}

cfg := &labelConfig{
Expand All @@ -61,6 +62,9 @@ func NewLabel(x, y float64, txt string, opts ...LabelOption) *Label {
for _, opt := range opts {
opt(cfg)
}
if cfg.TextStyle.Handler == nil {
cfg.TextStyle.Handler = style.Handler
}

if cfg.Normalized {
if !(0 <= x && x <= 1) {
Expand Down
18 changes: 11 additions & 7 deletions hplot/label_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
package hplot_test

import (
"fmt"
"log"

xfnt "golang.org/x/image/font"
"gonum.org/v1/plot/font"
"gonum.org/v1/plot/plotter"
"gonum.org/v1/plot/plotutil"
"gonum.org/v1/plot/text"
"gonum.org/v1/plot/vg"
"gonum.org/v1/plot/vg/draw"

"go-hep.org/x/hep/hplot"
)
Expand Down Expand Up @@ -48,11 +49,14 @@ func ExampleLabel() {
p.Add(l4)

// Label with a customed TextStyle
usrFont, err := vg.MakeFont("Courier-Bold", 12)
if err != nil {
panic(fmt.Errorf("could not create font (Courier-Bold, 12): %w", err))
usrFont := font.Font{
Typeface: "Liberation",
Variant: "Mono",
Weight: xfnt.WeightBold,
Style: xfnt.StyleNormal,
Size: 12,
}
sty := draw.TextStyle{
sty := text.Style{
Color: plotutil.Color(2),
Font: usrFont,
}
Expand All @@ -68,7 +72,7 @@ func ExampleLabel() {
p.Add(hplot.NewGrid())

// Save the plot to a PNG file.
err = p.Save(15*vg.Centimeter, -1, "testdata/label_plot.png")
err := p.Save(15*vg.Centimeter, -1, "testdata/label_plot.png")
if err != nil {
log.Fatalf("error saving plot: %v\n", err)
}
Expand Down
9 changes: 2 additions & 7 deletions hplot/plot.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,10 @@ type Plot struct {
func New() *Plot {
style := DefaultStyle
defer style.reset(plot.DefaultFont)
plot.DefaultFont = style.Fonts.Name
plot.DefaultFont = style.Fonts.Default

p, err := plot.New()
if err != nil {
// can not happen.
panic(err)
}
pp := &Plot{
Plot: p,
Plot: plot.New(),
Style: style,
}
pp.Style.Apply(pp)
Expand Down
82 changes: 50 additions & 32 deletions hplot/style.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
package hplot

import (
"github.com/golang/freetype/truetype"
"fmt"

"gonum.org/v1/plot"
"gonum.org/v1/plot/vg"
"gonum.org/v1/plot/font"
"gonum.org/v1/plot/font/liberation"
"gonum.org/v1/plot/text"
"gonum.org/v1/plot/vg/draw"
"gonum.org/v1/plot/vg/fonts"
)

var (
Expand All @@ -20,12 +22,16 @@ var (
// Style stores a given plot style.
type Style struct {
Fonts struct {
Name string // font name of this style
Title vg.Font // font used for the plot title
Label vg.Font // font used for the plot labels
Legend vg.Font // font used for the plot legend
Tick vg.Font // font used for the plot's axes' ticks
Name string // font name of this style
Default font.Font // font used for the plot
Title font.Font // font used for the plot title
Label font.Font // font used for the plot labels
Legend font.Font // font used for the plot legend
Tick font.Font // font used for the plot's axes' ticks

Cache *font.Cache // cache of fonts for this plot.
}
TextHandler text.Handler
}

// Apply setups the plot p with the current style.
Expand All @@ -37,57 +43,69 @@ func (s *Style) Apply(p *Plot) {
p.Plot.Y.Tick.Label.Font = s.Fonts.Tick
p.Plot.Legend.TextStyle.Font = s.Fonts.Legend
p.Plot.Legend.YPosition = draw.PosCenter
p.Plot.TextHandler = s.TextHandler
}

func (s *Style) reset(name string) {
plot.DefaultFont = name
func (s *Style) reset(fnt font.Font) {
plot.DefaultFont = fnt
}

// NewStyle creates a new style with the given truetype font.
func NewStyle(name string, ft *truetype.Font) (Style, error) {
// NewStyle creates a new style with the given font cache.
func NewStyle(fnt font.Font, cache *font.Cache) (Style, error) {
var sty Style
err := sty.init(name, ft)

sty.Fonts.Name = fnt.Name()
sty.Fonts.Default = fnt
sty.Fonts.Title = fnt
sty.Fonts.Label = fnt
sty.Fonts.Legend = fnt
sty.Fonts.Tick = fnt
sty.Fonts.Cache = cache

err := sty.init(fnt.Name())
if err != nil {
return sty, err
}

sty.TextHandler = text.Plain{
Fonts: sty.Fonts.Cache,
}

return sty, nil
}

func (sty *Style) init(name string, ft *truetype.Font) error {
func (sty *Style) init(name string) error {
sty.Fonts.Name = name
vg.AddFont(name, ft)
for _, t := range []struct {
ft *vg.Font
size vg.Length
ft *font.Font
size font.Length
}{
{&sty.Fonts.Title, 12},
{&sty.Fonts.Label, 12},
{&sty.Fonts.Legend, 12},
{&sty.Fonts.Tick, 10},
} {
ft, err := vg.MakeFont(sty.Fonts.Name, t.size)
if err != nil {
return err
if !sty.Fonts.Cache.Has(*t.ft) {
return fmt.Errorf("hplot: no font %v in cache", *t.ft)
}
*t.ft = ft
t.ft.Size = t.size
}

return nil
}

func init() {
vgfonts, err := fonts.Asset("LiberationSans-Regular.ttf")
if err != nil {
panic(err)
}

ft, err := truetype.Parse(vgfonts)
if err != nil {
panic(err)
}

err = DefaultStyle.init("Helvetica", ft)
var (
cache = font.NewCache(liberation.Collection())
err error
)
DefaultStyle, err = NewStyle(
font.Font{
Typeface: "Liberation",
Variant: "Sans",
},
cache,
)
if err != nil {
panic(err)
}
Expand Down

0 comments on commit 64a270d

Please sign in to comment.