2012-02-28 4 views
7

Graphics2D 객체 g을 사용하여 문자열을 그리는 데 g.drawString(str, x, y)을 사용하고 있습니다. g의 현재 글꼴이 str의 모든 문자를 포함하지 않습니다 (예 : 중국어 문자가 있음). Mac OS X에서는 대체 글꼴이 자동으로 사용되는 것처럼 보이지만 원하는 문자 대신 검은 색 사각형 외곽선이 나타나는 Windows에서는 그렇지 않습니다.Java2D/Graphics2D에서 대체 글꼴을 지정하는 방법

  • 플랫폼에 따라 동작이 다른 이유는 무엇입니까?
  • 문자가 누락 된 경우 대체 글꼴 (또는 여러 가지 대체 글꼴)을 어떻게 지정합니까?

(예를 들어, 좋은 글꼴 there. 중 하나)

업데이트/추가 정보는

그래서 모든 문자를 지원하지 않습니다 원래의 글꼴은 JVM의 중 하나가 아닙니다 logical fonts,하지만 내 애플과 함께 제공 번들 글꼴이며 Font.createFont()로 얻은 것입니다. 따라서 JRE의 lib/fonts/fallback 폴더에 글꼴을 추가해도 작동하지 않습니다.

답변

5

"나쁜"기호로 글꼴을 전환하도록 문자열을 지정하고 Graphics2D.drawString(AttributedCharacterIterator iterator, int x, int y)을 사용하여 결과를 렌더링 할 수 있습니다. 이점 : 모든 글꼴에서 작동합니다. 단점 : 어떤 종류의 중간 개체 캐싱이 없으면 더 느리게 작동합니다.

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

및 특정 부분에 대한 대체 글꼴로 :

그래서, 전체 문자열에 기본 글꼴 속성으로 AttributedString을 사용하는 것이 좋습니다

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

하면 자체 렌더링 :

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

그 결과 (물리적 인 "Segoe Print"는 메인 글꼴, 논리적 인 "Serif"는 fallback) :

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'리스트에 추가하십시오. 나는 세부 사항으로 대답을 확장 할 계획 이었지만 안타깝게도 표준 * 논리 * 글꼴에서만 작동합니다. 어쩌면 fontconfig-magic이 더 필요할 수도 있지만 내 능력과 경험이 부족합니다. 불쾌한 답변에 사과드립니다. – Mersenne

+0

잘못된 해결책을 삭제했습니다. 적어도 해결 방법은 목적입니다. – Mersenne

+0

대단히 감사합니다. –