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