如何在Java2D / Graphics2D中指定备用字体 [英] How do I specify fallback fonts in Java2D/Graphics2D

查看:1001
本文介绍了如何在Java2D / Graphics2D中指定备用字体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 g.drawString(str,x,y)来绘制一个带有 Graphics2D 对象 g 。当前字体 g 不包含 str 的所有字符(例如,我有中文字符)。在Mac OS X上,后备字体似乎是自动使用的,但不是在Windows上出现黑色方框轮廓而不是所需字符。




  • 为什么行为会因平台不同而有所不同?

  • 如何在缺少字符的情况下指定备用字体(或多个备用字体)?


(例如,其中一个很好的字体那里

更新/更多信息 不支持所有字符不是JVM的逻辑字体 a>,但是是一个捆绑的字体,与我的应用程序,并获得与 Font.createFont()。因此,在JRE的 lib / fonts / fallback 文件夹中添加字体在这里不起作用。

我们可以将字符串属性切换为坏符号的字体,并使用 Graphics2D.drawString(AttributedCharacterIterator iterator,int x,int y)来渲染结果。 优点:这将适用于任何字体。 缺点:没有某种中间对象的缓存,这将工作得更慢更脏。

所以,我建议使用

    >  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中指定备用字体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