八方塞がり

2007/09/30

プリンタに食わせるPostScriptがうまく動作しない原因が分かった。

PostScriptのコードを生成する「主筆」側では、紙の大きさや余白の大きさを知ることはできるのだが、文字の大きさを知ることができない。これはフォントに依存する問題であり、PostScriptインタプリタから情報を取得できない以上、致し方のない問題である。そのため、文字をどこに印字するか、どこで改行し、いつ改ページするかといった制御は、すべてPostScript側の演算により決定するようにしている。

それを実現するためには、印刷する各文字について一文字ずつ大きさ(幅)を取得しなければならない。そしてそれを実現するためにcshowオペレータを使用している。

cshowオペレータは、与えられた文字列を調べ、一文字ずつ分解し、各文字に対して与えられた手続きを実行するという機能を持っている。だからこれを使えば所定の目的を達することができる、そう考えたのだ。

だが、問屋はそれほど心優しく卸してはくれないようだ。

cshowオペレータはマルチバイト文字を考慮した上での文字の分割を行い、各文字に対して所定の手続きを実行する。だが、その手続きの中でできる処理には、ある程度の制約がある。

制約の一つは、showオペレータにより印字できる文字が、cshowオペレータにより分割された当該の文字だけだということだ。たとえば、cshowオペレータに”あいう”という文字を渡して分割処理をやらせたものとして、そのうちの”あ”に対して実行された「所定の手続き」について考えてみる。

この場合、「所定の手続き」の中で印刷できる文字は”あ”だけなのである。それ以外の文字を印刷しようとすると、エラーが発生する。

制約の二つ目は、「所定の手続き」の中では、分割された文字の最後の1バイトしか取得できないと言うことだ。たとえば、先ほどの例でいけば、「所定の手続き」の中では、”あ”の下位(?)1バイトしか取得できないと言うことになる。

この制約のせいで、事情に困った現象が発生する。

まず一つは改ページができなくなると言うことだ。改ページ処理自体はいいのだが、改ページに伴って行わなければならないヘッダやフッタの印刷ができないのだ。何せ、cshowオペレータにより実行される「所定の手続き」の中では、cshowにより分割された文字しか印刷できないのだから。

そういうことなら、cshowであらかじめ文字列の分割を行い、いったん配列か何かに蓄積した上で改行なり改ページなりを行えば良いように思うのだが、しかし、chowから呼び出される「所定の手続き」の中では、分割された文字の最後の1バイトしか取得できないという制約がある。そのため、分割した文字を再構成して配列に格納するなどと言った処理を行うことができない。すなわち、分割された文字は「所定の手続き」の中で印刷してしまわなければならないと言うことだ。

いったいどうすればいいのか。

文字列はcshowの中で印刷してしまわなければならない。だが、cshowの中では改ページを行うことはできない。でもって、改ページを行うべきタイミングは、cshowの中でしか知ることができない。

この八方塞がりな状態はどう打開したらいいのだろうか。何か、良い手だてはないものだろうか。

PostScriptのバグ

2007/09/24

ようやく「主筆」の印刷ダイアログからプリンタに出力できるようになった。lprに渡す引数を構成するロジックと、パイプを使ってlprの標準入力にPostScriptのデータを渡す部分を修正したら、何とか動作するようになった。

だが、印刷結果を見るとまだおかしな部分があるようだ。どうも、生成されたPostScriptに間違いがあるようなのだ。

一部はごく単純に、PostScript生成プログラムに渡す引数が間違っていただけであり、すぐに修正できたのだが、簡単には直りそうもないバグがまだ残っている。

それは、おそらく日本語フォントに関連する問題なのではないだろうか。PostScript内で文字列を表示するためにshowというオペレータを使用しているのだが、これがエラーを発生するのだ。

プリンタにより出力されたメッセージによれば、Error nameがtypecheckで、Offending operatorがshow、Error info stringがnon-CID for CID fontとなっている。

具体的にどこのshowで何の文字を出そうとして落ちているのかまでははっきりと判っているのだが、それがどうして失敗したのかが皆目見当がつかない。

やろうとしていることは、単にデバッグ用に挿入した"ABC"という文字列をshowオペレータで表示しようとしているだけなのだが。

これはどうやら、まじめにPostScriptの赤本を読まねばならないようだ。

印刷機能の進捗

2007/09/23

思いがけないイベントや、印刷機能にまつわる開発量が予想以上に大きかった都合上、進捗はかなり思わしくない。

だが、ここに来てようやくPostScriptをファイルに出力するところまではできた。まだちゃんと動作確認を取ったわけではないのだが、とりあえずそれっぽいものをファイルに出力できるようになった。

