Modify

Opened 14 months ago

Closed 13 months ago

Last modified 13 months ago

#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)

antialias.patch (3.0 KB) - added by nvarner 14 months ago.
i3wm-josm-latest.png (92.3 KB) - added by nvarner 14 months ago.
No antialiasing on JOSM latest, i3wm on Linuc
i3wm-josm-patch.png (276.9 KB) - added by nvarner 14 months ago.
Antialiasing on patched JOSM, i3wm on Linux
AAon.png (2.0 KB) - added by nvarner 14 months ago.
AAunset.png (769 bytes) - added by nvarner 14 months ago.
antialias_v2.patch (2.5 KB) - added by nvarner 14 months ago.
antialias_v3.patch (10.8 KB) - added by nvarner 13 months ago.
JOSM-setupTextAntiAliasing.diff (2.0 KB) - added by DevCharly 13 months ago.
Enable text antialiasing on Linux if not yet enabled and if neither running on Gnome or KDE desktop (Java 9+ only)
antialias_v5.patch (3.1 KB) - added by nvarner 13 months ago.
@DevCharly's patch with JosmEditorPane bullet antialiasing
remove_key_antialiasing.patch (765 bytes) - added by nvarner 13 months ago.
Removes unneeded KEY_ANTIALIASING line

Download all attachments as: .zip

Change History (33)

Changed 14 months ago by nvarner

Attachment: antialias.patch added

Changed 14 months ago by nvarner

Attachment: i3wm-josm-latest.png added

No antialiasing on JOSM latest, i3wm on Linuc

Changed 14 months ago by nvarner

Attachment: i3wm-josm-patch.png added

Antialiasing on patched JOSM, i3wm on Linux

comment:1 Changed 14 months ago by simon04

Milestone: 21.04
Owner: changed from team to simon04
Status: newassigned

comment:2 Changed 14 months ago by nvarner

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.

Changed 14 months ago by nvarner

Attachment: AAon.png added

Changed 14 months ago by nvarner

Attachment: AAunset.png added

Changed 14 months ago by nvarner

Attachment: antialias_v2.patch added

comment:3 Changed 13 months ago by simon04

Resolution: fixed
Status: assignedclosed

In 17798/josm:

fix #20706 - Enable text antialiasing for more JosmEditorPane (patch by nvarner)

comment:4 Changed 13 months ago by GerdP

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 Changed 13 months ago by DevCharly

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 Changed 13 months ago by simon04

Resolution: fixed
Status: closedreopened

comment:7 Changed 13 months ago by DevCharly

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 Changed 13 months ago by DevCharly

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 Changed 13 months ago by nvarner

@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:10 Changed 13 months ago by simon04

In 17807/josm:

see #20706 - Revert "Enable text antialiasing for more JosmEditorPane"

This reverts r17798.

comment:11 Changed 13 months ago by simon04

Milestone: 21.0421.05
Owner: changed from simon04 to nvarner
Status: reopenednew

comment:12 Changed 13 months ago by nvarner

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 JosmEditorPanes 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.

Changed 13 months ago by nvarner

Attachment: antialias_v3.patch added

comment:13 Changed 13 months ago by DevCharly

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( System.getProperty( "java.version" ) );
        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.

https://github.com/openjdk/jdk/blob/dedddd5ab2e39a30a039d24f629a7974048b0923/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java#L317-L373

Last edited 13 months ago by DevCharly (previous) (diff)

comment:14 Changed 13 months ago by nvarner

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);

Changed 13 months ago by DevCharly

Enable text antialiasing on Linux if not yet enabled and if neither running on Gnome or KDE desktop (Java 9+ only)

comment:15 Changed 13 months ago by DevCharly

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 Changed 13 months ago by nvarner

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 Changed 13 months ago by nvarner

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.

Changed 13 months ago by nvarner

Attachment: antialias_v5.patch added

@DevCharly's patch with JosmEditorPane bullet antialiasing

comment:18 Changed 13 months ago by simon04

Owner: changed from nvarner to simon04
Status: newassigned

comment:19 Changed 13 months ago by simon04

Resolution: fixed
Status: assignedclosed

In 17866/josm:

fix #20706 - Enable text antialiasing for more systems (patch by nvarner and DevCharly)

comment:20 Changed 13 months ago by simon04

Thank you!

comment:21 Changed 13 months ago by DevCharly

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.

Changed 13 months ago by nvarner

Removes unneeded KEY_ANTIALIASING line

comment:22 Changed 13 months ago by nvarner

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.

comment:23 Changed 13 months ago by simon04

In 17868/josm:

see #20706 - Remove unneeded KEY_ANTIALIASING (patch by nvarner and DevCharly)

Fixup r17866

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain simon04.
as The resolution will be set.
The resolution will be deleted.

Add Comment


E-mail address and name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.