おがさわらなるひこのオープンソースとかプログラミングとか印刷技術とか

おがさわらなるひこ @naru0ga が技術系で興味を持ったりなんだりしたことをたまーに書くブログです。最近はてなダイアリー放置しすぎて記事書くたびにはてな記法忘れるのではてなブログに移行しました。

クリエイティブ・コモンズ・ライセンス
特に断りがない場合は、本ブログの筆者によるコンテンツは クリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンスの下に提供されています。

Ghostscript についてちょっとだけ

明日某所でプレゼンしなきゃいけないんですがまだ自己紹介しかスライド書いてなくてどんぐらい喋ればいいかとか聞いてなくてスケジュール見たら1時間半もあるけどいったいオレにこの時間何をすればいいんだか教えてくれなおがさわらなるひこです。こんばんわ。

ネタは Linux 印刷ネタなんで、このブログ投影してダラダラ喋らせてもらえればラクなんですけど、さすがにそうもいかないわな。

ということで今日もこちらはさっさかやっつけるモードです。


昨日のエントリーで Ghostscript と Poppler という名前だけ出したんで、ちょっと説明しときます……とおもったら、GS だけで力尽きた。Poppler については明日。
よいこのみんなは各自調べてると思いますが、まあ、それはこのページなりの色を出しながら……。

Ghostscript とはなんぞや

知らん人はいないと思いますが……いや、印刷知らない人は知らないか、FLOSS な PostScript のインタプリターであります。

ややうんちく過剰気味の歴史

Adobe のふたり組は Xerox のパロアルト研究所 (俗にいう PARC) からのスピンアウト組なんですけど、その同僚だった L Peter Deutsch*1GNU プロジェクトの一つとして始めた PostScript の互換インタプリタということになります。


その後のことはあんまり詳しくないんですがPeterはGNUプロジェクトを抜け、Ghostscriptで商売することにしました。Alladin Software とかいう名前で Ghostscript (GS) とその UI ランチャーである GhostView (GSView) とかを作ってました。この頃は朧気に覚えてるんですが (社会人2年目ぐらいで TeX仕様書書いてたこともあって)、この会社どうやってビジネスを成立させてたのかよく知りません。

結局 Peter もこの会社を離れて、前後関係はわからないんですが社名が Artifex Software Inc. に変わります。私が Linux 印刷に関わり始めて GS を意識するようになったのはこのちょっとあとなんですが、どうも「最初はコマーシャルライセンスでリリースを行い、1年後にGPLでリリースする」というようなモデルを取っていたっぽいです。ターゲットとしてはアプライアンス商品とかリッチ組み込み、例えば MFP 向けの外付け RIP とかですね、そんな商売をしてたみたいす。この商売は今でも続いているので、GS はカラーマッチングとかそういう機能はそうとうちゃんと作りこんでます。そりゃ商売ですし。

ところがどっこい、先に書いた Michael Sweet が CUPS を始めたことでちょいと風向きが変わったようです。というのは Mike は CUPS 向けに機能を追加したかったから、GPL 版の GS を取ってきてフォークして ESP Ghostscript ってバージョンを提供し始めたんですね。で、こっちは最初から GPL だったし、Mike もコミュニティフレンドリーだったから、機能追加とかバグ修正とか進んできて、第一 CUPS と組み合わせて使うなら ESP 版なので、Artifex 版を1年待って使う意味ってほとんどなくなっちゃった。って、ここらへんから私がリアルタイムで入った頃です。

さて、ESP で CUPS と Ghostscript を作ってた Micheal Sweet ですが、CUPS が Mac OS X お正式な印刷システムに採用されたことから、おもむろに CUPS ごとドナドナされていきました。え、ESP Ghostscript? Apple は「おれら Quartz*2 使うからイラネーよそんなん」といってポイっとされちゃいました。え、あの、Unix 系で印刷するには ESP 版が必須なんですけど……orz

そこで OpenPrinting が媒役になって、Artifex はコマーシャル版と GPL 版を両方出す。その GPL 版に、ESP 版の変更をマージする。という作業をやったのが、あれもう何年ぐらい前だろう? とにかく Ghostscript 9.0 がそのバージョンです。俗に「merged Ghostscript」って言われたバージョン。

ただ、このマージ作業はけっこういろいろあったみたいで、我々日本人にとっては一生懸命入れた縦書き対応が「これは Artifex の顧客にとっては互換性が維持できないから」といわれてごっそり捨てられたりとか苦労したようです。少しずつ少しずつ入れていって、今はちゃんとしてますけどね。

マージが終わってからは OpenPrinting のメンバーが主体的に動くことはなくなって、再び Artifex がメンテする体制になっていったように見受けられます。3年ぐらい前は ML とかで議論してたと思うんだけど、今は ML は閑古鳥が鳴いてますねえ。Artifex の「中」で開発されてる雰囲気。

