Hatena::ブログ(Diary)

名もないテクノ手 このページをアンテナに追加 RSSフィード

EPUB版『InDesign者のための正規表現入門』

InDesignのTips一覧

2011-06-04

[][][][]角オプションで一定以上の数値が無効になる

角オプションのバグでもうイッパツ。この不具合は誰かがもう書いているかもしれませんが、参照用にエントリーします。

InDesign CS4から角オプションの描画が変わってしまいました。「角オプションで半径以上のRを指定しても半円にならないなー」とお困りの方も多いと思います。

f:id:seuzo:20110603224518p:image

f:id:seuzo:20110603224519p:image

これは高さ40ptのオブジェクトに20ptのRを指定したものですが、半円になっていませんね。これ、30ptを指定しても40ptを指定してもピタイチ変わりません。

もっと小さいオブジェクトでやってみるとこの現象がもっとハッキリします。

f:id:seuzo:20110603230200p:image

あー、もうがっかりだ。ブログ書いててうんざりする。いつまでこんなバグが残るんだろう?


(暫定的)解決方法

そもそも、InDesignの角オプション「丸み(外)」のRは正円の1/4円弧じゃないのはずっと以前からの有名なバグです。気になる人はお〜まちさんのスクリプト「角丸長方形に変換、または作成を行う」を使ってください。

(追記:2011-07-04T12:55:15+0900)あるいはPICTRIXさんのID_Capsuleでも半円になります。

これらのスクリプトを使えば、円弧が正しくなるだけでなく、半円のオブジェクトも作成できます。もちろん、一番の解決方法はAdobeさんがこのバグを正しく直してくれることです。

ちなみに、InDesign CS5.5でもこのバグは直っていません。ADPSとかやってる場合じゃないんじゃないの?

2011-05-11

[][][][][]強制改行している段落をテキスト変数で正しく拾う

テキスト変数はCS3から実装されていて、とても便利な機能です。しかし、強制改行(Shift-Return)を含んでいると強制改行部分にスペースが入ってしまいます。

f:id:seuzo:20110511182508p:image

おそらく、欧文組版の仕様で、単語間スペースを表していると思われます。けれど、ぼくらが使ってInDesignは日本語版ですよね。これ、お困りの方も多いと思います。

これをよりスマートに解決する方法を紹介します。


1)何もしない文字スタイルを2つ作ります。ここでは「見出し1行目」「見出し2行目」としました。

f:id:seuzo:20110511182510p:image

f:id:seuzo:20110511182509p:image


2)変数を2種類(1行目と2行目)定義します。「ランニングヘッド・柱(文字スタイル)」でそれぞれ手順1で作った文字スタイルを指定します。

f:id:seuzo:20110511182512p:image

f:id:seuzo:20110511182511p:image

f:id:seuzo:20110511182513p:image


3)見出しの段落スタイルの「先頭文字スタイル」で下記のように設定してください。
文字スタイル文字数文字区切る/含む
見出し1行目1強制改行で区切る
なし1強制改行を含む
見出し2行目1文章を含む

f:id:seuzo:20110511184808p:image


4)柱のテキストフレーム内で、手順2で作成したテキスト変数「見出し1行目」「見出し2行目」をそれぞれ挿入します。

f:id:seuzo:20110511190131p:image

見出しの段落スタイルを適用するだけで、強制改行を含んでいようといまいと、自動的に柱が生成されます。


今回、「先頭文字スタイル」を使いました。では「正規表現スタイル」も有効でしょうか? いいえ、残念ですが「正規表現スタイル」は使えません。想像ですけれど、テキスト変数がCS3からで正規表現スタイルがCS4から継ぎ足されたので、計算順序も変数を見てから正規表現スタイルを後に見てるんじゃないかと推測しています。ま、邪推でしょうけど^^


注意

(追記:2011-05-13T14:15:13+0900)上記の「先頭文字スタイル」で自動的に柱を生成する場合、注意することがひとつあります。

ひとつ前の段落で、強制改行によって2行分の文字スタイルが適用されている時、ターゲット段落が1行しかないと、前の段落の「見出し2行目」がそのまま生きてしまいます。

これを回避するには、1行しかないターゲット段落の行末に半角スペースなどを入れて、そのスペースに対して文字スタイル「見出し2行目」を手動で適用します。

2011-04-02

[][][][][]InDesign正規表現では、後読みに繰り返しや選択が使えない

