plot icon indicating copy to clipboard operation
plot copied to clipboard

Padding below X axis?

Open ak2344 opened this issue 8 years ago • 18 comments

I've added custom labels to my X axis but the text is getting cut off (the bottom half of the "y" in "May" isn't visible). Is there a way to add padding to the bottom of the graph?

ak2344 avatar Jul 10 '16 19:07 ak2344

You can use draw.Crop: https://godoc.org/github.com/gonum/plot/vg/draw#Crop.

However, if this is happening it is probably a bug so if you are willing to submit an example that reproduces the problem that would be appreciated.

ctessum avatar Jul 10 '16 22:07 ctessum

Thanks!

I will put together an example. What information would you need?

ak2344 avatar Jul 10 '16 22:07 ak2344

Attaching an example of a graph. vs65uphi6xjmv47u

ak2344 avatar Jul 10 '16 22:07 ak2344

We'd need the code that generated it too.

kortschak avatar Jul 10 '16 22:07 kortschak

Just ran into this myself. Taking the bar charts example and changing the last NominalX name to "Twenty" produces:

barchart

This is with gonum.org/v1/plot v0.8.0 in go.mod.

Will see if I can fix it up with draw.Crop.

danp avatar Nov 01 '20 23:11 danp

Thanks. I'll have a look at this soon.

kortschak avatar Nov 01 '20 23:11 kortschak

It looks to me like the glyphboxes are not being drawn on the tick labels in the tests either. They should be.

kortschak avatar Nov 02 '20 00:11 kortschak

I think this fixes the issue.

diff --git a/axis.go b/axis.go
index 1190ae5..1daf3d9 100644
--- a/axis.go
+++ b/axis.go
@@ -270,12 +270,13 @@ func (a horizontalAxis) draw(c draw.Canvas) {
 
        marks := a.Tick.Marker.Ticks(a.Min, a.Max)
        ticklabelheight := tickLabelHeight(a.Tick.Label, marks)
+       descent := a.Tick.Label.Font.Extents().Descent
        for _, t := range marks {
                x := c.X(a.Norm(t.Value))
                if !c.ContainsX(x) || t.IsMinor() {
                        continue
                }
-               c.FillText(a.Tick.Label, vg.Point{X: x, Y: y + ticklabelheight}, t.Label)
+               c.FillText(a.Tick.Label, vg.Point{X: x, Y: y + ticklabelheight - descent}, t.Label)
        }
 
        if len(marks) > 0 {
diff --git a/vg/draw/text.go b/vg/draw/text.go
index 35b6699..e19ff3e 100644
--- a/vg/draw/text.go
+++ b/vg/draw/text.go
@@ -74,7 +74,7 @@ func (sty TextStyle) Height(txt string) vg.Length {
                return vg.Length(0)
        }
        e := sty.Font.Extents()
-       return e.Height*vg.Length(nl-1) + e.Ascent
+       return e.Height*vg.Length(nl-1) + e.Ascent - e.Descent
 }
 
 // Rectangle returns a rectangle giving the bounds of

kortschak avatar Nov 02 '20 00:11 kortschak

A number of tests in vg/... don't update with the -regen flag.

kortschak avatar Nov 02 '20 00:11 kortschak

No, it's more complicated than that; the wiring of descents into font consideration is quite ad hoc.

kortschak avatar Nov 02 '20 01:11 kortschak

Thank you!

danp avatar Nov 03 '20 22:11 danp

@danp Thanks for following up with a reproducer; that's what go this fixed.

kortschak avatar Nov 04 '20 05:11 kortschak

@kortschak Some characters (such as ÀÉÈÎÙÔ) is also cut off in title and y axis label. test

wcshds avatar Apr 25 '22 18:04 wcshds

Thanks @wcshds. Maybe we should grow the bounding box a little.

@sbinet WDYT?

kortschak avatar Apr 26 '22 07:04 kortschak

apologies for dropping this on the floor. I'll have a look.

sbinet avatar May 10 '22 09:05 sbinet

ok, so the bounding box is indeed completely missing the accents: glyphbox_accents

asking on the #ui-text-rendering channel, Egon reminded me of the x/image/font.BoundString function that does what we want (and removing code from gonum to replace it with code from the almost-stdlib is great). but there are discrepancies. the code in gonum/plot - which more or less does what font.BoundString does - returns twice the width of font.BoundString:

https://go.dev/play/p/_hvN0Lw5YJ6

the scale parameter of opentype.Face (font.BoundString operates on font.Faces) is: Int26_6(0.5 + (fntSize * imgDPI * 64)/72)) = 1024 (with fntSize=12 and imgDPI=96) the pixelsPerEm parameter passed to sfnt.Font.GlyphAdvance (in doGonumWidth) equals to 2048. and this value is taken straight from sfnt.Font.UnitsPerEm() font.BoundString just uses sfnt.Font.GlyphBounds (whose code is like sfnt.Font.GlyphAdvance as far as advance is concerned). so... clearly there is a logical flaw somewhere. but I am stuck.

sbinet avatar May 12 '22 11:05 sbinet

Do you want something instead like this https://go.dev/play/p/GTsNZ7P8brW?

The font.Face.GlyphBounds and sfnt.Font.GlyphAdvance look like they have different understanding of advance.

kortschak avatar May 12 '22 12:05 kortschak

ok... so I gave up on trying to understand where exactly the difference is coming from.

  • sfnt.Font.GlyphBounds here
  • sfnt.Font.GlyphAdvance here ie: as far as advance is concerned, they look the same to me.

anyways. dropping the use of plot/font.Face.Extents() for the height, and using instead x/image/font.BoundString, I get the following image (using this new scheme only for the Ôag and Oag labels (bottom-left quarter)): accents-1

using that scheme for all strings: accents-2

ie: probably have to do with some impedance mismatch between code that uses plot/font.FaceExtents directly to get the height of the box and code that uses plot/text.Handler.Box.

I'll probably have to modify the plot/text.Handler interface, namely that Box method that needs to take an additional parameter (the DPI).

I must say, I am also considering just switching to go-text/typesetting and its shaping.Shaper interface. this quite large dependency is what Gio and Fyne are using for text typesetting. (and it's still being maintained, while x/image/font is less so).

sbinet avatar May 19 '22 13:05 sbinet