Sunday 19 January 2014

Rendering Japanese Postscript files under *nix via Ghostscript.

Postscript files are somewhat handy in keeping formats as plain as possible, however when distributed it can be a real pain especially when dealing with Postscript that uses other languages.

Here is a bit of a guide on howto render up for instance proper Japanese postscript files under most OS. Although the guide is written primarily for linux and specifically archlinux. I am sure similarly implemented methods may also work under other platforms so long as one is using Ghostscript to render postscripts for instance.

Before I continue, I like to thank some people from #ghostscript (IRC Channel on Freenode) for giving me help to get this working. In no apparent order whatsoever:
  • Robin_Watts
  • sags
  • ray_laptop
Ghostscript support is also available via stackoverflow.com #ghostscript (http://stackoverflow.com/questions/tagged/ghostscript).
I also like to thank Medowy (of mainly #deskthority) for offering to give a hand in seeing if the same set of postscript files would render properly on his/her machine.

Postscripts with Japanese fonts may seem rare so I will post examples of where I grabbed my postscripts from that featured Japanese fonts. In my case I was intending to work on contributing more stuff to wiki entry. Yes, I am a wiki sort of a guy as well, so sue me. Anyway, my work was focused on writing stuff about HHKB. For those of you whom aren't aware, I actually blogged about the HHKB that I received some few months ago. Due to the lack of information on a specific wiki site I decided to contribute information for the better good. I hindsight, I am also trying to improve my typing speeds and what not in the process...

Now, I grabbed a random .ps file from Eiichi Wada's site. Eiichi Wada is one of the co-developers for the HHKB. In fact what he did was the layout. Here is his homepage: http://member.wide.ad.jp/~wada/index-j.html For postscript files, scroll down to the "archive" area. For those who want to read stuff about HHKB, the first three links from the bottom up are HHKB related. Do be warned they are all Japanese.

When you open up the ps file or tried to convert it to pdf (without even looking at it) you will most likely it will look garbled. Something like this for instance:
This is not Japanese by the way, this is what happens when the renderer fails to find the suitable font required by the ps file and instead used a substitution. The substitution usually ends up being Courier font which is not compliant with Japanese characters.

When running ghostscript through console, more messages appears:
$ gs keyboard.ps
GPL Ghostscript 9.10 (2013-08-30)
Copyright (C) 2013 Artifex Software, Inc. All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Can't find (or can't open) font file /usr/share/ghostscript/9.10/Resource/Font/Ryumin-Light-H.
Can't find (or can't open) font file Ryumin-Light-H.
Querying operating system for font files...
Can't find (or can't open) font file /usr/share/ghostscript/9.10/Resource/Font/Ryumin-Light-H.
Can't find (or can't open) font file Ryumin-Light-H.
Didn't find this font on the system!
Substituting font Courier for Ryumin-Light-H.
Loading NimbusMonL-Regu font from /usr/share/fonts/Type1/n022003l.pfb... 3924092 2505298 10303912 5759890 1 done.
Can't find (or can't open) font file /usr/share/ghostscript/9.10/Resource/Font/GothicBBB-Medium-H.
Can't find (or can't open) font file GothicBBB-Medium-H.
Didn't find this font on the system!
Substituting font Courier for GothicBBB-Medium-H.
Loading StandardSymL font from /usr/share/fonts/Type1/s050000l.pfb... 4097316 2478813 10303912 6786729 3 done.
>>showpage, press <return> to continue<<
quit
>>showpage, press <return> to continue<<
>>showpage, press <return> to continue<<
>>showpage, press <return> to continue<<
>>showpage, press <return> to continue<<
>>showpage, press <return> to continue<<
$

This clearly shows there are missing fonts. So how does one go about locating and installing missing fonts? The people at #ghostscript has the answer. sags pointed out a link which has Japanese fonts for a rather old ghostscript version. The link is: http://www.enel.ucalgary.ca/People/far/howto/gs-ttf.html

What one needs to grab is the 5.6MB file named gs6.0.kanji.tar.gz. Extract it in a directory that ghostscript can have access to. In my case I extracted it into my ghostscript base installation directory which is /usr/share/ghostscript/9.10/.

