Tough issue with Text not drawn correctly, any experts that can take a look?

John Hendrikx john.hendrikx at gmail.com
Sat Mar 12 14:56:45 UTC 2022


TLDR: Skip to the Github link below.

So, I've run into an issue where a Label with wrap text set to true is 
only showing the first character of the text "as Kristoff (voice)" while 
all other kinds of texts show up correct (there's 100's of examples that 
all work, but only found one so far that doesn't work).  The label is 
placed in a VBox together with an Image and another wrap text Label.

Now, there is something really odd going on.  These VBox are placed in a 
3x3 Grid, and basically all of the labels used are displayed correctly.  
The Grid is fixed size, but the VBox content is rather flexible, and 
Labels that have a large amount of text should be wrapped and cause the 
Image in the VBox to become smaller to make space.

If I set the text of all these labels to a fixed value "as Kristoff 
(voice)" then ALL of them render incorrectly, only showing "a".  When I 
change the text to include a space behind the last character, then ALL 
of them render correctly.  In fact, any kind of change I do (like adding 
a "-" infront of this text) fixes the display problem.  So I suspect the 
issue has to do with the exact width of the text (126.0 in my case).

If I select the grid cell or move the cursor, the rendering immediately 
becomes correct for the cells involved, but all other cells keep showing 
just the "a".  If I hack LabeledSkinBase and remove the clip it 
generates if text doesn't fit, I can see that the ACTUAL content of the 
label is "a" and on the next line is "s Kristoff (voice)".  If I 
highlight the background of this label, I can see a box that would 
exactly fit the full text (and the box is only one line high), but it 
just isn't drawning it -- it only draws the "a" in the exact center of 
this box... It seems to know that the box should be that size to fit the 
label, but the text wasn't redrawn.

Now, because this layout is relatively complicated, with two reflowing 
labels and an Image that can "sacrifice" space if the labels demand 
more, I suspect JavaFX is doing multiple passes to get it correct -- 
debugging output does confirm that it does several attempts to get to 
the final size for this label (it starts with a width of 12.66 and a 
huge height wrapping on every character, then goes to 51x40 orso before 
settling on 126.0x18).

After a couple of hours debugging this and adding debug prints 
everywhere I started to suspect it was just not refreshing the Text or 
PrismTextLayout when it should; there is a LOT of caching and partial 
invalidation logic going on in these classes, most of which I just 
disabled during my search.

Finally I came to a piece of code in Text which is invalidating the text 
when `wrappingWidth` changes.  Changing only a single line there fixes 
my problem, but I'm unable to explain why.  I'm hoping someone can take 
a look at this code and say whether or not this change is indeed correct 
and the old code was incorrect...

A link to Github to the code involved: 
https://github.com/openjdk/jfx/blob/c6069d6845df4b90cca226e2b3dff49e3b48d8ac/modules/javafx.graphics/src/main/java/javafx/scene/text/Text.java#L669-L687

In this code there is a call to `needsTextLayout`.  Changing that to 
`needsFullTextLayout` fixes my issue.

The difference between `needsTextLayout` and `needsFullTextLayout` seems 
to be a call to TextLayout#setContent where the text and font is set.

If anyone knows this code that could help, or perhaps say if this change 
makes sense or not that would be helpful. I can be available for a call 
or whatever to give more details.

I would love to "fix" this in JavaFX via PR, but as I don't know how to 
test for this issue nor even how to describe it ("In super rare cases a 
wrappable label which in the end doesn't need wrapping only displays a 
single character"?) I'm unsure how I should file it to get a fix accepted :)

--John



More information about the openjfx-dev mailing list