top page > TeX > here

ghostscript による印刷


概要

内容は次のようなものです.

  1. FreeBSD/pc98 におけるパラレルポート・ドライバー (ppc0) の安定性.
  2. ghostscript の version と MJ-700V2C への対応状況.

目次

1. ppc0 の安定性
2. ghostscript と MJ-700V2C

1. ppc0 の安定性

パラレルポート・ドライバー (ppc0) は,default では割り込み処理を使って動くように設定されています. パラレルポート・バスシステム (ppbus) やプリンター・ドライバー (lpt) も含めて OS 起動時の log の関連部分を抜粋すると,次のようになります. (FreeBSD/pc98 7.2 の場合.)

ppc0: <Parallel port> at port 0x140-0x147 irq 14 on isa0
ppc0: SMC-like chipset (ECP/EPP/PS2/NIBBLE) in COMPATIBLE mode
ppc0: FIFO with 16/16/16 bytes threshold
ppbus0: <Parallel port bus> on ppc0
ppbus0: [ITHREAD]
lpt0: <Printer> on ppbus0
lpt0: Interrupt-driven port

一方,AT 互換機の話ですが文献 [1] には FreeBSD 4.2, 4.3 の頃からこの割り込み処理を使うと OS ごと固まるという問題が指摘されています. 私は相当長期間 FreeBSD(98) 4.9 にて印刷を行なって来ましたが,幸いこの問題には遭遇しませんでした.[2]

ところが,FreeBSD/pc98 5.3, 6.2, 7.2 で印刷してみると,印刷の途中でこの問題が生じて OS ごと落ちました. 1 ページの印刷ができないほどに不安定です. (PC やプリンターの機種,および他のデバイスの使い方は同一です.)

その対策として,/boot/device.hints を次のように変更して割り込みをやめ Polling モードにします. [3]

hint.ppc.0.at="isa"
hint.ppc.0.flags="0x10"   ← この行を加えます.
#hint.ppc.0.irq="14"      ← オリジナルのこの行は comment out します.

log は次のように変わり,Polling モードになったことが確認されます. これで印刷は安定します.

ppc0: <Parallel port> at port 0x140-0x147 flags 0x10 on isa0
ppc0: SMC-like chipset (ECP/EPP/PS2/NIBBLE) in COMPATIBLE mode
ppc0: FIFO with 16/16/16 bytes threshold
ppbus0: <Parallel port bus> on ppc0
lpt0: <Printer> on ppbus0
lpt0: Polled port

(2011.3.13) これで安定したと思ったのですが,この環境にて初めて総計 200 ページを印刷をしたところ,OS ごと 3 回も落ちました. 当然ですが,割り込みを使う場合よりは格段に安定しています. FreeBSD 4.9 の頃にも同様の大量の印刷を何度も行ないましたが,このようなことはありませんでした.

あくまで経験則として,lpr を繰り返し実行して印刷を spooler に溜めると不安定になるようです. (/var の容量に余裕はある状態だと思うのですが.)

(2011.12.3) FreeBSD/pc98 8.2 ですが,印刷をしたつもりでもプリンターが反応しないしエラーも出ないという症状になります.

GENERIC のプリンター関連の部分を以下のように変更して kernel を再構築し, (FreeBSD 7.2 は最初からこうなっています.)

# NEW Parallel port
#device         ppc
#device         ppbus           # Parallel port bus (required)
#device         lpt             # Printer
#device         plip            # TCP/IP over parallel
#device         ppi             # Parallel port interface device
#device         vpo             # Requires scbus and da
# OLD Parallel port
# Please stay olpt driver after ppc driver
#device         olpt

/boot/loader.conf に以下の部分を追加すれば印刷できるようになります. (これは当然,FreeBSD 7.2 でも必要です.)

ppc_load="YES"
lpt_load="YES"

GENERIC の comment out をもう少し小刻みにすれば「原因」に辿り着けるのでしょうが,暇がありません.

[1]「FreeBSD 徹底入門 (改訂版)」衛藤 ら,翔泳社 (2002) p.399
[2] うちで印刷するものはすべて PostScript です. 長大なものは gs が警告を出すので,20 ページ程度に分割します.
[3] [j]man にて ppc, lpt, lptcontrol を御覧下さい.

2. ghostscript と MJ-700V2C

2.1  状況

現在,うちで PC-98 に繋がっているプリンターは EPSON の MJ-700V2C です. このプリンターに対しては,FreeBSD 7.2 + ghostsctipt 8 の環境で PostScript のファイルが印刷できなくなりました.

FreeBSD ghostscript driver ppc/lpt mode 備考
4.97.07 mjc360 irq 印刷可能.
5.37.07 mjc360 polling 印刷可能.
6.27.07 mjc360 polling 印刷可能.
7.28.64 mj700v2c polling 印刷できない.
8.28.71 mj700v2c polling 印刷できない.

「印刷できない」の症状ですが,紙の四隅 (おそらく driver が設定しているマージン) を除いて,黒で塗り潰されます.

FreeBSD 7.2 における以下のような状況から,問題は driver (mj700v2c) にあると言えます.

  • PostScript でない場合には,問題なく印刷できる.
  • ESC/P2 に基づく他の driver (ap3250, st800) を用いると,マージンの大きさは異なるが印刷はできる.
    (マージンが違い過ぎて印刷されない部分があり,またカラーにも未対応なので,代替えにはなりません.)
  • 以下のように作成した印刷用のファイルの内容を hexdump で見ると,印刷されるはずのパターンがない.