The next step is to use the following Fontmap file (thanks to sags for this):
/min-21ku (min-21ku.gsf) ;
/min-22ku (min-22ku.gsf) ;
/min-23ku (min-23ku.gsf) ;
/min-24ku (min-24ku.gsf) ;
/min-25ku (min-25ku.gsf) ;
/min-26ku (min-26ku.gsf) ;
/min-27ku (min-27ku.gsf) ;
/min-28ku (min-28ku.gsf) ;
/min-30ku (min-30ku.gsf) ;
/min-31ku (min-31ku.gsf) ;
/min-32ku (min-32ku.gsf) ;
/min-33ku (min-33ku.gsf) ;
/min-34ku (min-34ku.gsf) ;
/min-35ku (min-35ku.gsf) ;
/min-36ku (min-36ku.gsf) ;
/min-37ku (min-37ku.gsf) ;
/min-38ku (min-38ku.gsf) ;
/min-39ku (min-39ku.gsf) ;
/min-3aku (min-3aku.gsf) ;
/min-3bku (min-3bku.gsf) ;
/min-3cku (min-3cku.gsf) ;
/min-3dku (min-3dku.gsf) ;
/min-3eku (min-3eku.gsf) ;
/min-3fku (min-3fku.gsf) ;
/min-40ku (min-40ku.gsf) ;
/min-41ku (min-41ku.gsf) ;
/min-42ku (min-42ku.gsf) ;
/min-43ku (min-43ku.gsf) ;
/min-44ku (min-44ku.gsf) ;
/min-45ku (min-45ku.gsf) ;
/min-46ku (min-46ku.gsf) ;
/min-47ku (min-47ku.gsf) ;
/min-48ku (min-48ku.gsf) ;
/min-49ku (min-49ku.gsf) ;
/min-4aku (min-4aku.gsf) ;
/min-4bku (min-4bku.gsf) ;
/min-4cku (min-4cku.gsf) ;
/min-4dku (min-4dku.gsf) ;
/min-4eku (min-4eku.gsf) ;
/min-4fku (min-4fku.gsf) ;
/min-50ku (min-50ku.gsf) ;
/min-51ku (min-51ku.gsf) ;
/min-52ku (min-52ku.gsf) ;
/min-53ku (min-53ku.gsf) ;
/min-54ku (min-54ku.gsf) ;
/min-55ku (min-55ku.gsf) ;
/min-56ku (min-56ku.gsf) ;
/min-57ku (min-57ku.gsf) ;
/min-58ku (min-58ku.gsf) ;
/min-59ku (min-59ku.gsf) ;
/min-5aku (min-5aku.gsf) ;
/min-5bku (min-5bku.gsf) ;
/min-5cku (min-5cku.gsf) ;
/min-5dku (min-5dku.gsf) ;
/min-5eku (min-5eku.gsf) ;
/min-5fku (min-5fku.gsf) ;
/min-60ku (min-60ku.gsf) ;
/min-61ku (min-61ku.gsf) ;
/min-62ku (min-62ku.gsf) ;
/min-63ku (min-63ku.gsf) ;
/min-64ku (min-64ku.gsf) ;
/min-65ku (min-65ku.gsf) ;
/min-66ku (min-66ku.gsf) ;
/min-67ku (min-67ku.gsf) ;
/min-68ku (min-68ku.gsf) ;
/min-69ku (min-69ku.gsf) ;
/min-6aku (min-6aku.gsf) ;
/min-6bku (min-6bku.gsf) ;
/min-6cku (min-6cku.gsf) ;
/min-6dku (min-6dku.gsf) ;
/min-6eku (min-6eku.gsf) ;
/min-6fku (min-6fku.gsf) ;
/min-70ku (min-70ku.gsf) ;
/min-71ku (min-71ku.gsf) ;
/min-72ku (min-72ku.gsf) ;
/min-73ku (min-73ku.gsf) ;
/min-74ku (min-74ku.gsf) ;
/min.r21 /min-21ku ;
/min.r22 /min-22ku ;
/min.r23 /min-23ku ;
/min.r24 /min-24ku ;
/min.r25 /min-25ku ;
/min.r26 /min-26ku ;
/min.r27 /min-27ku ;
/min.r28 /min-28ku ;
/min.r30 /min-30ku ;
/min.r31 /min-31ku ;
/min.r32 /min-32ku ;
/min.r33 /min-33ku ;
/min.r34 /min-34ku ;
/min.r35 /min-35ku ;
/min.r36 /min-36ku ;
/min.r37 /min-37ku ;
/min.r38 /min-38ku ;
/min.r39 /min-39ku ;
/min.r3a /min-3aku ;
/min.r3b /min-3bku ;
/min.r3c /min-3cku ;
/min.r3d /min-3dku ;
/min.r3e /min-3eku ;
/min.r3f /min-3fku ;
/min.r40 /min-40ku ;
/min.r41 /min-41ku ;
/min.r42 /min-42ku ;
/min.r43 /min-43ku ;
/min.r44 /min-44ku ;
/min.r45 /min-45ku ;
/min.r46 /min-46ku ;
/min.r47 /min-47ku ;
/min.r48 /min-48ku ;
/min.r49 /min-49ku ;
/min.r4a /min-4aku ;
/min.r4b /min-4bku ;
/min.r4c /min-4cku ;
/min.r4d /min-4dku ;
/min.r4e /min-4eku ;
/min.r4f /min-4fku ;
/min.r50 /min-50ku ;
/min.r51 /min-51ku ;
/min.r52 /min-52ku ;
/min.r53 /min-53ku ;
/min.r54 /min-54ku ;
/min.r55 /min-55ku ;
/min.r56 /min-56ku ;
/min.r57 /min-57ku ;
/min.r58 /min-58ku ;
/min.r59 /min-59ku ;
/min.r5a /min-5aku ;
/min.r5b /min-5bku ;
/min.r5c /min-5cku ;
/min.r5d /min-5dku ;
/min.r5e /min-5eku ;
/min.r5f /min-5fku ;
/min.r60 /min-60ku ;
/min.r61 /min-61ku ;
/min.r62 /min-62ku ;
/min.r63 /min-63ku ;
/min.r64 /min-64ku ;
/min.r65 /min-65ku ;
/min.r66 /min-66ku ;
/min.r67 /min-67ku ;
/min.r68 /min-68ku ;
/min.r69 /min-69ku ;
/min.r6a /min-6aku ;
/min.r6b /min-6bku ;
/min.r6c /min-6cku ;
/min.r6d /min-6dku ;
/min.r6e /min-6eku ;
/min.r6f /min-6fku ;
/min.r70 /min-70ku ;
/min.r71 /min-71ku ;
/min.r72 /min-72ku ;
/min.r73 /min-73ku ;
/min.r74 /min-74ku ;
/goth-21ku (goth-21ku.gsf) ;
/goth-22ku (goth-22ku.gsf) ;
/goth-23ku (goth-23ku.gsf) ;
/goth-24ku (goth-24ku.gsf) ;
/goth-25ku (goth-25ku.gsf) ;
/goth-26ku (goth-26ku.gsf) ;
/goth-27ku (goth-27ku.gsf) ;
/goth-28ku (goth-28ku.gsf) ;
/goth-30ku (goth-30ku.gsf) ;
/goth-31ku (goth-31ku.gsf) ;
/goth-32ku (goth-32ku.gsf) ;
/goth-33ku (goth-33ku.gsf) ;
/goth-34ku (goth-34ku.gsf) ;
/goth-35ku (goth-35ku.gsf) ;
/goth-36ku (goth-36ku.gsf) ;
/goth-37ku (goth-37ku.gsf) ;
/goth-38ku (goth-38ku.gsf) ;
/goth-39ku (goth-39ku.gsf) ;
/goth-3aku (goth-3aku.gsf) ;
/goth-3bku (goth-3bku.gsf) ;
/goth-3cku (goth-3cku.gsf) ;
/goth-3dku (goth-3dku.gsf) ;
/goth-3eku (goth-3eku.gsf) ;
/goth-3fku (goth-3fku.gsf) ;
/goth-40ku (goth-40ku.gsf) ;
/goth-41ku (goth-41ku.gsf) ;
/goth-42ku (goth-42ku.gsf) ;
/goth-43ku (goth-43ku.gsf) ;
/goth-44ku (goth-44ku.gsf) ;
/goth-45ku (goth-45ku.gsf) ;
/goth-46ku (goth-46ku.gsf) ;
/goth-47ku (goth-47ku.gsf) ;
/goth-48ku (goth-48ku.gsf) ;
/goth-49ku (goth-49ku.gsf) ;
/goth-4aku (goth-4aku.gsf) ;
/goth-4bku (goth-4bku.gsf) ;
/goth-4cku (goth-4cku.gsf) ;
/goth-4dku (goth-4dku.gsf) ;
/goth-4eku (goth-4eku.gsf) ;
/goth-4fku (goth-4fku.gsf) ;
/goth-50ku (goth-50ku.gsf) ;
/goth-51ku (goth-51ku.gsf) ;
/goth-52ku (goth-52ku.gsf) ;
/goth-53ku (goth-53ku.gsf) ;
/goth-54ku (goth-54ku.gsf) ;
/goth-55ku (goth-55ku.gsf) ;
/goth-56ku (goth-56ku.gsf) ;
/goth-57ku (goth-57ku.gsf) ;
/goth-58ku (goth-58ku.gsf) ;
/goth-59ku (goth-59ku.gsf) ;
/goth-5aku (goth-5aku.gsf) ;
/goth-5bku (goth-5bku.gsf) ;
/goth-5cku (goth-5cku.gsf) ;
/goth-5dku (goth-5dku.gsf) ;
/goth-5eku (goth-5eku.gsf) ;
/goth-5fku (goth-5fku.gsf) ;
/goth-60ku (goth-60ku.gsf) ;
/goth-61ku (goth-61ku.gsf) ;
/goth-62ku (goth-62ku.gsf) ;
/goth-63ku (goth-63ku.gsf) ;
/goth-64ku (goth-64ku.gsf) ;
/goth-65ku (goth-65ku.gsf) ;
/goth-66ku (goth-66ku.gsf) ;
/goth-67ku (goth-67ku.gsf) ;
/goth-68ku (goth-68ku.gsf) ;
/goth-69ku (goth-69ku.gsf) ;
/goth-6aku (goth-6aku.gsf) ;
/goth-6bku (goth-6bku.gsf) ;
/goth-6cku (goth-6cku.gsf) ;
/goth-6dku (goth-6dku.gsf) ;
/goth-6eku (goth-6eku.gsf) ;
/goth-6fku (goth-6fku.gsf) ;
/goth-70ku (goth-70ku.gsf) ;
/goth-71ku (goth-71ku.gsf) ;
/goth-72ku (goth-72ku.gsf) ;
/goth-73ku (goth-73ku.gsf) ;
/goth-74ku (goth-74ku.gsf) ;
/goth.r21 /goth-21ku ;
/goth.r22 /goth-22ku ;
/goth.r23 /goth-23ku ;
/goth.r24 /goth-24ku ;
/goth.r25 /goth-25ku ;
/goth.r26 /goth-26ku ;
/goth.r27 /goth-27ku ;
/goth.r28 /goth-28ku ;
/goth.r30 /goth-30ku ;
/goth.r31 /goth-31ku ;
/goth.r32 /goth-32ku ;
/goth.r33 /goth-33ku ;
/goth.r34 /goth-34ku ;
/goth.r35 /goth-35ku ;
/goth.r36 /goth-36ku ;
/goth.r37 /goth-37ku ;
/goth.r38 /goth-38ku ;
/goth.r39 /goth-39ku ;
/goth.r3a /goth-3aku ;
/goth.r3b /goth-3bku ;
/goth.r3c /goth-3cku ;
/goth.r3d /goth-3dku ;
/goth.r3e /goth-3eku ;
/goth.r3f /goth-3fku ;
/goth.r40 /goth-40ku ;
/goth.r41 /goth-41ku ;
/goth.r42 /goth-42ku ;
/goth.r43 /goth-43ku ;
/goth.r44 /goth-44ku ;
/goth.r45 /goth-45ku ;
/goth.r46 /goth-46ku ;
/goth.r47 /goth-47ku ;
/goth.r48 /goth-48ku ;
/goth.r49 /goth-49ku ;
/goth.r4a /goth-4aku ;
/goth.r4b /goth-4bku ;
/goth.r4c /goth-4cku ;
/goth.r4d /goth-4dku ;
/goth.r4e /goth-4eku ;
/goth.r4f /goth-4fku ;
/goth.r50 /goth-50ku ;
/goth.r51 /goth-51ku ;
/goth.r52 /goth-52ku ;
/goth.r53 /goth-53ku ;
/goth.r54 /goth-54ku ;
/goth.r55 /goth-55ku ;
/goth.r56 /goth-56ku ;
/goth.r57 /goth-57ku ;
/goth.r58 /goth-58ku ;
/goth.r59 /goth-59ku ;
/goth.r5a /goth-5aku ;
/goth.r5b /goth-5bku ;
/goth.r5c /goth-5cku ;
/goth.r5d /goth-5dku ;
/goth.r5e /goth-5eku ;
/goth.r5f /goth-5fku ;
/goth.r60 /goth-60ku ;
/goth.r61 /goth-61ku ;
/goth.r62 /goth-62ku ;
/goth.r63 /goth-63ku ;
/goth.r64 /goth-64ku ;
/goth.r65 /goth-65ku ;
/goth.r66 /goth-66ku ;
/goth.r67 /goth-67ku ;
/goth.r68 /goth-68ku ;
/goth.r69 /goth-69ku ;
/goth.r6a /goth-6aku ;
/goth.r6b /goth-6bku ;
/goth.r6c /goth-6cku ;
/goth.r6d /goth-6dku ;
/goth.r6e /goth-6eku ;
/goth.r6f /goth-6fku ;
/goth.r70 /goth-70ku ;
/goth.r71 /goth-71ku ;
/goth.r72 /goth-72ku ;
/goth.r73 /goth-73ku ;
/goth.r74 /goth-74ku ;
/min (min.gsf) ;
/min-RKSJ (min.gsf) ;
/min-EUC (min.gsf) ;
/min-V (min.gsf) ;
/Ryumin-Light /min ;
/Ryumin-Light-H /min ;
/Ryumin-Light-RKSJ /min-RKSJ ;
/Ryumin-Light-RKSJ-H /min-RKSJ ;
/Ryumin-Light-EUC /min-EUC ;
/Ryumin-Light-EUC-H /min-EUC ;
/Ryumin-Light-V /min-V ;
/goth (goth.gsf) ;
/goth-RKSJ (goth.gsf) ;
/goth-EUC (goth.gsf) ;
/goth-V (goth.gsf) ;
/GothicBBB-Medium /goth ;
/GothicBBB-Medium-H /goth ;
/GothicBBB-Medium-RKSJ /goth-RKSJ ;
/GothicBBB-Medium-RKSJ-H /goth-RKSJ ;
/GothicBBB-Medium-EUC /goth-EUC ;
/GothicBBB-Medium-EUC-H /goth-EUC ;
/GothicBBB-Medium-V /goth-V ;
/GothicBBB-Medium-90ms-RKSJ-H /goth-RKSJ ;
/Ryumin-Light-90ms-RKSJ-H /min-RKSJ ;
Once that is done, save the filename as "Fontmap" (without quotes) and then invoke ghostscript to load the Fontmap. Ghostscript will not do so automatically when the fonts are not in it's own search path so there are two ways to do this:
1) Start ghostscript with the -I switch followed by the path/to/fonts. For instance in my case with ungzipped tar under /usr/share/ghostscript/9.10 with an extra directory as /usr/share/ghostscript/9.10/gs6.0.kanji and with fonts directory that also contains Fontmap file. I would invoke ghostscript via "gs -I /usr/share/ghostscript/9.10/gs6.0.kanji/fonts".
2) Set an environment variable for ghostscript. "export GS_LIB=/path/to/kanji/fonts". Then run ghostscript.
What these does is it adds extra directories to ghostscript search path. So the next time when you lauch ghostscript with the Japanese postscript file, it will load up the Japanese fonts that setup prior to invoking ghostscript to open the file.
The output should be like this when the setup has been successful:
For those that are keen, the screenshots are from the file named keyboard.ps (和田英一. 個人用小型キーボード. 1995年度WIDEプロジェクト研究報告書. (Japanese)). Also, it seems like ghostscript got the update whereas other postscript viewers did not get the update. In either cases I believe ps2pdf would be included as part of ghostscript and one can easily convert postscript files to pdf once they can successfully render the output of the ps file.
Remember, if you see ghostscript showing garbled output of a postscript file, converting it to pdf will still leave you the same garbled output except it is now a pdf file and not a ps file. 

Further reading (thanks to ray_laptop):
  • Ghostscript for newbie is available via Ghostscript GIT repository: http://git.ghostscript.com/?p=ghostpdl.git;a=blob_plain;f=gs/doc/Use.htm;hb=HEAD
  •  "How Ghostscript finds font files": http://git.ghostscript.com/?p=ghostpdl.git;a=blob_plain;f=gs/doc/Use.htm;hb=HEAD#Finding_files in http://git.ghostscript.com/?p=ghostpdl.git;a=blob_plain;f=gs/doc/Use.htm;hb=HEAD#Font_lookup