Java 字体渲染

标签 java fonts rendering antialiasing

我一直在尝试增强我用 Java 编写的 GUI 系统以使用子像素抗锯齿并且取得了成功,除了两个剩余的异常。这是我的 other question from a few weeks ago 的后续.

第一个问题是将渲染提示KEY_ANTIALIASING设置为VALUE_ANTIALIAS_ON会导致KEY_TEXT_ANTIALIASING设置为LCD(子像素)时被忽略A值。任何人都可以阐明这一点吗?目前,我被迫在渲染文本之前 VALUE_ANTIALIAS_OFF 并在渲染文本之后将其重新打开(以便其他绘画,如圆圈等,是 AA'd)。下面的独立测试程序证明了这个问题。

第二个问题是我找不到查询 AA 的底层 O/S 设置的方法,所以我必须做一个相当笨拙的解决方法,即创建一个 Swing JLabel,获取它是 FontMetrics,获取它的 FontRenderContext,然后从中获取 AA 提示。除了在完全不使用 Swing 的程序中涉及 Swing 之外,它不会在运行任何 J2ME JVM 的设备上运行。谁能建议一个更好的方法来做到这一点?需要J5或者J6也没关系,因为现在的kludge已经需要J6了(不过最好只需要J4)。我已经尝试过所有默认设置并使用 AWT 组件代替 JLabel


测试程序

此程序验证要使子像素 AA 起作用,必须首先禁用常规 AA 设置。 (PS:我写入后台缓冲区是因为我的底层 GUI 确实如此,而且我想在等效的上下文中进行测试)。

import java.awt.*;
import java.awt.event.*;

public class AwtTestFrame1b extends Panel {

private final Font                      font=new Font(Font.SANS_SERIF, Font.PLAIN, 16);
private final int                       line=25;

AwtTestFrame1b() {
    setBackground(SystemColor.control);
    }

public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D)g;

    int                                 py=0;

    py=paintText(g2d,py,null                                        ,false);
    py=paintText(g2d,py,null                                        ,true );
    py+=line;

    py=paintText(g2d,py,RenderingHints.VALUE_TEXT_ANTIALIAS_OFF     ,false);
    py=paintText(g2d,py,RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT ,false);
    py=paintText(g2d,py,RenderingHints.VALUE_TEXT_ANTIALIAS_ON      ,false);
    py=paintText(g2d,py,RenderingHints.VALUE_TEXT_ANTIALIAS_GASP    ,false);
    py=paintText(g2d,py,RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB,false);
    py+=line;

    py=paintText(g2d,py,RenderingHints.VALUE_TEXT_ANTIALIAS_OFF     ,true );
    py=paintText(g2d,py,RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT ,true );
    py=paintText(g2d,py,RenderingHints.VALUE_TEXT_ANTIALIAS_ON      ,true );
    py=paintText(g2d,py,RenderingHints.VALUE_TEXT_ANTIALIAS_GASP    ,true );
    py=paintText(g2d,py,RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB,true );
    py+=line;
    }

private int paintText(Graphics2D g2d, int py, Object val, boolean aa) {
    Graphics2D                          dgc=g2d;
    char[]                              txt=("The quick brown fox jumped over the lazy dog ("+val+", General AA: "+aa+")").toCharArray();
    Image                               img=null;

    GraphicsConfiguration cfg=getGraphicsConfiguration();
    img=cfg.createCompatibleImage(getWidth(),line);
    dgc=(Graphics2D)img.getGraphics();
    dgc.setColor(getBackground());
    dgc.fillRect(0,0,getWidth(),line);
    dgc.setColor(g2d.getColor());

    if(aa       ) { dgc.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON ); }
    else          { dgc.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF); }
    if(val!=null) { dgc.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,val); }
    dgc.setFont(font);

    dgc.drawChars(txt,0,txt.length,10,line-5);
    g2d.drawImage(img,  0,py,  null);

    dgc.dispose();
    img.flush();

    return (py+line);
    }

public static void main(String[] args) {
    Frame                               wnd=new Frame("AWT Antialiased Text Sample");

    wnd.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e) {
            System.exit(0);
            }
        });
    wnd.add(new AwtTestFrame1b());
    wnd.setSize(new Dimension(1000, 600));
    wnd.setVisible(true);
    }

}

最佳答案

AWT Desktop Properties有什么帮助吗?特别是“awt.font.desktophints”——它们包含 native 组件使用的 AA 提示,但可以应用于您想要的任何 Graphics2D。

只是在黑暗中拍摄,最近阅读了 Filthy Rich Clients 中的 AA 部分。

使用看起来像这样:

String str = "A quick brown fox jumps over the lazy dog";
Toolkit tk = Toolkit.getDefaultToolkit();
Map desktopHints = (Map)(tk.getDesktopProperty("awt.font.desktophints"));
Graphics2D g2d = (Graphics2D)g;

if(desktopHints != null) {
    g2d.addRenderingHints(desktopHints);
}

g2d.drawString(str, someX, someY);

我能够使用这些提示获得与 LCD HRGB 模式相同的结果(使用您的示例类和 drawChars 和 drawImage,为简单起见,只需键入 drawString),并且在我的机器上没有其他调用。

我不确定这需要什么版本的 Java,如果它是您正在寻找的...

关于Java 字体渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2018102/

相关文章:

java - hibernate + jsf + spring 的缓存提供程序

java - Android ScrollView填充60%

css - 如何在 css 中忽略字体的内在填充

java - 提交表单时显示提醒

java - 未设置密码时如何连接 JDBC postgres 连接而无需密码

javascript - 我应该如何在使用 AngularJS 构建的整个网站中设置字体 'bariol Regular'?

ruby-on-rails - Prawn PDF 在同一个 PDF 中同时支持英文和日文/中文/泰文/韩文

rendering - 解释预乘 alpha 的工作原理

ruby-on-rails - Rails 3>在Rake任务中渲染 View

CSS 不会阻止 Firefox Quantum 上的渲染