InDesign正規表現で、後読み(戻り読み)には繰り返しや選択が使えません。これはInDesign正規表現の仕様です。たとえば下図のようなキャプションの「●」だけに文字スタイルを適用したいときを考えてみましょう。

f:id:seuzo:20110402154921p:image

最初に思いつくのはこんな正規表現です。

(?<=^図\d?\d)●

しかし、マッチしません。「(?<=^図\d+)●」なども同様です。後読みの中では繰り返しは使えません。

正規表現クックブックのP95「後読みのさまざまなレベル」に少し解説がありました。ちょっとだけ引用します。

正規表現ソフトウエアは、テキストを左から右に探すように設計されてきました。多くの場合、後読みはちょっとしたハックとして実装されています。後読みに書き込まれた文字数を計算し、その字数分だけ後戻りし、後読み内のテキストと対象テキストを左から右に比較するのです。

要するに、基本的には後読み内のテキストは固定長でなければならないってことです。*1


後読み中の選択

今度は、選択を使ってこんな正規表現を試してみます。

(?<=^図\d\d|^図\d)●

これだと、2桁の数字の後ろの●だけにマッチします。1桁の後ろの●にはマッチしません。選択の順序を入れ替えて(?<=^図\d|^図\d\d)とすると、1桁の後ろの●にだけマッチすます。これもやはり選択が正しくサポートされていないのでしょう。*2

後読み中の選択をサポートしている言語、たとえばRuby1.9系*3で下記のように書いた時は正しく動作します。

p /(?<=^図\d\d|^図\d)●/ =~"図2●ほげほげ" #=>2
p /(?<=^図\d|^図\d\d)●/ =~"図2●ほげほげ" #=>2
p /(?<=^図\d\d|^図\d)●/ =~"図18●ほげほげ" #=>3
p /(?<=^図\d|^図\d\d)●/ =~"図18●ほげほげ" #=>3

解決策

とりあえず、こんな感じで解決してみました。

(?<=^図\d\d)●|(?<=^図\d)●

f:id:seuzo:20110402165021p:image

この正規表現スタイルをもった段落スタイルを適用すれば、●文字だけが文字スタイル適用になったのがわかります。

f:id:seuzo:20110402165022p:image

この場合だけに限れば、先頭文字スタイルを使っても解決するかもしれません。しかし、正規表現スタイルは先頭文字スタイルよりも格段に扱いやすいので、いろいろなバリエーションを習得すると吉でしょう。

*1:ただし、これは実装によるので、Javaや.NET Frameworkでは量指定子が使えるようです。

*2:選択が未サポートだとしたらエラーになるはずなので、もしかしたらバグかもしれない

*3:1.8系は後読みをサポートしません

2011-03-06

[][][][][]連結しているテキストフレームをフィットさせる。

D

連結しているテキストフレームは、「フレームを内容に合わせる」ことができません。テキストフレームの線で罫囲みしているような場合、アキが不揃いになるので是非ともフィットさせたいところ。新組だけじゃなく、訂正時も微調整が必要になります。だけど、できません。

そんな時にちゃちゃっとスクリプトで合わせます。誰かもう書いているような気もしますけど...

/*
fit_textframe4linked.jsx
連結しているテキストフレームをフィットさせる
2011-03-06  0.1 とりあえず。
2011-03-06  0.2 テキストフレームが改行で終わっている時も正しくフィットするようにした。テキストフレームが1行だけの時にも正しくフィットさせるため、テキストフレームの高さ(縦組の場合は左右)だけを変えるようにした。

*/

#target "InDesign"

////////////////////////////////////////////エラー終了
function my_error(mess) {
	if (mess !== "") {alert (mess)}
	exit();
}

////////////////////////////////////////////正規表現検索置換
/*
my_range	検索置換の範囲
my_find	検索オブジェクト ex.) {findWhat:"(わたく?し|私)"}
my_change	置換オブジェクト ex.)  {changeTo:"ぼく"}
*/
function my_RegexFindChange(my_range, my_find, my_change) {
	//検索の初期化
	app.findGrepPreferences = NothingEnum.nothing;
	app.changeGrepPreferences = NothingEnum.nothing;
	//検索オプション
	app.findChangeGrepOptions.includeLockedLayersForFind = false;//ロックされたレイヤーをふくめるかどうか
	app.findChangeGrepOptions.includeLockedStoriesForFind = false;//ロックされたストーリーを含めるかどうか
	app.findChangeGrepOptions.includeHiddenLayers = false;//非表示レイヤーを含めるかどうか
	app.findChangeGrepOptions.includeMasterPages = false;//マスターページを含めるかどうか
	app.findChangeGrepOptions.includeFootnotes = false;//脚注を含めるかどうか
	app.findChangeGrepOptions.kanaSensitive = true;//カナを区別するかどうか
	app.findChangeGrepOptions.widthSensitive = true;//全角半角を区別するかどうか

	app.findGrepPreferences.properties = my_find;//検索の設定
	app.changeGrepPreferences.properties = my_change;//置換の設定
	
	my_range.changeGrep();//検索と置換の実行
	//return my_range.findGrep();//検索のみの場合:マッチしたオブジェクトを返す
}

