UPM and vertical font metrics: please help to clarify

☆'s picture

Please help me to understand how UPM is related to ascenders and descenders. For example, look at Times New Roman (TTF) metrics, UPM = 2048 (see image below).

I used to believe that UPM = Ascender - Descender, but now I find that I was wrong. But what metrics expression must be equal to UPM? What plus what (or minus what) must give exactly 2048 in this example? I don’t see appropriate values at all. Help me to clarify, please.

blank's picture

Read Karsten Lucke’s guide to vertical metrics: http://kltf.de/downloads/FontMetrics-kltf.pdf

Also, Adam Twardoch posted a python script that does a good job calculating vetical metrics in the thread: http://www.typophile.com/node/71230

☆'s picture

Thank you for quick default answer, but I have read that guide before posting my question.

The guide says on page 1 that Ascender + Descender equals to UPM. But I don’t see that equality in real fonts, and therefore I posted my question.

In Times New Roman (see my screenshot) Typo Ascender + Typo Descender = 1420 + 442 = 1862, Ascender + Descender = 1825 + 443 = 2268, Win Ascent + Win Descent is the same. None of these gives UPM 2048.

Maybe Lucke’s guide is wrong?

Twardoch’s Python script calculates line spacing, but doesn’t help with my question too.

Igor Freiberger's picture

Ascender and Descender are values defined by the font designer. In principle, their sum must be equal to UPM. Anyway, this is not always true because the designer can let a gap between these limits and the UPM. So, the sum of asc/desc would be minor than UPM.

Sample: Arial's UPM is 2048, but asc/desc sum is 1922.

This gap is useful to avoid line conflicts when using stacked double diacritics (like these in Vietnamese or for Indic transliterations). Another possibility is to let room for increasing overshoots in bolder weights. As long as I did watch, this is common in TT fonts and rare in T1 ones.

If you have diferences between asc/desc, actual glyph extremes and UPM, the font editor will find other values when it calculates TypoAscender and TypoDescender fields. Anyway, this will not cause problems and is valid only for TT fonts.

WinAscent and WinDescent are equal to Ascender and Descender values in this TT panel. These values are get by the program itself and results from the actual vertical extremes of the font.

Although WinAsc/WinDesc would be the same defined by designer as ascender and descender, many glyphs demand higher extremes. See, for example, some ornaments, mathematical symbols or diacritical combinations – not to mention most of script fonts. If you make asc/desc limits match these taller glyphs, the remaining glyphs would become very small or cause excessive line gap. So, at least in almost all fonts I saw, the nominal limits are ignored when designing especial kinds of glyphs.

Sample: in Minion, stacked diacritics go far away from ascender.

Sidenote: your name is not shown for me (and surely for others) because U+2606 is a glyph not present in many fonts.

k.l.'s picture

Hello Mr Matrosov, there are two things to consider: First, you need to inspect a number of fonts rather than just one. Second, if you look at more than just the first page of the document you will see that it presents ideal-world relations which do not need to be like that. In fact page 2 explicitly says that "none of the following conditions is required by any specifications" [last "s" needs to go] and mentions, as the third of these conditions, Ascender+Descender=UPM.

You need to keep in mind the purpose of this document, John Hudson's earlier description, Read Roberts' research, and Adam Twardoch's script. Different applications determine the (default/automatic) line-to-line distance in different ways, choosing (sets of) values almost arbitrarily – thanks to TTF/OTF fonts offering a bunch of alternatives. So the question we are trying to address is, how to keep line-to-line distance consistent across applications? [I will try to improve the wording of the first paragraph.]

(Perhaps the OT/OFF specification should explicitly deprecate certain table data in the long run ...)

☆'s picture

Thank you Mr. Freiberger for detailed and thorough explanation. Now I seem to understand nearly all that I was concerned.
Still a little issue is not clear to me, and I will be grateful if you help me to understand.
For example, we type text in simple Notepad, and set font to Times, size 72px (for simplicity). As far as I understand, Notepad allocates a rectangular place for each letter, and this place has height exactly 72 pixels. The letter of course must not fit exactly into this rectangle, it is simply a box to which the glyph will be bound.
And there I don’t get one thing. Where in this box the baseline will be positioned? How many pixels exactly from top (or bottom) of the box? How will Notepad (or other software) calculate it? How can I calculate it from given font metrics?
I thought before that asc + desc = UPM strictly, and the position of baseline can be calculated proportionally. But it turns out far more complicated, and I need help to get it.
P.S. Sorry for my imperfect English.

