RFR: JDK-8314215 Trailing Spaces before Line Breaks Affect the Center Alignment of Text

John Hendrikx jhendrikx at openjdk.org
Sun Sep 10 21:14:06 UTC 2023


There are a number of tickets open related to text rendering:

https://bugs.openjdk.org/browse/JDK-8314215

https://bugs.openjdk.org/browse/JDK-8145496

https://bugs.openjdk.org/browse/JDK-8129014

They have in common that wrapped text is taking the trailing spaces on each wrapped line into account when calculating where to wrap.  This looks okay for text that is left aligned (as the spaces will be trailing the lines and generally aren't a problem, but looks weird with CENTER and RIGHT alignments.  Even with LEFT alignment there are artifacts of this behavior, where a line like `AAA  BBB  CCC` (note the **double** spaces) gets split up into `AAA  `, `BBB  ` and `CCC`, but if space reduces further, it will wrap **too** early because the space is taken into account (ie. `AAA` may still have fit just fine, but `AAA  ` doesn't, so the engine wraps it to `AA` + `A  ` or something).

The fix for this is two fold; first the individual lines of text should not include any trailing spaces into their widths; second, the code that is taking the trailing space into account when wrapping should ignore all trailing spaces (currently it is ignoring all but one trailing space).  With these two fixes, the layout in LEFT/CENTER/RIGHT alignments all look great, and there is no more early wrapping due to a space being taking into account while the actual text still would have fit (this is annoying in tight layouts, where a line can be wrapped early even though it looks like it would have fit).

If it were that simple, we'd be done, but there may be another issue here that needs solving: wrapped aligned TextArea's.

TextArea don't directly support text alignment (via a setTextAlignment method like Label) but you can change it via CSS.

For Left alignment + wrapping, TextArea will ignore any spaces typed before a line that was wrapped.  In other words, you can type spaces as much as you want, and they won't show up and the cursor won't move.  The spaces are all getting appended to the previous line.  When you cursor through these spaces, the cursor can be rendered out of the control's bounds.  To illustrate, if you have the text `AAA                 BBB CCC`, and the text gets wrapped to `AAA`, `BBB`, `CCC`, typing spaces before `BBB` will not show up.  If you cursor back, the cursor may be outside the control bounds because so many spaces are trailing `AAA`.

The above behavior has NOT changed, is pretty standard for wrapped text controls, and IMHO does not need further attention.

Now, for RIGHT alignment, the new code does change things a bit.  Where before the single trailing space that was not collapsed was shown at the end of each wrapped line, this space is now gone.  Typing further spaces after `AAA` will not show up, but they are still there, and moving the cursor through them will move the cursor beyond the right side of the control's bounds (just like LEFT alignment has such a case).  Some Text rendering implementations will "clamp" the cursor to prevent this (browsers), while others will render the cursor in the margin (but eventually the cursor disappears if there is not enough margin and there are too many spaces).

Personally, I think this is absolutely fine.  Wrapped text controls all have this kind of behavior, where typing a space just before the wrapping point seemingly has no effect until a non-space character is typed.

For CENTER alignment, the case is similar to LEFT alignment, except there is a bit less space available to render "invisible" spaces.

# Screenshots

Using `Label`s containing the text `AAA  BBB  CCC` (note the doubled space between words)

## First wrapping point

### Before
![image](https://github.com/openjdk/jfx/assets/995917/0b781556-30ee-4504-a222-e9daff756f7b)
Note the odd trailing space in Center and Right alignments.

### After
![image](https://github.com/openjdk/jfx/assets/995917/429da72d-ded7-4ba6-9b6f-d1fbc7d753c0)

## Small but text would still fit

### Before
![image](https://github.com/openjdk/jfx/assets/995917/e19971f7-a36d-415a-b1a5-2ff3ac423c9b)
Note how the wrapping occurs earlier than needed, leading to "empty" lines that contained invisible spaces

### After
![image](https://github.com/openjdk/jfx/assets/995917/e4344297-880e-4218-860b-e1ddfb2b46be)
Note how everything still fits

-------------

Commit messages:
 - Fix to ignore trailing white space for wrapping and alignment

Changes: https://git.openjdk.org/jfx/pull/1236/files
 Webrev: https://webrevs.openjdk.org/?repo=jfx&pr=1236&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8314215
  Stats: 51 lines in 1 file changed: 47 ins; 4 del; 0 mod
  Patch: https://git.openjdk.org/jfx/pull/1236.diff
  Fetch: git fetch https://git.openjdk.org/jfx.git pull/1236/head:pull/1236

PR: https://git.openjdk.org/jfx/pull/1236


More information about the openjfx-dev mailing list