-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8185261: Font fallback sometimes doesn't work in Swing text components #7313
Conversation
👋 Welcome back dbatrak! A progress list of the required criteria for merging this PR into |
@JB-Dmitry The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
Webrevs
|
* @test | ||
* @bug 8185261 | ||
* @summary Tests that font fallback works reliably in JEditorPane | ||
* @key headful |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the test depends on the headful libraries? Don't we need to test both headful and headless cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, the test will work just as fine in a headless environment. Copied that line without fixing. Will remove it.
@@ -0,0 +1,114 @@ | |||
/* | |||
* Copyright 2022 JetBrains s.r.o. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that different files use different style of "Copyright 2022 JetBrains s.r.o", is the current correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To my knowledge, it's correct. It's also used in other JetBrains source code currently.
* Font with fallback components (using CompositeFont), its Font2D handle | ||
* should be copied to derived fonts. | ||
*/ | ||
private transient boolean withFallback; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder how it will work if the Font was read from the system, then serialized/deserialized and then used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I fully understand the question. Font
object cannot have both createdFont
and withFallback
fields set, at least in the current implementation.
If we're talking about 'created' fonts (created from a file), the fix doesn't change anything with regard to their behavior - after serialization/deserialization the font might not work, I guess, if it's not registered using GraphicsEnvironment.registerFont
. In any case, it will lose it's 'created' status, and will change behavior correspondingly.
If we're talking about 'fonts with fallback' (like the ones JEditorPane
creates under the hood), they will lose their fallback components after serialization/deserialization. But that's also how it worked before the proposed change. I'm not going to address that problem in this PR.
@@ -1848,6 +1857,7 @@ public boolean equals(Object obj) { | |||
nonIdentityTx == font.nonIdentityTx && | |||
hasLayoutAttributes == font.hasLayoutAttributes && | |||
pointSize == font.pointSize && | |||
withFallback == font.withFallback && | |||
name.equals(font.name)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know how much of the fix falls apart if this is changed, but I am not sure about adding this invisible attribute to equals(). I suppose font2DHandle would have the same issue .. but I didn't think that could be used in equals because it is assigned lazily so it would present even more problem.
I do see that it would be tricky to have some private extra equality testing in the code that finds the right fall back but I'd still like to see if that approach might work. Can you add in to the bug a more detailed explanation of where exactly you see the problem occur ?
I need some convincing and really would like to see if there is an alternative solution that I might prefer but that is something I can't switch on to right now since nothing is coming to me which means it is likely to take some time.
I didn't get the JCK comment createdFont is transient .. and nothing serializes the font data.
Serialization of Font objects is just serializing the fields liek name and style and size but there's no guarantee that it will behave the same .. I mean if I serialize Segoe UI on WIndows and try to deserialize it on Linux nothing in the world can fix the issue that Linux doesn't have that font.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Serialization of Font objects is just serializing the fields liek name and style and size but there's no guarantee that it will behave the same .. I mean if I serialize Segoe UI on WIndows and try to deserialize it on Linux nothing in the world can fix the issue that Linux doesn't have that font.
Since the Font object will lose some fields during serialization its behavior will be changed even on the same platform.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added some more details to the ticket about why exactly given test case isn't working as expected. Please let me know if I wasn't clear enough.
I don't know how much of the fix falls apart if this is changed, but I am not sure about adding this invisible attribute to equals().
That added line in equals()
method is actually the main change in the fix. As you say, one could possibly also try to compare font2DHandle
-s instead, but that would require forcing the population of that field in equals
method, which seems to have larger potential for side effects.
As a font with fallback components can produce different rendering that the font without them, I believe, they shouldn't be considered 'equal'. Of course, there's an alternative method to fix this - make font metrics cache distinguish such fonts explicitly, without modifying Font.equals()
. But font metrics cache isn't the only place comparing fonts using equals()
method, and such a solution, I believe, would just mean waiting for other trouble in future.
The fact that equals
would be using some private information isn't perfect of course. Ideally, this information (whether the font supports font fallback or not) should be public, and it should be possible to specify this property when creating a font object, but that needs introducing new API methods, and I don't want to go that far at the moment. Also, we're already living in a non-perfect world, where two Font
objects with identical public properties might behave differently, and now we're just changing equals
method to reflect that.
As for the comment about JCK, that relates to a yet another implementation option - do not introduce a new field, and just add comparing of createdFont
fields in equals
method. That's the way it was originally implemented in JBR 4 years ago, but after we found out it breaks JCK, the fix was changed to use a separate field. Corresponding JCK test, creates a font object from a file on filesystem, using Font.createFont
method, serializes/deserializes it, and checks that the result is 'equal' to the initially created font. As createdFont
field is transient, it's reset to false
after serialization/deserialization, and the test obviously fails, if we try to include createdFont
check into equals
. Making createdFont
field not transient also doesn't seem to be an option, as that is also considered an API change.
Yes, I noted this would present even more problems.
I was getting at this with my comment
But it wasn't (isn't) clear to me without tracking this down if some piece of the implementation is making Taking a look I think the problem starts with getCompositeFontUIResource() So another approach is to define a subclass of FontUIResource in which it over-rides hashCode() and equals() It would only be equal to another CompositeFontUIResource with the same base font sun.font.CompositeFontUIResource extends FontUIResource { ... public void boolean equals(Object o) { Then in sun.font.FontUtilities we add
Ah but this won't work if we are mixing Font and this sub-class since equals then won't be symmetric .. The explanation about JCK indicates that JCK could also obtain a font from Swing that has fallbacks, |
That's true - after the fix, a font with fallback components will not be equal to the original one after serialization/deserialization. In my opinion, that's OK, as after that it will behave not in the way original font does - that's already the case now. Are you saying that is still a no-go? Then we either need to change the serialization format for |
@prrace Any chance of looking at this? |
Still needs a review. |
I know .. I know .. I just (a) don't like it, and (b) don't have a good alternative. |
@prrace So, how do we proceed from here? Should I just wait and ping you periodically? |
Still waiting for a response. If you're not comfortable with changing |
Not having a feedback on PR for months is pretty discouraging. If any help in solving this issue isn't going to be accepted, let me know - I'll stop pinging then. Just in case, let me re-iterate on the available options, as I see them:
|
@JB-Dmitry This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
@JB-Dmitry This pull request has been inactive for more than 8 weeks and will now be automatically closed. If you would like to continue working on this pull request in the future, feel free to reopen it! This can be done using the |
The proposed fix makes fonts with and without fallback components distinguishable (in terms of
equals
method), so thatfont metrics cache (and other similar code) can handle them separately. This is achieved by adding a new boolean field
to
Font
class, specifically denoting fonts with fallback components. The latter ones don't need to pretend to be'created' fonts anymore, to preserve their
Font2D
handle.It's not possible to use the existing
createdFont
field inequals
implementation, as JCK requires a 'real' createdfont (the one obtained using
Font.createFont
method) to be equal to the same font after serialization anddeserialization.
Progress
Issue
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/7313/head:pull/7313
$ git checkout pull/7313
Update a local copy of the PR:
$ git checkout pull/7313
$ git pull https://git.openjdk.java.net/jdk pull/7313/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 7313
View PR using the GUI difftool:
$ git pr show -t 7313
Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/7313.diff