oldnick's picture

In your example, the percentage of the 72px square identified as Ascender Height will appear above the baseline, and the percentage identified as Descender Height will appear below it. Therefore, if the UPM is 1,000, the Ascender Height is 750 and the Descender Height is 250, there will be 54 px above the baseline and 18 px below. You don't have to calculate: that's what the dimensions are for.

☆'s picture

→ oldnick

Your calculations assume that asc + desc = UPM. But my question is about an example where their sum ISN’T equal to UPM. Here UPM is 2048, but asc + desc = 1420 + 442 = 1862 — so where is baseline?

Igor Freiberger's picture

Good question. I don't know.

Initially, I thought exactly what OldNick told. But some tests show me other results.

I took DejaVu Serif and set its x-height to 0. No change. Caps height to 0. No change. Back to original values I changed ascender from 1556 to 556. And the result in FontLab preview was this:

DejaVu Serif with ascender decreased by 1000upm.

So, when you reduce the ascender (and did no change other metric values), line height seems to be affected.

Still with the ascender modified by –1000, I set the descender from the original –492 to –1492. And the preview in FontLab was back to normal, indicating the program consider the sum from ascender and descender to define the line height.

Back to original values, I decreased the ascender again by 1000upm. Generated the font as OT CFF and OT TTF without recalculating the TT-specific values (WinAscent, etc.). Tested the font in InDesign, Word and NotePad. Interestingly, the font leading and baseline were normal.

So, the ascender value is not considered by these applications to define leading and baseline. Note in this case the sum asc+desc was 1000upm minor than the original one and the proportion asc/desc was completely broken. Anyway, the lines were still OK.

It's also possible that FL someway fixed this value in export process, but I don't bet on this. Put simply, these tests did not found an answer. They just put aside my initial presumption.

But I noticed that, even with metrics greatly modified, the glyphs did remain at the same place. This is a glyph window capture from FontLab after I decreased all values by 1000upm:

Even with all metrics greatly modified, the glyph outline keeps it place.

As you can see, ascender, caps height, x-height and descender were severely modified towards bottom. But the baseline, the outline and the marks were not affected in any way.

This may be the answer: what determine baseline position is simply the baseline (y=0 line) used during font creation. To change other values will not affect the baseline and the glyph position is defined considering its relationship with this reference.

Now, it's time to get help from people who know much more than me on this matter. I'm also curious to see the answer.

oldnick's picture

Your calculations assume that asc + desc = UPM. But my question is about an example where their sum ISN’T equal to UPM. Here UPM is 2048, but asc + desc = 1420 + 442 = 1862 — so where is baseline?

The baseline remains the same: it's the zero, zero reference point from which the characters are drawn, as noted above. 1420 is approximately 76.5% of 1,862 and 442 is approximately 23.5% of 1,862; however, the characters are likely to occupy only 91% of the available vertical space.

☆'s picture

→ oldnick

Seems that I failed again to properly explain my question.

You speak about ­“the available vertical space”. Let’s assume here’s this space according to my example. Since the program allocates space equal to font size, its height is exactly 2048 units:

Now, there is a real letter from the font, having height 1862 units. The baseline is marked with dashed line:

And then, what exactly happens when a program (i.e. Notepad) displays this letter in that box? How are the letter and the box positioned relative to each other? Are they top-aligned (first figure below), bottom-aligned (second figure), or something else?

I don’t understand this.

Thomas Phinney's picture

> Since the program allocates space equal to font size

Which program would that be?

My understanding is that on Windows, most applications allocate vertical space and do line positioning based on os2.usWinAscender + os2.usWinDescender, scaled to the current point size. Similarly on the Mac, only with hhea.Ascent and hhea.Descent (and hhea.LineGap for subsequent lines).

Most Adobe apps do use the em, plus the sTypoAscender and sTypoDescender for the same purpose. But they are capable of letting text overhang the frame on any side. The more sophisticated ones such as InDesign even let you decide on what basis to set the first baseline in the frame.


k.l.'s picture

Mr Matrosov, maybe I now got what your question is. It is not so much about "how UPM is related to ascenders and descenders" as stated in your initial post but rather about "how UPM relates to any kind of metrics".