Ghostscript とデバイスとドライバー

Ghostscript は PostScript という言語のインタプリターでもあるわけですが、当然 PostScript が表現するイメージを描画せなばなりません。でも、描画って、いったい何に?

Ghostscript には「デバイス」という考えがあります。gs --help を叩くとこんなのが出てきますよね。

$ gs --help
GPL Ghostscript 9.06 (2012-08-08)
Copyright (C) 2012 Artifex Software, Inc.  All rights reserved.
Usage: gs [switches] [file1.ps file2.ps ...]
Most frequently used switches: (you can use # in place of =)
 -dNOPAUSE           no pause after page   | -q       `quiet', fewer messages
 -g<width>x<height>  page size in pixels   | -r<res>  pixels/inch resolution
 -sDEVICE=<devname>  select device         | -dBATCH  exit after last file
 -sOutputFile=<file> select output file: - for stdout, |command for pipe,
                                         embed %d or %ld for page #
Input formats: PostScript PostScriptLevel1 PostScriptLevel2 PostScriptLevel3 PDF
Default output device: x11alpha
Available devices:
   alc1900 alc2000 alc4000 alc4100 alc8500 alc8600 alc9100 ap3250 appledmp
   atx23 atx24 atx38 bbox bit bitcmyk bitrgb bitrgbtags bj10e bj10v bj10vh
   bj200 bjc600 bjc800 bjc880j bjccmyk bjccolor bjcgray bjcmono bmp16 bmp16m
   bmp256 bmp32b bmpgray bmpmono bmpsep1 bmpsep8 ccr cdeskjet cdj1600 cdj500
   cdj550 cdj670 cdj850 cdj880 cdj890 cdj970 cdjcolor cdjmono cdnj500 cfax
   chp2200 cif cljet5 cljet5c cljet5pr coslw2p coslwxl cp50 cups declj250
   deskjet devicen dfaxhigh dfaxlow display dj505j djet500 djet500c dl2100
   dnj650c epl2050 epl2050p epl2120 epl2500 epl2750 epl5800 epl5900 epl6100
   epl6200 eplcolor eplmono eps9high eps9mid epson epsonc epswrite escp
   escpage faxg3 faxg32d faxg4 fmlbp fmpr fs600 gdi hl1240 hl1250 hl7x0
   hpdj1120c hpdj310 hpdj320 hpdj340 hpdj400 hpdj500 hpdj500c hpdj510
   hpdj520 hpdj540 hpdj550c hpdj560c hpdj600 hpdj660c hpdj670c hpdj680c
   hpdj690c hpdj850c hpdj855c hpdj870c hpdj890c hpdjplus hpdjportable ibmpro
   ijs imagen inferno inkcov iwhi iwlo iwlq jetp3852 jj100 jpeg jpegcmyk
   jpeggray la50 la70 la75 la75plus laserjet lbp310 lbp320 lbp8 lex2050
   lex3200 lex5700 lex7000 lips2p lips3 lips4 lips4v lj250 lj3100sw lj4dith
   lj4dithp lj5gray lj5mono ljet2p ljet3 ljet3d ljet4 ljet4d ljet4pjl
   ljetplus ln03 lp1800 lp1900 lp2000 lp2200 lp2400 lp2500 lp2563 lp3000c
   lp7500 lp7700 lp7900 lp8000 lp8000c lp8100 lp8200c lp8300c lp8300f
   lp8400f lp8500c lp8600 lp8600f lp8700 lp8800c lp8900 lp9000b lp9000c
   lp9100 lp9200b lp9200c lp9300 lp9400 lp9500c lp9600 lp9600s lp9800c
   lps4500 lps6500 lq850 lxm3200 lxm5700m m8510 mag16 mag256 md1xMono md2k
   md50Eco md50Mono md5k mgr4 mgr8 mgrgray2 mgrgray4 mgrgray8 mgrmono miff24
   mj500c mj6000c mj700v2c mj8000c ml600 necp6 npdl nullpage oce9050 oki182
   oki4w okiibm omni oprp opvp paintjet pam pamcmyk32 pamcmyk4 pbm pbmraw
   pcl3 pcx16 pcx24b pcx256 pcx256 pcx2up pcxcmyk pcxgray pcxmono pdfwrite
   pdfwrite pgm pgmraw pgnm pgnmraw photoex picty180 pj pjetxl pjxl pjxl300
   pkm pkmraw pksm pksmraw plan plan9bm planc plang plank planm png16 png16m
   png256 png48 pngalpha pnggray pngmono pnm pnmraw ppm ppmraw pr1000
   pr1000_4 pr150 pr201 ps2write psdcmyk psdrgb psgray psmono psrgb pswrite
   pxlcolor pxlmono r4081 rinkj rpdl samsunggdi sgirgb sj48 spotcmyk st800
   stcolor sunhmono t4693d2 t4693d4 t4693d8 tek4696 tiff12nc tiff24nc
   tiff32nc tiff48nc tiff64nc tiffcrle tiffg3 tiffg32d tiffg4 tiffgray
   tifflzw tiffpack tiffscaled tiffsep txtwrite uniprint x11 x11alpha
   x11cmyk x11cmyk2 x11cmyk4 x11cmyk8 x11gray2 x11gray4 x11mono xcf xes
Search path:
   /usr/share/ghostscript/9.06/Resource/Init :
   /usr/share/ghostscript/9.06/lib :
   /usr/share/ghostscript/9.06/Resource/Font :
   /usr/share/ghostscript/fonts : /var/lib/ghostscript/fonts :
   /usr/share/cups/fonts : /usr/share/ghostscript/fonts :
   /usr/local/lib/ghostscript/fonts : /usr/share/fonts
For more information, see /usr/share/doc/ghostscript/Use.htm.
Please report bugs to bugs.ghostscript.com.

この Available Devices: 以降にずらずらずらずらっと並んでいるのが、Ghostscript が扱える「デバイス」です。デバイス、といってもリアルなデバイスと一対一に紐付いているわけではなくて、同じ出力形式を受け付けるデバイスを代表しているような感じです。例えば lips4v というのはキヤノンレーザープリンターで LIPS 4V という言語を受け付けるもの向けのデバイスですし、pxlcolor というのは HP の PCL XL 言語のカラー版のデバイスです。
ちょっと面白いデバイスもありますね。png16m というのは1600万色版の png を生成するデバイスですし、x11X Window System の画面上に、つまり普通の Unix 系の GUI の画面に描画するデバイスです。

さてこのようなデバイスをどうやって GS は対応してきたかというと、GS には「ドライバー」という仕組みがあります。ドライバーといっても CUPS システムで言うところのドライバーでも Linux 的なカーネルモードドライバーでもありません。つまり、「オレが渡された PS を解釈したところによると、こういう絵を描いてくれと言ってるぞ」とドライバーの関数をコールすると、ドライバーはそれに応じてイメージを書いたり内部状態を変化させたりプリンターが解釈可能なデータを生成したりするわけです。さらに、gs にオプション、例えば -o papaersize=a4 とか渡してやると、それも解釈してプリンターに A4 を選ばせたりとかそういう機能も持ってた。

昔はおおらかだったので、「オレの持ってるプリンターのドライバー書いたよー」「おー、じゃあ取り込むよー」という感じだったわけですが、さっき言ったように Artifex としては GS は FLOSS であると同時に商売道具なのでメンテナンスする対象は増やしたくないわけです。そこで、今の Artifex / GS コミュニティは:

  • イメージ系のデバイス、標準化によって追加したデバイス (cups, opvp)、ごくポピュラーなデバイス (pxlmono とか) を除き、ほかのデバイスは一切サポートしない。
  • 新たなデバイスを追加することもしない。

ということになりました。とはいえ、CUPS 印刷システムであれば、それでもすごく困ることはない……という建前なのですけどね。

GS まとめ

馬鹿みたいに長く描いちゃいましたが、つまるところ:

  • FLOSS な世界で唯一まともに使える PostScript インタプリタ
  • 頑張って作ってるけど、開発コミュニティは閉鎖的
  • いろんなプリンターデバイスをサポートしているが、整理されつつある
  • が、CUPS 使ってる限りは大丈夫なはず
  • GS の持ってるドライバーに依存してる人は今のうちに考えといたほうがいいかも?

てなとこですかね〜

*1:関係ないですけどこの人はスティーブン・レヴィの「ハッカーズ」に、小学生の頃からMITのAIラボに出入りして、ハッカーじゃない大学院生を「そんな馬鹿げたプログラムがうまく動くわけがないよ」とちゃちゃを入れて怒りを買う (けど、あってるのは常に彼の方) というエピソードで登場します。当時のAIラボのハッカーたちは年齢とかよりもハックの能力だけで人を評価していたため、彼はすぐにMITハッカーたちの仲間入りをします。そのあとPARCに行ってSmalltalkとかやって、動的言語JITは多分かれが初めて書いた、とSmallltalkerの方に教えてもらいました。んでSmalltalkでビジネスをやるためにPARCを止めたんだけどそこも離れて、GSとかを始めたみたい。

*2:PDF のイメージングモデルを採用した OS X のグラフィックエンジン。OS X の場合は全てのアプリは Quartz を使って PDF を生成し、CUPS フィルターは OS X が提供する PDF 操作ライブラリを利用できます。