2012-02-28 2 views
7

Я использую g.drawString(str, x, y), чтобы нарисовать строку с объектом Graphics2Dg. Текущий шрифт g не охватывает все символы str (у меня есть, например, китайские символы). В Mac OS X резервный шрифт, кажется, автоматически используется, но не в Windows, где вместо квадратных символов появляются черные квадратные контуры.Как указать резервные шрифты в Java2D/Graphics2D

  • Почему поведение отличается от платформы?
  • Как указать резервный шрифт (или несколько резервных шрифтов) в случае отсутствия символов?

(К примеру, один из хороших шрифтов there.)

Update/Подробнее

Итак, оригинальный шрифт, который не поддерживает все символы не один из виртуальной машины Java-х logical fonts, но в комплекте шрифт, который поставляется с моим приложением, и был получен с Font.createFont(). Таким образом, добавление шрифтов в папку JRE lib/fonts/fallback здесь не работает.

ответ

5

Мы можем указать строку для переключения шрифта на «плохие» символы и использовать Graphics2D.drawString(AttributedCharacterIterator iterator, int x, int y) для визуализации результата. Advantage: это будет работать с любым шрифтом. Недостаток: без какого-либо кэширования промежуточных объектов это будет работать медленнее и грязнее.

Итак, я предлагаю использовать 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'. Обычным способом является добавление пользовательского файла шрифта в резервную последовательность. Необходимые строки: 'filename.Yourfont = YOURFONT.TTF' и' allfonts.yourfont = Yourfont'; затем добавьте 'yourfont' в список' sequence.fallback'. Я планировал расширить ответ с подробностями, но, к сожалению, он работает только для стандартных * логических * шрифтов. Возможно, потребуется еще немного магии шрифтов, но это не соответствует моим навыкам и опыту. Прошу прощения за непонятный ответ. – Mersenne

+0

Я удалил неправильное решение. По крайней мере, обходной путь - это цель. – Mersenne

+0

Awesome, спасибо за вашу большую помощь! –

Смежные вопросы