First a remark about the EM in UPM. In digital type, the EM does not refer to a "real" box. You better consider the EM as a yardstick – an abstract letter-height yardstick which establishes a link between micro and macro level, between font-internal unit system and font-external unit system: The font-internal unit system is defined via UPM, i.e. as the number of units per EM. It is the letter-design grid or resolution. The font-external unit system may be typographic point, millimeter, pixel, etc. And this abstract EM serves to project the font-internal unit system onto the font-external unit system.
An example. You have a font with 2048 units per EM, internally, which is to be projected on 12 pt type size, externally. So 1 pt = 2048 M-units or 1 M-unit = 1/2048 pt. Now it does not matter whether OS/2.sTypoAscender + OS/2.sTypoDescender = head.unitsPerEm or not. To calculate baseline positions, you need to know which sets of metrics an application uses to determine the distance a) from top of the text frame to the first baseline and b) from baseline to baseline. If an application uses OS/2.usWinAscent [= 1825 in your screenshot] for a) then the first baseline has a distance of
      (1825 M-units * 12 pt) / 2048 M-units = 10,69 pt
from the top of the text frame. And if an application uses OS/2.usWinAscent + OS/2.usWinDescent [= 1825 and 443 in your screenshot] for b) then the line-to-line distance is
      ((1825 + 443) M-units * 12 pt) / 2048 M-units = 13.29 pt
Thinking of UPM as a box is a bit misleading. (But it makes sense to think of a box when designing type!)

Hope there are no grave errors in this description.

Thomas Phinney's picture

I've been working on a blog post on this topic on and off since before Christmas. That's a brilliantly clear description, which I will be happy to quote part of.

However, I think you have an error in the example "So 1 pt = 2048 M-units or 1 M-unit = 1/2048 pt." I believe that given that you are scaling the font to 12 pts the example should be "So 12 pt = 2048 M-units or 1 M-unit = 12/2048 pt."



k.l.'s picture

How embarrassing, I knew something like this would sneak in ...

A blog post sounds great, perfect for a (to be reanimated) link collection!

☆'s picture

Mr. Phinney and k.l., thank you for good explanation. It was very useful to me.

twardoch's picture

I usually explain it as follows:

The primary meaning of the UPM size is that it determines the size of glyphs at a given point size. When a font has 1000 UPM, and the capital H is 700 units tall, then when set at 10 pt, the capital H will be exactly 7 pt tall. When the font has 500 UPM and the capital H is 700 units tall, then when set at 10 pt, the capital H will be exactly 14 pt tall.

In other words, if you want your glyphs to appear slightly larger, the designer can either scale the actual glyph outlines up, or he can reduce the UPM size declared in the font. The second solution is often much simpler, because you only need to change one value in the font.

In more detail:

The three kinds of linespacing values (hhea, OS/2.Typo and OS/2.Win) determine the distance between two consecutive baselines. The tricky value is hhea.LineGap, because it's used by some Mac apps, while it is ignored by a few.

The reason why it's recommended that UPM = OS/2.TypoAscender + OS/2.TypoDescender, because some applications (I believe InDesign) determine the offset of the *first* baseline in a text frame as UPM – OS/2.TypoDescender. So in order for this to be equal to OS/2.TypoAscender, the above rule needs to be followed.

But a much more important recommendation is:

OS/2.TypoAscender + OS/2.TypoDescender + OS/2.TypoLineGap = OS/2.WinAscent + OS/2.WinDescent = hhea.Ascender + hhea.Descender + hhea.LineGap

Theoretically, it would be possible to assume that this means that:
OS/2.TypoAscender = hhea.Ascender
OS/2.TypoDescender = hhea.Descender
OS/2.TypoLineGap = hhea.LineGap

However, because some applications ignore hhea.LineGap, then perhaps it's a better rule to do:
OS/2.WinAscent = hhea.Ascender
OS/2.WinDescent = hhea.Descender
hhea.LineGap = 0

Since OS/2.Win values don't have a "LineGap" parameter, and if you do follow the rule UPM = OS/2.TypoAscender + OS/2.TypoDescender, then it means that OS/2.TypoLineGap is the UPM percentage that you want the line gap to be. If your intention is for the default linespacing to be 120% of the UPM, then OS/2.TypoLineGap should be 20% of the UPM. So if the UPM is 1000, 20% of the UPM, and logically, OS/2.TypoLineGap would be 200. If you want the default linespacing to be 125% of the UPM, then OS/2.TypoLineGap would be 250 for a 1000 UPM font.

The OS/2.TypoLineGap value needs then to be split in two and those partial values need to be added to OS/2.WinAscent and OS/2.WinDescent. If the font tends to have more "ink" above the OS/2.TypoAscender, then a larger part of the line gap value should be added to OS/2.WinAscent. If the font tends to have more "ink" below the OS/2.TypoDescender, then a larger part of the line gap value should be added to OS/2.WinDescent.

