Search code examples
fontspython-imaging-libraryfont-sizetruetype

how to convert font units (with certain font size) to pixels?


i have a font.ttf which i need to calculate the value of its unit to pixels when using this font with certain font size lets say 100,

as you see this is a gylph in some software for fonts editing, and the selected coordinates is presented in font units which are dynamic to how big is the font when using, Is there an equation to calculate the units in pixels when font is used with given size ?

example


Solution

  • A key unit to understand here is the em. It's what establishes the connection between the units for outlines you see in a font design tool and the number of pixels that are used for a rasterized glyph.

    Glyph outlines in OpenType / TrueType fonts are designed on a grid, and the designer sets the size for that grid on a font-wide basis. The grid is set to some number of font design units per em (UPM). So, for example, a font designer might specify 1000 font units per em, or 2048 font units per em. That value is stored in the font.

    Note that this doesn't determine how large the glyphs can be. Suppose a font is created using 2048 units per em. The glyph for a character like "X" might be 1000 units from bottom to top, or it might be 3000 units from bottom to top. The units per em doesn't constrain the total size of the grid that can be used, or the size of outlines within the grid.

    When you set text size in a text editor, word processing app or desktop publishing app (e.g., Notepad, Word, Pagemaker) the app will typically use units of "points". A printers point is a physical unit, approximately 1/72 of an inch; in digital type, a point is exactly 1/72 of an inch. But when you select a text size, what you are actually setting is points per em.

    So, suppose a font is designed with a grid of 1000 font design units per em; and suppose in the app the text size is set to 18 points (per em). 18 points is 0.25"; so the 1000 design units of the em correspond to 0.25". Or, if the text size is set to 144 points, the 1000 design units of the em correspond to 2".

    The other important factor to your question is how many display pixels correspond to an "inch". At a minimum, the physical pixel density of the actual display is part of this—number of pixels per physical inch. But another factor might be scaling that is applied by the host operating system, and that can depend on the display form factor and the expected viewing distance. For example, a 27" 4K desktop monitor is likely to be viewed from a distance just under two feet; when displaying on a 55" 4K TV, the content is going to be viewed from distances more like ten feet. The TV's pixel density is about half that of the desktop monitor, but the typical viewing distance is more like five times farther away. So, all that gets considered when determining how a logical inch of content relates to a physical inch on the display.

    A further complication is that the software could have a logical notion of pixel that isn't the same as the display physical pixels. One way this can be manifested is a "display resolution" setting in software. So, for instance, an LCD display might physically have a pixel resolution of 1920 x 1024, but the software might be set to assume a resolution of 1024 x 768. (Of course, for that configuration, an app will draw assuming a 1024 x 768 display, but then the content of each pixel somehow needs to map onto the physical pixels. There are different ways that might be managed.)

    Ultimately, what matters is what the software assumes, logically, is the size of the display in pixels and number of pixels per "inch" (PPI). What gets set in the font rasterizer is pixels per em. The designer's outline gets scaled onto a grid based on the assumed pixels per em (PPEM).

    So:

    • font designer sets font design units per em
    • application sets text size in points per em
    • 72 points per em
    • the OS (or whatever software is driving the display) assumes some number of pixels per inch

    And:

    ppem pixels / em

    = (text-size pts / em) * (1 inch / 72 pts) * (logical-ppi pixels / inch)

    = (text-size * logical-ppi / 72) pixels / em

    Now if you look at the size of some feature in glyph outline data, you can use the above as the factor to get from the size of that feature in design units to the size of the feature in (logical) pixels.

    (feature-size units) * (1 em / font-upm units) * (ppem pixels / em)

    = (feature-size * ppem / font-upm) pixels

    So, for example, if the text size is 12 pts and the ppi is 120, that means the ppem is 20 pixels/em. Then, suppose the font's UPM is 1000 and the height of the outline for "X" is 600 units. In pixels, the "X" glyph will be (600 * 20 / 1000 =) 12 pixels high.