2012-02-28 4 views
7

g.drawString(str, x, y)を使用して、Graphics2Dオブジェクトgで文字列を描画しています。 gの現在のフォントは、strのすべての文字をカバーしていません(私はそこに中国語の文字があります)。 Mac OS Xでは、フォールバックフォントが自動的に使用されているように見えますが、Windowsでは希望の文字の代わりに黒い四角の輪郭が表示されます。Java2D/Graphics2Dでフォールバックフォントを指定する方法

  • なぜプラットフォームによって動作が異なりますか?
  • 文字が欠落している場合は、代替フォント(または複数の代替フォント)を指定する方法を教えてください。

(例えば、素敵なフォントthere。の1)

更新/詳細は

だから、すべての文字をサポートしていないオリジナルのフォントはJVMのではありませんlogical fontsしかし、私のアプリに付属しているFont.createFont()で得られたバンドルフォントです。したがって、JREのlib/fonts/fallbackフォルダにフォントを追加することはできません。

答えて

5

"不良"シンボルでフォントを切り替えるように指定できます。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"がフォールバック):

enter image description here

コンプリートなっ-に被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; 
    } 
} 
+0

が、それはまたないfontconfig.properties' 'の修正whith作品。通常の方法は、フォールバックシーケンスにカスタムフォントファイルを追加することです。必要な行は 'filename.Yourfont = YOURFONT.TTF'と' allfonts.yourfont = Yourfont'です。 'yourfont'を' sequence.fallback'リストに追加してください。私は細部まで答えを広げることを計画しましたが、残念なことに標準の*論理*フォントでしか動作しません。 fontconfig-magicが必要になるかもしれませんが、それは私のスキルと経験から外れています。私は不愉快な答えをお詫びします。 – Mersenne

+0

私は間違った解決策を削除しました。少なくとも、回避策はその目的です。 – Mersenne

+0

あなたの大きな助けに感謝します! –

関連する問題