How can the fixed letter/character width be achieved in a message window with UMG?

(This is a translation of a [Japanese [Content removed] by Kitamura Toshihide.)

Thank you for your continued support.

I would like to know how to fix the letter width when displaying text in message windows etc. using UMG.

In the following thread, there is a similar issue reported:

BUG: Letter spacing depends on zoom / screen size

[Content removed]

The answer there, however, contains the following:

A limitation of this however is that we have to respect kerning rules when rending vector text at different scales (Which introduces integer rounding). In fact this issue occurs even with zero letter spacing.

So I guess that is still the expected behavior of the current font rendering. However, I would like to ask if there is any way to fix the width currently.

If the width is not fixed, line breaks can occur at unintended positions. This may cause overlapping with the next line. Also, the text may extend beyond the window width. This is quite difficult to handle.

One possible workaround is to arrange letters/characters one by one, but this method can’t use kerning. Also, this method is not ideal in terms of localization.

When this issue occurred in the past, we addressed it by converting all font glyph widths that were calculated as integers into floats (not kerning widths, but XAdvance, BaseLine, MaxHeight, and related parts). However, this approach was costly because there were too many places to convert. So I’d appreciate it if you could provide any official solution or workaround. Is there any plan to update for this issue?

Also, when I practiced the float conversion of XAdvance, I did not find any issues with font rendering, but even so, in order to display letters/characters neatly, is it necessary to render each letter/character using the integer width?

I have attached the reproduction file, MsgTest.zip. In the project, I changed the DPI scale to be linear up to 4K.

900x540

[Image Removed]

1120x630

[Image Removed]

再現手順
- Switch the Level Editor > Play > New Viewport Resolution to 900x540 and 1120x630, and start it.

- The line break position in the first line of the image will change.

- You can also see similar issues by zooming in and out using the mouse wheel in the UMG editing screen.

Hello,

About the issue you are having, I understand that character wrapping will occur at places that are incorrect in Japanese, right?

However, I’m not sure to understand the second part of the issue: “This may cause overlapping with the next line. Also, the text may extend beyond the window width.”

In the case of localized text, this the kind of thing we are expecting (text taking more or less lines), can you rephrase it maybe if I understand wrongly ?

The instability in the width of the text is caused by 2 things:

  • the imprecision due to the usage of int in the computation as you already noticed. This is something that we know about, but so far it wasn’t a priority, so we have no ETA for now. However, as it seems you fixed that on your side, it should not introduce any regression on the display quality (I already experimented what you did). Note that if using distance fields (see below) there is absolutely no pixel rounding requirements. It’s even better to avoid rounding.
  • the grid fitting done by Freetype (one of the middleware we use to handle text) in order to improve the quality of text, especially at small size. The good news is that you have control on that:
    • You can explicitly disable it on your font face, but the quality of (small) texts could be reduced:
    • Alternatively, you can also enable Signed Distance Field Text Rendering, that will automatically disable the grid fitting, whatever the value of hinting is for a given font.

Please not that while disable grid fitting alone will increase the stability of the text width, and allow to display it at smaller size than before without having it wrapping at different position (work quite well in UMG designer, but not that much in PIE from my initial tests), it doesn’t solve completely the issue.

Thanks!

[mention removed]​

(This is a translation of a Japanese post by Kitamura Toshihide.)

I am very sorry that I missed your reply.

> About the issue you are having, I understand that character wrapping will occur at places that are incorrect in Japanese, right?

Yes, your are correct. By the way, I wrote “If the width is not fixed, line breaks can occur at unintended positions.”, but it should have been “If the width is not fixed, line breaks can occur at unintended positions when the window width changes”, and the “window width” there refers to the width of the entire game application window.

> However, I’m not sure to understand the second part of the issue: “This may cause overlapping with the next line. Also, the text may extend beyond the window width.”

> In the case of localized text, this the kind of thing we are expecting (text taking more or less lines), can you rephrase it maybe if I understand wrongly ?

I am sorry for the lack of clarity. I don’t care about line break positions changing due to localization. As you mentioned, the number of characters may vary depending on the language, so that it is natural that the width of the text and the line break positions change.

I wrote:

“If the width is not fixed, line breaks can occur at unintended positions. This may cause overlapping with the next line. Also, the text may extend beyond the window width. This is quite difficult to handle.”

By this, I meant that it is “quite difficult to handle” because, in a specific language (such as Japanese), the change of the application’s window size can affect the length of the text rendering. For example, suppose the display area of the message window is 30 characters wide and 4 lines tall. When you change the window size, the text may sometimes be displayed in 5 lines. Additionally, if you are using something like an item name which has no line breaks in a TextBlock, it may overlap with the message frame.

Since the text width varies depending on the window size, there are more things to pay attention to during development, which is why I used the phrase “quite difficult to handle.”

> the imprecision due to the usage of int in the computation as you already noticed. This is something that we know about, but so far it wasn’t a priority, so we have no ETA for now. However, as it seems you fixed that on your side, it should not introduce any regression on the display quality (I already experimented what you did). Note that if using distance fields (see below) there is absolutely no pixel rounding requirements. It’s even better to avoid rounding.

Thank you very much for your experiment. Also, I felt relieved that I received information that if using SDF, it is correct to perform calculations with floats. I’d appreciate it if you could provide some support of this on the engine side, as well.

If you do not care about height accuracy, I found it is possible to fix the text width by only changing XAdvance. However, FFreeTypeAdvanceCache::FindOrCache() was changed in CL8197520. This change needs to be restored. (Considering scaling for each character may cause variability.)

> You can explicitly disable it (grid fitting) on your font face, but the quality of (small) texts could be reduced

I had also tested “disabling grid fitting” before, and confirmed that the width became relatively stable. However, as you mentioned, it was not perfect and lacked stability yet. So, in the end, I needed to modify the engine to calculate Glyph width in float.

If possible, I would appreciate it if you could incorporate this support into your roadmap.

If changing the window size affects the results, more checks and considerations should be done on the development side. This, in the end, will lead to more man-hours. If the results become more stable, the system will be easier to use.