当我在Java 6下运行swing GUI应用程序时,它们会自动为所有字体使用我配置的子像素抗锯齿设置。与标准AA选项相比,结果有了很大改进。
但是当我绘制到图像时,我无法初始化图形上下文以使用系统的AA配置。尝试使用Java的不同AA提示是一个失败的原因,因为没有子像素方法适用于所有用户。
有没有办法为给定的图形上下文继承系统AA设置,而不必选择一个并明确设置提示?目前我必须使用GASP AA来避免标准AA用小字体给出的可怕结果。我试过没有为文本AA设置任何内容,也没有设置任何AA提示。
更新2010-01-05
我想我已将此归结为此;当直接绘制到AWT图形上下文时,子像素AA提示似乎只被尊重;当我画到双缓冲图像时,它只是标准AA;但当我绕过双缓冲图像时,子像素AA就完成了。
否则,The_Fire的答案将适用于具有Swing可用的JVM(但不适用于J2ME JVM);请注意,The_Fire的答案不适用于使用AWT组件(使用新的Label()而不是新的JLabel()失败),可能是因为在将组件实现到显示之前无法提取FontRenderContext。
我目前获取目标图片图形上下文的代码如下所示:
try {
if((dbImage=dctRoot.createImage(wid,hgt,1))!=null) { // if createImage returns null or throws an exception the component is not yet displayable
dbGraphics=(Graphics2D)dbImage.getGraphics();
if(dctRoot.properties.getBoolean("Antialias",true)) {
try {
// set AA on overall
dbGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING ,RenderingHints.VALUE_ANTIALIAS_ON);
// set text AA to platform/impl default
dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
// try to override platform/impl AA with font-specified AA (Java 6+)
try { dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.class.getField("VALUE_TEXT_ANTIALIAS_GASP").get(null)); } catch(Throwable thr) {;} // yes, ignore exception
}
catch(Throwable thr) {
dctRoot.log.println("Antialiasing not supported on this JVM ("+thr+").");
dctRoot.setProperty("Antialias","False"); // turn off AA for subsequent painting
}
}
}
}
catch(Throwable thr) {
dbImage=null;
dbGraphics=null;
}
创建图像的代码使用底层的AWT组件,它构成了我所有绘画的背景 - 组件是一个Panel,因为我需要能够执行setFocusCycleRoot,因此它可以很好地与其他AWT一起使用组件。创建图像代码如下:
public DctImage createImage(int wid, int hgt, float accpty) {
GraphicsConfiguration cfg=awtComponent.getGraphicsConfiguration();
Image img=null;
if(transparentImages) {
//y { img=new BufferedImage(wid,hgt,BufferedImage.TYPE_INT_ARGB); } // NB: J2ME CDC/PP 1.1 does not have the BufferedImage constructors (one day I may discover a way to create a BufferedImage via another API!!)
try { img=cfg.createCompatibleImage(wid,hgt,Transparency.TRANSLUCENT); }// NB: J2ME CDC/PP 1.1 does not have this API, but prefer to use GraphicsConfiguration over new BufferImage(...)
catch(NoClassDefFoundError thr) { transparentImages=false; createImage(wid,hgt,accpty); } // try again with transparency disabled
catch(NoSuchMethodError thr) { transparentImages=false; createImage(wid,hgt,accpty); } // try again with transparency disabled
catch(NoSuchFieldError thr) { transparentImages=false; createImage(wid,hgt,accpty); } // try again with transparency disabled
}
else {
img=cfg.createCompatibleImage(wid,hgt);
}
if(accpty>0 && SET_ACCELERATION_PRIORITY!=null) {
try { SET_ACCELERATION_PRIORITY.invoke(img,new Object[]{new Float(accpty)}); } catch(Throwable thr) {;}
}
return (img==null ? null : new DctImage(img));
}
答案 0 :(得分:7)
我发现这里有一些因素。
首先,需要从底层AWT组件创建图像,并且必须在没有透明度的情况下创建图像:
cfg.createCompatibleImage(wid,hgt);
而不是
cfg.createCompatibleImage(wid,hgt,Transparency.TRANSLUCENT);
其次,由于一些莫名其妙的原因,主AA设置KEY_ANTIALIASING必须关闭才能使用LCD子像素AA。
最后,最重要的是,可以使用以下方法轻松检索桌面字体呈现提示:
java.awt.Toolkit.getDesktopProperty("awt.font.desktophints")
更新2010-01-05
在Java 6.26中重新测试,似乎需要将常规AA设置为渲染文本AA的问题终于得到解决(通过Oracle的方式......在Sun只是几年之后十年太晚了。)
答案 1 :(得分:5)
使用Swing,我能够获得正确的文本抗锯齿提示:
JLabel label = new JLabel();
FontMetrics fm = label.getFontMetrics( label.getFont() );
Object aaHintValue = fm.getFontRenderContext().getAntiAliasingHint();
在我的系统上,这会返回RenderingHits.VALUE_TEXT_ANTIALIAS_LCD_HRGB
。
答案 2 :(得分:2)
java.awt.Toolkit.getDesktopProperty(“awt.font.desktophints”)似乎在linux上为null,至少没有任何特殊的vm命令行选项,可能是因为它无法弄清楚平台的默认值是什么。如果在Graphics2D实例上设置提示,添加例如“-Dawt.useSystemAAFontSettings = lcd”似乎可以解决它并启用子像素渲染。
答案 3 :(得分:1)
等等,您是否在Windows JVM上运行此代码?我认为ClearType是一种微软技术,Swing通过一些本机代码继承(即,在Linux或其他非Microsoft平台上不可用)。
我曾经写过一个servlet来生成带有在Debian上运行的反别名字体的JPG,这就是我使用的代码
Font font = new Font("Komix", Font.PLAIN, 8);
Graphics2D g2;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
FontRenderContext frc = g2.getFontRenderContext();
g2.setFont(font);
g2.setPaint(Color.black);
g2.drawString(sMessage, xOffset, yOffset);
Offhand我不记得是否有任何代码依赖于Swing(我导入了javax.swing并且servlet大约有300行,所以我可能认为我需要它用于其他东西),快速查看Google看起来这正好在AWT领域。希望有所帮助。