Fontographer 5 includes an algorithm that works just as described (and always assume that the default linespacing should be 120% of the UPM). I've written a Python script for FontLab Studio that makes the same calculation:

I hope that in the next version of Fontographer, we'll add a customization field that will allow the user to choose the default percentage (for users who want it to be different than 120%).


xy's picture


If Adam or anybody else could comment… I'm wondering…

Basically from Adam's post and Karten Luecke's PDF, I take it this is now the real* recommended way to go:

"However, because some applications ignore hhea.LineGap, then perhaps it's a better rule to do:
OS/2.WinAscent = hhea.Ascender
OS/2.WinDescent = hhea.Descender
hhea.LineGap = 0"

Is this still valid or has it changed in the last 2 years?
I have opened a few fonts created in the last 2-3 years and it seems everybody is doing it differently.
On a few occasions I have seen reputable foundries not respecting this recommendation and putting larger values in the OS2/Win tables than in the hhea, probably with the desire to avoid letters such as Aringacute to be cut out. Does it lead to bigger linespacing in some applications, what is the drawback to this?

Fontlab "calculate values automatically" has lead us to some quite terrible cutouts in windows applications (winascent and windescent = 0). So apparently nothing got calculated or what?

An update to the update of the update of the update which dates back to 2003 would be nice.

jasonc's picture

Yes, setting those pairs of values differently will give you different line spacing in some Windows apps vs. Mac apps. Unfortunately these values in Windows are often also used as a clipping zone, so they do need to be set correctly for the largest glyphs in the font.

Jason C

xy's picture

Thanks for the answer Jason. But I'm still a bit confused.

If they need to be set for the largest glyphs, why are Karsten Luecke, John Husdon and Adam Twardoch recommending to follow the "UPM + linespacing" system. In many fonts, this system doesn't allow enough space for Aringacute and Scommaaccent , which together don't fit in 1,2/1,2 x UPM.
Or is the recommendation then to also make sure these two letters fit in that box?

Also one thing that is very unclear and abstract to me: how should these metrics be applied across a family.
I think Karsten Luecke recommends to take the biggest values in the family, and to apply them to all the fonts in the family. That would imply that fonts with variable ascenders/descenders values would have their descenders or ascenders "floating" in certain weights, right?

From what I have seen, not many people follow this. More people respect the UPM box, but apply different ascenders and descenders values (basically the box moving up or down across the family). That caused problems?

John Hudson's picture

If they need to be set for the largest glyphs, why are Karsten Luecke, John Husdon and Adam Twardoch recommending to follow the "UPM + linespacing" system.

I think you are misinterpreting the recommendation, at least as I express it. You are presuming that linespacing is 1.2 x UPM, whereas the recommendation is to start with the non-clipping bounding box and then use that to calculate the linespacing (excepting in the case of No.6, below).

1. Start with the OS/2 WinAscent/WinDescent values, which must be sufficient to prevent clipping of the tallest and deepest glyphs in the font family*. This is the primary purpose of these values.

2. Because most Windows apps (erroneously) also use these values to calculate default linespacing, it follows that all other vertical metrics (treated as positive integers) should sum to the same total as WinAscent + WinDescent, presuming you want compatible linespacing regardless of which metrics set is used by software. Ergo:

3. Set the OS/2 TypoAscender and TypoDescender values to proportionally reflect the actual ascender and descender height of the typeface, but in such a way that they sum to the UPM. This is the basic check that ensures the scaling factor of the typeface relates to the design in some meaningful way. So, for example, if your font is on a UPM of 1000 and your actual ascender =740 and your actual descender =240, you would apportion 20 extra units to the TypoAscender and TypoDescender to bring the sum of the two up to 1000.

4. The difference between the sum of (TypoAscender + TypoDescender) and the sum of (WinAscent + WinDescent) gives you your TypoLineGap value.

5. There are two possible ways to set the Mac hhea table vertical metrics. One way is to set the Ascender and Descender values to be equivalent to the OS/2 WinAscent and WinDescent values, and then set the hhea LineGap value to 0 (zero). The other way is to set the three hhea values to be identical to the OS/2 Typo- values. Adobe did some testing on this a few years ago, and found that there was some discrepancy in Mac applications regarding how to calculate the distance from the top of a text frame for the first baseline. Their recommendation for best results in most places, in terms of compatibility with Windows layout, was to use the second method, i.e. match the hhea metrics to the OS/2 Typo- metrics.