後は生成したPostScriptをlprに喰わせる部分を作るだけだ。というか、この辺りも一応は作ったのだが、まだ動かしていないから何とも言えない。少なくとも、一発で動作するとは思えない。

lprが外部のコマンドなのは致し方ないとしても、PostScriptを生成する部分までもが別プロセスに切り分けてある都合上、全ての設定値を取得した後の実際に印刷する処理が結構大きくなってしまった。

まず、PostScript生成プログラムに喰わせる入力データをパイプに書き込み、それをPostScript生成プログラムの標準入力に繋ぎ、標準出力をlprの標準入力かファイルに繋がなければならない。

こういった処理は、シェル・スクリプト等で作っているのであればそう困難な処理でもないのだが、Cでゴリゴリ記述するとなると想像以上に辛い。特に、エラー処理を考えると複雑さは想像を絶する。

「主筆」は所詮フリーソフトであり、それ程難しいことを考えているわけでもないのだが、それでもそれなりにはエラー処理を実装している。だが、パイプやファイル・ディスクリプタの操作の周辺については、エラー時の処理は多少手を抜いてある。

「主筆」のエラー処理の基本的方針は、エラーメッセージを表示し、環境に悪影響を与えないよう後始末をしつつ、当該の処理を中断するというものだ。だから、ファイルを開いている場合であればそのファイルを閉じ、作業用にメモリを確保しているのであればそのメモリ領域を開放するようにしている。だが、ファイル・ディスクリプタの操作周辺では、エラーの発生箇所によっては、完全には環境を元通りしないで処理を中断してしまう部分がある。

無論、ただ手抜きの為だけにエラー処理をごまかしている訳ではない。環境を完全に元通りにするのが困難であるか、あるいは不可能であると判断したから、そのような手抜きの実装になっているのだ。

例えば、PostScript生成プログラムの起動について考えてみる。ここでは標準入力と標準出力をそれぞれ別のファイルやパイプなどに割り当ててあげなければならない。

このとき、標準入力をファイルに差し替えるのに成功した後で、標準出力の割り当ての変更に失敗したとしたら、どうだろうか。

単純な回答としては、変更してしまった標準入力を元に戻してから処理を中断するべきである。だが、標準出力の割り当ての変更に失敗した時点で、標準入力の割り当てを元に戻す処理を行うことができるのだろうか。失敗した原因が何であれ、その失敗した処理と同じ処理を行って原状の回復ができるとは思えない。

一応、上記の例では回復させる処理は明らかであるため、実装してあるにはしてある。ただ、いざというときには予想通りに動作するとは思えないだけである。

パイプ制御はエラー処理だけでも複雑なのだが、それ以外の正常系の処理もやはりそれ相当に複雑である。正直、ここまで作ってきて言うのもなんだが、そろそろ疲れた。

休暇中の進捗

2007/09/22

結局のところ、この数日の間は会社を休んだのだが、しかし「主筆」の開発は全く進まなかった。当然だが。

休みの間やったことといえば、葬式関係の諸々と実家で飼っているペットの世話と、時々かかってくる仕事の電話に応答しただけだ。なにせ、実家にはSolarisのマシンはないし、リモートで操作できるような環境を整えてあるわけでもない。だから、たとえどんなに暇でも開発作業を進めるわけには行かなかった。

だがそれはどうでもいい。作業が進まなかったからといっても、特に何を失うわけでもない。つらいのはテレビが見れなかったことだ。どうしても地方と東京近郊とでは放送しているテレビ番組が違うし、そもそも受信できない局もある。そのため、見たい番組のほとんど全てが見れなくなってしまった。これほどひどい状態に陥ったのは、生まれてこの方一度もない。

無論、俺自身出きる限りの努力は尽くした。だが、なにぶんイベントがイベントであるため、あまり表立った行動をとることもできず、結局のところ状況の改善には貢献しなかった。

開発も進められない、テレビも見られない、かといってそれほど忙しいわけでもない。仕方がないから本を数冊買って読んでみたが、それもすぐに終わってしまい、本当に暇だった。こうすることがないと、激務の本業に戻れなくなるのではないかと心配になる。だが、プロジェクトは日々遅延しつつあり、俺がどう思おうと職場には復帰せざるを得まい。さもなくば退職あるのみだ。

気だるいが、仕方がない。非日常はこの辺で切り上げて、つらい日常生活に戻ることとするか。

職業

2007/09/19

通夜でやるイベントのなかに納棺と呼ばれるものがある。直接的には遺体を棺桶に詰めるだけの作業なのだが、それに付随して遺体のメイク、すなわち死化粧が行われる。そしてこの作業は、その筋の専門家によりおこなわれる。

