選択テキストを約物カーニング→文字ツメ→変形(長体・平体)で指定ライン数に追い込む「shorten_line_selection 0.5」
同梱ファイル2Files
- README.txt このファイルです。とにかく最初によんでください。
- shorten_line_selection.jsx スクリプト本体です。
動作環境
このスクリプトが正常に動作する環境は以下の通りです。Windows環境でも動作する可能性がありますが、動作確認はしていません。
- MacOS X10.7.3
- InDesign CS5_J(7.0.4)
インストール
スクリプト本体(shorten_line_selection.jsx)を
~/Library/Preferences/Adobe InDesign/Version 7.0-J/ja_JP/Scripts/Scripts Panel/
にコピーしてください。エイリアスを入れておくだけでもかまいません。
スクリプトパレットから使用します。
使用方法
- 「ウインドウ」メニューから「スクリプティング」ー「スクリプト」を選択し、スクリプトパレットを出します。
- 変形をかけたい部分のテキストを選択します。
- スクリプトパレットから、スクリプト「shorten_line_selection.jsx」をダブルクリックします。
- テキストが変形されたのを確認してください。
設定
スクリプトをエディタまたはESTKで開くと、最初の部分に以下の設定があります。この設定値を変更すれば、簡単にカスタマイズできます。
変数名 | 初期値 | 説明 |
---|---|---|
kerning_var | -300 | 約物のカーニング量。限界値ではなく、定数値。:: カーニングしない時は0にする |
my_tsume_limit | 25 | 文字ツメの限界値(%):: 適用しない時は0にする |
my_scale_limit | 70 | 文字変形の限界値(%):: 適用しない時は0にする |
my_line_limit | -1 | 何ライン以内に収めるか。-1を指定すると、常に現状よりも-1ラインとなる。-2は無効。 |
既知の不具合、またはToDo、あるいは仕様
- カーニング、文字ツメ、変形は縮小方向のみに働きます。例えば、2ライン分を選択していて、3ラインになったりしません。
免責事項
ライセンス
GNU GPLv3
http://sourceforge.jp/projects/opensource/wiki/licenses%252FGNU_General_Public_License_version_3.0
履 歴
2010-02-10 ver.0.1 とりあえず
2010-02-15 ver.0.2 my_line_limitに「-1」を指定すると、常に-1ラインにするようにした。
2012-03-14 ver.0.3 最初の
文字ツメを試し、解消しなかった時に変形するようにした。文字変形のルーチンはmilligrammeさんのhttp://www.milligramme.cc/wp/archives/591 を参考にさせていただきました、感謝。文字属性の変更と復帰のために1文字づつのリスト(オブジェクト)にした。こうすることで、現在のツメないし変形に加算されるようにした(そして速度は遅くなった)。文字変形の限界値を超えて復帰するとき、アラートを出すようにした。文字を選択していない時(InsertionPoint)、挿入点の段落を処理対象にした。
2012-03-14 ver.0.4 約物カーニングを最初に試すようにした。ToDo:行ツメに失敗してもカーニング値だけは戻らない。
2012-03-14 ver.0.5 行ツメに失敗してもカーニング値も含めてUndoできるようにした。副作用として、行ツメに成功した場合もUndo一発で復元できるようになった。この、UndoModes.FAST_ENTIRE_SCRIPT使っているので、気持ち程度は速くなったかも。UndoModesの使い方は、@k_kazutoshi さんに教えていただきました。感謝します。https://twitter.com/k_kazutoshi/status/179901033370234880
ソースコード
/* shorten_line_selection.jsx 選択したテキスト部分を文字ツメ、変形(長体・平体)させて、指定ライン数以内に収めます。 2010-02-10 ver.0.1 とりあえず 2010-02-15 ver.0.2 my_line_limitに「-1」を指定すると、常に-1ラインにするようにした。http://d.hatena.ne.jp/seuzo/20100215/1266213438 2012-03-13 ver.0.3 最初の 文字ツメを試し、解消しなかった時に変形するようにした。文字変形のルーチンはmilligrammeさんのhttp://www.milligramme.cc/wp/archives/591 を参考にさせていただきました、感謝。文字属性の変更と復帰のために1文字づつのリスト(オブジェクト)にした。こうすることで、現在のツメないし変形に加算されるようにした(そして速度は遅くなった)。文字変形の限界値を超えて復帰するとき、アラートを出すようにした。文字を選択していない時(InsertionPoint)、挿入点の段落を処理対象にした。 2012-03-14 ver.0.4 約物カーニングを最初に試すようにした。ToDo:行ツメに失敗してもカーニング値だけは戻らない。 2012-03-14 ver.0.5 行ツメに失敗してもカーニング値も含めてUndoできるようにした。UndoModes.FAST_ENTIRE_SCRIPT使っているので、気持ち程度は速くなったかも。UndoModesの使い方は、@k_kazutoshi さんに教えていただきました。感謝します。https://twitter.com/k_kazutoshi/status/179901033370234880 */ #target "InDesign" //////////////////////////////////////////// 設定 var kerning_var = -300 //約物のカーニング量。限界値ではなく、定数値。:: カーニングしない時は0にする var my_tsume_limit = 25;//文字ツメの限界値(%):: しない時は0にする var my_scale_limit = 70;//文字変形の限界値(%):: しない時は0にする var my_line_limit = -1;//何ライン以内に収めるか。-1を指定すると、常に現状よりも-1ラインとなる。-2は無効。 ////////////////////////////////////////////エラー処理 function myerror(mess) { if (arguments.length > 0) { alert(mess); } exit(); } ////////////////////////////////////////////正規表現検索置換 /* my_range 検索置換の範囲 my_find 検索オブジェクト ex.) {findWhat:"(わたく?し|私)"} my_change 置換オブジェクト ex.) {changeTo:"ぼく"} my_changeが渡されない時は検索のみ、マッチしたオブジェクトを返す。 my_changeが渡されると置換が実行されて、返値はなし。 */ 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;//検索の設定 if (my_change == null) { return my_range.findGrep();//検索のみの場合:マッチしたオブジェクトを返す } else { app.changeGrepPreferences.properties = my_change;//置換の設定 my_range.changeGrep();//検索と置換の実行 } } ////////////////////////////////////////////target_objに含まれる約物を検索して、kerningを実行 function kerning_yakumono(target_obj, kerning_var) { ////////////////正規表現文字列の作成と検索(1:起こし括弧類) var regex_str = "「『([{‘“〈《【〔";//起こし括弧類 var hit_obj = []; var hit_obj = my_RegexFindChange(target_obj, {findWhat:"[^「『([{‘“〈《【〔 \s\n\r][" + regex_str + "]"}); for (i = 0; i < hit_obj.length; i++) { hit_obj[i].insertionPoints.item(1).kerningValue = kerning_var; //カーニング処理(1) } ////////////////正規表現文字列の作成と検索(2:受け括弧類と句読点類) regex_str = "」』)]}’”〉》】〕、,。.";//受け括弧類と句読点類 hit_obj = my_RegexFindChange(target_obj, {findWhat:"[" + regex_str + "][^」』)]}’”〉》】〕、,。.\s\n\r]"}); for (i = 0; i < hit_obj.length; i++) { hit_obj[i].insertionPoints.item(1).kerningValue = kerning_var; //カーニング処理(2) } ////////////////正規表現文字列の作成と検索(3:中点類) regex_str = "・:;";//中点類 kerning_var2 = kerning_var / 2; hit_obj = my_RegexFindChange(target_obj, {findWhat:"[" + regex_str + "][^\n\r]"}); for (i = 0; i < hit_obj.length; i++) { hit_obj[i].insertionPoints.item(1).kerningValue = kerning_var2; //カーニング処理(3) } hit_obj = my_RegexFindChange(target_obj, {findWhat:"[^\n\r][" + regex_str + "]"}); for (i = 0; i < hit_obj.length; i++) { hit_obj[i].insertionPoints.item(1).kerningValue = kerning_var2; //カーニング処理(3) } hit_obj = my_RegexFindChange(target_obj, {findWhat:"[" + regex_str + "][" + regex_str + "]"}); for (i = 0; i < hit_obj.length; i++) { hit_obj[i].insertionPoints.item(1).kerningValue = kerning_var; //カーニング処理(3) } } ////////////////////////////////////////////my_objの文字数分の文字属性prop_listを取得してオブジェクトで返す //ex.) prop_list = ["horizontalScale", "tsume"] function get_char_prop(my_obj, prop_list) { var my_data = new Object(); for (var i =0; i < prop_list.length; i++){ my_data[prop_list[i]] = my_obj.characters.everyItem()[prop_list[i]]; } return my_data; } ////////////////////////////////////////////my_objに文字数分の文字属性prop_objをセット(復帰)する。何も返さない function set_char_prop(my_obj, prop_obj) { for ( var p in prop_obj) { if (prop_obj.hasOwnProperty (p)) { //alert(p);// //alert(prop_obj[p]); for (var i = 0; i < my_obj.characters.length; i++) {//セットするときは1文字づつ my_obj.characters[i][p] = prop_obj[p][i]; } } } } ////////////////////////////////////////////配列aryの各々の要素にnを加算。要素が数値であることを期待 function add_each_number(ary, n) { for (var i = 0; i < ary.length; i++) { ary[i] += n; } return ary } ////////////////////////////////////////////カーニングと文字ツメと変形 //最初に約物のカーニングを試す。約物のカーニングで収拾できなければ文字ツメ //次に文字ツメをmy_tsume_limit_numになるまで試してみる。文字ツメで収拾できなければ文字変形へ //my_target_obj(テキストオブジェクト)を、最大my_scale_limit_num(%)まで変形して、my_line_limit_num(行)以内に収める var my_func = function set_tsume_scale(args) { var my_target_obj = args[0]; var my_kerning_var = args[1]; var my_tsume_limit_num = args[2]; var my_line_limit_num = args[3]; var my_scale_limit_num =args[4]; if (my_target_obj.lines.length <= my_line_limit_num) {return 1;}//選択行数が指定行数以下ならなにもしない var HorV = my_target_obj.parentStory.storyPreferences.storyOrientation == StoryHorizontalOrVertical.HORIZONTAL ? 'horizontalScale':'verticalScale';//my_target_objは縦組みか横組みか。HorVはStrings var tmp_tsume_obj = get_char_prop(my_target_obj, ["tsume"]);//文字ツメのオブジェクト var tmp_HorV_obj = get_char_prop(my_target_obj, [HorV]);//変形率のオブジェクト。 ディープコピーするのめんどいので、2回つくることにした。 //約物カーニング if (my_kerning_var !== 0) { kerning_yakumono(my_target_obj, my_kerning_var); my_target_obj.recompose();//文字列の再描画 if (my_target_obj.lines.length === my_line_limit_num) {return 1;}//収拾したらreturn } //ツメ var tmp_tsume_list = tmp_tsume_obj["tsume"]; //var tmp_tsume_max =Math.max.apply(null, tmp_tsume_list);//現在のツメ量の最大値 //myerror(tmp_tsume_list); while (my_target_obj.lines.length > my_line_limit_num){ if (my_tsume_limit_num === 0) {break}//文字ツメはやらない if (Math.max.apply(null, tmp_tsume_list) > my_tsume_limit_num) {break}//現在のツメ量の最大値がリミットを超えたら、ツメで調整をあきらめてbreak tmp_tsume_list = add_each_number(tmp_tsume_list, 0.01);//各文字のツメを1%づつ加算 set_char_prop(my_target_obj, tmp_tsume_obj);//ツメを実行 my_target_obj.recompose();//文字列の再描画 if (my_target_obj.lines.length === my_line_limit_num) {return 1;}//収拾したらreturn } //変形しない設定になっている。行ツメは成功していない if ((my_scale_limit_num ===0) && (my_target_obj.lines.length > my_line_limit_num)){ return ("ユーザー設定により、行の変形をおこないませんでした。\n設定:my_scale_limit =0"); } //変形 var tmp_scale_list = tmp_HorV_obj[HorV]; while (my_target_obj.lines.length > my_line_limit_num){ tmp_scale_list = add_each_number(tmp_scale_list, -1);//各文字の変形率を1%づつ減算 set_char_prop(my_target_obj, tmp_HorV_obj);//各文字の変形を実行 my_target_obj.recompose();//文字列の再描画 if (my_target_obj.lines.length === my_line_limit_num) {return 1;}//収拾したらreturn if (my_target_obj[HorV] < my_scale_limit_num) {//変形限界を超えてしまったら return ("変形限界の設定値" + my_scale_limit_num + "%を超えても" + my_line_limit_num +"行に収まりませんでした。"); } } } ////////////////////////////////////////////実行処理 function main() { if (app.documents.length == 0) {myerror("ドキュメントが開かれていません")} var my_document = app.documents[0]; if (my_document.selection.length !== 1) {myerror("テキストを一カ所だけ選択してください")} var my_selection = my_document.selection[0]; var my_class =my_selection.reflect.name; if (my_class === "InsertionPoint") { my_selection = my_selection.paragraphs[0]; } else { if (my_selection.paragraphs.length > 1) {myerror("段落をまたいで処理できません")} my_class = "Text, TextColumn, Story, Paragraph, Line, Word, Character, TextStyleRange".match(my_class); if (my_class === null) {myerror("テキストを選択してください")} } //my_line_limitに-1が指定されていた if (my_line_limit === -1) { my_line_limit = my_selection.lines.length - 1; if(my_line_limit < 1) {myerror("設定my_line_limitが不正です")}//1行以上は詰められないので終了 } //文字ツメ量は1/100で指定 if (my_tsume_limit <= 0) { my_tsume_limit = 0; } else if (my_tsume_limit > 100) { my_tsume_limit = 1; } else { my_tsume_limit = my_tsume_limit / 100; } //処理 var mess = app.doScript(my_func, ScriptLanguage.JAVASCRIPT, [my_selection, kerning_var, my_tsume_limit, my_line_limit, my_scale_limit], UndoModes.FAST_ENTIRE_SCRIPT, 'MyUndo'); //文字列のメッセージが返ってきたら、失敗したので復元しろって合図 if (typeof mess === "string") { my_document.undo(); myerror(mess); } } main();