source-foundry/font-line

Line spacing/vertical metrics approach discussion thread

chrissimpkins opened this issue · 22 comments

@davelab6 @kenlunde

Be interested in your expertise & thoughts about the approach that we are using to set and modify the line spacing/internal leading in fonts with this tool. Vertical metrics modifications have been a common request among developers who use the Hack typeface because few text editors aimed at developers currently support line spacing adjustments. We are restricted to modification of the font files in order to broadly support tighter and looser line spacing. While highly subjective, the issue matters to developers because some like to fit as much code into a view as humanly possible (the small font size, tightly line spaced crowd) and others want improved legibility that comes with additional whitespace between lines.

I based our vertical metrics modifications approach on Karsten Lücke's approach defined here.

The details of the OpenType table metrics changes are in the project README file here and the calculations are performed in the modify_linegap_percent() function defined in this module.

The approach that I took for Version 1.003 and beyond of Source Han Sans and Noto Sans CJK involved 1) setting OS/2.sTypoAscender (880) and OS/2.sTypoDescender (-120) so that their sum equals the UPM (1000), which also represents the CJK em-box in which the glyphs for ideographs, kana, hangul, and other full-width symbols are optically centered; 2) setting both OS/2.sTypoLineGap and hhea.LineGap to 0 (zero); and 3) setting OS/2.usWinAscent/hhea.Ascender and OS/2.usWinDescent/hhea.Descender in a harmonized way that a) involves factoring out glyphs that are unusually tall and are used only in vertical writing, such as U+3031 and U+3032, along with the vertical forms of U+2E3A, U+2E3B, and U+302A through U+302D; and b) using the highest values across all weights for this purpose. This is described in the Source Han Sans ReadMe (the PDF will download if clicked) file (see the 'OS/2' Table Overrides section on page 15). Anyway, this gave us the best results.

@kenlunde Thank you very much Ken. I really appreciate this feedback. How does your team perform cross platform testing of the rendering of these vertical metrics? Is this all manual across a number of different text rendering applications/environments in Windows, OS X, and Linux or are there available tools to examine this?

The use of zero height for the OS/2.sTypoLineGap and hhea.LineGap seems to be a common approach as well based upon inspection of a number of typefaces (I noticed this in Source Code Pro and a number of other professionally designed faces). Is there a benefit to this over the use of a value in the OS/2.sTypoLineGap field on one of the OS's? For those who want to override the intended line space design in a typeface, do you feel that it is better to modify the leading in the OS/2.usWinAscent/hhea.Ascender and OS/2.usWinDescent/hhea.Descender fields and leave the OS/2.sTypoLineGap at 0? Aside from clipping issues, are there any other potential side effects that might happen with this? The multiple properties and different platform/application specific approaches eliminate any semblance of clarity with this issue.

For my future reference, the description of the OS/2 table mods in Source Han Sans is on page 15 of the pdf linked by @kenlunde in #2 (comment)

