2009年03月27日

XML要素から独立テキストフレーム/インラインテキストフレームを作る、続く/続きアイコンを付ける

InDesign+XMLによる自動組版で作られた書籍も実績を重ねて10冊以上となりました。それぞれは構成もスタイルもまちまちですが、処理系のライブラリ化、抽象化を進めることで1冊ごとの対応の時間、作業時間は着実に短縮できてきています。

ただ、大半のお客様にとっては、その組版がXML処理で自動生成されたものであるのかあるいは手で1つずつ積み上げたものであるのかといったことはどうでもよいことであり、成果物である紙(あるいはPDF)の見栄えが直接の評価対象です。修正要望の中には自動組版で処理するには辛いものも多いのですが、手作業修正を経験し、その流れを自動化することを試み実装する、という繰り返しによって自動組版の機能を向上できたのもまた事実です(とはいえ終盤でちゃぶ台返しは本当に辛いので勘弁してください…)。

ということで、最近実装したものを2つご紹介。ソースコードはInDesign Hacking with JavaScriptにあります。CS3用です。CS4は環境がないので不明です。

1つはコラムなどの処理のためのスクリプトライブラリlibProcessXMLmakeBlock.jsxです。指定のXML要素から独立またはインラインのテキストフレームを作ります。前にもこの実装はしたのですが、当時のものはバギーで不具合も多いものでした。今回のものも完全ではありませんが(たとえばフレームに移動された側のXMLドキュメントの該当箇所に、空行1行が残ってしまう)、今後わりと応用が効きそうです。呼び出しはこんな感じ。

#include "libProcessXMLmakeBlock.jsx"
var obj = new Object; // パラメータ格納用のオブジェクト
  // 適用するオブジェクトスタイル。getObjectStyleByNameはlibCommon.jsxライブラリのもの
obj.objectStyle = getObjectStyleByName(app.activeDocument, "コラム");
  // フレームの幅。0なら自動
obj.width = 0;
  // インラインフレーム化するか。インラインはまだバギーかも
obj.inline = false;
  // ドキュメントオブジェクト、XPath、パラメータオブジェクトを指定して実行
MakeBlock(app.activeDocument, "//column", obj);

過去のライブラリAPIではパラメータを引数にずらずら並べていたのですが、リファクタリングなども面倒なので、Objectクラスをハッシュ風に使うようにしています。今後のスクリプトでは基本的にこのスタイルで進めていきます。XMLを探すのもCS3から使用できるglue codeを使うようにしてみました。でもなんかglue codeかネイティブのXPath探索にバグがあるような気がします。glue code版のXML呼び出しは確かに速度的には悪くないのですが、コールバックのコードのデバッグが困難で、XPathの問題も解明できていません(CS4だと直ってるとかなバグかも)。InDesign CS3の機能制限を避けるべく必死なコードも一部あります。

もう1つは表やコードリストなどがページをまたぐときに「続く」などのアイコンを入れられるようにするlibProcessXMLforContinuous.jsx。まだ開発途上ですが、このスクリプトで手作業の量はだいぶ軽減できています。手だと忘れやすいところですしね。

#include "libProcessXMLforContinuous.jsx"
var obj = new Object; // パラメータ格納用のオブジェクト
  // 配置するレイヤー。nullの場合には現在選択中のレイヤー。存在しない場合は作成される
obj.layername = "続く/続き";
  // 前側ページに配置するファイルオブジェクト。nullの場合は配置しない。placeできるオブジェクトならなんでもよい?
obj.nextostyle = File("tuduku.eps");
obj.nextostyle = getObjectStyleByName(app.activeDocument, "続く"); // 画像オブジェクトスタイル
obj.nextoffset = [0, 0, 0, 0]; // 基本配置位置(現時点では版面右下)からのオフセット
  // 後側ページに配置するファイルオブジェクト
obj.tofile = File("tuduki.eps");
obj.toostyle = getObjectStyleByName(app.activeDocument, "続き");
obj.tooffset = [0, 0, 0, 0]; // 現時点では基本配置位置は版面左上
 // 右ページで分かれる場合にのみ配置するか(現時点では左閉じのみ想定)
obj.spread = false;

// ドキュメントオブジェクト、XPath、パラメータを指定して実行
processXMLforNextToIcon(app.activeDocument, "//codelist", obj);

配置位置が版面基準なのがちょっとナニなんですが、最下段を調べるのは実はけっこう難しい。ページのlinesの最後を見てそのベースラインを…という感じなのですかね。ただそれが表だったりするとまた困難だったりするわけですが。

では、Happy InDesigning!