% gs -sDEVICE=mj700v2c -sOutputFile=a.mj a.ps   ← 出力するファイル名は任意.
GPL Ghostscript 8.64 (2009-02-03)
Copyright (C) 2009 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
>>showpage, press <return> to continue<<        ← ここで [Return] を打つ.

GS<1>quit
  • FreeBSD の (8.2 を除く) 他の version にて作成した印刷用のファイルは,FreeBSD 7.2 にて問題なく印刷できる.
    (上述の「印刷されるはずのパターン」は,このファイルを hexdump したものと比較すれば明瞭です.)

このファイルを印刷するには,root または su にて次のようにします.

# cat a.mj > /dev/lpt0

また,このファイルの中身を見るには,次のようにします.

% hexdump -Cv a.mj | more

色は 1b 72 (ESC + r) の後に,パターンは 1b 2e (ESC + .) の後に,指定するデータがあります. mj700v2c driver による出力は,以下の例のようにパターンの部分がすべて同一であり,これがまともに印刷されない理由です.

00000000  1b 40 1b 28 47 01 00 01  1b 28 69 01 00 01 1b 28  |.@.(G....(i....(|
00000010  65 02 00 00 01 1b 55 00  1b 28 55 01 00 0a 1b 2b  |e.....U..(U....+|
00000020  01 1b 28 43 02 00 72 10  1b 28 56 02 00 00 00 1b  |..(C..r..(V.....|
00000030  28 76 02 00 00 ff 1b 72  00 1b 2e 01 0a 0a 01 a0  |(v.....r........|
00000040  0b 81 aa 81 aa 8d aa 0d  1b 72 02 1b 2e 01 0a 0a  |......r......|
00000050  01 a0 0b 81 aa 81 aa 8d  aa 0d 1b 72 01 1b 2e 01  |........r....|
00000060  0a 0a 01 a0 0b 81 aa 81  aa 8d aa 0d 1b 72 04 1b  |..........r..|
00000070  2e 01 0a 0a 01 a0 0b 81  aa 81 aa 8d aa 0d 0a 1b  |.............|
00000080  72 00 1b 2e 01 0a 0a 01  a0 0b 81 aa 81 aa 8d aa  |r............|

なお,印刷の試験には /usr/local/share/ghostscript/8.64/examples/ にある以下の二つのファイルを用いました.

  • alphabet.ps (文字のみ,かつモノクロ)
  • colorcir.ps (図形が主体,かつカラー)

2.2  修正

/usr/ports/print/ghostscript8 にて make を実行すると,そこに work が作成されます. 問題にしている driver に関連するソースは work/ghostscript-8.64/ 以下にあります.すなわち,

contrib/japanese/gdevmjc.c  (Epson MJ-700V2C, MJ500C, MJ-6000C, MJ-8000C)
base/gdevescp.c             (Epson AP3250, Stylus 800)
base/gdevcdj.c              (HP)

gdevmjc.c が driver mj700v2c, mj500c, mj6000c, mj8000c のソースです. また gdevescp.c, gdevcdj.c は,gdevmjc.c の最初の version の作成時に参考にしたソースとのことです.

以下の二通りのやり方で修正を試みました.

  1. gdevescp.cgdevmjc.ccp し,マージンを MJ-700V2C に合わせて変更する.
    修正したソースと修正の手順を記した文書はここにあります. → mjc.tgz
  2. http://bugs.ghostscript.com/show_bug.cgi?id=689595 にある gdevmjc.c の patch を試用する.

結果は次のようになりました.

  1. の場合,印刷位置が縦横ともに数ミリ変わったが,それ以外は同じ出力が得られる.
    (ただし,720 dpi には未対応.また,カラーには対応できない.)
  2. の場合,図形は印刷用のファイルのパターンに反映されるが,文字は反映されない.
    (patch を作成した人が,べた塗りの絵の印刷しか試みていないのか?)

うちで印刷するのはモノクロの 360 dpi ばかりなので,前者の修正で十分です. (カラー印刷の必要が生じたら,古い FreeBSD を使えば良いわけですが,既にカラーのインクは切れかけてかすれています.)

mj700v2c driver を本来の性能が出るように修正したいのであれば,その基になった gdevcdj.c が大きく変更されているので,できれば先ずこれが HP のプリンターで正常に動作していることを確認した上で,これを修正した方が確実のような気がします.

それと,今回作成したモノクロ版の driver ですが,ghostscript 7.07mjc360 driver に比べて印字は速いです. それゆえ,このモノクロ版も残しておきたいところです.

(補記.2011.3.13) EPSON は昨年 MJ-700V2C のインクの供給を終えました. うちにはもう予備のインクはありません. この先,driver の修正を続けたものかどうか逡巡しております.

(補記.2011.12.3) 通販で黒のインクを 2 本手に入れました. これで問題を少しだけ先送りにできます.

2.3  その他

印刷環境としては以下のように設定しておくと便利です.
(1) /etc/printcap に次のような内容を追加します.

ps|PS printer on local port:\
        :sh:\
        :lp=/dev/lpt0:\
        :if=/usr/local/libexec/psprint.sh:\   ← このファイル名は任意です.
        :sd=/var/spool/output/lpd:\
        :lf=/var/log/lpd-errs:

(2) /usr/local/libexec/ に次のような内容のファイル psprint.sh を作成します. (内容はプリンター等により異なります.またファイル名は /etc/printcap の記述に従います.)

#!/bin/sh
/usr/local/bin/gs -r360 -q -dNOPAUSE -sDEVICE=mj700v2c -sOutputFile=- - quit.ps

このように設定しておけば,次のようにして a.ps を印刷することができます.

% lpr -P ps a.ps

確認や中断には各々 lpq, lprm を使います.