如何获得文本组件中使用的抗锯齿模式(基础 system/OS 设置)

How to get antialiasing mode as used in text components (underlying system/OS setting)

所以我试图通过继承 JTextArea 并覆盖 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 );
    }
}

在标记的行中,我将抗锯齿提示设置为RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB。这将导致与文本区域完全相同的字体呈现:

省略此行仅使用默认值:

但这并不适用于所有系统。从图形对象中查询 FontRenderContext 或最初分配的渲染提示只是 return Default antialiasing text mode,这不能是用于渲染文本区域的模式。

所以我的问题是:如何从文本component/java系统中获取实际使用的抗锯齿模式?

注意:我并不是要实现一个完全成熟的行编号编辑器,所以这个解决方案的 "inefficiency" 是无关紧要的。另外,在过去的几年里,我在组件的 paint 方法中直接渲染文本时遇到过几次这个问题,所以这只是一个例子。

深入研究 Java lib 源代码可以发现文本区域(可能还有其他文本组件)的字体渲染使用内部 class sun.swing.SwingUtilities2。这在内部保存所需的信息并从 java.awt.Toolkit.

查询它

所以从系统获取文本抗锯齿信息的代码是:

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

地图的内容是(以我为例)

{Text-specific antialiasing enable key=LCD HRGB antialiasing text mode, Text-specific LCD contrast key=120}

这正是需要的信息。

请注意 sun.awt.SunToolkit.DESKTOPFONTHINTS 被禁止 API,因此应替换为 "awt.font.desktophints"