As an aside, it also seems that the use of OS/2.sTypoLineGap = 0 is recommended for web fonts. (#1)

@typesupply @benkiel

Tal and Ben, do you happen to have any insight/thoughts about the most optimal cross-platform approach to OpenType vertical metrics on the desktop and web? We are developing an open source OT vertical metric reporting + post-build modification tool. I'd be interested in your experience, current approach, and thoughts about our (yet very early and open to modification) approach here.

See the top post for the impetus.

https://github.com/googlefonts/gf-docs/blob/master/VerticalMetricsRecommendations.md is the original research by Raph Levien on this from about 5 years ago; basically the conclusion is that each of the 3 sets of ascent/decent values should be the same, the ymax and ymin of the family, and both linegaps should be zero.

FontBakery has a reporting method and a autofixing method that is very similar to the code you have here.

@davelab6

This article was extremely helpful Dave. It looks like the web font approach differs from that on the desktop/print side. Is there a reason why this approach is not broadly used in many typefaces out there that are designed for the screen? I took a look through a large number of system fonts on OS X, and a variety of non-system fonts used in coding. Many/most use either the approach that I started with here or one like @kenlunde described above with TypoAscender and TypoDescender set to the UPM size, spacing added to the hhea Asc/Desc and OS/2 winAsc/winDesc values (without a consistent pattern, some add more space above and some equal space above and below) and both OS/2.linegap and hhea.linegap values set to zero. Some notable examples use a TypoDescender to TypoAscender height that is less than the UPM size oddly enough (namely Times New Roman, Georgia, and Courier New system font builds on OS X 10.11.4). Unfortunately, this is all anecdotal and it would be nice to have a more systematic review of how these changes look in commonly used editors across Windows, OS X, and at least one commonly used Linux distro, similar to the treatment on the web browser side.

Here are some of the salient points (for me) that I pulled out of the document that you linked. I am adding them here for my future reference.

For creating fonts: definitely make sure usWinAscent and usWinDescent values include the bounding box of all glyphs in the font, as anything falling outside will be clipped. Do make sure that usWinAscent values matches hhea Ascender and sTypoAscender (same for Descent). Do use zero values for hhea LineGap and sTypoLineGap (in general, we’ll want any excess budget to be reserved for additional accents, and also it’s quite difficult to make line gaps consistent).

Add to the vertical space budget. Note that the ascent and descent values will almost always need to increase, otherwise there will be clipping. In this case, do add equally to ascent and descent. This way, baseline positioning won’t be affected in the case that line-height is set.

These cross-platform x browser images are very helpful: http://levien.com/webfonts/vmtx/

As is this summary of the findings: https://github.com/googlefonts/gf-docs/blob/master/VerticalMetricsRecommendations.md#detailed-analysis-of-browser-testing

I'm sure that this tool duplicates functionality that has been previously developed. This was built primarily as a tool to support simple vertical metrics modifications in our fonts (and other fonts used in situations where the default line spacing cannot be adjusted programmatically on the renderer side) as we have a number of issue reports open with requests for wider and narrower line spacing. This is simply the toothpick from the Swiss army knife that is Font Bakery and I am quite certain that I would receive some blowback if I asked our users to do the following in order to modify line spacing ;)

dependencies

What I do for web fonts is different than for print fonts.

For web fonts, what @davelab6 pointed to is what I do. You want line heights to be consistent between browsers, this does that.

For print/desktop fonts, your concerns are different. I do pretty much what @kenlunde described. The hhea and win values take care of clipping in Word, and the Typo values give you the desired vertical metrics in design applications. How you handle the Typo values depends on the font's design, and will likely not align with an actual height of a character in the font. You're picking values that are rational for the design, not mathematical.

@benkiel Thank you very much for this feedback Ben. I really appreciate it.

Can you clarify what you mean in this comment?

How you handle the Typo values depends on the font's design, and will likely not align with an actual height of a character in the font

What aspect of design do you use to define this relationship?

Do you have recommendations for how one might safely place control of these metrics in the user's hands? The goal here is in part to settle on an acceptable strategy for these definitions, but also to permit those who we will assume know nothing about these issues to modify these values in a way that the typeface appears satisfactory without significantly compromising the design. I understand that this is, perhaps, unacceptable from a design purist standpoint but I would like to try to develop a strategy that empowers users to make the typeface more usable/functional for themselves in situations where editors do not permit line spacing adjustments. This situation is not unusual in the current era of source code editors. Fortunately, the ASCII set comprises the vast majority of glyph use there so we are not dealing with a great deal of outlier points. This will without doubt significantly impact glyph sets that rely on vertical relationships across lines (e.g. the block element glyphs and box drawing glyphs) and potentially glyphs that extend far above or below the confines of the Ascender and Descender if the spacing is tightened. The tool comes packaged with this warning :)

I wonder to what degree the conventions in browsers, design applications, and Word that we've discussed so far apply to commonly used source code editors. If knowledge of this is out there, I haven't been able to dig it up to date.

Is there a simple way to identify the ymax and ymin in the OpenType tables? Is this value captured during builds in a field? If so, I can safeguard against clipping by restricting the spacing reduction to the point where black meets black.

There are head.yMin and head.yMax in the 'head' table.

@kenlunde 👍 thank you!

To add to the discussion with regard to the sTypoAscender and sTypoDescender values in the 'OS/2' table, while I cannot speak with any authority to non-CJK fonts, at least for CJK fonts I feel somewhat strongly that these values 1) add up to equal the UPM and 2) correspond to the top and bottom of the ideographic em-box in which CJK glyphs are optically centered. For the other vertical metrics values, I see little or no disagreement.

Agree with @kenlunde about the Typo values. They should sum to the UPM, they should not clip key characters (i.e., don't allow them to be less than the cap height or higher than the lowercase g) and they should be rational (sTypoDescender should be less than sTypoAscender). For latin fonts there isn't the issue of centering the way CJK has. sTypoLinegap will be the result of adding the absolute values of the hhea ascender & descender values, minus the UPM. If this number is exceptionally large —i.e., way over 120% of the UPM, then you may want to force it to be less. This will cause clipping on the exceptionally large glyphs, but is reasonable not to have a huge linegap. For fonts on a 1000 UPM, I start to edit if the sTypoLinegap is greater than 325 (depending on the design, script typefaces will tend to have a larger line gaps than other designs).

@kenlunde Noted. Thank you very much Ken. It seems that you and @benkiel are in agreement about this approach for screen/print use. Do you use the same approach with CJK web fonts?

@benkiel Thanks for the clarification. I was under the impression that you were setting s.TypoLinegap to 0 but it sounds as though you are using a strategy that is similar to what I started with here. These upper and lower limits are very helpful too. Thanks for all of this information!

@davelab6 Thanks Dave! I forgot about that article. I definitely agree with Rainer's sentiments re: vertical metrics:

Whoa. And now, for a coffee break. Or some ice cream. Or both.

I will take a good look through all of the metrics suggestions in that article and here in this thread again this evening. Thanks for all of the input!

@chrissimpkins: Someone else at Adobe can correct me if I am wrong, but we prefer to have uniform vertical metrics for web and desktop use. Our fonts started off using desktop vertical metrics, because that was the primary use case. Now that fonts are much more easily used on the web, it is now a very strong use case, and in some ways, stronger than desktop use. It doesn't make sense to have separate fonts for desktop and web use, especially if the fonts have a large footprint (CJK).

Going one step further, one phenomenon that I have observed is that fonts that include vertical metrics that are meant to work for web use generally work well for desktop use, but not vice-versa.

@davelab6 @kenlunde Thank you very much Dave and Ken. Still tossing around how to handle the defaults here. I think that I am going to simply support manual modifications of these values for those who would like to script changes to meet the metrics that they would like.

Based upon the conversation and multiple approaches described/discussed here:

As of v0.6.0, I am deferring to and maintaining the original font metrics design for vertical metrics changes with the percent command. The "Google Fonts", "Adobe Fonts", and original default approach are all supported now. The tool analyzes the approach used in the font before the modifications are performed and automates the changes to a user defined %UPM line spacing value. This addresses issue #6 and supports all of the different approaches that you are using based upon the conversation here.

I will add support for manual modification of the individual metrics values from the command line in a future version.