gonum / plot

A repository for plotting and visualizing data
BSD 3-Clause "New" or "Revised" License
2.74k stars 203 forks source link

all: correctly handle descent in glyphbox of text symbols #650

Closed sbinet closed 3 years ago

sbinet commented 3 years ago

Fixes gonum/plot#649.

Please take a look.

sbinet commented 3 years ago

it might actually be a bug in truetype.

as part of #613, I am playing with migrating away from github.com/golang/freetype/truetype over to golang.org/x/image/font

here is what truetype (ttf) returns for the font's extend, compared with what x/image/font/sfnt returns (with sfnt.HintingNone):

--- FAIL: TestFontExtends (0.01s)
    font_test.go:26: invalid font extents:
        ttf= vg.FontExtents{Ascent:9.814453125, Descent:-3.0322265625, Height:12.8466796875}
        sft= vg.FontExtents{Ascent:8.9111328125, Descent:-2.1630859375, Height:11.4990234375}

and with sfnt.HintingFull:

--- FAIL: TestFontExtends (0.01s)
    font_test.go:26: invalid font extents:
        ttf= vg.FontExtents{Ascent:9.814453125, Descent:-3.0322265625, Height:12.8466796875}
        sft= vg.FontExtents{Ascent:9.0625, Descent:-2.1875, Height:11.5625}

(the default of truetype seems to be HintingNone. I am just posting the HintingFull bit for completeness)

here is what I get when using the font metrics from sfnt: labels_glyphboxes as you can see, the glyphbox "fits" better. there is probably still an issue, though: the bottom letter (for YAlign = draw.YBottom) doesn't land nicely on the requested y coordinate.

the (unscaled) x/image/font.Metrics returned by sfnt is:

font.Metrics{
   Height:2355,
   Ascent:1825,
   Descent:443,
   XHeight:940,
   CapHeight:1341,
   CaretSlope:image.Point{X:0, Y:1},
}

where:

type Metrics struct {
    // Height is the recommended amount of vertical space between two lines of
    // text.
    Height fixed.Int26_6

    // Ascent is the distance from the top of a line to its baseline.
    Ascent fixed.Int26_6

    // Descent is the distance from the bottom of a line to its baseline. The
    // value is typically positive, even though a descender goes below the
    // baseline.
    Descent fixed.Int26_6

    // XHeight is the distance from the top of non-ascending lowercase letters
    // to the baseline.
    XHeight fixed.Int26_6

    // CapHeight is the distance from the top of uppercase letters to the
    // baseline.
    CapHeight fixed.Int26_6

    // CaretSlope is the slope of a caret as a vector with the Y axis pointing up.
    // The slope {0, 1} is the vertical caret.
    CaretSlope image.Point
}
sbinet commented 3 years ago

hacking a bit the Gio library to display the "bounding box" of each text line it draws (in magenta), I get: labels

from the overlaps of the gio-boxes in the multi-line labels, I'd be enclined to say the CapHeight ot the bottom line is the bottom of the line gap.

but applying that formula doesn't pan out.

I am stumped.

kortschak commented 3 years ago

What do you want to do with this?

sbinet commented 3 years ago

I've asked some help on the Gio mailing list on what's the proper mental model for multi-lines text boxes.

as is, we are already shrinking the glyphbox around a piece of text. it's not as tight as it could be but it's already an improvement.

I'd go with what we have right now and re-iterate when/if some clever mind on Gio chimes in. this will incur some churn on the reference files, but oh well...

codecov-io commented 3 years ago

Codecov Report

Merging #650 (5ebe841) into master (a51a196) will increase coverage by 0.39%. The diff coverage is 72.45%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #650      +/-   ##
==========================================
+ Coverage   70.28%   70.67%   +0.39%     
==========================================
  Files          55       57       +2     
  Lines        4620     4911     +291     
==========================================
+ Hits         3247     3471     +224     
- Misses       1203     1256      +53     
- Partials      170      184      +14     
Impacted Files Coverage Δ
cmpimg/checkplot.go 0.00% <0.00%> (ø)
vg/draw/text.go 0.00% <0.00%> (ø)
vg/vggio/vggio.go 72.27% <72.27%> (ø)
cmpimg/cmpimg.go 63.80% <76.19%> (+24.62%) :arrow_up:
legend.go 94.11% <100.00%> (ø)
vg/vggio/context.go 100.00% <100.00%> (ø)
vg/vgimg/vgimg.go 49.68% <100.00%> (+0.64%) :arrow_up:
version.go 0.00% <0.00%> (ø)
... and 1 more

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update b130901...5ebe841. Read the comment docs.

sbinet commented 3 years ago

PTAL

sbinet commented 3 years ago

FYI, I now get the following gio glyphboxes (in magenta): labels they snap nicely around the text lines.

(this new image was created with a hacked version of Gio to display those glyphboxes, and after having migrated gonum/plot to x/image/font.)

sbinet commented 3 years ago

(the last squash+rebase+force-push was just to get a nicer git-history, no code change)