2012-02-28 34 views
7

Używam g.drawString(str, x, y), aby narysować ciąg z obiektem Graphics2Dg. Obecna czcionka g nie obejmuje wszystkich znaków str (mam np. Chińskie znaki). W systemie Mac OS X czcionka zastępcza wydaje się być automatycznie używana, ale nie w systemie Windows, gdzie zamiast znaków poszukiwanych pojawiają się czarne kwadratowe kontury.Jak określić czcionki zastępcze w Java2D/Graphics2D

  • Dlaczego zachowanie różni się w zależności od platformy?
  • Jak określić czcionkę zastępczą (lub kilka czcionek zastępczych) w przypadku braku znaków?

(Na przykład, jedna z miłych czcionek there).

Aktualizacja/Więcej informacji

Tak, oryginalna czcionka, która nie obsługuje wszystkie znaki, które nie jest jednym z JVM na logical fonts, ale jest dołączoną czcionką dołączoną do mojej aplikacji i uzyskał ją pod numerem Font.createFont(). Tak więc dodawanie czcionek do folderu JRE lib/fonts/fallback nie działa tutaj.

Odpowiedz

5

Możemy przypisać ciąg znaków, aby zmienić czcionkę na "złe" symbole i użyć Graphics2D.drawString(AttributedCharacterIterator iterator, int x, int y), aby wyświetlić wynik. Advantage: To zadziała z dowolną czcionką. Wadą:: bez buforowania obiektów pośrednich będzie działać wolniej i brudniej.

Więc proponuję korzystania AttributedString z głównego atrybutu czcionki na całej wyrażenie:

AttributedString astr = new AttributedString(text); 
astr.addAttribute(TextAttribute.FONT, mainFont, 0, textLength); 

iz awaryjnej czcionką na określonych częściach:

astr.addAttribute(TextAttribute.FONT, fallbackFont, fallbackBegin, fallbackEnd); 

rendering się:

g2d.drawString(astr.getIterator(), 20, 30); 

Wynik (fizyczna "Segoe Print" jako główna czcionka, logiczna "Serif" jako druga):

enter image description here

Kompletna niby-to-be-SSCCE Kod:

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

Przepraszam, też nie działa pokojowe modyfikacji 'fontconfig.properties'. Zwykle należy dodać niestandardowy plik czcionki do sekwencji zastępczej. Wymaganymi liniami są: 'filename.Yourfont = YOURFONT.TTF' oraz' allfonts.yourfont = Yourfont'; następnie dodaj 'yourfont' do listy' sequence.fallback'. Planowałem poszerzyć odpowiedź o szczegóły, ale niestety działa to tylko dla standardowych * logicznych * czcionek. Może potrzeba więcej magii fontconfig, ale jest to poza moimi umiejętnościami i doświadczeniem. Przepraszam za nieużyteczną odpowiedź. – Mersenne

+0

Usunąłem złe rozwiązanie. Przynajmniej obejście ma swój cel. – Mersenne

+0

Niesamowite, dziękuję za wspaniałą pomoc! –