adobe-type-tools / afdko

Adobe Font Development Kit for OpenType
https://adobe-type-tools.github.io/afdko/
Other
1.05k stars 167 forks source link

psstemhist -z does not find flat descenders #1688

Open frankrolf opened 4 years ago

frankrolf commented 4 years ago

I cannot find p or q-descenders running psstemhist -z -g A-Z,a-z font.ufo on the attached UFO file.

font.ufo.zip

skef commented 2 years ago

There are at least two causes of this. One is a bad pruning calculation that wasn't using abs() as it should have, that's easily fixed.

The other is trickier, and in this code that goes back (in one form or another) as long as we have records:

           if ((top == t && CloseSegs(sg2, vLst->vSeg2, vert) &&
                 (vert || (!InBlueBand(t, gLenTopBands, gTopBands) &&
                           !InBlueBand(bot, gLenBotBands, gBotBands) &&
                           !InBlueBand(b, gLenBotBands, gBotBands)))) ||
                (bot == b && CloseSegs(sg1, vLst->vSeg1, vert) &&
                 (vert || (!InBlueBand(b, gLenBotBands, gBotBands) &&
                           !InBlueBand(t, gLenTopBands, gTopBands) &&
                           !InBlueBand(top, gLenTopBands, gTopBands)))) ||
                (abs(top - t) <= gMaxMerge && abs(bot - b) <= gMaxMerge &&
                 (vert ||
                  (t == top || !InBlueBand(top, gLenTopBands, gTopBands))) &&
                 (vert ||
                  (b == bot || !InBlueBand(bot, gLenBotBands, gBotBands))))) {
                if (s == spc && val == v && !vert) {
                    if (InBlueBand(t, gLenTopBands, gTopBands)) {
                        if (t < top)
                            goto replace;
                    } else if (InBlueBand(b, gLenBotBands, gBotBands)) {
                        if (b > bot)
                            goto replace;
                    }
                } else
                    goto replace;

sg2 and vLst->vSeg2 are associated with top, and so forth. So what this is doing is if two stems have the same location on one side and neither side falls in a blueValue, the lower-weighted one gets replaced with the higher-weighted one, which will generally be the one that is less wide.

I'm not going to do anything about this for the moment, but one easy solution would be to have InBlueBand (or its Python equivalent) always return true when gathering zone information, so that every location is privileged and therefore no location is. @frankrolf and I can play around with values sometime to see what works best.