4
votes

I have a problem with displaying unicode characters in my swing application.
In think the problem is the used font, which does not contain appropriate characters for chinese language.
(only empty boxes are displayed)

Here are some more infos to my Problem (i did some investigation):
Linux (Kubuntu 14.04):
When i start my program with JAVA 6, chinese characters are not displayed (only empty boxes).
(asking the labels font via getFont() returns: DejaVu Sans)
When i start my program with JAVA 7, chinese characters are displayed correctly!
(asking the labels font via getFont() returns: DejaVu Sans)

Windows (8.1):
When i start my program with JAVA 6, chinese characters are displayed correctly!
(asking the labels font via getFont() returns: SansSerif)
When i start my program with JAVA 7, chinese characters are displayed correctly!
(asking the labels font via getFont() returns: SansSerif)

$JAVA_HOME/lib/fonts, (which seems to be used as fallback-font) both java versions (6+7) contain the same fonts. (on both systems)
The font files have same size (Java6 + Java7) and fontconfig.properties.src are also both the same.

When i am asking directly the Label (via getFont()) it returns "SansSerif" on Windows(8.1) and "DejaVu Sans" on my Kubuntu(14.04).
(see the screenshots)

Started on Linux with JAVA 6:
enter image description here

Started on Linux with JAVA 7:
enter image description here

"SansSerif" on Windows is showing the characters correctly, but which SansSerif-Font is used? MS SansSerif (the only Font with SansSerif in name) does not have all of this chinese characters.

EDIT:
Same with DejaVuSans.
It looks like DejaVu Sans does not have chinese characters! (however, they are displayed!)

EDIT 2:
i tried the code Andrew posted (see: How to determine if 2 fonts have equivalent glyphs?), but with chinese example Text
this is the result:

Started on Linux with JAVA 6:
enter image description here

Started on Linux with JAVA 7:
enter image description here

EDIT 3:
as reqested, here the String which i have tested:

String s = "\u6253\u5370\u8FC7\u671F\u8BC1\u4E66\u8BB0\u5F55"; //means: 打印过期证书记录
JOptionPane.showMessageDialog(null, s);

Question is:
Which font (on the system) is really used and how can i find out?
Thanks in advance!

2
I'm not sure of the answer to your question. OTOH, to find which fonts can display the string, I'd recommend checking Font.canDisplayUpTo(String).. - Andrew Thompson
Thanks for your suggestion, but with Font.canDisplay... i cannot find out which font is used. - Ben
True, but you can always use a Font that works.. BTW - I was thinking also it should be possible to compare the GlyphVector of the Serif font with those of all fonts, for a list of those that produce the same glyph vector.. But that is not something I'd want to put into a production app. since it is potentially time consuming. I can't really see the point of determining which fonts the logical fonts on a particular system map to. As the screen-shots demonstrate, they might change between Java versions. - Andrew Thompson
"(Question 2) What can i do fix the problem when using Java 6." Part of the reason why SO encourages one question per question is well underlined here in that I already gave a way (in comments) to that question. Should I promote that to an answer even if I cannot answer the other question? Please choose between the questions and split the other out to a separate question. - Andrew Thompson
you did not gave any way to find out which font is used. you only suggest how to find out if the font can display the text.In addition to that, i will not split my problem into 2 questions (to spam up stackoverflow). rather i will remove my second question, so people like you will not have problems with it.I will then findout myself.(even if this is clearly part of my problem) - Ben

2 Answers

5
votes

This is an answer to my own question.

I did some more investigation:
it appears to be, that for some types of languages(characters), a special configuration is used.

Support for Linux and Solaris 11 fonts
Historically, the logical fonts for the JDK were statically specified in a fontconfig.properties file. However, on the various implementations of Linux, there is no consistency in the presence of fonts. So, without custom files, Asian (CJK) text, etc, would not be rendered. In JDK 7, on Linux, and for Solaris 11, in the absence of a customized fontconfig.properties file for the OS version, the default behavior is to use the system libfontconfig to select fonts to use for the logical fonts. In this case, the logical fonts will reflect the fonts used by the Gnome/KDE desktop applications which use the same platform library.

this is what i found here: http://docs.oracle.com/javase/7/docs/webnotes/adoptionGuide/

That means first, there is a difference in choosing the correct font in Java 6 and Java 7.
Next, i checked my (java 6) fontconfig-file and i found following (reduced to important parts only):

# Component Font Mappings
allfonts.chinese-cn-iso10646=-arphic-ar pl uming cn-light-r-normal---%d---c--iso10646-1

# Font File Names
filename.-arphic-ar_pl_uming_cn-light-r-normal---%d---c--iso10646-1=/usr/share/fonts/truetype/arphic/uming.ttc

# Search Sequences
sequence.allfonts=latin-1
sequence.allfonts.UTF-8.zh.CN=latin-1-cjk,chinese-cn-iso10646
sequence.allfonts.UTF-8.zh.TW=latin-1-cjk,chinese-tw-iso10646
sequence.allfonts.UTF-8.zh.HK=latin-1-cjk,chinese-hk-iso10646

This specified font (here: uming.ttc) should be used, when the default font cannot display the requested character.
After that, i checked the existence of /usr/share/fonts/truetype/arphic/uming.ttc.
This font/file was not present!
(i checked on 3 different Ubuntu installations!)

i do not know why exactly it was not installed (but nevertheless used in java fontconfig), but after executing (on different PC, but with same problem):

  sudo apt-get install fonts-arphic-uming

to install the missing font, i tested again (with JAVA 6):

enter image description here

Everything seems to be OK now.

(I think nims answer goes into similar direction, but it was (in my opinion) too broadly.Further, java does not really mix and match fonts.)

1
votes

Java 7 uses fontconfig on Linux so it know how to fallback when a font is missing glyphs. To check the fallbacks fontconfig uses on a given system you may use the fc-* commands (fc-match, etc)

However your jre is likely to include private fallback rules in addition to the system ones (fontconfig*xml)

You can not simulate this behaviour on java 6 since fontconfig is not a simple priority list where a single font is used at any given time. It will mix and match fonts depending on the needs of the text to display and the preferences expressed by the app (font pattern).

A fontconfig-enabled software will always work if there is one font capable of displaying the text present on-system. An app that does not use fontconfig will fail as soon as the font name hardcoded in the app does not match what is available. There is a huge variation in installed fonts on Linux systems, you can not expect that a font present on one installation will also be present in another one (precisely because all modern Linux apps use fontconfig and do not care).