その作業自体は、決して気持ちのいいもではなかったが特に何の問題もない。ただ、気になったのは「専門家」なる人物が結構かわいい若い女だったことだ。死後硬直した親父の死体をまえに不謹慎な気もしたが、かわいかったものは仕方がない。

ところで、あの女は何を思ってあんな職業に就いたのだろうか。一般的に、職業としてのメイクといえば、生きている人間に対して化粧を行うものを言うのではないだろうか。死者に対して化粧を行うのは、そう一般的な生業とは思われない。彼女の人生がどういったものだったのかは知らないが、まさかこんな事を専属で行うことになるとは、なってみるまで想像だにしなかったに違いない。

いわれてみれば、俺は結構子供の頃からコンピュータ関連の職業に就くことを目的としていたように思う。少なくとも高校の進学先を考える時点で、そのことは明確に意識していたはずだ。

そのことがいいことだったのかどうかは判らない。目標に向かって一筋に突き進むことを良しとするか、世の中にどんな職業があるのかも判らない内に自分の将来を決定してしまうことを愚かと見るか、その評価は後になってから、自分が後悔しているか否かで決定されるのだろう。少なくとも、今の俺には何ともいえない。

とりあえず、あのネェちゃんがかわいかったということと、葬儀屋や医者に比べればSEという職業はドラマにはなり得ないということだけは、よく判った。

葬式

2007/09/17

親父が死んだ。倒れてから約20時間。その間の出来事は俺の人生における一大事ではあったのだが、しかし、驚いたのはその後の展開だ。

倒れて、病院に運ばれ、呼吸が停止し、徐々に脈が弱くなり、心電図のグラフがゆっくりと平坦に近づき、脈が検出できなくなり、医者に死を告げられた、その4時間後には葬儀屋の打ち合わせコーナーで式場の大きさを決めているのだ。

病院というのは人の命を救うべく、考え得るありとあらゆる手を尽くす場所、すなわち合理と科学の権化のようなところである。それに対して葬式というのは、文化や風習・宗教の要請により行う、いわば非科学的な儀式である。その間の切り替わりがあまりに性急で、戸惑ったわけでも、面食らったわけでもないが、感慨深いものがあったと思う。

文化の切り替わりついて、特に象徴的だと思ったのが、霊安室での出来事だ。葬儀屋が病院に到着すると、親父の遺体がICUから霊安室を抜け、葬儀屋の車に乗せられたわけだが、そのとき病院の用意した可動式ベッド(例のストレッチャーという奴だ)から、葬儀屋の用意したそれに乗せ変えられるという作業があった。

病院の所有物であるベッドで使用されている布団は、使い古した木綿の肌掛け布団、要は実用本位のものであるのに対して、葬儀屋のそれは、素材は知らないがテラテラと光る、それっぽい刺繍の入った重厚な布団である。遺体が移し替えられた瞬間に、俺が存在する文化の様式が全く異なったものになったのだ。

無論、その効用については疑うべくもない。竹内式に従い死亡宣告が下されはしたものの、外見的には何らの変化もない親父のそれを見ていると、むやみに悲しみがこみ上げてくる。だが、葬儀屋と一緒に俺の人生においてはあり得ないほどの額の出費について検討していれば、やたらと花飾りの個数にこだわる親戚に責め苛まれていれば、会社の上司や同僚に然るべき事務連絡を繰り返していれば、悲しいなどと言っている余裕は無くなる。もっと直接的に身に迫る問題に忙殺されていると、自分が何のためにそれをやっているのかを忘れてしまう。

だが、あまりに早急な存在様式の変化に、坊主に払わなければならない金額の大きさに、さすがの俺も驚いた。というか、面食らった。

以前、「お葬式」という映画があったが、あれはまさに正鵠を射ていると言えるのではないだろうか。我ながら人生の不思議さの一端にふれたように思う。

lpr

2007/09/09

UNIXで印刷するにはlprとか言うコマンドを使用する必要があるらしい。では、アプリケーションから印刷したい場合にはどうしたらいいのだろうか。単純にlprコマンドを内部で呼び出すしかないのだろうか。

まぁ、別にそれであってはいけない理由はないのだが、外部のコマンドを呼び出すのは、単純な関数呼び出しに比べればずっと複雑で面倒だから、できれば避けたいと思う。

更に、「主筆」ではテキストをPostScriptに変換する部分は別のプロセスに切り分けた都合上、lprへの入力にはPostScriptに変換する処理の標準出力を繋いでやる必要があるように思う。つまり、パイプ工事をしなければならないと言うことだ。面倒なことこの上ない。

