dompdf / php-font-lib

A library to read, parse, export and make subsets of different types of font files.
GNU Lesser General Public License v2.1
1.73k stars 256 forks source link

Can I query the measurements of a letter? #61

Closed lpaulsen93 closed 6 months ago

lpaulsen93 commented 7 years ago

I got a question about the skills of this lib.

Could I use the lib to query the exact measurements of a letter? E.g. what is the width and hight for letter 'A' in size '12pt' using font 'xyz'.

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/45156691-can-i-query-the-measurements-of-a-letter?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).
gingerbeardman commented 6 years ago

in this circumstance the correct term is the A glyph

bsweeney commented 6 months ago

This question is pretty old, so I assume you've moved on. Just wanted to provide some info in case someone else was interested.


You can retrieve the metrics of the glyph representing a character, but the actual measurements (pixels, millimeters) depend on usage (medium and size). There are various metrics available so the actual metrics you want depend on your use case.

For example, Cpdf calculates the space taken up by a glyph using the glyph's horizontal metric for the width and the font's ascender/descender (or font bounding box) for the height. This data is pulled from a font metrics file (AFM/UFM) generated from the font data, but to retrieve the metrics directly you would do something like the following:

// Load the font:
$font = Font::load("path/to/file.ttf");
$font->parse();

// Retrieve the units per EM
$funits_per_em = $font->getData("head", "unitsPerEm");

// Retrieve the font bounding box and calculate the height
$bbox = [
    $font->getData("head", "xMin"),
    $font->getData("head", "yMin"),
    $font->getData("head", "xMax").
    $font->getData("head", "yMax")
];
$f_height = $bbox[3] - $bbox[1];

// Retrieve the horizontal metrics for the character "A" (U+0061)
$glyphIndexArray = $font->getUnicodeCharMap();
$glyphIndex = $glyphIndexArray[61];
$hmtx  = $font->getData("hmtx");
$f_width = $hmtx[$glyphIndex][0];

The metrics values you retrieve are in font units (FUnits), which is "the smallest measurable unit in the em square, an imaginary square that is used to size and align glyphs." To determine the actual size of the rendered glyph you need to know the resolution of the target medium (e.g. 72ppi) and the desired size of the text (e.g. 12pt). From there you can calculate the measurement on the target medium by multiplying the metric value by a scale determined using the following formula: unit_size * device_resolution / ( unit_resolution * funits_per_em ). Working in points, the unit resolution is 72 pt per inch.

// calculate the measurement of the character
$unit_size = 12; // 12pt
$device_resolution = 72; // 72ppi
$unit_resolution = 72; // 72ppi
$scale = $unit_size * $device_resolution / $unit_resolution * $funits_per_em;
$width = $f_width * $scale;
$height = $f_height * $scale;

Recommended reading: TrueType Fundamentals