DTPab

DTPにまつわるあれこれ

InDesignの合成フォント関係スクリプト3件

Twitterで意外に反響があってびっくりしました。InDesignの合成フォントまわり、本当に面倒なんですよね。やっぱりみんな苦労するところは同じなのか…w

さて、合成フォント関係のスクリプトを3つ紹介します。

  • すべての合成フォントに特例文字セットをまとめて追加
  • 末尾が-\dの合成フォントをまとめて削除
  • 合成フォントの各セットに登録されている文字を書き出し
続きを読む

ScriptUIを少しだけ簡単に利用するモジュール

随分前のもくもく会で、ScriptUIを楽に生成するモジュールを公開しました。
実はそのモジュールを知っている方が前回のもくもく会にいらしてくださり、使い方について改めて説明しました。

説明していて思ったのですが、コードが、その、なんというか、気持ち悪い!www

そこでリライトしてやろうと思い立って書き直しました(コードはGitHubです)。

また、使い方はこちらです。
とっつきにくいSUIですが、慣れてしまえば結構面白いので、ぜひ遊んでみてください^^/

1if-1for(3):特定の文字スタイルの次の文字

f:id:uske_S:20180721002323p:plain

職場で「ある文字スタイルが当たっている文字の、次の文字をスクリプトで処理したいが可能か?」と聞かれたので、試しに書いてみました。
そしたら結果的に1if-1forで収まったのでここに書いておきます。
この画像は、スクリプトで色が青くなる文字スタイル(A)を検索し、その次の文字に赤くなる文字スタイル(B)を当ててみた結果です。

f:id:uske_S:20180809212840g:plain

InDesignの検索だと、例えば「(?<=A)B」として検索するときに、検索条件に文字スタイルを設定するとAもBもその文字スタイルが当たっていないと検索ヒットしません。でもこれがスクリプトならできるよね、ということです。

コードはこちらです。例によって半人前のスクリプトですのであしからず。
たまには最大限にコメント入れてみました。

var doc = app.activeDocument;
app.findGrepPreferences = null; //正規表現検索条件のリセット
//正規表現検索条件の同時定義はpropertiesプロパティにオブジェクトを渡す
app.findGrepPreferences.properties = {
    findWhat: ".+",
    appliedCharacterStyle: doc.characterStyles.itemByName("A")
};
//ドキュメントを対象に検索->検索結果を配列として取得
var findList = doc.findGrep();

for (var i=0; i<findList.length; i++) {
    //検索マッチの最後のCharacterオブジェクト
    var lastChar = findList[i].characters[findList[i].characters.length-1];
    //ストーリー上での、検索マッチの次の文字のindex
    var nextIndex = lastChar.index + 1;
    //その文字のCharacterオブジェクト
    var nextChar = lastChar.parentStory.characters[nextIndex];
    //nextCharが利用可能か?(ストーリーの最後で次の文字が存在しない場合などを回避)
    if (nextChar.isValid) {
        //利用可能であれば文字スタイルを割り当て
        nextChar.appliedCharacterStyle = doc.characterStyles.itemByName("B");
    }
}

Aという文字スタイルとBという文字スタイルを用意したドキュメントで実行してください。

今回で3回目の不定期連載ですが、意外と書けるんですよね、if文とfor文を1回使うだけで。
ただこのスクリプトには難点があって、めちゃくちゃ処理が遅いです。なぜならとてもまだるっこしい処理をしているからです*1

まぁパフォーマンスについては別の機会に考えるとして、「次の文字」を取得するという方法ではnextItemメソッドというものがあります。これはほとんどのコレクションオブジェクトが持っているメソッドで、文字通り、コレクションのあるメンバーを基準に(その基準となるメンバーをnextItemメソッドの引数として渡します)次のメンバーを取得するメソッドです。
先程のfor文をnextItemメソッドを使ってリライトするとこんな感じでしょうか。

for (var i=0; i<findList.length; i++) {
    //検索マッチの最後のCharacterオブジェクト
    var lastChar = findList[i].characters[findList[i].length-1];
    //次のCharacterオブジェクト
    var nextChar = findList[i].characters.nextItem(lastChar);
    //nextCharが利用可能か?(ストーリーの最後で次の文字が存在しない場合などを回避)
    if (nextChar.isValid) {
        //利用可能であれば文字スタイルを割り当て
        nextChar.appliedCharacterStyle = doc.characterStyles.itemByName("B");
    }
}

ほかにもいろいろ方法がありますので、オブジェクトモデルと睨めっこしながら、思いついたものを試してみてください〜^^/

*1:余談ですが、僕が初めて実装した「検索結果の次の文字を取得する」という処理のアイディアが、この何ともまだるっこしい方法でしたw