Repository navigation
FOP-1896: A font's descender is not taken from a typo descender above the baseline, nor guessed as 0 - #119
Open
plutext wants to merge 1 commit into
Open
FOP-1896: A font's descender is not taken from a typo descender above the baseline, nor guessed as 0#119plutext wants to merge 1 commit into
plutext wants to merge 1 commit into
Conversation
… the baseline, nor guessed as 0 OpenFont.determineAscDesc took OS/2 sTypoAscender/sTypoDescender, in its first branch and in its fallback, without checking the descender's sign. Wingdings, Wingdings 2 and 3, Lucida Sans, Lucida Fax and Lucida Sans Typewriter have sTypoDescender +420 where their hhea descender is -432, so the text area lay wholly above the baseline and the underline ran through the letters. The OS/2 values are now used only when sTypoDescender <= 0. guessVerticalMetricsFromGlyphBBox replaced the ascender and descender with the bounds of the 'd' and 'p' glyphs whenever the two exceeded the em, whether or not it had found those glyphs, so a font without them got 0 and 0 (most Noto fonts for scripts other than Latin, symbol fonts; Wingdings once its OS/2 values are refused). It now replaces them only with values found either side of the baseline. The two conditions of the patch attached to FOP-1896 in 2011. Tests patch sTypoDescender in memory: AndroidEmoji with +650 (Wingdings' case) and DejaVuLGCSerif with +492 (the Lucida case); testGetLowerCaseAscent now expects AndroidEmoji's 2200 where it expected 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes FOP-1896.
OpenFontsets a TrueType or OpenType font's ascender and descender in two steps, and each has a defect.They stack: fixing the first alone makes the font in the issue worse.
1. A typo descender above the baseline.
determineAscDesctakes OS/2sTypoAscenderandsTypoDescender, in its first branch and in its fallback, without checking the descender's sign. Severalshipping fonts have it wrong. Windows' Wingdings, Wingdings 2 and 3, Lucida Sans, Lucida Fax and Lucida Sans
Typewriter have
sTypoDescender+420 of 2048 where their hhea descender is -432. Maiandra GD,Haettenschweiler and Lucida Handwriting are similar. FOP takes the positive value, so the text area lies wholly
above the baseline (0.565 em for Wingdings), and the underline runs through the letters, as the issue reports.
The OS/2 values are now used only when
sTypoDescender <= 0.2. A guess from glyphs the font does not have. When the chosen ascender and descender together exceed the
em,
guessVerticalMetricsFromGlyphBBoxreplaces them with the top of thedglyph and the bottom of thepglyph, whether or not it found them. A font without them gets an ascender and a descender of 0;
TTFFileTestCaseasserts exactly that for AndroidEmoji, beside "TODO: Nedd to be fixed?". Of 2,547 distinctfont files loaded through
FontLoader(the font sets of several Linux desktop distributions, and a Windows and Officeset), 978 get 0 and 0. They include most Noto fonts for scripts other than Latin, the Droid script fonts, MT
Extra and Algerian. With a text area of height 0, the baseline sits in the middle of the line and the glyphs
rise into the line above. The guess now replaces the table values only when both were found, either side of
the baseline (
localAscender > 0 && localDescender < 0).Wingdings needs both: its hhea box (1841 + 432) exceeds its em and it has no
dorp, so refusing its OS/2values alone sends it to the guess, which gives 0 and 0.
These are the two conditions of the patch Eugene Markovskyi attached to FOP-1896 in 2011, arrived at
independently and then compared. That patch also required a negative hhea descender in the second branch,
which none of the 2,547 fonts needs: none has a positive one.
Measured at 11pt (area tree; text area height, and baseline from its top):
Line pitch does not change, since
line-heightstill sets it; what moves is where the baseline sits in theline. Every font the change moves had, before it, an ascender of 0 or a descender at or above the baseline;
after it, none of the 2,547 has either.
Tests. No new font:
TTFFileTestCasepatchessTypoDescender(OS/2 offset 70) in memory.testPositiveTypoDescenderNotTakenWithoutGlyphsToGuessFrom: AndroidEmoji with +650 is Wingdings' case, andexpects its hhea values, 2200 and -650.
testPositiveTypoDescenderNotTakenWithGlyphsToGuessFrom: DejaVuLGCSerif with +492 is the Lucida case, andexpects its glyph bounds, 1556 and -426.
testGetLowerCaseAscentexpects AndroidEmoji's 2200 where it expected 0, and its descender, -650.All three fail without the change. The fop-core suite passes with it: 3663 tests, 0 failures (4 skipped), and
checkstyle reports 0 violations.
🤖 Generated with Claude Code