Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine height and depth of a PostScript font?

I'm looking for PostScript code that estimates a PostScript font's height (room for ascender) and depth (room for descender). Could a font's bounding box (FontBBox) be used for this?`

Here is some background for my question: glyphs of a font are sitting on a baseline. Obviously glyphs with descenders will reach below the baseline and I want to know how far below the baseline descenders can reach such that I can provide sufficient space in a layout.

I have seen PostScript code that renders a given string to check its dimension. I'm rather interested in a general answer for a given font.

like image 856
Christian Lindig Avatar asked Nov 28 '11 13:11

Christian Lindig


2 Answers

Well, you've already discovered the two "shortcuts". The FontBBox gives the bounding box of all the glyphs in the font superposed together. false charpath flattenpath pathbbox gives the box for a specified string.

For a Type 3 (user-defined) font this is all you can reaonably expect to do; but for the more-popular Type 1 fonts, there is a wealth of metric information both in the font and in a "metrics" file (for other applications).

But this is the part I don't know very well. So I'm going to read-up (in the Adobe Type 1 manual) and expand this answer later.

Edit: Actually, it looks like these may be the best ways in general.

There is an array of vertical alignment values in a Type 1 font, in the /Private dictionary, under the name /BlueValues; but there is no guarantee that the font honors them. The first number in the array is the baseline overshoot; this is the bottom edge of letters like 'O' which dip below the baseline. And the largest value in the array will be either the ascender-height overshoot or the cap-height overshoot (whichever is higher). But any individual character may be plotted without regard to these values (hence, no guarantee).

On the other hand, the FontBBox itself may reflect the bounding box of any "special" characters present in the font, whether or not they're accessible through the encoding vector (ie. you can't show them, but must glyphshow them).

So the best bet would probably be to take the pathbbox of a string of all the characters you intend to use. This would ignore the contribution of any other characters that may be present but are irrelevant to your purpose. And don't forget to flattenpath to remove the control points from the curves (which may be far outside the "real" bounding box).

like image 140
luser droog Avatar answered Dec 28 '22 07:12

luser droog


luser droog's answer looks fairly complete and no doubt more robust than mine, but I wasn't satisfied that it was the simplest way to determine a usable vertical space for a standard font that allowed me to create a workable newline. here is what I came up with:

%!ps-nonconforming
/inch {72 mul} bind def
/Helvetica 10 selectfont
1 inch 10 inch moveto
/fontheight currentfont dup /FontBBox get dup 3 get % top
 exch 1 get sub % top - bottom
 exch /FontMatrix get 3 get mul def % adjusted by height multiplier
/lineheight fontheight 1.2 mul def % add 20% for line spacing
/newline {0 lineheight neg rmoveto} bind def % negate height to move downwards
gsave (lineheight: ) show lineheight 20 string cvs show grestore
newline gsave (that worked!) show grestore
showpage

result of running it with gs test.ps:

ghostscript rendering of test.ps


a day later, looking at this again, and realized the OP wanted to treat ascenders and descenders separately. so here's an illustration of just using the descenders:

%!ps-nonconforming
/inch {72 mul} bind def
/Helvetica 30 selectfont
1 inch 2 inch moveto
/descender currentfont dup /FontBBox get 1 get % bottom (negative number!)
 exch /FontMatrix get 3 get mul def % adjusted by height multiplier
% first draw a gray line at base of text
gsave 7.5 inch 0 rlineto 0.5 setgray stroke grestore
gsave (descender: ) show descender 20 string cvs show ( pixels) show grestore
gsave 0 descender 1 sub rmoveto  % one pixel below lowest descender
7.5 inch 0 rlineto 0 setgray stroke grestore
showpage

and the result of gs -sDEVICE=pnggray -g640x480 -o/tmp/descender.png descender.ps: line under lowest descender

like image 35
jcomeau_ictx Avatar answered Dec 28 '22 08:12

jcomeau_ictx