#20706 closed enhancement (fixed)
[PATCH] Enable text antialiasing for more systems
Reported by: | nvarner | Owned by: | simon04 |
---|---|---|---|
Priority: | minor | Milestone: | 21.05 |
Component: | Core | Version: | latest |
Keywords: | Cc: |
Description
On some systems, text outside the map (e.g. in menus and on the splash screen) is not antialiased. I found this issue on a Linux computer with i3wm and another with OpenBox, but not on a Linux system with Cinnamon, a Windows 10 computer, or an OS X 10.10 system. Additionally, bullet points were not antialiased on the Linux and Windows systems, but were on the Mac.
This patch forces antialiasing for that text and those bullet points, with an advanced preference to disable it if desired.
Attachments (10)
Change History (33)
by , 4 years ago
Attachment: | antialias.patch added |
---|
by , 4 years ago
Attachment: | i3wm-josm-latest.png added |
---|
comment:1 by , 4 years ago
Milestone: | → 21.04 |
---|---|
Owner: | changed from | to
Status: | new → assigned |
- Is setting
awt.useSystemAAFontSettings
really necessary? According to https://docs.oracle.com/javase/8/docs/technotes/guides/2d/flags.html#aaFonts it defaults to true - In various locations in the code we set
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
unconditionally. I'd like to follow this style here as well and omit checking the preferencegui.forceAntialiasing
comment:2 by , 4 years ago
It is necessary to set awt.useSystemAAFontSettings
. I believe that the default of "true"
means to use whatever Java thinks the system's antialiasing settings are, while "on"
forces antialiasing to be used. I'll upload screenshots showing the difference. I'll also upload a patch without the gui.forceAntialiasing
preference.
by , 4 years ago
by , 4 years ago
Attachment: | AAunset.png added |
---|
by , 4 years ago
Attachment: | antialias_v2.patch added |
---|
comment:4 by , 4 years ago
I think this caused a regression on Windows 10. See ticket:20771#comment:7 and following. Esp. the text in the popup that displays the startup progress looks worse, somehow unsteady. I tried r17796 from https://josm.openstreetmap.de/jenkins/job/JOSM/jdk=JDK8/7303/artifact/dist/josm-custom.jar and it looked normal, r17798 from https://josm.openstreetmap.de/jenkins/job/JOSM/jdk=JDK8/7305/artifact/dist/josm-custom.jar shows the problem.
Is-Local-Build:true Build-Date:2021-04-19 21:12:41 Identification: JOSM/1.5 (17798 SVN de) Windows 10 64-Bit OS Build number: Windows 10 Home 2004 (19041) Memory Usage: 124 MB / 1972 MB (117 MB allocated, but free) Java version: 15.0.1+9, AdoptOpenJDK, OpenJDK 64-Bit Server VM Look and Feel: javax.swing.plaf.metal.MetalLookAndFeel Screen: \Display0 1920×1080 (scaling 1,00×1,00) Maximum Screen Size: 1920×1080 Best cursor sizes: 16×16?32×32, 32×32?32×32 System property file.encoding: Cp1252 System property sun.jnu.encoding: Cp1252 Program arguments: [--status-report]
comment:5 by , 4 years ago
Setting awt.useSystemAAFontSettings=on
on all platforms is not a good idea.
On Windows this changes font antialiasing type from "lcd" to "grayscale", which makes to text look more bold.
Don't know what happens on macOS.
This setting affects all L&Fs.
@nvarner could you please run following snippet on:
- a Linux system that do not paint text anitialised
- a Linux system that do paint text anitialised
and post the outputs?
import java.awt.Toolkit; public class AAInfo { public static void main( String[] args ) { Object hints = Toolkit.getDefaultToolkit().getDesktopProperty( "awt.font.desktophints" ); System.out.println( hints ); } }
comment:6 by , 4 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
comment:7 by , 4 years ago
A possible solution to force AA (if disabled by default), without affecting already enabled AA, could be:
if( Toolkit.getDefaultToolkit().getDesktopProperty( "awt.font.desktophints" ) == null ) { Utils.updateSystemProperty("awt.useSystemAAFontSettings", "on"); }
comment:8 by , 4 years ago
BTW I would remove
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
from JosmEditorPane.paintComponent()
(which was added by the patch for this ticket)
KEY_TEXT_ANTIALIASING
is used only for text and is set by the L&Fs.
KEY_ANTIALIASING
is used to paint the bullets.
comment:9 by , 4 years ago
@GerdP, I can reproduce the issue. I missed it in testing.
@DevCharly, without antialiasing, the output was null
, and with antialiasing, the output was {Text-specific antialiasing enable key=LCD HRGB antialiasing text mode}
. Your solution would probably work. After rereading the docs, you also seem to be right about KEY_TEXT_ANTIALIASING
. I'll work on a patch now to address these.
comment:11 by , 4 years ago
Milestone: | 21.04 → 21.05 |
---|---|
Owner: | changed from | to
Status: | reopened → new |
comment:12 by , 4 years ago
Unfortunately, @DevCharly's solution didn't work because of an unexpected side effect of getDesktopProperty
. When called on X11, it determines whether to enable antialiasing and caches that decision so that changing "awt.useSystemAAFontSettings"
does not enable antialiasing. The only solutions I could come up with were:
- using reflection to work around the caching and set antialiasing after calling
getDesktopProperty
(the approach I took in the new patch, which works but is very fragile) - using reflection to read the
"awt.font.desktophints"
property without the caching (also fragile) - overriding
paintComponent
on every Swing component and setting rendering hints in the same way rendering hints are set to antialias bullets (likely to lead to lots of code duplication, instances of non-antialiased components missed in the patch, an extra requirement while extending the GUI, ...)
If someone has a better solution, or knows how to make the rendering hint based solution more practical, that should be used instead of my solution. It emits warnings about illegal reflective access at runtime that will eventually become errors, so a new solution will eventually be needed anyway. It may be better to apply a smaller patch which only enables antialiasing in JosmEditorPane
s until a better solution to the whole problem is found. However, this patch does enable antialiasing on my machine, and I confirmed through log messages and screenshot comparison that this patch does not affect rendering on my Windows, Mac, or antialiasing-enabled Linux systems (except that bullets are antialiased on systems where they previously were not).
Technical details and patch explanation:
The side effect starts at getDesktopProperty, which (on X11) calls initializeDesktopProperties, which calls addPropertyChangeListener, which calls initXSettingsIfNeeded, which saves the current font hints in desktopProperties
. The hints are obtained via getDesktopFontHints, which calls useSystemAAFontSettings, then getDesktopAAHints. In useSystemAAFontSettings
, the return value depends on "awt.useSystemAAFontSettings"
, but also sets the checkedSystemAAFontSettings
flag, which prevents further calls to the function from recognizing changes to the property.
To work around this, the patch introduces a new class, AntialiasingUtil
, with two public methods. isDisabledX11
checks if the current toolkit extends XToolkit
and Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints") == null
, triggering the side effect. tryEnableX11
should be called if this returns true. It updates the system property to enable antialiasing, then removes the old value cached in desktopProperties
, unsets checkedSystemAAFontSettings
so the new value of the property will be seen, and uses getDesktopFontHints
to get antialiasing RenderingHints
and insert it into desktopProperties
.
The patch also extends ReflectionUtils
with methods designed to work around the fact that the toolkit classes are part of the unexported, internal sun.awt
package, so .class can't be accessed for them. They search for fields and methods on superclasses of a given class.
by , 4 years ago
Attachment: | antialias_v3.patch added |
---|
comment:13 by , 4 years ago
Sorry, did not expect that the desktop properties are cached.
@nvarner could you please run following snippet on the two Linux systems (i3wm and OpenBox) that do not paint text anitialised and post the outputs?
I also wonder what Linux UI toolkit is used on those systems? Gnome, KDE, other?
import java.awt.Toolkit; public class AAinfo { public static void main( String[] args ) { Toolkit toolkit = Toolkit.getDefaultToolkit(); System.out.println( toolkit.getDesktopProperty( "awt.font.desktophints" ) ); System.out.println( toolkit.getDesktopProperty( "gnome.Xft/Antialias" ) ); System.out.println( toolkit.getDesktopProperty( "gnome.Xft/RGBA" ) ); System.out.println( toolkit.getDesktopProperty( "fontconfig/Antialias" ) ); } }
Those desktop properties are used in sun.awt.UNIXToolkit.getDesktopAAHints()
to determine current Linux AA settings.
comment:14 by , 4 years ago
i3wm printed
11.0.11 null null null
and Openbox printed
11.0.8 null null null
I'm not sure what you mean by UI toolkit. As I understand it, i3wm and Openbox are alternatives to Gnome and KDE, and all four sit directly on top of X11. That said, I'm not very familiar with how it works, so please let me know what I'm missing.
I also want to clarify that the caching happens with any calls to getDesktopProperty
, not just "awt.font.desktophints"
. I checked on i3wm and the below snippet did not paint antialiased text. It did use antialiasing when I reran it without the calls to getDesktopProperty
.
Toolkit toolkit = Toolkit.getDefaultToolkit(); System.out.println( System.getProperty( "java.version" ) ); System.out.println( toolkit.getDesktopProperty( "gnome.Xft/Antialias" ) ); System.out.println( toolkit.getDesktopProperty( "gnome.Xft/RGBA" ) ); System.out.println( toolkit.getDesktopProperty( "fontconfig/Antialias" ) ); System.setProperty("awt.useSystemAAFontSettings", "on"); JFrame parent = new JFrame(); JLabel label = new JLabel("example"); parent.add(label); parent.pack(); parent.setVisible(true);
by , 4 years ago
Attachment: | JOSM-setupTextAntiAliasing.diff added |
---|
Enable text antialiasing on Linux if not yet enabled and if neither running on Gnome or KDE desktop (Java 9+ only)
comment:15 by , 4 years ago
Many thanks for the information. This helps (me) a lot :)
There is another way to enable AA that works without system property awt.useSystemAAFontSettings
:
modifying UI defaults of current look and feel.
I've uploaded a patch, which I've tested only on Windows (with some tricks), but it should work on Linux.
Please give it a try.
It works only for Java 9 and later.
If necessary, I can also implement it for Java 8, which requires usage of reflection to access some public fields/methods in SwingUtilities2
that are no longer available in Java 9+.
comment:16 by , 4 years ago
This is a great solution! I didn't know you could do that. It works great for me on i3wm, and I'll test it more when I have time later.
I think this patch has to be paired with another to antialias bullets. As far as I know, the changes I originally proposed to JosmEditorPane
(minus the unneeded line you caught @DevCharly) antialiased the bullets but didn't cause any issues, so I'll try testing with that as well.
comment:17 by , 4 years ago
I tested the @DevCharly patch with JosmEditorPane bullet antialiasing on my i3wm, Openbox, Mac, and Windows, and it looked good. The only changes I saw were antialiased text in i3wm and Openbox and antialiased bullets in Windows.
by , 4 years ago
Attachment: | antialias_v5.patch added |
---|
@DevCharly's patch with JosmEditorPane bullet antialiasing
comment:18 by , 4 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:21 by , 4 years ago
While updating my working copy I realized that @nvarner added following line to my patch in MainApplication.setupTextAntiAliasing()
:
UIManager.getLookAndFeelDefaults().put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
This is not necessary and actually does nothing because Swing
does not read KEY_ANTIALIASING
from UI defaults (as far as I know).
Only KEY_TEXT_ANTIALIASING
is used.
by , 4 years ago
Attachment: | remove_key_antialiasing.patch added |
---|
Removes unneeded KEY_ANTIALIASING line
comment:22 by , 4 years ago
Whoops, I tried that to see if I could avoid modifying JosmEditorPane and forgot to remove it after testing. It doesn't have any effect and the patch I just uploaded should remove the line.
No antialiasing on JOSM latest, i3wm on Linuc