JBR-1929 FractionalMetricsSupport

(cherry picked from commit bbdc159762)
This commit is contained in:
Sergey Malenkov
2020-02-20 16:14:08 +03:00
committed by jbrbot
parent e5e01f4e52
commit 5a027cfe06
2 changed files with 86 additions and 77 deletions

View File

@@ -427,6 +427,7 @@ public abstract class JComponent extends Container implements Serializable,
* AA text hints.
*/
private transient Object aaHint;
private transient Object fmHint;
private transient Object lcdRenderingHint;
static {
@@ -732,6 +733,8 @@ public abstract class JComponent extends Container implements Serializable,
// aaText shouldn't persist between look and feels, reset it.
aaHint = UIManager.getDefaults().get(
RenderingHints.KEY_TEXT_ANTIALIASING);
fmHint = UIManager.getDefaults().get(
RenderingHints.KEY_FRACTIONALMETRICS);
lcdRenderingHint = UIManager.getDefaults().get(
RenderingHints.KEY_TEXT_LCD_CONTRAST);
ComponentUI oldUI = ui;
@@ -4116,6 +4119,8 @@ public abstract class JComponent extends Container implements Serializable,
public final Object getClientProperty(Object key) {
if (key == RenderingHints.KEY_TEXT_ANTIALIASING) {
return aaHint;
} else if (key == RenderingHints.KEY_FRACTIONALMETRICS) {
return fmHint;
} else if (key == RenderingHints.KEY_TEXT_LCD_CONTRAST) {
return lcdRenderingHint;
}
@@ -4160,6 +4165,9 @@ public abstract class JComponent extends Container implements Serializable,
if (key == RenderingHints.KEY_TEXT_ANTIALIASING) {
aaHint = value;
return;
} else if (key == RenderingHints.KEY_FRACTIONALMETRICS) {
fmHint = value;
return;
} else if (key == RenderingHints.KEY_TEXT_LCD_CONTRAST) {
lcdRenderingHint = value;
return;

View File

@@ -67,6 +67,7 @@ import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.text.BreakIterator;
import java.text.CharacterIterator;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
@@ -102,9 +103,11 @@ import sun.font.FontUtilities;
import sun.java2d.SunGraphicsEnvironment;
import sun.print.ProxyPrintGraphics;
import static java.awt.RenderingHints.KEY_FRACTIONALMETRICS;
import static java.awt.RenderingHints.KEY_TEXT_ANTIALIASING;
import static java.awt.RenderingHints.KEY_TEXT_LCD_CONTRAST;
import static java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT;
import static java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_OFF;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB;
@@ -565,25 +568,9 @@ public class SwingUtilities2 {
? null
: c.getClientProperty(KEY_TEXT_ANTIALIASING);
if (aaHint != null) {
Object oldContrast = null;
Object oldAAValue = g2.getRenderingHint(KEY_TEXT_ANTIALIASING);
if (aaHint != oldAAValue) {
g2.setRenderingHint(KEY_TEXT_ANTIALIASING, aaHint);
} else {
oldAAValue = null;
}
Object lcdContrastHint = c.getClientProperty(
KEY_TEXT_LCD_CONTRAST);
if (lcdContrastHint != null) {
oldContrast = g2.getRenderingHint(KEY_TEXT_LCD_CONTRAST);
if (lcdContrastHint.equals(oldContrast)) {
oldContrast = null;
} else {
g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST,
lcdContrastHint);
}
}
Object oldAAValue = configureHint(KEY_TEXT_ANTIALIASING, g2, aaHint);
Object oldFMValue = configureHint(KEY_FRACTIONALMETRICS, g2, c);
Object oldContrast = configureHint(KEY_TEXT_LCD_CONTRAST, g2, c);
if (needsTextLayout) {
TextLayout layout = createTextLayout(c, text, g2.getFont(),
@@ -593,12 +580,9 @@ public class SwingUtilities2 {
g2.drawString(text, x, y);
}
if (oldAAValue != null) {
g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue);
}
if (oldContrast != null) {
g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, oldContrast);
}
restoreHint(KEY_TEXT_ANTIALIASING, g2, oldAAValue);
restoreHint(KEY_FRACTIONALMETRICS, g2, oldFMValue);
restoreHint(KEY_TEXT_LCD_CONTRAST, g2, oldContrast);
return;
}
@@ -904,34 +888,15 @@ public class SwingUtilities2 {
Graphics2D g2 = (Graphics2D) g;
if (aaHint != null) {
Object oldContrast = null;
Object oldAAValue = g2.getRenderingHint(KEY_TEXT_ANTIALIASING);
if (aaHint != null && aaHint != oldAAValue) {
g2.setRenderingHint(KEY_TEXT_ANTIALIASING, aaHint);
} else {
oldAAValue = null;
}
Object lcdContrastHint = c.getClientProperty(KEY_TEXT_LCD_CONTRAST);
if (lcdContrastHint != null) {
oldContrast = g2.getRenderingHint(KEY_TEXT_LCD_CONTRAST);
if (lcdContrastHint.equals(oldContrast)) {
oldContrast = null;
} else {
g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST,
lcdContrastHint);
}
}
Object oldAAValue = configureHint(KEY_TEXT_ANTIALIASING, g2, aaHint);
Object oldFMValue = configureHint(KEY_FRACTIONALMETRICS, g2, c);
Object oldContrast = configureHint(KEY_TEXT_LCD_CONTRAST, g2, c);
g2.drawString(new String(data, offset, length), x, y);
if (oldAAValue != null) {
g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue);
}
if (oldContrast != null) {
g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, oldContrast);
}
restoreHint(KEY_TEXT_ANTIALIASING, g2, oldAAValue);
restoreHint(KEY_FRACTIONALMETRICS, g2, oldFMValue);
restoreHint(KEY_TEXT_LCD_CONTRAST, g2, oldContrast);
}
else {
g2.drawString(new String(data, offset, length), x, y);
@@ -1248,7 +1213,6 @@ public class SwingUtilities2 {
*/
private static FontRenderContext getFRCProperty(JComponent c) {
if (c != null) {
GraphicsConfiguration gc = c.getGraphicsConfiguration();
AffineTransform tx = (gc == null) ? null : gc.getDefaultTransform();
// [tav] workaround deadlock on MacOSX until fixed, JRE-226
@@ -1260,16 +1224,22 @@ public class SwingUtilities2 {
.getDefaultTransform();
}
Object aaHint = c.getClientProperty(KEY_TEXT_ANTIALIASING);
return getFRCFromCache(tx, aaHint);
if (aaHint == null) aaHint = VALUE_TEXT_ANTIALIAS_DEFAULT;
Object fmHint = c.getClientProperty(KEY_FRACTIONALMETRICS);
if (fmHint == null) fmHint = VALUE_FRACTIONALMETRICS_DEFAULT;
return getFRCFromCache(tx, aaHint, fmHint);
}
return null;
}
private static final Object APP_CONTEXT_FRC_CACHE_KEY = new Object();
private static FontRenderContext getFRCFromCache(AffineTransform tx,
Object aaHint) {
if (tx == null && aaHint == null) {
private static FontRenderContext getFRCFromCache(AffineTransform tx, Object aaHint, Object fmHint) {
if ((tx == null || tx.isIdentity())
&& (aaHint == VALUE_TEXT_ANTIALIAS_OFF || aaHint == VALUE_TEXT_ANTIALIAS_DEFAULT)
&& (fmHint == VALUE_FRACTIONALMETRICS_OFF || fmHint == VALUE_FRACTIONALMETRICS_DEFAULT)) {
return null;
}
@@ -1283,41 +1253,31 @@ public class SwingUtilities2 {
}
Object key = (tx == null)
? aaHint
: (aaHint == null ? tx : new KeyPair(tx, aaHint));
? new KeyArray(aaHint, fmHint)
: new KeyArray(tx, aaHint, fmHint);
FontRenderContext frc = cache.get(key);
if (frc == null) {
aaHint = (aaHint == null) ? VALUE_TEXT_ANTIALIAS_OFF : aaHint;
frc = new FontRenderContext(tx, aaHint,
VALUE_FRACTIONALMETRICS_DEFAULT);
cache.put(key, frc);
}
return frc;
return cache.computeIfAbsent(key, k -> new FontRenderContext(tx, aaHint, fmHint));
}
private static class KeyPair {
private static class KeyArray {
private final Object[] array;
private final Object key1;
private final Object key2;
public KeyPair(Object key1, Object key2) {
this.key1 = key1;
this.key2 = key2;
KeyArray(Object... array) {
this.array = array;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof KeyPair)) {
public boolean equals(Object object) {
if (!(object instanceof KeyArray)) {
return false;
}
KeyPair that = (KeyPair) obj;
return this.key1.equals(that.key1) && this.key2.equals(that.key2);
KeyArray that = (KeyArray) object;
return Arrays.equals(that.array, array);
}
@Override
public int hashCode() {
return key1.hashCode() + 37 * key2.hashCode();
return Arrays.hashCode(array);
}
}
@@ -2345,4 +2305,45 @@ public class SwingUtilities2 {
var oldTx = oldGC != null ? oldGC.getDefaultTransform() : null;
return !Objects.equals(newTx, oldTx);
}
/**
* @param key the key of the hint to be set
* @param g the graphics to configure
* @param c the component that provides a hint value
* @return a value previously set in the given graphics,
* or {@code null} if a hint value is not set
*/
private static Object configureHint(RenderingHints.Key key, Graphics2D g, JComponent c) {
if (c == null) return null; // component is not specified
return configureHint(key, g, c.getClientProperty(key));
}
/**
* @param key the key of the hint to be set
* @param g the graphics to configure
* @param newValue the new value to set
* @return a value previously set in the given graphics,
* or {@code null} if a hint value is not set
*/
private static Object configureHint(RenderingHints.Key key, Graphics2D g, Object newValue) {
if (newValue == null) return null; // new value is not provided
Object oldValue = g.getRenderingHint(key);
if (newValue.equals(oldValue)) return null; // value is not changed
g.setRenderingHint(key, newValue);
return oldValue;
}
/**
* @param key the key of the hint to be set
* @param g the graphics to configure
* @param oldValue the stored value to set
*/
private static void restoreHint(RenderingHints.Key key, Graphics2D g, Object oldValue) {
if (oldValue == null) return; // nothing to restore
g.setRenderingHint(key, oldValue);
}
}