4

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!

Community
  • 1
  • 1
Ben
  • 3,378
  • 30
  • 46
  • 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)`](http://docs.oracle.com/javase/8/docs/api/java/awt/Font.html#canDisplayUpTo-java.lang.String-).. – Andrew Thompson Sep 04 '14 at 10:40
  • Thanks for your suggestion, but with `Font.canDisplay...` i cannot find out **which** font is used. – Ben Sep 04 '14 at 10:43
  • 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 Sep 04 '14 at 10:49
  • *"**(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 Sep 04 '14 at 10:52
  • 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 Sep 04 '14 at 10:57
  • See also [this Q&A](http://stackoverflow.com/q/25683630/418556) which might help determine from where the fonts are sourced. – Andrew Thompson Sep 05 '14 at 10:19
  • @Andrew: I tried your code. When choosing Arial BOLD (on the left), i get Arial BOLD (on the right). When i choose DejaVu Sans (my labels font), i get **Bitsream Vera Sans** and **DejaVu Sans** (nothing more). But i am afraid that this will not help. – Ben Sep 05 '14 at 10:39
  • @Andrew: i did some more tests! when using JAVA 7, i get **Bitsream Vera Sans**, **DejaVu Sans** , **Dialog.plain** and **SansSerif.plain**! (so there are also differences between J6 and J7 here) – Ben Sep 05 '14 at 10:49
  • *"I tried your code."* I strongly recommend trying it explicitly with the Chinese text seen in your dialog. Since I do not know the code points needed to create that text, I am unable to test it here. – Andrew Thompson Sep 05 '14 at 10:55
  • Well this has turned into a great question (IMO). Sorry I can't provide more help towards an answer. BTW - could you share with us a code snippet we could use to reconstruct that Chinese text (e.g. starting from the code points)? I suspect if you just posted the actual text as a comment we would *not* be able to copy/paste it into an IDE because of encoding issues. (Oh, and I'm running Windows, so I doubt I'll be able to reproduce the exact problem, but there might be others running Ubuntu who can.) – Andrew Thompson Sep 05 '14 at 11:45
  • Just a quick update. I tried the Chinese text on Windows. The `JTextField` displayed the characters. Checking the font used in the text field showed `Dialog plain`. When I asked which fonts deliver the same glyphs for those characters, the software showed a long list (10+ as opposed to 2 or 3 as was typical for the English sentence). Most of the listed fonts were logical fonts though, leaving the remaining 3 as `MingLiU`, `MingLiU_HKCS` or `PMingLiU`.. – Andrew Thompson Sep 06 '14 at 11:18

2 Answers2

5

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.)

Community
  • 1
  • 1
Ben
  • 3,378
  • 30
  • 46
1

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).

nim
  • 2,345
  • 14
  • 13
  • *"It will mix and match fonts depending on the needs of the text to display"* Interesting. I had begun to suspect as much, but had no information to confirm it. – Andrew Thompson Sep 05 '14 at 10:51
  • OK, but i have some problems with it: **1.**: i do not use any custom/non-default font. **2.**: i did not made any changes to the default (java/swing) configuration. **3.**: In Windows, there are no problems in displaying chinese fonts, between Java 6 and Java 7. – Ben Sep 05 '14 at 10:54
  • Windows font lists tend to be very uniform, because it is very slow to change and limited by Microsoft use of proprietary fonts. Its desktop roots means the default installation is likely to bundle more fonts than a Linux server one. Therefore the old "use hardcoded font lists" java 6 approach is less likely to result in misses on this platform. (Also Java 6 was produced by SUN, and the only desktop platform SUN cared about was Windows since no one used Solaris for desktop anymore, it could never admit Linux ate its cake, and SUN had proposed a competitor to fontconfig no one adopted). – nim Sep 05 '14 at 11:33
  • BTW the modernization of the text support in Java that was made possible by the resumption of development after the end of SUN's stewardship is not finished, fontconfig was the first step the next one is there http://openjdk.java.net/projects/harfbuzz/ Things will move again in the next Java releases. – nim Sep 05 '14 at 11:39