6. All of this advice presumes that you are a) looking for maximum compatibility and b) that you are content for the OS/2 WinAscent and WinDescent to always determine the default linespacing. In some fonts, though, the inclusion of very tall glyphs that are only used in specific situations can result in too-wide linespacing if the WinAscent and WinDescent no-clipping zone also determines linespacing. In this case, some software will use the Typo- metrics instead if the OS/2 fsSelection bit 7 is switched on. This mechanism enables you to decouple the linespacing from the WinAscent/WinDescent values, in which case the hhea metrics should definitely correspond to the Typo- metrics. Obviously this mechanisn, because not supported everywhere, means that metrics can no longer ensure compatibility; it's a trade-off.

* Yes, the OS/2 and hhea table vertical metrics should be identical across all the fonts in a family. Hence, it makes sense that the WinAscent/WinDescent values are based on the height and depth of the tallest and deepest glyphs overall, which are typically found in the heaviest fonts.

jasonc's picture

Sorry, my comment was only about one small part of this large debate. Basically... what John Hudson said.

jason C

xy's picture

Hello John, Thank you for the thorough answer!
Practical case:

What would you do with a typeface where the highest point it 1185 and lowest -220
If these are the values I enter in WinAscent and WinDescent, it means TypoLineGap would be 405.
That's a big gap…

Paragraph 6> so in this case, if I activate OS/2 fsSelection bit 7 (how does that work? With ttx?) then some applications would again have a default linespacing based on the key dimensions metrics, while other would have a linespacing of 140% ?

John Hudson's picture

That's a big gap…

Yes. The convention employed in many fonts of default linespacing being 120% of the em was only ever practical, in terms of OS/2 WinAscent/WinDescent values, for fairly basic Latin character sets. As soon as one gets into other scripts, or even stacked Latin diacritic marks as found in Vietnamese and that troublesome /Aringacute/ -- troublesome not least because it is extremely rare in actual use, so should one worry about including it or not clipping it? --, this convention won't work. I've made the case to Microsoft several times that fonts should include script- and language-specific vertical metrics data so, for instance, the default linespacing for English text and Vietnamese text could be different and appropriate. In the meantime, though, we have to work with the existing set of metrics and how they are interpreted by existing software, which means, for most Windows programs, accepting that the non-clipping zone and linespacing will be the same, derived from the WinAscent/WinDescent values.

I've not tried setting fsSelection bit 7 with TTX, but I presume it is possible. I use DTL OTMaster, which is a bit awkward in that it expresses the value as a hexadecimal rather than a binary, so I have to enter the binary value in a scientific calculator, convert to hex, and then enter that value in OTMaster. I presume the next generation of font editors will provide toggle options for the newly defined fsSelection bits. Note that in addition to setting the bit, you also need to set the OS/2 table version to 4, and this implies that you should probably set bits 8 and 9 appropriately.

...then some applications would again have a default linespacing based on the key dimensions metrics, while other would have a linespacing of 140% ?

No software, to my knowledge, calculates default linespacing based on 'key dimensions metrics' -- by which I presume you mean the set of ascender, cap height, x-height and descender metrics so labelled by FontLab -- all use OS/2 metrics (Windows) or hhea metrics (Mac). If you set fsSelection bit 7, which is really only meaningful is your OS/2 Typo- metrics and Win- metrics do not sum to the same total height, then you will get inconsistent metrics between different applications. Also note that this isn't as predictable as it should be, because MS Word applies its own algorithm to spacing text set in fonts with fsSelection bit 7 enabled.

xy's picture

Hello John,

Thanks a lot for taking the time, things are clearer now. I really appreciated it!

Finally I decided to dismiss (clip) the Aringacute which allows me to follow your recommendation, with a linegap of 125%.

Martin Silvertant's picture

Could someone help me out? I'm trying to define the metrics for this typeface I'm about to transport to FontLab and can't make sense of it. Here are my key values:

If it helps at all, my cap height is 690 and my x-height is 482. When I calculate the value for the LineGap, I get to 32 rather than the roughly 200 I'm supposed to get. Am I supposed to decrease the Typo-values for OS/2?

By the way, in a different thread you guys were talking about the meaning of the word 'typo' and how you've never seen it being used for anything other than to mean a typographical error. I just realized the alternate meaning is used in FontLab! TypoAscender, TypoDescender and TypoLineGap.

Syndicate content Syndicate content