9

オブジェクトg.drawString(str, x, y)で文字列を描画するために使用しています。の現在のフォントは のすべての文字をカバーしているわけではありません(たとえば、中国語の文字が含まれています)。Mac OS X では、フォールバック フォントが自動的に使用されるように見えますが、Windows では使用されず、目的の文字の代わりに黒い四角形のアウトラインが表示されます。Graphics2Dggstr

  • プラットフォームによって動作が異なるのはなぜですか?
  • 文字が欠落している場合に代替フォント (または複数の代替フォント) を指定するにはどうすればよいですか?

(たとえば、素敵なフォントの 1 つです )

アップデート/詳細情報

したがって、すべての文字をサポートしていない元のフォントは、JVM の論理フォントの 1 つではなく、私のアプリに付属し、 で取得したバンドル フォントですFont.createFont()。そのため、JRE のlib/fonts/fallbackフォルダーにフォントを追加しても、ここでは機能しません。

4

1 に答える 1

6

「悪い」シンボルのフォントを切り替える文字列を属性としてGraphics2D.drawString(AttributedCharacterIterator iterator, int x, int y)指定し、結果をレンダリングするために使用できます。利点: これはどのフォントでも機能します。欠点: 中間オブジェクトの何らかのキャッシュがないと、これはより遅く、より汚いものになります。

AttributedStringしたがって、文字列全体でメインのフォント属性を使用することをお勧めします。

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 Print」がメイン フォント、論理的な「Serif」がフォールバック):

ここに画像の説明を入力

想定される SSCCE コードを完成させます。

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;
    }
}
于 2012-02-28T13:20:52.173 に答える