Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

TextMesh Pro Sprite Glyph's Glyph Metric height does not visually change the height of a sprite glyph

Discussion in 'UGUI & TextMesh Pro' started by zander_m, Mar 19, 2021.

  1. zander_m

    zander_m

    Joined:
    Feb 7, 2019
    Posts:
    15
    When using Sprite Glyphs, changes to the height (H:) property of a glyph's Glyph Metrics, visually changes the width and vertical positioning of the rendered glyph (and not the height). This behavior is present in TMPro 3.0.4 and earlier.

    Here's a GIF showing how increasing and decreasing the Glyph Metric's height affects the rendered glyph


    Every other Glyph Metric property is applied in a way that seems intuitive, height is the wacky outlier. This is especially apparent when working with custom non-square glyphs/emoji/sprites.

    After a bit of digging, I wanted to shed some light on what's going on for anyone running into this behavior, as well as mention the "workarounds" that will likely get you to the result you're expecting (actually adjusting the glyph height).

    TL;DR / How do I fix it:
    You've got some options for actually adjusting the visual height of a Sprite Glyph.
    1. Assign a Point Size value greater than 0 in the Face Info for your TMP_Sprite Asset, then adjust the glyph metric's height.
    2. Adjust the scale of the glyph to compensate (amount depends on the font the glyphs get embedded in).
    3. Adjust the scale and width of the glyph metric instead.

    In more detail:
    As mentioned in the TMPro changelog (afaik there is no up-to-date documentation), when Face Info is not defined for a Sprite Asset (Point Size <= 0), the Sprite Asset will "inherit the Face Info metrics of the current font asset". As part of this inheriting process, a "default scale" is calculated for each Sprite Glyph. This default scale means that no matter what value you use for the glyph metric's height, the rendered glyph will always get scaled so it's visual height matches that of the tallest glyph in the font that the sprite glyphs are embedded in. (as defined by FaceInfo.ascentLine) This scaling totally undoes the visual height change you might expect to see when adjusting a property called "height".
    To make the whole thing even weirder looking, the rendered glyph's vertical positioning relative to the text baseline does adjust (as if the glyphs height was visually changing), resulting in the sprite shifting up and down as the height property changes.

    The "default scale" logic can be seen (as of TMPro 3.0.4) in TMPro_Private.cs:1943 or TMPro_UGUI_Private.cs:2041 respectively. The line containing
     m_currentFontAsset.m_FaceInfo.ascentLine / sprite.m_Glyph.metrics.height 

    So again, those "fixes":
    1. By assigning a Point Size greater than zero to the TMP_Sprite Asset's Face Info, this "default scale" value no longer needs to be inherited from the Face Info for the current font asset. Instead it's directly calculated using the supplied Point Size and Scale. After adding this, changing the glyph metric's height will behave much closer to the way you'd probably expect in this case.
    2. You can manually adjust the glyphs scale to counteract this "default scale". But again, the amount you'll need to scale by to do this perfectly depends on the height of the tallest character in the font you embed the glyph sprites in.
    3. Instead of adjusting the height, you can adjust all the other values. Scale the glyph, adjust the width to make it narrower/wider (probably also adjust AD and BY to match). Basically you can accomplish a visual height change by touching everything except height (which is kind of a pain).

    Unsolicited suggestions for a "real fix":
    I'm hesitant to call this behavior a bug, but it certainly feels extremely weird to interact with. To me, most of this confusion boils down to the glyph metric height essentially meaning two very different things depending on the context.

    In the context of "Sprite Asset has a defined Face Info" glyph metric's height is the "rendered glyph height" and adjusting it works as you'd expect.
    In the context of "Sprite Asset does not have a defined Face Info", the glyph metric's height instead acts as a modifier that is applied to the ascentLine (height of tallest glyph) of the Face Info we're inheriting from, which is then used to scale the glyph. (This is the unintuitive one shown in the gif)

    There are a couple potential options here that seem reasonable to me. The first (and maybe simplest) would be to to dynamically hide the height glyph metric altogether (forcing the use of width and scale to achieve taller narrower glyphs) if Face Info was defined for the TMP_Sprite Asset.
    Alternatively renaming the "H:" glyph metric property in the inspector to something that indicates it's use in conjunction with ascentLine as ratio. Though this would still be confusing to modify due to the inherited and unknown value of ascentLine.
    Or, we could borrow the patterns used by other Unity UI layout components and dynamically change the scale value as height is adjusted in order to compensate for the default and make the resulting visual change match expectations. (This approach could also be nice for maintaining the likely desired relationship between glyph width and horizontalAdvance, or height and horizontalBearingY)


    Anyway, those are all just suggestions. Sorry for the big wall of text.
    Hopefully someone gets a tiny bit of use out of this and can make a more informed decision on how to go about adjusting some glyph heights!