handleGlue (v.1.3.0) の日本語説明

Adobe Exchange に handleGlue というイラレ用エクステンションを載せて頂いているんですが、掲載ページの機能説明とかが基本英語なので、日本語の説明をこちらに載せておこうと思います。

掲載ページ: https://exchange.adobe.com/creativecloud.details.1648.html

以下の動画を見て頂ければ、どんなものかだいたい分かると思いますが、以降の説明を読んで頂くとオプションの機能や制限などもより分かって頂けると思います。

現バージョンでは、システム言語が日本語の場合はUIが日本語になります。

f:id:shspage:20200309211733j:plain

機能

選択オブジェクトの中のオープンパスの、選択されている端点をその他のパスに接する位置に移動します。その際、ハンドルの傾きが接点での接線の傾きに等しくなるように調整します。

使い方

移動したいアンカーポイント(端点)と、移動先になるパスを選択し、Runボタンを押してください。

オプション

最近点(ラジオボタン

選択されているアンカーポイントを移動先の最も近い位置に移動します。

角度(ラジオボタン

選択されているアンカーポイントを、ハンドルの傾きが移動先の接点での接線の傾きと同じになるような位置に移動します。

一括(チェックボックス

有効な場合、選択オブジェクトの中の全てのオープンパスの選択端点が移動対象になります。選択パスが全てオープンパスの場合は、最背面のパスが移動先になります。 無効の場合、最前面のオープンパスのみが移動対象になります。

接点にアンカー追加(チェックボックス

有効な場合、移動先の接点の箇所にアンカーポイントを追加します。

パス全体を移動(チェックボックス

有効な場合、選択アンカーと一緒にパス全体が移動されます。両端が選択されている場合は、両端の移動量の平均値がその他のアンカーポイントに適用されます。

曲率を調整(チェックボックス

有効な場合、移動元パスの選択端点での曲率が、移動先の接点での曲率に合うように、移動元のハンドルの長さの調整を試みます。結果のパスは見栄え良くフィットすることもあれば、大きく形が変わってしまうこともあります。 接点が直線上になるときや、移動元にハンドルがない場合、調整は行われません。調整に失敗した場合はメッセージを表示します。調整量の上限の目安はスクリプト中で設定されています(MAX_CURVATURE_ADJUST_RATIO)。

Undo(ボタン)

直前に実行した Run の前の状態への復元を試みます。 実際に行なっているのは、通常のUndoを行ってから、アンカーポイントの選択状態をRunの際に記憶したものに戻すことです。 ボタンを押した際の選択パスの数とそれぞれのアンカー数が直前のRunを実行したときと異なる場合は、メッセージを表示し、Undoを取り消します。 逆に同じであれば、選択パスがRun実行時と違っていてもUndoが行われます。 このとき、UndoされるのはRunの結果とは無関係の他の操作である場合もありえます(重要)。 という、不確かな機能のボタンなのですが、これで助かる場合もあるので設けています。

説明は以上です。

まだ発展途上のエクステンションではありますが、イラレで変な形を描きたい時にお役に立てれば幸いです。

正規表現で文字スタイル割り当て.jsx

先日、@jamierob さんとのやりとりの中で作ったスクリプトが自分にも便利でよく使っているので紹介しようと思います。

作ったと言っても、コアな部分は Adobeスクリプティングフォーラムの Select part of point text objects matching a regex expression で言及されていた pixxxel schubser さんのスクリプトで、私はUIをつけたりしただけです。

機能は選択されているテキストオブジェクトの内容を正規表現で検索して、一致した箇所に指定した文字スタイルを割り当てるというものです。

例えば画像のような設定で実行すると、テキストの行頭の数字を太字にできます。(Charcter Style 1 が太字のスタイル)

f:id:shspage:20181211201956p:plain

スクリプトでの文字スタイルの割り当てには、clearingOverrides というオプションがあり、これを有効にしないと文字スタイルが適用されない場合があります。 このオプションが何を意味するかは何となく分かるのですが、どういう時に有効/無効にする必要があるのか、私もよくわかっていません。よくわからないときは有効にしておけばよいものだと思います。

また、正規表現について、各テキストオブジェクトを順に処理するループの中で再定義しないとうまく動作しないようでした。これも実際どういう仕組みなのか、把握し切れていないのですが。

スクリプト@jamierob さんが以下で公開しています。 https://github.com/jamesw05/illustrator-shortcuts/blob/master/apply_Style_With_RegExp.jsx

現時点のバージョンのUIやメッセージを日本語にしたものを私のGistに置いておきます。 https://gist.github.com/shspage/82e70da926dc5c9bfdc591d1c4afb7d5

文字スタイルじゃなくて、書体とサイズを適用するようにしてもいいかなとも思いますが、UI 作るのが面倒だし、文字スタイルにしたほうが後から一括変更したい時などに融通も利くしなので、このままでもいいかなと思っています。 正直、このスクリプトを使うようになってから、文字スタイルをよく使うようになりました。

スクリプトでパステキストを扱う

Illustrator上で入力した文字(テキストオブジェクト)は以下の3種類のいずれかになります。

ポイントテキスト
エリアテキスト
パステキスト

f:id:shspage:20170514195339p:plain

先日、パステキストのパスを初めてJavaScriptで扱ってみたら 色々と発見などがあったので、記事にしたいと思います。

パステキストの判別

JavaScript でテキストオブジェクト(TextFrameItem)の種類を判別するには kind というプロパティを参照します。kind の値は上記の種別と対応した以下の3種類です。

TextType.POINTTEXT
TextType.AREATEXT
TextType.PATHTEXT

判別の処理は例えば以下のように行います。

// 選択オブジェクトがパステキストのときにメッセージを表示する。
var obj = app.activeDocument.selection[0];

if(obj.typename == "TextFrame"
   && obj.kind == TextType.PATHTEXT){
    // 処理
    alert("パステキストです");
}

パス上文字の始点と終点を取得する

パステキストで文字が沿っているパスの情報は、TextFrameItem の textPath というプロパティで取得できます。この値は TextPath オブジェクトです。

また、パス上での文字の始点・終点は、TextFrameItem の startTValue, endTValue から取得できます。

// 選択されているパステキストのstartTValue, endTValueを表示する。
var textFrame = app.activeDocument.selection[0];

alert("startTValue = " + textFrame.startTValue
      +"\rendTValue   = " + textFrame.endTValue);

f:id:shspage:20170514195537p:plain

~TValue( T の値 )という名前から想像できるように、この値はベジエ曲線のパラメーターに基づくものです。 *1

ベジエ曲線のパラメーターは2つのアンカー間の曲線上の位置によって 0~1 の値をとりますが、 ~TValue はこれに始点側アンカーのインデックスを足した値になっています。

例えば、パス上文字の始点がパスの1つ目と2つ目のアンカー の間にある場合、startTValueは 0~1 の間の値になり、 2つ目と3つ目のアンカーの間にある場合は 1~2 の間の値になります。 *2

…というのはオープンパスの場合で、 クローズパスの場合はもう少し考慮が必要な点があります。

クローズパスの場合

f:id:shspage:20170514195559p:plain

まず、上の図ではパスのアンカーは4つなので、 上記の考え方からすると startTValue と endTValue は 0~4 の間の値になりそうなんですが、 ここでの endTValue は 4.5 という値になっています。

文字がパスの始点(=終点)をまたいでいるので、 こうなるのだろうなという感じではありますが、 さらにこの文字の始点・終点を手作業で動かすと、 下の画像のようなおかしな値になります。

f:id:shspage:20170514195609p:plain

内部でどういう計算をしているのかわかりませんが、 この値から最初の画像のような素直な値を 取得するには、アンカーの数で割った余りを取得すればよいようです。 (次項の「注意が必要な点」も考慮してください。)

f:id:shspage:20170514195617p:plain

パス上文字の始点と終点を設定する

startTValue, endTValue は、適当な値を代入することで変更できます。

startTValue に 0、 endTValue に「アンカー数マイナス1」を設定すると、 パス上文字の範囲がパスの始点と終点になります。

注意が必要な点は、endTValue に startTValue より小さい値を設定するとエラー になることです。

前項のクローズパスでの性質を考慮して パステキスト (クローズパス)に startTValue, endTValue を設定する処理を function にすると以下のように書くことができます。

function setTValue(textFrame, startT, endT){
    var len = textFrame.textPath.pathPoints.length;
    startT %= len;
    endT   %= len;
    if(endT < startT){
       endT += len;
    }
    textFrame.startTValue = startT;
    textFrame.endTValue = endT;
}

スクリプトによるパステキストのパスの変更

TextPath は通常のパスと同じように pathPoints などの属性を持っているため、 スクリプトでアンカーやハンドルの位置や数を変えることができます。 (PathItem とはプロパティやメソッドが異なる部分もあります。)

スクリプトで TextPath の pathPoints を操作する場合に注意が必要な点は、 startTValue, endTValue の値が変わってくれないことです。 このため、処理によってアンカー数が変わる場合は、 これらの値の変更も必要になることがあります。

別に掲載 している「 円弧にする 」というスクリプトの中にこの位置の調整処理があります。 このスクリプトには下の画像のようにパステキストが沿うパスを 適当な円弧にする機能がありますが、 TextPath のアンカー数を変更し、パスの長さも変わるので、 文字の位置を再設定する必要があるのです。

f:id:shspage:20170514195649p:plain

処理はベジエ曲線に関する汎用的な操作(計算)の組み合わせです。 詳しくはここで書くと長くなるので、追って記事を作ろうと思いますが、 工程だけ順を追って書くと以下のようなことをしています。

1. パスの長さ ( L1 ) を算出する。
2. パスの始点から startTValue にあたるパス上の点までの長さ ( S1 ) を算出する。
3. L1 に対する S1 の割合 ( R ) を算出する。
4. パスを変更する。
5. 変更後のパスの長さ ( L2 ) を算出する。
6. L2 に割合 R を掛けた長さ ( S2 ) を算出する。
7. パスの始点からの長さが S2 になるパス上の点のパラメーターを算出する。
  パラメーターとアンカーのインデックスから startTValue が求められる。
8. startTValue を設定する。
(endTValue についても同様に行う。)

パスの長さを計算しているのは、TextPath に length というプロパティがないためです。

undoの問題

スクリプトで startTValue, endTValue を変更した場合、 スクリプト実行後に undo をしてもこれらが実行前の値に戻らないようです。

スクリプトでの変更は undo の対象になっていないのか、 内部的な仕組みはよくわかりませんが、

これについては今のところ以下のような手順で処理をして回避しています。

1. 元のパスを複製
2. 複製したパスを操作
3. 元のパスを削除

こうすると undo はパス自体の変更ではなく削除の undo になるので、 文字の位置は実行前の状態に戻ります。

文字を添わせる側を操作する

パステキストは手作業での操作により文字をパスの反対側に添わせることができますが、 このとき TextPath の polarity というプロパティの値が PolarityValues.NEGATIVE になります。 polarity の既定値は PolarityValues.POSITIVE です。

polarity はスクリプトで設定することもできます。

// パステキスト(文字は既定の側に沿う)を選択して実行すると、
// 文字がパスの反対側に沿う。
var textFrame = app.activeDocument.selection[0];
textFrame.textPath.polarity = PolarityValues.NEGATIVE;

f:id:shspage:20170514195813p:plain

polarity が NEGATIVE になると、パスの向き(PathPoint の順番)が逆になります。 このとき、startTValue と endTValue は元のパスの終点を 0 とした値となります。

とりあえず以上です

*1:ベジエ曲線のパラメーターについては追って記事にする予定です。

*2:1つ目のアンカーのインデックスが 0 になります。