Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ascender and Descender calculation seems off #7

Closed
TeckniX opened this issue Apr 19, 2013 · 5 comments · Fixed by #129
Closed

Ascender and Descender calculation seems off #7

TeckniX opened this issue Apr 19, 2013 · 5 comments · Fixed by #129
Milestone

Comments

@TeckniX
Copy link

TeckniX commented Apr 19, 2013

While use one of the Google webfonts: drsugiyama-regular, i noticed that php-font-lib created some really high ascender and descender limits, causing some extra line spacing. (DomPDF use)

Link to the font used from Google's web font:
http://www.google.com/fonts/#ChoosePlace:select/Collection:Dr+Sugiyama

Are the ascender and descender wrong in the font, causing this issue? If you look at the font loaded within the browser, paragraph layouts do not seem to show the extra line spacing.

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/1304232-ascender-and-descender-calculation-seems-off?utm_campaign=plugin&utm_content=tracker%2F317728&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F317728&utm_medium=issues&utm_source=github).
@shokre
Copy link

shokre commented Oct 6, 2016

I can confirm the issue.

Using Google Open Sans Regular font .afm file created with FontForge has following metrics:

UnderlineThickness 102
UnderlinePosition -103
Ascender 760
Descender -240
FontBBox -550 -271 1205 1048

while .ufm file created with php-font-lib has:

UnderlineThickness 50
UnderlinePosition -75
FontHeightOffset 0
Ascender 1069
Descender -293
FontBBox -550 -271 1204 1048

Rendering .pdf using DomPDF library with debugLayout enabled, native PDF fonts are rendered properly while custom Open Sans .ttf fonts (included with @font-face) are rendered with vertical offset (DejaVu Sans font with pre-generated metrics is included in DomPDF).
Sample: metric-broken.pdf

After manually replacing metrics in .ufm file with metrics from .afm file generated with FontForge, rendering is improved (Note: Only Open Sans Regular metrics are updated)
Sample: metric-fontforge.pdf

I've located the issue in AdobeFontMetrics.php (in php-font-lib), and the following simple metric-hack.diff makes DomPDF rendering more consistent with rendering of native PDF fonts. It seems that values in hhea header are not properly converted.
Sample: metric-hack.pdf

NOTICE: I'm not quite sure that this is the right way to solve this issue. I've done tests only with Open Sans (variants Regular and Bold), and DejaVu Sans Regular fonts, and only with DomPDF library.

Workaround for DomPDF

Use custom fontDir and fontCache, and one of the following:

  • Create .afm file with FontForge and rename it to .ufm or
  • manually tweak Ascender and FontHeightOffset by hand in generated .ufm file.

Package versions

# composer show
dompdf/dompdf      v0.7.0    DOMPDF is a CSS 2.1 compliant HTML to PDF converter
phenx/php-font-lib 0.4       A library to read, parse, export and make subsets of different types of ...
phenx/php-svg-lib  0.1       A library to read, parse and export to PDF SVG files.

@jmatthiesen81
Copy link

Hey fellows,

during our implementation of a design editor, based on KonvaJS where the customer can declare and place marker elements, we had big trouble with this issue. The post-rendering of dynamic elements is processed via DomPDF. Due to the wrong calculation of the Ascender and Descender, the text is not placed at the correct position.

I was calculating a lot of time and came to the following result.
Before the call of e.g. $font->normalizeFUnit($hhea["ascent"]) in \FontLib\AdobeFontMetrics::write the ascender and descender values should be added and the sum put in relation to the unitsPerEm. The relation factor from $unitsPerEm / ($ascent + $descent) should be multiplied with the ascender and descender values and the results passed to the $font->normalizeFUnit calls.

After I made these changes, our rendered PDFs are looking perfect.

Best regards Jan

@bsweeney
Copy link
Member

Thanks for the issue analysis! Feel free to submit a pull request if you have time, but we'll review and work that into an upcoming release regardless if appropriate.

@bsweeney bsweeney added this to the 0.5.4 milestone Dec 17, 2021
@sergey-shambir
Copy link

@shokre Thanks a lot, the workaround works!
I've written a PHP script that does the following:

  • loads the OpenSans font using FontMetrics::registerFont()
  • postprocesses ".ufm" files to override Ascender / Descender (values 760 and -240 suitable for all OpenSans font variants)

This issue is probably caused by the difference between the terms "Ascender" / "Descender" in AFM and TrueType

  1. Adobe Font Metrics File Format Specification v4.1 states that
    • Ascender is the Y-axis distance between the top of the latin "d" letter and the origin (i.e. 0 in glyph coordinates)
    • Descender is the Y-axis distance between the bottom of the latin "p" letter and the origin
  2. Apple's TrueType Reference Manual - Apple Developer states that
    • typoAscender is the maximum of glyph ascender values
    • typoDescender is the mimimum of glyph descender values

So Ascender/Descender in AFM cannot be calculated from TrueType font metadata (neither "hhea" nor "OS/2").
Maybe dompdf can read "glyf" table in TrueType font file, find parameters for latin "d" and "p" letters and use their yMax / yMin as Ascender / Descender for Adobe Font Metrics file.

Unfortunately, I'm not ready to make patch and submit pull request now.

@bsweeney
Copy link
Member

Maybe dompdf can read "glyf" table in TrueType font file, find parameters for latin "d" and "p" letters and use their yMax / yMin as Ascender / Descender for Adobe Font Metrics file.

This is exactly right, except that php-font-lib should be doing the work so that the values in the AFM/UFM are correct. I tested with Open Sans and get the expected results.

The updated logic will populate CapHeight (H), XHeight (x), Ascender (d), and Descender (p) values based on the glyph data as outlined by the specification. Ascender and Descender will fall back to the old logic if their respective glyphs are not present since the spec language around those values is that they are "usually" or "typically" based on those characters. I couldn't think of a related TrueType table record to reference for the other two values so they will not have a fallback and will be excluded if their glyphs are not present.

bsweeney added a commit that referenced this issue Dec 13, 2023
CapHeight, XHeight, Ascender, and Descender values should be based off of character data.

fixes #7
@bsweeney bsweeney linked a pull request Dec 13, 2023 that will close this issue
bsweeney added a commit that referenced this issue Dec 30, 2023
CapHeight, XHeight, Ascender, and Descender values should be based off of character data.

fixes #7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants