问题描述
使用 > AttributedString astr = new AttributedString(text);astr.addAttribute(TextAttribute.FONT,mainFont,0,textLength);
以及特定部分的备用字体:
astr.addAttribute(TextAttribute.FONT,fallbackFont,fallbackBegin,fallbackEnd);
渲染本身:
g2d.drawString(astr.getIterator(),20,30);结果(物理Segoe打印作为主要字体,逻辑Serif作为后备): $ / code>
/ p>
完成所谓的SSCCE代码:
$ p $ import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.TextAttribute;
import java.text.AttributedString;
import javax.swing.JComponent;
import javax.swing.JFrame;
$ b $ public class FontTest extends JFrame {
$ b $ public FontTest(){$ b $ setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
getContentPane()。setLayout(new BorderLayout());
getContentPane()。add(new TestStringComponent());
pack();
public static void main(String [] args){
java.awt.EventQueue.invokeLater(new Runnable(){$ b $ public void run() {
new FontTest()。setVisible(true);
}
});
class TestStringComponent extends JComponent {
$ b $ protected void paintComponent(Graphics g){
Graphics2D g2d =(Graphics2D)g ;
g.setColor(getBackground());
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(getForeground());
字体mainFont = new Font(Segoe Print,Font.PLAIN,25);
字体fallbackFont =新字体(Serif,Font.PLAIN,25);
String s =汉德繁古印汉考繁古印Test Test;
g2d.drawString(createFallbackString(s,mainFont,fallbackFont).getIterator(),20,30);
}
public Dimension getPreferredSize(){
return new Dimension(500,40);
$ b私有AttributedString createFallbackString(字符串文本,字体mainFont,字体fallbackFont){
AttributedString result = new AttributedString(text);
int textLength = text.length();
result.addAttribute(TextAttribute.FONT,mainFont,0,textLength);
boolean fallback = false;
int fallbackBegin = 0;
for(int i = 0; i< text.length(); i ++){
boolean curFallback =!mainFont.canDisplay(text.charAt(i));
if(curFallback!= fallback){
fallback = curFallback;
if(fallback){
fallbackBegin = i;
} else {
result.addAttribute(TextAttribute.FONT,fallbackFont,fallbackBegin,i);
}
}
}
返回结果;
}
}
I'm using g.drawString(str, x, y) to draw a String with a Graphics2D object g. The current font of g does not cover all the characters of str (I have e.g. Chinese chars in there). On Mac OS X, a fallback font seems to be automatically used, but not on Windows, where black square outlines appear instead of the wanted characters.
- Why is the behavior different depending on the platform?
- How do I specify a fallback font (or several fallback fonts) in case of missing characters?
(For instance, one of the nice fonts there.)
Update/More Info
So, the original font that doesn't support all characters is not one of the JVM's logical fonts, but is a bundled font that comes with my app and was obtained with Font.createFont(). So, adding fonts to the JRE's lib/fonts/fallback folder doesn't work here.
We could attribute string to switch font on "bad" symbols and use Graphics2D.drawString(AttributedCharacterIterator iterator, int x, int y) to render result. Advantage: this will work with any font. Drawback: without some sort of caching of intermediate objects this will work slower and dirtier.
So, i suggest using AttributedString with main font attribute on whole string:
AttributedString astr = new AttributedString(text); astr.addAttribute(TextAttribute.FONT, mainFont, 0, textLength);
and with fallback font on specific parts:
astr.addAttribute(TextAttribute.FONT, fallbackFont, fallbackBegin, fallbackEnd);
The rendering itself:
g2d.drawString(astr.getIterator(), 20, 30);
The result (Physical "Segoe Print" as main font, logical "Serif" as fallback):
Complete supposed-to-be-SSCCE code:
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.font.TextAttribute; import java.text.AttributedString; import javax.swing.JComponent; import javax.swing.JFrame; public class FontTest extends JFrame { public FontTest() { setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); getContentPane().setLayout(new BorderLayout()); getContentPane().add(new TestStringComponent()); pack(); } public static void main(String[] args) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new FontTest().setVisible(true); } }); } } class TestStringComponent extends JComponent { protected void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g; g.setColor(getBackground()); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(getForeground()); Font mainFont = new Font("Segoe Print", Font.PLAIN, 25); Font fallbackFont = new Font("Serif", Font.PLAIN, 25); String s = "Test 漢鼎繁古印 Test 漢鼎繁古印 Test"; g2d.drawString(createFallbackString(s, mainFont, fallbackFont).getIterator(), 20, 30); } public Dimension getPreferredSize() { return new Dimension(500, 40); } private AttributedString createFallbackString(String text, Font mainFont, Font fallbackFont) { AttributedString result = new AttributedString(text); int textLength = text.length(); result.addAttribute(TextAttribute.FONT, mainFont, 0, textLength); boolean fallback = false; int fallbackBegin = 0; for (int i = 0; i < text.length(); i++) { boolean curFallback = !mainFont.canDisplay(text.charAt(i)); if (curFallback != fallback) { fallback = curFallback; if (fallback) { fallbackBegin = i; } else { result.addAttribute(TextAttribute.FONT, fallbackFont, fallbackBegin, i); } } } return result; } }
这篇关于如何在Java2D / Graphics2D中指定备用字体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!