面倒だ、ということは別に大した事ではないのだが、それ以外にも悩ましい問題がある。それは、呼び出すべきlprコマンドをどこで指定させるのか、ということだ。つまり、設定値をどこに持たせるのかという問題だ。

「主筆」の設定は、主に下記のような方法で変更できるようになっている。


  1. リソースファイル

  2. 環境変数

  3. 起動時の引数

  4. リソース数により指定された設定ファイル

  5. 環境変数により指定された設定ファイル



上記の内、「起動時の引数」の使用用途は明らかだから特に迷うことはない。だが、環境変数で設定させるか、リソースで設定させるかは、なかなか明確には決められない要因がある。

元々は、「主筆」の設定はリソースで行うようにしていた。だが、リソースでの設定内容はエディタ本体(すなわちTaEditというプログラム)の中からしか参照することができない。そこで、一部の設定を環境変数により行うようにした。

つまり、リソースと環境変数は、下記のように使い分けられると言うことだ。


  1. TaEditというプログラムで使う設定値はリソースに持ってくる。例えば、motifやXt・X周辺の設定や、メッセージ、UI関係の挙動など。

  2. TaEditというプログラム以外で使用される可能性のある設定値は環境変数に持ってくる。例えば、TaEdit自体や主筆サーバ・クライアント・エンコード変換などの各プログアムのパス名や、エンコード変換で使用する設定値などがそうだ。



このルール自体は明確であり、これに従えば、ある設定値をリソースに持ってくるか環境変数にするかを悩む事はないはずである。だが、そうすると気持ちの悪い事象が発生することになる。

環境変数には、使い分けの都合上、「主筆」で起動される各種プログラムのパス名が記述されることが多い。例えば「TaEdit……」というプログラムのパス名は、全て環境変数で指定するようにしている。

だが、lprコマンドはエディタ本体でしか使用しない。つまり、上記のルールを適用するとリソースに設定するべきものとなるはずである。それでいいのだろうか。

上記のルールは、あくまでも開発する側の理論であり、ユーザからすれば全く関知しない世界の事である。それなのに、あるプログラムのパス名は環境変数で指定し、別のプログラムのパス名はリソースで設定するというのはどうだろうか。ユーザにとっては理解しがたいことのように感じられないだろうか。

つまり、リソースか環境変数かという区分は、上記のように、その設定値を使うプログラムが誰かということから決定するべきではなく、むしろ、ユーザ側から見た何らかの基準に従い分類されるべきなのである。例えば、UI関係(色やフォントなど)はリソースで設定するが、実行時の環境(プログラムのパス名など)は、環境変数で指定させるなどいったように。

ユーザ側から見た理論に基づいて分類するとなると、各項目ごとにそれぞれ人間的な判断が必要になり、技術屋としては気持ちの悪いことこの上ない。だが、一般人からみれば、技術屋の言うことの方が理解不能で気色の悪いことであるものだし、こういった価値判断の重要性は忘れてはいけないことだとも思う。

でもまぁ、どうでもいいっていえば、どうでも良いことなんだがな。

壁紙のエロ画像

2007/09/02

電車内で通信制大学のレポートを片づけようとしてsigmarionIIIを取り出し開いたのはいいが、壁紙が思いっきりエロ画像だった。隣に座っていたガキ(女)に見られたような気がしたが、まぁいいか。

当初の予定では夏休み中に「主筆」の印刷機能を実装し、第19版として公開する予定だったが、間に合わなかった。今は、印刷ダイアログが一通り動作するようになり、後はPostScriptを生成するプロセスを起動して、lprに渡す部分を実装する部分が残っているのみである。

もともと、PostSctiptを生成するプログラムには、紙一枚に複数ページを縮小して印刷する機能は実装しないつもりでいた。だが、印刷ダイアログに勢いで「N-Up」という項目を付けてしまったから、先の機能もちゃんと作っておくことにした。

追加する処理の内容としては、印刷する内容を縮小して、回転して、然るべき位置に移動させるだけだから、基本的には難しいことではないはずである。だが、回転した後に移動する場合、どっちが上でどっちが下なのか、あるいは移動した後に回転すると、どこを中心に回るのか、縮小した後に移動する場合、それぐらいの距離を動かせばいいのか、それがなかなか把握しづらい。

同じ問題がOpenGLにおけるポリゴンの描画でも発生する。あの場合は、明確に行列演算という形で、どのように考えるべきかが示されているが、残念ながら俺には理解できない。OpenGLにせよ、PostScriptにせよ、これはいろいろやってみて感覚的に理解するしかないようだ。