InDesign:合成フォント内のフォントを置き換えるスクリプト

またまた「InDesign JavaScript教室 第2期延長講座」からのスクリプトです。

合成フォント、私は使いません。というのも以前のバージョンでは、同名の合成フォントが増殖する」というバグがあって扱いが面倒だからです(「InDesign 合成フォント 増殖」で検索。ただし現在は解消されているはずとどこかで聞きました)。

ただそれ以前に、なぜ合成フォントを使うのか、その理由がわからないというのがあります。というのもフォントにも当然制作者(フォントデザイナー)がいて、その人がプロの視点で「この形と大きさ(バランス)で世に出そう」と決めたわけです。合成フォントというのはどんな理由があるにせよ、フォントデザイナーの気持ちをないがしろにしている気がするのです。

とはいえ、私もフォントを変えるケースはあります。イチからわかる! InDesign JavaScript 指南書』ではソースコードの部分のフォントFira Monoを使っているのですが、このフォントの「&(アンパサンド)」は

なので、日本ではなじみが薄く読みにくいだろうということで変えています。あと、こだわりがある(多くの場合は無知だったり本質ではないところで差別化を図ろうとしていたり)クライアントにはつける薬はないので、

のように両方の字形を持つフォントを用意していたりしますね。


さて本題です。Type1フォントのサポート終了が間近に迫り、既存データのフォントの置き換えが課題だという話で「合成フォント中の欧文フォントを一括で変えたいんです」ということです。

上に書いた通り、合成フォントをほぼ使わない身としては、それに関するスクリプトは昔調査したきり(いざとなれYsukeさんの記事がある)で、すぐに書けるというものではありません。まずは調べるところからスタートです。

新しいドキュメントを作って適当に合成フォントを1つ作成して調査スタート。

var doc = app.documents[0];
var cfs = doc.compositeFonts;
alert(cfs.length);

で、合成フォントの数が2というのがわかります。そこで

var doc = app.documents[0];
var cfs = doc.compositeFonts;
for (var i = 0; i < cfs.length; i++){
	alert(cfs[i].name);
}

で名前を調べてみると「[No composite font]」と「font1」であることが分かります。後の方は自分で作ったものです。ということは先のものは「[合成フォントなし]」という組み込みの合成フォントだということがわかりました。これは変更ができない合成フォントで、変更しようとするとエラーになります。

次に合成フォントの中身を見ていきます。

var doc = app.documents[0];
var cf = doc.compositeFonts[1];
var cfe = cf.compositeFontEntries;
for (var i = 0; i < cfe.length; i++){
	alert(cfe[i].name);
}

実行すると「漢字」「かな」「全角約物」「全角記号」「半角欧文」「半角数字」「特1」と出ました。つまCompositeFontEntryオブジェクトは最初からインデックスが固定されており、

CompositeFontEntries[0] → 漢字

CompositeFontEntries[1] → かな

CompositeFontEntries[2] → 全角約物

CompositeFontEntries[3] → 全角記号

CompositeFontEntries[4] → 半角欧文

CompositeFontEntries[5] → 半角数字

CompositeFontEntries[6]以降 → 追加した特例文字

という仕組みになっていることがわかります。


実は講座の中ではこんなにきれいにできたわけではなくて、次のようなスクリプトを走らせて、色々条件を変えて確認したというところです。かなり試行錯誤したりしててあまりお見せできるようなものではないのですが、逆にそれがよかったらしいです(笑)

var doc = app.documents[0];
var cpf = doc.compositeFonts[1];
var oubun = cpf.compositeFontEntries[4];
var prp = oubun.reflect.properties;
for (var p in prp) {
	$.writeln("------------------");
	$.writeln("プロパティ名: " + prp[p].name);
	$.writeln("  読み書き: " + prp[p].type);
	$.writeln("  データ型: " + prp[p].dataType);
	$.writeln(" Collection: " + prp[p].isCollection);
	try {
		$.writeln("  現在値: " + oubun[prp[p].name]);
	} catch(e){
		$.writeln("  現在値:現在使用不可");
	}
}

講座の中ではある程度の結論を出して終了、そのChatworkで補足、最終的にはこのブログでまとめという形になります(汗。


で、最終結果の合成フォント内のフォントを置き換えるスクリプトはこうなりました(フォント名は適当)。でもこれ実務で動かしてないから、現場に合わせてもう少し改良が必要かなあ。

var cpf;
var cpfe;
var i, j;
var doc = app.documents[0];
for (i = 1; i < doc.compositeFonts.length; i++) { //1から始める!
	cpf = doc.compositeFonts[i];
	for (j = 4; j < cpf.compositeFontEntries.length; j++) { //欧Type1ら4から始めてよい
		cpfe = cpf.compositeFontEntries[j];
		switch (cpfe.appliedFont) {
			case "Times":
				cpfe.appliedFont = "Fira Mono";
				cpfe.fontStyle = "Medium";
				break;
			case "Minion Pro":
				cpfe.appliedFont = "Fira Mono";
				cpfe.fontStyle = "Regular";
				break;
			default:
		}
	}
 }