textratypist icon indicating copy to clipboard operation
textratypist copied to clipboard

Twemoji glyphs are misaligned

Open metaphore opened this issue 1 year ago • 1 comments

Hi, and thanks for the amazing features this library provides! It's mind-blowing to realize what you can do with those old boring libGDX texts now :raised_hands:

I ran into layout problems using Twemoji. I noticed that the emoji glyphs were misaligned when I tried them with my 9-pixels-high font. I thought, there might be something wrong with my font glyph markup, but emojis behave weird even with the default libGDX font.

val font = Font()
KnownFonts.addEmoji(font)
val label = TypingLabel("[+🤡] This is a [+😄]test message.", font)
label.setPosition(100f, 100f)
label.pack()
label.debug()
stage.addActor(label)

image image

So clearly, there's space reserved in the text for the emoji glyphs, but they are shifted by a constant value. Am I missing something? Or maybe there are specific requirements for the font to be compatible with Twemoji?

textratypist version is 0.10.0

metaphore avatar Jan 23 '24 19:01 metaphore

So, fonts can be configured in a lot of ways in the more recent TextraTypist versions, and one of those ways is the position and size of inline images (such as emoji or the game-icons.net icons). The configuration is rather counterintuitive and needs some fiddling back and forth, typically with larger values first (both positive and negative, usually) and then refining until you have it lined up just how you want it. The method on a Font you probably want is setInlineImageMetrics(); this is called on most fonts in KnownFonts, and looking at the source there might help some. That method takes 3 arguments; the docs are important:

  • Changing offsetX with a positive value moves all GlyphRegions to the right.
  • Changing offsetY with a positive value moves all GlyphRegions down (this is possibly unexpected).
  • Changing xAdvance with a positive value will shrink all GlyphRegions (this is probably unexpected).

Your first font (lsans) probably needs offsetX of about -16 to -20, as well as a small negative value for offsetY, like -2 . You may want to use a small positive number for xAdvance, which actually will scale down because of how the emoji are stored. Your second font needs an offsetX of I'd say at least -32, likely more negative, and offsetY might be -1 (not needed if you shrink the images with xAdvance set to 4 o so).

You can also sometimes accomplish parts of this by changing the descent up or down (with setDescent()), though with some pixel fonts this might not work as well. Generally, most fonts don't look good out of the box when you use underline and strikethrough, because the correct positions for those aren't stored in a .fnt file, and we have to guess. The configuration for descent is part of this, and so is setLineMetrics(), which takes x adjustment, y adjustment (which might be flipped relative to the offsetY for inline images, I can't remember), length adjustment for the line and thickness adjustment for the line.

Generally, fonts you add need to have at least some of these configured to use additional features beyond just text display. I'd like to find some way to store the configuration in some new file format, but that would have to be much later, probably after a 1.0.0 release breaks compatibility with the counterintuitive configuration and makes things like y movement always mean the same direction. It would also be nice to get the inline images more sane out of the box, but that involves the Font they are placed into... Hm... I'll look into this, I know lots of people want to use their game's own typeface with TextraTypist and the configuration is not that easy right now.

tommyettinger avatar Jan 24 '24 03:01 tommyettinger

OK, so the whole last comment I made almost a year ago is now going to be untrue in the next version -- emoji now have some configuration that they know about per emoji set (so Twemoji, OpenMoji, and Noto Color Emoji all have slightly different adjustments made automatically), and the configuration should be actually fairly intuitive now. the xAdvance metric seems to be the culprit in the original post, and that's fully available to use now, affecting x-advance and not sizing. I'll check how this works in 1.2.0-SNAPSHOT, or 1.1.1 or whatever number it is (it will be 1.2.0 when I am finally happy with all the tests). Version 1.1.0 still has some trouble with metrics for emoji and other inline images.

tommyettinger avatar Dec 31 '24 04:12 tommyettinger

The last comment is also now not true, partially: I may have gotten the default emoji (and many other inline images, probably not all) to not need any adjustments for most fonts. The 1.2.0 release is, of course, taking longer than expected! I keep working on other projects that come up, like Liftoff version 1.13.1.1 . The last I checked, inline image stretching wasn't working from the center, how I wanted it to, so that might be one last thing to change. I'm not sure if I will even change it, if everything else works...

tommyettinger avatar Jan 19 '25 10:01 tommyettinger

Woohoo, almost a year later, but the current version works!

Image

I didn't need to make any changes to the default Font, I used your sample code (translated back to Java, which is nice and easy), and it worked on the first try. Yay!

tommyettinger avatar Jan 20 '25 07:01 tommyettinger

Thanks a lot @tommyettinger This indeed will make usage of the library easier for newcomers!

metaphore avatar Jan 20 '25 10:01 metaphore