PDFLang で PDF を分解する
画面の上では、PDF は平らな一枚に見えます。ページの写真のようなものです。実際は 違います。PDF は部品の詰まった箱で、ファイルについて人が尋ねることのほとんど — これはちゃんと印刷できるか、何か欠けていないか — は、実はその部品のどれかについての 質問です。
PDFLang は中に手を伸ばす方法を五つ渡してくれます。四つはスクリプトが始まった時点で すでにそこにあり、五つ目は自分で描きます。
どのスクリプトも doc という変数から始まります。開く手続きも読み込みも要りません。
doc が、いま検査されているファイルそのものです。
check "何を見ているのか" { print("ファイル:", doc.filename) print("ページ数:", doc.page_count) print("タイトル:", doc.title)}doc.title と doc.author はファイルのメタデータから来ます。PDF が自分自身について
持っている情報で、ページ上には現れません。書き出した人が埋めていないことが多く、
空のままであることがよくあります。それ自体が検査の対象になります。
check "ファイルが自分の名前を持っている" { assert doc.title != "", "PDF のメタデータにタイトルがありません"}doc は三つのリストも持っています。doc.pages、doc.fonts、doc.images です。
普通のリストなので、リストにできることはすべてできます。
doc.pages はページを一枚ずつ渡します。各ページは自分の寸法と、乗っているインキの
量と、どのボックスが定義されているかを知っています。
寸法の単位はポイントです。PDF が考える単位で、1 インチ = 72 ポイント。A4 なら
595 × 842 になります。ただしポイントで考える必要はありません。210mm や 8.5in と
書けば比較は成立します。
check "すべて A4 か" { doc.pages.each { |page| assert page.width > 200mm, "#{page.number} ページが狭すぎます: #{page.width}pt" }}page.number に注目してください。ページは会話と同じく 1 から数えます。ですから
失敗メッセージに出る番号は、人がそのまま開くページ番号です。
そしてボックスがあります。印刷用のページは、そのページをどう扱うかを示す矩形をいくつか 持っています。TrimBox は断裁機が切る位置、BleedBox はそれより少し大きい領域で、 断裁位置を越えて色を伸ばしておく場所です。1 ミリのずれで白い縁が出ないようにするため です。これらがないファイルは、画面上は完璧に見えても印刷所では使えません。
check "断裁の準備ができている" { doc.pages.each { |page| assert page.has_trim_box, "#{page.number} ページに TrimBox がありません" assert page.has_bleed_box, "#{page.number} ページに BleedBox がありません" }}ページは page.tac も報告します。そのページで最もインキが乗る場所の量を百分率で
表したものです。4 色すべてが全力なら 400% になりますが、それを受ける印刷機はあり
ません。300% がよく使われる上限です。
doc.fonts はファイルが使っている書体を並べます。そして各書体は、ひとつの重要な問い
に答えます。埋め込まれているか。
埋め込まれたフォントは PDF の中を一緒に旅します。埋め込まれていないフォントは名前が 書いてあるだけで、ファイルを開いた機械が手持ちの書体で代用します。文字が消えるわけ ではありません。形が変わるのです。行の折り返しが変わり、1 行に収まっていた見出しが 2 行になり、印刷されるまで誰も気づきません。
check "すべてのフォントがファイルと一緒に運ばれる" { doc.fonts.each { |font| assert font.is_embedded, "フォント '#{font.name}' が埋め込まれていません" }}doc.images はファイル内のすべての画像を、page.images は特定のページの画像を
返します。理解しておく価値があるのは dpi です。
DPI は 1 インチあたりのドット数、つまり印刷 1 インチの中にどれだけの情報があるかです。 PDFLang は画像のメタデータに書かれた数値を報告しません。報告するのは実効解像度、 すなわち画像が実際に持つ画素数を、印刷される寸法で割った値です。1000 画素の写真を 20 センチに引き伸ばせば、それは低解像度の画像です。メタデータが何と言おうと関係あり ません。印刷が鮮明になるかどうかを決めるのはこの数字です。
check "印刷に耐える鮮明さ" { doc.images.each { |img| assert img.dpi >= 300, "#{img.page_number} ページの画像: #{img.dpi} DPI、300 必要です" }}もうひとつよく使われるのが img.color_space です。オフセット印刷は CMYK で動きます。
RGB のままの画像は変換が必要で、変換すると色がずれます。刷版を作る前に気づくほうが
ましです。
自分で描く領域
Section titled “自分で描く領域”ここまでの四つはファイルに付いてきます。五つ目は違います。region は自分で定義する 矩形で、ページ全体ではなく一部について問うためのものです。
footer = region(0, 0, 595, 60, "フッター")band = region(20mm, 250mm, 60mm, 15mm, "警告帯")覚えておくべきことがひとつあります。原点の位置です。PDF では 0, 0 はページの
左下の角であり、左上ではありません。Y は上に向かって増えます。
region があるから、仕事にとって本当に意味のある規則が書けます。「このファイルに法定 文言が入っているか」ではなく、「法定文言がそのために確保された帯の中にあるか」です。
check "警告帯" { band = region(0, 700, 595, 142, "帯") content = text::extract_from_region(1, band) assert content.contains("要処方"), "帯に必須の文言がありません"}region 同士は比較もできます。footer.intersects(header) は二つの領域が重なっているか
を教えます。他の用途に確保した場所へ迷い込んだ要素を捕まえる方法です。
footer.expand(5mm) と footer.inset(3mm) は、余裕を持たせた、あるいは狭めた複製を
返します。公差のためです。
次に読むもの
Section titled “次に読むもの”文書の型の章に、五つすべてのプロパティとメソッドが例つきで並んで います。参照用の資料です。通読するのではなく、必要になったときに引いてください。