So I'm trying to make a small text preview with line numbers by inheriting from a JTextArea
and overwriting paintComponent()
.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class PreviewPane extends JTextArea {
public PreviewPane() {
setText( "first row\nsecond row\nthird row" );
}
@Override
protected void paintComponent( Graphics graphics ) {
Graphics2D g = (Graphics2D) graphics;
int emWidth = g.getFontMetrics().stringWidth( "m" );
int lineHeight = g.getFontMetrics().getHeight();
int baseLine = g.getFontMetrics().getAscent();
g.translate( 2 * emWidth, 0 );
super.paintComponent( g );
g.translate( -2 * emWidth, 0 );
g.setColor( getBackground() );
g.fillRect( 0, 0, 2 * emWidth - 1, getHeight() - 1 );
g.setColor( Color.LIGHT_GRAY );
g.drawLine( 2 * emWidth - 1, 0, 2 * emWidth - 1, getHeight() - 1 );
g.setColor( Color.BLACK );
// "guessed" value for antialiasing
g.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB );
for ( int i = 1; i <= 3; i++ ) {
g.drawString( String.valueOf( i ), getMargin().left, getMargin().top + baseLine + ( i - 1 ) * lineHeight );
}
}
public static void main( String[] args ) {
JFrame frame = new JFrame();
frame.setBounds( 0, 0, 640, 480 );
frame.getContentPane().add( new PreviewPane(), BorderLayout.CENTER );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setVisible( true );
}
}
In the marked line, I set the antialiasing hint to RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB
. This will lead to the exact font rendering as the text area:
Omitting this line just uses the default:
But this will not work on every system. Querying the FontRenderContext
or the originally assigned rendering hints from the graphics object just return Default antialiasing text mode
, which cannot be the mode used for rendering the text area.
So my question is: How to obtain the actually used antialiasing mode from the text component/java system?
Note: I'm not trying to implement a fully fledged line numbering editor, so the "inefficiency" of this solution is irrelevant. Also, I came across this issue several times in the past years when directly rendering text in component's paint methods, so this is just an example.
Digging through the Java lib source reveals that font rendering of text area (and presumably the other text components as well) use internal class sun.swing.SwingUtilities2
. This holds the desired information internally and queries it from the java.awt.Toolkit
.
So the code to get text antialiasing information from the system is:
Toolkit tk = Toolkit.getDefaultToolkit();
Map map = (Map) tk.getDesktopProperty( sun.awt.SunToolkit.DESKTOPFONTHINTS );
g.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, map.get( RenderingHints.KEY_TEXT_ANTIALIASING ) );
The content of the map is (in my case)
{Text-specific antialiasing enable key=LCD HRGB antialiasing text mode, Text-specific LCD contrast key=120}
which is the exact information needed.
Note that sun.awt.SunToolkit.DESKTOPFONTHINTS
is forbidden API and therefore should be replaced by "awt.font.desktophints"
.