////////////////////////////////////////////オブジェクトの座標と幅、高さを得る 
function get_bounds(my_obj) {
	var tmp_hash = new Array();
	var my_obj_bounds = my_obj.visibleBounds; //オブジェクトの大きさ(線幅を含む)
	tmp_hash["y1"] = my_obj_bounds[0];
	tmp_hash["x1"] = my_obj_bounds[1];
	tmp_hash["y2"] = my_obj_bounds[2];
	tmp_hash["x2"] = my_obj_bounds[3];
	tmp_hash["w"] = tmp_hash["x2"] - tmp_hash["x1"]; //幅
	tmp_hash["h"] = tmp_hash["y2"] - tmp_hash["y1"]; //高さ
	return tmp_hash; //ハッシュで値を返す
}

////////////////実行
if (app.documents.length === 0) {my_error("ドキュメントが開かれていません")}
var my_doc = app.documents[0];
var my_selection = my_doc.selection;
for (var i = 0; i < my_selection.length; i++) {
    if (! (my_selection[i] instanceof TextFrame)) {my_error("テキストフレームだけを選択してください")}
    var tmp_textframe = my_selection[i].duplicate();//選択テキストフレームの複製
    my_RegexFindChange(tmp_textframe.parentStory,  {findWhat:"\\s\\z"},  {changeTo:""});//最後の改行文字を削除
    tmp_textframe.fit(FitOptions.FRAME_TO_CONTENT);//フィットさせる
    var tmp_bounds = get_bounds(tmp_textframe);//複製テキストフレームの大きさを得る
    var my_sel_bounds = get_bounds(my_selection[i]);//元テキストフレームの大きさを得る
    tmp_textframe.remove();//複製したテキストフレームを消去
    var my_HorV = my_selection[i].parentStory.storyPreferences.storyOrientation;//横組かタテ組みか
   if (my_HorV === StoryHorizontalOrVertical.HORIZONTAL) { //横組み
       my_selection[i].visibleBounds = [my_sel_bounds["y1"], my_sel_bounds["x1"], my_sel_bounds["y1"] + tmp_bounds["h"], my_sel_bounds["x2"]];//テキストフレームの大きさをセット
   } else if (my_HorV === StoryHorizontalOrVertical.VERTICAL) { //縦組み
       my_selection[i].visibleBounds = [my_sel_bounds["y1"], my_sel_bounds["x2"] - tmp_bounds["w"], my_sel_bounds["y2"], my_sel_bounds["x2"]];//テキストフレームの大きさをセット
    }
 }

複製したテキストフレームをフィットさせて大きさを得ているだけですね^^

連結している表組みなんかにも応用ができるんですけれど、表「しか」ない場合は1行しかないので、最初のテキストフレームでちょっと失敗します。高さだけ変えるように直そうかな...

(追記:2011-03-06T22:53:50+0900)ver.0.2 修正しました。

ファイルでダウンロードしたい人はこちら:fit_textframe4linked.jsx.zip 直

2011-01-05

[][][][][]プレビューを見ながら設定したはずの表の段落アキが無視される。

「表の属性」ダイアログの「表の設定」タブで、表の段落アキを変更する時、プレビューをオンにして異なるタブに移動すると段落アキが無視される。

再現手順は

  1. 表を選択する
  2. 「表」メニューの「表の属性」ダイアログの「表の設定」タブを開く
  3. プレビューをオンにする
  4. 「表の前のアキ」「表の後のアキ」の値を変更する
  5. 「行の罫線」など他のタブに移動する
  6. 「OK」ボタンをクリックする
  7. アキの値が無視されている

ちょっとわかりにくいので、ムービーを見てください。

D

ここまで大きい値だとすぐに気がつきますが、小さい値を変更した場合は気がつきにくいので注意。