Ticket #20706: antialias_v3.patch
File antialias_v3.patch, 10.8 KB (added by , 4 years ago) |
---|
-
src/org/openstreetmap/josm/gui/MainApplication.java
148 148 import org.openstreetmap.josm.spi.lifecycle.InitStatusListener; 149 149 import org.openstreetmap.josm.spi.lifecycle.Lifecycle; 150 150 import org.openstreetmap.josm.spi.preferences.Config; 151 import org.openstreetmap.josm.tools.AntialiasingUtil; 151 152 import org.openstreetmap.josm.tools.FontsManager; 152 153 import org.openstreetmap.josm.tools.GBC; 153 154 import org.openstreetmap.josm.tools.Http1Client; … … 1033 1034 } 1034 1035 // Disable automatic POST retry after 5 minutes, see #17882 / https://bugs.openjdk.java.net/browse/JDK-6382788 1035 1036 Utils.updateSystemProperty("sun.net.http.retryPost", "false"); 1037 // Force text antialiasing, not including mappaint text, when antialiasing is not enabled by default on X11 1038 // See #20706 1039 if (AntialiasingUtil.isDisabledX11() && !AntialiasingUtil.tryEnableX11()) { 1040 Logging.warn("Antialiasing could not be enabled"); 1041 } 1036 1042 } 1037 1043 1038 1044 /** -
src/org/openstreetmap/josm/gui/widgets/JosmEditorPane.java
3 3 4 4 import java.awt.Color; 5 5 import java.awt.Font; 6 import java.awt.Graphics; 7 import java.awt.Graphics2D; 8 import java.awt.RenderingHints; 6 9 import java.io.IOException; 7 10 import java.io.InputStream; 8 11 import java.net.URL; … … 86 89 return conn.getContent(); 87 90 } 88 91 92 @Override 93 public void paintComponent(Graphics g) { 94 // Force antialiasing within the JosmEditorPane for antialiased bullet points 95 Graphics2D g2d = (Graphics2D) g.create(); 96 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 97 super.paintComponent(g2d); 98 g2d.dispose(); 99 } 100 89 101 /** 90 102 * Adapts a {@link JEditorPane} to be used as a powerful replacement of {@link javax.swing.JLabel}. 91 103 * @param pane The editor pane to adapt -
src/org/openstreetmap/josm/tools/AntialiasingUtil.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.tools; 3 4 import java.awt.Toolkit; 5 import java.awt.RenderingHints; 6 import java.lang.reflect.Field; 7 import java.lang.reflect.Method; 8 import java.util.Map; 9 10 /** 11 * Utility class to detect and enable antialiasing on systems which do not enable it by default 12 * @since xxx 13 */ 14 public final class AntialiasingUtil { 15 16 private AntialiasingUtil() { 17 // Hide default constructor for util classes 18 } 19 20 /** 21 * Determines if the current system is running X11 and has antialiasing disabled 22 */ 23 public static boolean isDisabledX11() { 24 Toolkit toolkit = Toolkit.getDefaultToolkit(); 25 return ReflectionUtils.extendsClassWithName(toolkit.getClass(), "sun.awt.X11.XToolkit") 26 && toolkit.getDesktopProperty("awt.font.desktophints") == null; 27 } 28 29 /** 30 * Attempts to enable antialiasing on X11 31 * @return true if enabling antialiasing was successful, otherwise false 32 */ 33 public static boolean tryEnableX11() { 34 try { 35 Utils.updateSystemProperty("awt.useSystemAAFontSettings", "on"); 36 37 Toolkit toolkit = Toolkit.getDefaultToolkit(); 38 39 // Unset cached desktop hints 40 Map<String, Object> desktopProperties = getToolkitDesktopProperties(toolkit); 41 desktopProperties.remove("awt.font.desktophints"); 42 43 // Unset flag so new font hints look for new value of awt.useSystemAAFontSettings 44 Field checkedSystemAAFontSettings = getSunToolkitCheckedSystemAAFontSettings(toolkit); 45 checkedSystemAAFontSettings.setBoolean(toolkit, false); 46 47 // Get antialiasing font hints 48 Method getDesktopFontHints = getSunToolkitGetDesktopFontHints(toolkit); 49 Object renderingHints = getDesktopFontHints.invoke(null); 50 51 desktopProperties.put("awt.font.desktophints", renderingHints); 52 } catch (ReflectiveOperationException | RuntimeException e) { 53 Logging.log(Logging.LEVEL_WARN, e); 54 return false; 55 } 56 return true; 57 } 58 59 /** 60 * Get the value of the desktopProperties field from {@link java.awt.Toolkit} through reflection. May emit an 61 * illegal reflective access warning. 62 * @param toolkit the toolkit to get the desktopProperties from 63 * @return the value of the desktopProperties field from toolkit 64 * @throws ReflectiveOperationException if the field could not be found 65 * @throws RuntimeException if the field could not be set accessible 66 */ 67 private static Map<String, Object> getToolkitDesktopProperties(Toolkit toolkit) throws ReflectiveOperationException, RuntimeException { 68 Field desktopPropertiesField = Toolkit.class.getDeclaredField("desktopProperties"); 69 ReflectionUtils.setObjectsAccessible(desktopPropertiesField); 70 @SuppressWarnings("unchecked") // desktopProperties has type Map<String, Object> and is protected 71 Map<String, Object> desktopProperties = (Map<String, Object>) desktopPropertiesField.get(toolkit); 72 return desktopProperties; 73 } 74 75 /** 76 * Get the boolean checkedSystemAAFontSettings field from sun.awt.SunToolkit through reflection. May emit an 77 * illegal reflective access warning. 78 * @param toolkit the toolkit to get the checkedSystemAAFontSettings field from 79 * @return the checkedSystemAAFontSettings field or null if it could not be found 80 * @throws RuntimeException if the field could not be set accessible 81 */ 82 private static Field getSunToolkitCheckedSystemAAFontSettings(Toolkit toolkit) throws RuntimeException { 83 Field field = ReflectionUtils.getSuperclassField(toolkit.getClass(), "checkedSystemAAFontSettings", boolean.class); 84 ReflectionUtils.setObjectsAccessible(field); 85 return field; 86 } 87 88 /** 89 * Get the getDesktopFontHints method or no arguments returning {@link RenderingHints} from sun.awt.SunToolkit 90 * through reflection. May emit an illegal reflective access warning. 91 * @param toolkit the toolkit to get the getDesktopFontHints method from 92 * @return the getDesktopFontHints method or null if it could not be found 93 * @throws RuntimeException if the method could not be set accessible 94 */ 95 private static Method getSunToolkitGetDesktopFontHints(Toolkit toolkit) throws RuntimeException { 96 Method getDesktopFontHints = ReflectionUtils.getInheritedMethod( 97 toolkit.getClass(), 98 "getDesktopFontHints", 99 new Class[] {}, 100 RenderingHints.class 101 ); 102 ReflectionUtils.setObjectsAccessible(getDesktopFontHints); 103 return getDesktopFontHints; 104 } 105 } -
src/org/openstreetmap/josm/tools/ReflectionUtils.java
2 2 package org.openstreetmap.josm.tools; 3 3 4 4 import java.lang.reflect.AccessibleObject; 5 import java.lang.reflect.Field; 6 import java.lang.reflect.Method; 5 7 import java.security.AccessController; 6 8 import java.security.PrivilegedAction; 9 import java.util.Arrays; 7 10 import java.util.Collection; 11 import java.util.Optional; 8 12 import java.util.function.Function; 9 13 10 14 import org.openstreetmap.josm.plugins.PluginHandler; … … 70 74 } 71 75 return null; 72 76 } 77 78 /** 79 * Get the matching method implemented directly on the class or inherited from a superclass (or superclass of a superclass...). 80 * @param searchOn class to start the search from 81 * @param name the name that the matching method must have 82 * @param parameterTypes the types the parameters of the matching method must have 83 * @param returnType the type the matching method must return 84 * @return the first matching method found, starting from the given class and proceeding through superclasses, or 85 * null if no match was found 86 * @since xxx 87 */ 88 public static Method getInheritedMethod(Class<?> searchOn, String name, Class<?>[] parameterTypes, Class<?> returnType) { 89 while (searchOn != null) { 90 Optional<Method> firstMatch = Arrays.stream(searchOn.getDeclaredMethods()) 91 .filter(method -> methodMatches(method, name, parameterTypes, returnType)) 92 .findFirst(); 93 if (firstMatch.isPresent()) { 94 return firstMatch.get(); 95 } 96 searchOn = searchOn.getSuperclass(); 97 } 98 return null; 99 } 100 101 private static boolean methodMatches(Method method, String expectedName, Class<?>[] expectedParameterTypes, Class<?> expectedReturnType) { 102 return method.getName().equals(expectedName) 103 && Arrays.equals(method.getParameterTypes(), expectedParameterTypes) 104 && method.getReturnType().equals(expectedReturnType); 105 } 106 107 /** 108 * Get the matching field which is part of the class or a superclass (or superclass of a superclass...). 109 * @param searchOn class to start the search from 110 * @param name the name that the matching field must have 111 * @param type the type that the matching field must have 112 * @return the first matching field found, starting from the given class and proceeding through superclasses, or 113 * null if no match was found 114 * @since xxx 115 */ 116 public static Field getSuperclassField(Class<?> searchOn, String name, Class<?> type) { 117 while (searchOn != null) { 118 Optional<Field> firstMatch = Arrays.stream(searchOn.getDeclaredFields()) 119 .filter(field -> field.getName().equals(name) && field.getType().equals(type)) 120 .findFirst(); 121 if (firstMatch.isPresent()) { 122 return firstMatch.get(); 123 } 124 searchOn = searchOn.getSuperclass(); 125 } 126 return null; 127 } 128 129 public static boolean extendsClassWithName(Class<?> doesExtend, String className) { 130 while (doesExtend != null) { 131 if (doesExtend.getName().equals(className)) { 132 return true; 133 } 134 doesExtend = doesExtend.getSuperclass(); 135 } 136 return false; 137 } 73 138 }