ActiveScriptRubyIllustrator10

hs9587 2003/1/1-, 2005/4/10- (, 2008/3/23)

rdソース(memo.txt) with index.rb

ruby -r erb -e 'ERB.new($stdin.read).run' < memo.txt | ruby "C:\Program Files\ruby-1.8\bin\rd2.rb" -r rd/rd2html-ext-lib --native-inline --ref-extension --headline-title --head-element --with-part=head:head --with-css=hs9587.css > memo.html

2008/3/23

連絡事項: つづき は別で

全然更新していませんでした。その後別に書き始めました。こことは趣が異なり、まだまだ Ruby とプログラミング中心ですが、おいおい Illustrator系の話しにもなるでしょう。

2005/11/6

ちょっと音を鳴らす

また、Illustrator ではない話。

Windows環境で、ちょっと音を鳴らすにはどうしたら良いだろうか。 Illustrator の自動処理が終わったら、その時にちょっとチャイムを鳴らすなど。 コマンドラインや VBScriptで音を鳴らせるなら、Ruby からもそれを呼べばいいわけだ。

WIN32OLE.new('WScript.Shell').Run('sndrec32 /play /close "C:\WINNT\Media\ding.wav"', 0, true)

この辺りでは、大概 require済みと思うので、require 'win32ole' の行は省略。

sndrec32 とその呼び出しの解説

スクリプトからの音声起鳴は何処でも気に掛かるようです、マイクロソフトの 「Hey, Scripting Guy!」 にそういう QandA が挙がっていました。

あとは個々の記述について

midi とか mp3 とか

Scripting Guy の説明にもありましたが、 wavファイルより一般の音声ファイルにサウンドレコーダーは対応していません。 ウィンドウズメディアプレイヤー mplayer, mplayer2, wmplayer 等を探しましょう。

このメモの項目の一覧

2005/7/2

InputBox (VBS) その2

前回 InputBox (VBS) によって入力ダイアローグを出すことを考えたが、その続き。

相変わらず Illustrator ではない話。というか Ruby の話ですらないかもしれない。

Tempfile

一時作成する .vbsファイルの取り扱い、やっぱり Tempfile を使おう。 そうすれば既存チェックとか File.Delete とか余計な心配しなくていいし。

require 'tempfile' 
default = 'qwertyuiop' 
vbsbasename = 'vbsinputbox' 
tmpvbs = Tempfile.new(vbsbasename) 
  tmpvbs.puts %Q[WScript.Echo InputBox("message", "title", "#{default}")] 
tmpvbs.close(false) 
  input = `cscript #{tmpvbs.path} //E:VBScript //nologo` 
tmpvbs.close(true) 

require 'win32ole' 
WIN32OLE.new('WScript.Shell').Popup(input.to_s) 

WshShell.Exec

前段ではバッククォート(``)で実行したが、 WshScriptExecオブジェクト で実行するとその部分はこのようになる。

exec = wsh.Exec("cscript #{tmpvbs.path} //E:VBScript //nologo") 
sleep 0.1 while exec.Status == 0 
input = exec.StdOut.ReadAll() 

同期実行のためには、その Statusプロパティ を見ていてやればいい。 結果の標準出力は StdOutプロパティ から。

後ろのコマンドプロンプト窓

これを消すのは難しい。

WshShell.Run なら Window最小化の指定は出来るが値を返す手段がない。 その IntWindowStyle にしたところで、 2、6 とか指定したとき、 cscript窓(コマンドプロンプト窓)だけじゃなくて所要の InputBoxダイアローグまで最小化してしまう。

もう諦めるしかないのか。

IntWindowStyle 内容

2005/6/26

InputBox (VBS)

さて、メッセージボックスを出すことは 出来ようなった。 Yes/No/Cancel やその他の選択の返り値も得ることが出来る。

ということで、簡単なテキストの入力ダイアローグが欲しい。 勿論、前述の vruby でも、他の GUIツールキットでも、いろいろ出来るわけだが、 そこまで真面目なことをしなくてもなんとかならないだろうか。

VBScript には InputBox というのがあるので、それでなんとか。

default = 'qwertyuiop'
vbsfname = 'inputbox.vbs'
raise "A file '#{vbsfname}' already exists." if FileTest.exist?(vbsfname)
  File.open(vbsfname, 'w'){ |f| f.puts %Q[WScript.Echo InputBox("message", "title", "#{default}")] }
  value = `cscript #{vbsfname}`
File.delete(vbsfname)
# input = value.split("\n")[3].to_s
input = /\n\n/.match(value).post_match

require 'win32ole'
WIN32OLE.new('WScript.Shell').Popup(input)

RHG読書会::東京 Sound Stage 「鈴木さんを囲む会 2005-05-14 (土)」(二次会) の項にも同内容を書いています、ご参考まで。

メッセージボックス (再び)

前にもメッセージボックスの事は書いた。 vruby (VisualuRuby) を使うのであった。

実は、WSH(WindowsScriptHost) の WScript.Shell オブジェクトの Popup メソッドでも同じことが出来る。

require 'win32ole'
wsh = WIN32OLE.new('WScript.Shell')
yes_no = wsh.Popup('メッセージ', 0, 'Title', 4 + 32 + 0x40000)
case yes_no
  when 6
    wsh.Popup('Yes', 0, 'Title', 0 + 64 + 0x40000)
  when 7
    wsh.Popup('No' , 0, 'Title', 0 + 16 + 0x40000)
end # case yes_no

引数と返り値、アイコンなどについては、 既述 WConstの値と返り値アイコンと規定値 と同じ。

この辺りでは大概において Win32OLEライブラリは require済みと思うので、 メッセージダイアログを出すだけなら、 そして WScript.Shellオブジェクトを使い捨てにするなら、 次行程度いでも良いかもしれない。

WIN32OLE.new('WScript.Shell').Popup('メッセージ', 0, 'Title', 0 + 48 + 0x40000)

JavaScript の alertメソッド

更に、DoJavaScript を使って JavaScript の alertメソッドを呼ぶという手もある。 まあ、alert自体の返り値がないのは不便なので、 わざわざこちらを使うケースは少ないでしょう。

# illu は llustrator の Applicationオブジェクト本体
illu.DoJavaScript('alert("メッセージ");')

既報、 「Rubyist Magazine 0006号」 にも同じことをまとめています。ご参考まで。

2005/6/18

GroupItem の解除

このあいだ、GroupItem への集積 については書いた、 今度はそのグループアイテムを解除することを考えよう。 ただ残念なことに、 オブジェクト - メニュー の [グループ解除(U) Ctrl + Shift + G] に相当するものはない。 グループの構成要素をチマチマ一つずつ操作していかねばならない。

# grp はなんか GroupItem
grp.PageItems.Count.downto(1) do |i|
  grp.PageItems.item(i).MoveToBeginning(grp.Layer)
end 

或いは、

grp.PageItems.item(1).MoveToEnd(grp.Layer) while grp.PageItems.Count>0

ただ、グループ解除後の居場所を考えると前者の方が良い様に思う

PageItem

そのグループ (GroupItem) にどんなものが入っているかは分からないので、 描画オブジェクトを統一的に取り扱う PageItem のコレクションを使う。 PageItemがもっと多態的だと使い出があるのに。 まあ今は MoveTo云々があるので善しとしよう。

逆順

.item() でのインデックス指定は重なりの上からで、 変更があった場合はその場で繰り上がったり下がったりする。 WIN32OLEオブジェクトの提供する each での実行中にも番号がつけ変わってくので、 コレクション.each でこの作業を実行すると変なことになる。

奇数番目だけ消えて、偶数番目が残る。 each が別にインデックスエラーにならないのは、ちゃんと動的に Count をかぞえてる訳だが、 エラーが起こらないだけになんとも変な感じに思えたりする。

そういうわけなので、逆順に実行するか、それとも最初の要素をずっと見続けるようにする。

重なり順の保存

重なり順を保存するため、逆順なら MoveToBeginning を使う。 最初の要素だけ見るというのなら、MoveToEnd を使うことになる。

いずれにせよ、レイヤーの先頭か末尾かに移動してしまう。 他の描画オブジェクトとの関係で言えば、 重なり順のその場でグループ解除できるわけではない。

また、その際の行き先レイヤーだが、 上記では該当グループ自体の所属するレイヤーとした。 これはアクティヴレイヤー (doc.ActiveLayer) 宛てとしても良いかもしれない。

重なり順とインデックス

先にも少し言及したが、それぞれのコレクションでの、 添数付けは、描画オブジェクトの重なり順になっている。

一番上にあるのが .item(1)、一番下になるのが .item(…Items.Count)、 例えばレイヤーなら。

  1. doc.Layers.item(1)
  2. doc.Layers.item(2)
  3. ……
  4. doc.Layers.item(doc.Layers.Index(doc.ActiveLayer))
  5. ……
  6. doc.Layers.item(doc.Layers.Count)

2005/5/13

Rubyist Magazine 0006号

Ruby のウェブマガジン「Rubyist Magazine 0006号」 <URL:http://jp.rubyist.net/magazine/?0006> に、記事を書かせてもらいました。

よければ見てやって下さい。

2005/4/10

ご挨拶 (2005-04-10)

しばらく更新すべき内容が無かったのですが、またいくつかの事例に出会ったので、少し案件を追加します。

その間に、 Adobe Illustrator は CS版にバージョンアップしましたが、僕は 10.0.3 の儘です。 このメモでは Illustrator 10 のまま話を続けます。

一方、Ruby1.8 になりました。こちらは ActiveScriptRuby を使っていて、1.8にバージョンアップしています。とはいっても、 Ruby自体に関わるような記述は余り多くないので、さほど気にする事は無いでしょう。

さらに、Illustratorの自動化という話題も世上に散見されるようになりました。 嬉しいことです。

Illustrator10自動化作戦with JavaScript
古籏 一浩 (著); 毎日コミュニケーションズ ; ISBN: 4839913544 ; (2004/01)
紙の本です、書店の本棚でこれを見つけたときは感動しました。
IllustratorCS自動化作戦with JavaScript
<URL:http://www.openspc2.org/book/IllustratorCS/>
そのCS版、出版はされないそうです。 同サイトには、Photoshop, InDesign の自動化の話などもあります
イラレで便利 for Adobe Illustrator
<URL:http://park17.wakwak.com/~ddpp/6ot/js_ill/index.html>
イラストレーターのクラタさんのところです。JavaScript の公開もしています、 イラストレーションの実践で鍛えられた事柄群です。

GroupItem への集積

各種グラフィックItemをグループ化して GroupItem を得る事を考えよう。

Cut (Copy) & Paste

どうだろうか。これで良いようなものだが、 Illustrator自体の編集メニューの「カット(コピー)」、「ペースト」(Ctrl+X,C,V) と同じで、自分の位置を忘れてしまうのが不便だ。

スクリプトなんだから事前に Positionメソッドで対象の位置を憶えておけば良い訳だが、 それもなんか迂遠だ。

# doc はなんかIllustrator.Documentオブジェクト
grp = doc.GroupItems.Add
path = doc.PathItems.item(1)
pos = path.Position
path.Cut
grp.Paste
pasted_path = grp.PathItems.item(1)
pasted_path.Position = pos

MoveToBeginning, MoveToEnd

Illustrator編集メニューの「前面へペースト」「背面へペースト」(Ctrl+F,B)に 相当するのが両メソッドである。

PathItem
MoveToBeginning(Document/Layer/GroupItem)
Nothing
Move the PathItem to the front of a container.
MoveToEnd(Document/Layer/GroupItem)
Nothing
Move the PathItem to the end of a container.

他にも個々のグラフィックItemにはこのメソッドがある。 場所がその儘なのは非常に良い。 前記のように一度座標にしておいて代入し直すのと違い、原理的に全く同じ場所なのは非常に良い。 ただ、カット&ペーストしか出来ない(もとのを残せない) のがちょっと限界かな。

# doc はなんかIllustrator.Documentオブジェクト
grp = doc.GroupItems.Add
path = doc.PathItems.item(1)
path.MoveToBegining(grp)

2003/10/18

ドーナツ型に中を抜く

ドーナツ型、というか Pierced disk 型に、真中が抜けていて回りに帯状にものがある状態。 或は、額縁上のオブジェクト。

それには、 Illustrator の使い方として、 パスファイダパレットの「前面オブジェクトで型抜き」 を用いる。

それをアクションに登録しておいて DoScriptで呼び出す。 出来あがりは複合パス CompoundPathItem になるので、扱いには注意が必要。

2003/10/11

PathPoint.Selected の値

他の多くのオブジェクトの Selectedプロパティとは違って、 PathPointの Selectedプロパティは真偽値ではなく、AiPathPointSelection enumeration という 専用の値になっていて、端点(アンカーポイント と コントロール ポイント)の選択の様子を表す。

PathPoint Properties
Selected
AiPathPointSelection enumeration
Are points of this path point selected? If so, which one(s)?.
AiPathPointSelection
Which points, if any, of a path point are selected?

enumerarion (alphabetical oreder)

aiAnchorPoint    : 2
aiLeftDirection  : 3
aiLeftRightPoint : 5
aiNoSelection    : 1
aiRightDirection : 4

enumerarion (valuation oreder)

aiNoSelection    : 1
aiAnchorPoint    : 2
aiLeftDirection  : 3
aiRightDirection : 4
aiLeftRightPoint : 5

選択の状況は名前の通りで、 非選択、 アンカーポイントのみ選択、 アンカーポイントに加えて左右のコントロール(片方or双方)も選択、 という状態を示す。 コントロールポイントだけの選択状態がないのは、もともとの Illustrator の動作を反映している。

2003/10/5

DoScript と Selection

Illustrator での作業では、下記 矢印を引くパスファインダで交点を求める の様に application.DoScript でアクション(メニュー)を呼んでやらないといけないことがいろいろ出てきそうだ。 その際には、アクション類は選択されたオブジェクトに作用する事も多いので、 アクティブドキュメントの Selectionプロパティとのやり取りも重要になってくるだろう。

  1. 選択オブジェクトの整理
    1. 関係無いオブジェクトの選択を解除し
    2. 所要のオブジェクトを選択する
  2. DoScript でアクションを実行
  3. 終るのを待って
  4. また選択オブジェクトの整理

終るのを待って

アクションの実行には結構時間がかかる事があるので、ここできちんと待たないと 期待する動作をしないことになる。 アクションの実行が終る前に必要なオブジェクトの選択を解除してしまってはいけない。 それには application.ActionIsRunning でチェックする。

sleep 0.23 while illu.ActionIsRunning
Application Properties
ActionIsRunning
R/O Boolean
Is an action still running?

選択オブジェクトの整理

document.Selection と application.Selection に書いた。 要はアクティブドキュメントの Selectionプロパティを空配列にする。

To deselect all objects in the current document, simply set the selection to Empty

( Array.new() を代入する。nilの代入で済む事もある )

DoScript でアクションを実行

application.DoScript でアクションを実行する。

DoScript(action As String, from As String, [dialogs As Boolean])
  Plays an action from the Actions palette.

矢印を引くパスファインダで交点を求める など参照。 そういえば、矢印を引く の時のサンプルの動作が不安定だったのは、 この注意事項を気にしていなかったせいかもしれない。

2003/10/1

document.Selection と application.Selection

application.Selection は、アクティブドキュメントの選択オブジェクトだとという事だが、 その document.Selection とは、少し挙動が違う。選択解除するのに nil の代入が効かない。

require 'win32ole'

$illu = WIN32OLE.connect('Illustrator.Application')
$doc = $illu::Documents.Add(AiEnum::AiDocumentCMYKColor)
$path = $doc.PathItems.Add
# <!-- snip path-lines -->

def testSelection(str)
  obj = eval(str)
  if obj
    puts(str + '.size = ' + obj.size.to_s)
  else
    puts(str + ' is false.')
  end
end # def testSelection(str)

def run(str)
  eval(str) ; puts str
end # def run(str)

puts "\nnil\n"                       # => nil
testSelection('$illu.Selection')     # => $illu.Selection is false.
testSelection('$doc.Selection')      # => $doc.Selection is false.

puts "\napplication.Selection"       # => application.Selection
run('$path.Selected = true')         # => $path.Selected = true
testSelection('$illu.Selection')     # => $illu.Selection.size = 1

run('$illu.Selection = nil')         # => $illu.Selection = nil     # nil
testSelection('$illu.Selection')     # => $illu.Selection.size = 1  # but not nil
testSelection('$doc.Selection')      # => $doc.Selection.size = 1

puts "\ndocument.Selection"          # => document.Selection
run('$path.Selected = true')         # => $path.Selected = true
testSelection('$doc.Selection')      # => $doc.Selection.size = 1

run('$doc.Selection = nil')          # => $doc.Selection = nil
testSelection('$doc.Selection')      # => $doc.Selection is false.


puts "\nArray.new()\n"               # => Array.new()
testSelection('$illu.Selection')     # => $illu.Selection is false.
testSelection('$doc.Selection')      # => $doc.Selection is false.

puts "\napplication.Selection"       # => application.Selection
run('$path.Selected = true')         # => $path.Selected = true
testSelection('$illu.Selection')     # => $illu.Selection.size = 1

run('$illu.Selection = Array.new()') # => $illu.Selection = Array.new()
testSelection('$illu.Selection')     # => $illu.Selection is false.

puts "\ndocument.Selection"          # => document.Selection
run('$path.Selected = true')         # => $path.Selected = true
testSelection('$doc.Selection')      # => $doc.Selection.size = 1

run('$doc.Selection = Array.new()')  # => $doc.Selection = Array.new()
testSelection('$doc.Selection')      # => $doc.Selection is false.

カレントのドキュメント ActiveDocument の全ての選択を解除しようとするとき、 application.Selection へ nil を代入しても選択解除なされないが、 document.Selection への nil の代入では選択解除となる。 何れにせよ、空Array を代入すれば選択解除できる。

application.ActiveDocument.Selection を使うなり、 いつでも Array.new() を代入するようにしたりが無難。

Application Properties
Selection
Variant Array (of objects)
All of the currently selected objects in the active (frontmost) document. See note for more information.
document.Selection

2003/9/15

Document.Selection の挙動

Document.Selection は全ての選択されたオブジェクトの配列とされる。

Document Properties
Selection
Variant Array (of objects)
The array of references to the objects in this document's current selection.

それで、何も選択されていない時は何も返らない (nilが返る) 事に注意。 Document.Selection の呼出し自体には成功するが、size 零の配列では無くて nil が結果となる。

require 'win32ole'
require 'vr/vruby'
title = 'IllustRuby'
illu = WIN32OLE.connect('Illustrator.Application')

begin
  doc = illu.ActiveDocument
#rescue WIN32OLERuntimeError => err
rescue => err
  VRLocalScreen.newform.messageBox(err,title, 0 + 48 + 0x40000)
  # MB_OK = 0, MB_ICONWARNING = 48, MB_TOPMOST = 0x40000  
  abort
end

selected = doc.Selection

if selected then
  num = selected.size
  msghead = (num==1)?'One item is':"#{num} items are"
else
  msghead = "#{selected.type} are" # NilClass
end # if selected then

msg = "#{msghead} selected \nin the document `#{doc.Name}'." 
VRLocalScreen.newform.messageBox(msg,title, 0 + 64 + 0x40000)
# MB_OK = 0, MB_ICONINFORMATION = 64, MB_TOPMOST = 0x40000  

2003/9/12

Matrixの作用

なんかマトリックスの作用が最初思っててた感じと違って、でもやってみれば当たり前の様な感じでもある。 ちゃんとまとめてないし、サンプルソースも用意できないけど様子だけ標語的に述べる。

2003/9/7

矢印を引く

矢印を引きたい、しかしそんなオブジェクト、メソッドはスクリプトにはない、 パスファインダで交点を求める の時と同じ様に、アクションを定義しておいて Application.DoScript 。

矢印をひく

そもそも Illustrator で矢印を引くこと自体 FAQ な らしい。

  1. 線を引く、直線ツールでも何でもいいが閉パスは駄目、必ずオープンパス
  2. 線を書いた直後はそのパスと端点はみんな選択状態になってる
  3. [フィルタ]メニュー - [スタイライズ] - [矢印にする] を実行
  4. 「矢印にする」ダイアローグが開くので、始点終点の矢のかたちを 27種類のなかから選び、 拡大・縮小の割合を入力して「OK」
  5. パスはグループになり、その中には最初のパスと矢先(元)(鏃矢柄)図形のパスがある
  6. 矢印の先端は最初のパスの端点より先になるのには注意する事、 始めにパスを描く時はその分を見込んでおかなくてはならない。

アクションの定義

  1. 線を引いて選択状態にしておく
  2. 適当なアクションのセットで「 新規にアクションを作成」
  3. 上記のようにして矢印をひく
  4. 「再生/記録を中止」
  5. アクションメニューからアクションの保存をしたほうが良いでしょう。

スクリプトからの呼出

path = doc.PathItems.Add

a = path.PathPoints.Add
b = path.PathPoints.Add

a.Anchor = [100, 400]
a.LeftDirection  = a.Anchor
a.RightDirection = a.Anchor
a.Selected = false

b.Anchor = [240, 300]
b.LeftDirection  = b.Anchor
b.RightDirection = b.Anchor
b.Selected = true

# 各頂点(始終点)も選択しとかないといけない
# 終点(アクションではこっちに矢印をつける様に定義した)だけ選択しといても良いみたい
# まあ、両端(と途中の点)を選択しておくのが無難

path.Closed = false
path.Selected = true

illu.DoScript('myArrow', 'myActions')

doc.Selection.each do |item|
  item.Selected = false
end # doc.Selection.each do |item|

最後のブロックは、作った矢印グループを選択解除する為のもの。 ここでなにか変数に代入しておけば今作った矢印をあとから参照できる。

ちなみに、端点を Select しておかないと、 “オブジェクト「矢印にする」は現在使用できません” ダイアローグがでて矢印がひけなかったりする事がある。 またそのダイアローグでキャンセルしたりすると、 アクションパレットにへんなアクションの残骸が残ったりする。

2003/7/31, /8/28

Colorオブジェクトの生成と代入

直接生成すべきオブジェクトとして挙げたものの中の Color系オブジェクトは、 では実際どのように生成し、代入すべきなのだろうか。

AiColor enumeration
aiColorNone =		0
aiColorCMYK =		1
aiColorGray =		2
aiColorRGB =		3
aiColorSpot =		4
aiColorPattern =	5
aiColorGradient =	6
AiDocumentColorSpace
aiDocumentRGBColor =	1
aiDocumentCMYKColor =	2

試行

それでは Color を作ろう
require 'win32ole'

# color = WIN32OLE.new('Illustrator::Color') # 'new': Unknown OLE server : `Illustrator::Color' (WIN32OLERuntimeError)
color = WIN32OLE.new('Illustrator.Color')
puts "N: color.Color = #{color.Color}" # 0 # aiColorNone

作成されただけの Colorオブジェクトの色型は無名 aiColorNone である。

win32ole('::')

そういえば、win32ole的には、'::'は使えないんだね、'.'でないと。( 無効なクラス文字列です。)

<Illustrator.Color> .Color に直接代入する事は出来ない
begin
  color.Color = 2
rescue WIN32OLERuntimeError
=begin
in 'method_missing':  (WIN32OLERuntimeError)
    OLE error code:0 in <Unknown>
      <No Description>
    HRESULT error code:0x8002000e
      パラメータの数が無効です。
=end
ensure
  puts "N|2: color.Color = #{color.Color}" # 0 # aiColorNone
end

Colorオブジェクトの Colorプロパティは R/O ( Read Only ) なので、直接代入する事は出来ない。 WIN32OLERuntimeError になってしまう。

<Illustrator.Color> .Color ではないプロパティへのアクセス

.Color ではないプロパティへのアクセスも難しい。 相当する色空間プロパティに、別途作った CMYKColor や GrayColor を代入する事で item のカラーを設定する。 代入、設定されていない色系プロパティへのアクセスは失敗する。(初めは不定だが、Documentの色空間や Grayを期待しても良かろう)

そして CMYKDocumentを用意する
illu = WIN32OLE.connect('Illustrator.Application')

module AiEnum; end
WIN32OLE::const_load(illu, AiEnum) 

doc = illu::Documents.Add(AiEnum::AiDocumentCMYKColor)

path = doc.PathItems.Add
Gray
gray = WIN32OLE.new('Illustrator.GrayColor')
gray.Gray = 40 # 40%
color.Gray = gray
path.StrokeColor = color

成功

パスはグレーになる、

CMYK
cmyk = WIN32OLE.new('Illustrator.CMYKColor')
cmyk.Cyan, cmyk.Magenta, cmyk.Yellow, cmyk.Black = 0,30,0,0 # 薄桃色
color.CMYK = cmyk
path.FillColor = color

成功

Fill は CMYK(薄桃色)に満たされる。

RGB
rgb = WIN32OLE.new('Illustrator.CMYKColor')
rgb.Red, rgb.Green, rgb.Blue = 0,0,40 # 淡青色
color.RGB = rgb
path.StrokeColor = color

失敗 -> なんかCMYK(不定色)になってる

もともとの Dobumentの色空間に反するものは出来ないようである。 しかし、Grayだったものは自分の色空間の天然色にはなるようだ、そして、色値は不定値になる。

整理(推定)

2003/6/15

外部ファイル

余所の画像ファイルを持ってくるにはどうしたら良いのだろうか。

GroupItems.CreateFromFile(imageFile As String)
GroupItem objecr, Places an external vector art file as a GroupItem in the document.
PlacedItem.File
String, The file containing the placed object. PlacedItems work only with embedded vector files: EPS, PDF, SVG and embedded AI.
RasterItem.File
String, The file containing the RasterItem, if it is stored externally.

と言う事だ、各 Fileプロパティに所要の画像ファイル名を代入してしまえば良い。

require 'win32ole'
illu = WIN32OLE.connect('Illustrator.Application')
doc = illu.Documents.Add

raster = doc.RasterItems.Add
# raster.File = "C:\ruby\illustrator\fromfile\door.jpg" # \のエスケープが難しいので
raster.File = 'C:\ruby\illustrator\fromfile\door.jpg'   # "文字列ではなく、'文字列が楽

raster.Resize(13,13) # 100% # RasterItem.Resize は 100%が基準の百分率値

raster.Position = [200,500] # Resize、Rotate、Transform(transformationMatrix) は兎も角、
# 移動は Translate するより Positionを直接弄る方が見易い (他のオプションが必要無い時は)。

ベクトル系の画像は PlacedItemとして、そうでない画像は RasterItemとして取り込めば良さそうだ。 ファイル名の指定には、\のエスケープが大変なので、"文字列" ではなくて '文字列' の方が分かり易い。

外部ファイルの埋込み

このようにして呼んで来た画像をファイルに埋込むのかどうかは、この呼出の時に設定する物ではない。 saveas なり何なりで全体を保存するときに指定するのである。

Document.SaveAs([saveIn As String], [options As EPSSaveOptions/IllustratorSaveOptions/PDFSaveOptions])
Nothing, Saves the document in the specified file as an Illustrator, EPS, or PDF file.
IllustraorSaveOptions.EmbedLinkedFiles
Boolean, Are linked image files to be included in the saved document. Only valid for SaveOptions that specify an Illustrator compatibility of version 7 or later.

Colorオブジェクト他

各種 Colorオブジェクトやオプション類などで、Illustrator.Applicationから生成するのではなく、 直接生成すべきオブジェクト。 マニュアルの中ほど、オブジェクトの生成に関する注意書きの所にその様な記述があった。

<URL:http://partners.adobe.com/asn/developer/scripting/docs/IllustratorScriptingGuide.pdf#Referencing and creating objects in Visual Basic>

直接生成すべきオブジェクト

例えば

require 'win32ole'
color = WIN32OLE.new('Illustrator.RGBColor')
color.Red, color.Green, color.Blue = 255,0,0  # 真っ赤

Illustrator起動中とはいえ 其々のオブジェクトは個別には稼動しているわけではないので、 connect ではなくて new で生成する。 Illustrator起動中で無いとIllustreatorの起動をはじめて

(WIN32OLERuntimeError)
   HRESULT error code:0x80080005
     サーバーの実行に失敗しました。

とエラーになるのは、Application本体の時と同様。

メッセージボックスアイコン

相変わらず Illustrator ではない話。

アイコンと規定値

前述の様にすればメッセージボックスを表示出来た。 その際、メッセージ本文の左に、 丸く赤い所に白抜き×、黄色い三角にビックリ、青いはてな、青いiの字 といったアイコンを出したい。 また、 「YES」「NO」「CANCEL」とか釦が複数出るときは、デフォルトで選択状態になってる釦を指定してやりたい。

アイコン
MB_ICONERROR            = 16   # 丸く赤い所に白抜き×
MB_ICONSTOP             = 16   #      同上
MB_ICONHAND             = 16   #      同上
MB_ICONQUESTION         = 32   # 白い吹出しの中に青い ?
MB_ICONEXCLAMATION      = 48   # 黄色い三角の中に !
MB_ICONWARNING          = 0x30 #      同上
MB_ICONINFORMATION      = 64   # 白い吹出しの中に青く i の字
MB_ICONASTERISK         = 64   #      同上
MB_USERICON             = 128  # (ユーザアイコンの指定法不明)
デフォルト選択
MB_DEFBUTTON1           = 0
MB_DEFBUTTON2           = 256
MB_DEFBUTTON3           = 512
MB_DEFBUTTON4           = 0x300 # 768
MB_TOPMOST
MB_TOPMOST              = 0x40000 # 262144

例えば

VRLocalScreen.newform.messageBox('message', 'title', 3 + 32 + 512) 
# 3 = WConst::MB_YESNOCANCEL
# 32 = WConst::MB_ICONQUESTION 
# 512 = WConst::MB_WConst::MB_

こうすると、はてなアイコンが付いて、3番目の釦(キャンセル)が最初にフォーカスしている。 更に、MB_TOPMOST を加算しておくと、ボックスは常に最前面に表示されるようになる。

他にも contrib/msgboxconst.rb な値はあるので、いろいろ機能があるのでしょう。 その辺は Windows のダイアローグの説明をみれば色々わかるのだと思います。

2003/6/6

メッセージボックス

スクリプトメニューから_2 [DOS窓のない呼出] とすると、 今度はメッセージダイアローグを出したくなる。 それには vruby ( ActiveScriptRuby には最初から入っている) を使う事が出来る。

vrubyでメッセージボックス

この節は Illustrator ではなくて vruby (VisualuRuby計画(仮称)) のことになります。 しかも、余り(到底)正当ではない使い方です。

最小限のスクリプト
require 'vr/vruby'
VRLocalScreen.newform.messageBox('message', 'title', 0) # 0 = WConst::MB_OK

第1項 'message' を表示するダイアローグである、第2項 'title' は Windowタイトルになる。

本来 VRLocalScreen.newform は新たにフォームオブジェクトを作成するので、 それに各種 Widget を配置して行くのが普通の流れだろう。 それらの Widget の機能と操作によっては Windows のメッセージボックスを呼び出す事もあるわけだ、 その メッセージボックス だけを用いる。

YesNoで動作を変える
require 'win32ole'
require 'vr/vruby'

frm = VRLocalScreen.newform
msg = "Hello, rubyillustrator is here.\nDo you create a hello document ?"
res = frm.messageBox(msg, 'ruby illustrator', 4)   # 4 = WConst::MB_YESNO

case res
  when 6                                           # YES->6, NO->7
    illu = WIN32OLE.connect('Illustrator.Application')
    doc = illu.Documents.Add
    hello = doc.TextArtItems.Add
    hello.Contents = 'Hello rubyillustrator world!'
    hello.Position = [230, 700]
    hello.Resize(300, 300)
  when 7                                           # YES->6, NO->7
    frm.messageBox('adieu', 'ruby illustrator', 0) # 0 = WConst::MB_OK
  else
    raise
end # case res

messageBox引数の第3項には、require 'vr/contrib/msgboxconst' に一覧のある WConst定数の値を指定するとメッセージボックスの表象が変る。 そして、そのダイアローグの釦押下の結果が返ってくる。

WConstの値と返り値
MB_OK                   = 0 # OK->1
MB_OKCANCEL             = 1 # OK->1, CANCEL->2
MB_ABORTRETRYIGNORE     = 2 # ABORT->3, RETRY->4, IGNORE->5
MB_YESNOCANCEL          = 3 # YES->6, NO->7, CANCEL->2
MB_YESNO                = 4 # YES->6, NO->7
MB_RETRYCANCEL          = 5 # RETRY->4, CANCEL->2

2003/6/1

スクリプトメニューから_2 [DOS窓のない呼出]

そうは言っても、.vbsからの呼出の度に DOS窓が現れるのを煩わしく感じる場合も在ろう。 その時は

WshShell.Run( "WScript.exe ""<rubyファイルのフルパス名>"" ")

とすれば良いのだろう。'""' な '"' のエスケープや、フルパス名が安心である。

2003/5/31

スクリプトメニューからの実行

今まで書いてきた rubyスクリプトは Illustratorの外から実行していた。 Illustratorのスクリプトメニューからの呼出しも出来るようにしたい。 しかし、Illustratorは、.vbs, .js, .exe しか認識しない。 その為、WScript.Shell.Run, WScript.Shell.Exec によって rubyスクリプトを呼び出すだけの VBScriptを書く。

Dim WshShell, oExec
Set WshShell = CreateObject("WScript.Shell")
Set oExec = WshShell.Exec( <rubyファイルのフルパス名> )

または

Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run( <rubyファイルのフルパス名> )

標準入出力などと相互作用出来る Execメソッドは、新しい(XP以降?) WSH にしか無い様なので、 その時は Runメソッドを使用する。

或は exerb によって .exe実行ファイルにしてやってもよい。

[ファイル]-[スクリプト]-[参照] メニューでの初めに参照するフォルダは (標準的なインストールでは)

C:\Program Files\Adobe\Illustrator 10.0.3\Support Files\Contents\Windows\

になるので、その辺に入れれば良いだろう。 このフォルダには、.vbs, .js, .exe へのショートカット を入れても参照される。

また、[ファイル]-[スクリプト]-メニューから直接呼び出せるようにするには、

C:\Program Files\Adobe\Illustrator 10.0.3\プリセット\スクリプト\

に所要のファイルを置くと良い。ここにはショートカットを置いても参照されない。 実際にこのメニューに登録するには、Illustyratorを再起動する必要があることに注意。

2003/3/29

テキスト内改行

テキスト文字列内で改行するには "\r" を挿む、"\n" ではないのに注意。

一文字毎に "\r" を挿めば縦書きもどきにもなる。 (縦書き文字ツールの名前がわからない)

2003/3/16

テキスト位置_2

(V|G|C)Bounds を表す Fixed rectangle の指定するのが、左上座標と右下座標(この順)であるということを 実感していなかった(なんとなく左下点を思い描いてたりした)のが混乱の要因だった様だ。 もう一度状況を整理する。

  1. Layer等の TextArtItems から、TextArtItem を取り(作り)出す。最初は Addメソッドで作ることになろう。
  2. 書きたい文字はそのオブジェクトで TextArtItem.Contents に代入すればよい。
  3. その際 TextArtItem.Kindプロパティには AiTextType enumeration を設定できる筈だが、 AiPointText (Default?)を明示的にセットしよう。
  4. そして、VisibleBoundsである。これは FixedRectangleとして、左上点と右下点を代表する。

    visibles = text.VisibleBounds
    vw = (visibles[2] - visibles[0]).abs
    vh = (visibles[3] - visibles[1]).abs

    そういう意味では下記にすれば .absは要らない筈なわけだ、

    vw = (visibles[2] - visibles[0])
    vh = (visibles[1] - visibles[3])
  5. この幅を基準に移動すれば所要位置にテキスト

    text.Position = [ center[0] + @left - vw/2, center[1] + @bottom + vh/2 ] # 此れが所要の筈なんだ、pointが左上なんで -vw +vh と符号がずれる(2003/3/16)

    centerがテキストの中心になる様に移動したつもり。

  6. 上下余白(英文)や右裾流れの為に厳密に中心が合うわけではないが、概ねこんな感じ。
  7. 回転のことは未だ詳しく検討してない。一応回転 text.Rotate(direction) してても大丈夫だったんだけど、 Boundsの具体的な辺りとか、ちゃんと検討していない。
まとめ
AiPointTextとして、Boundsが与えるのが左上右下である事をきちんと注意すれば、 テキスト位置は調整出来る様だ。

Fixed rectangle (Coordinates - Scripting Illustrator, IllustratorScriptingGuide.pdf)

To work with rectangular coordinates where there are a pair of x and y values, Illustrator uses the special class called a fixed rectangle. This class is comprised of a list with four items in AppleScript and a variant array with four elements in Visual Basic. The coordinates of a .xed rectangle in order are: left, top, right, bottom.

AiTextType enumeration

AiTextType

2003/2/25

テキスト位置

どうも上下方向で下にずれるような感じ。 TextArea は左上をpointするのでなく、左下をポイントするのか?

というより、pathテキストか、pointテキストか、エリアテキストかをきちんとすべきであった

pointテキスト
左上

ってことになるようだ(正対配置の場合)

pathテキストは駄目みたい。pointテキストをちゃんと指定しよう。そしてそれでも、上下的には中央ではない。 ベースラインと上端の中央にくる感じ。(VigibleBoundsってどういう意味?、こんなことなの?)

DoScriptパスファインダー アウトラインの線色

Application.DoScript で予め作っておいた「パスファインダー アウトライン」アクションを実行する。 得られたアウトライン線のパスStrokeColor.Color は Gray になる傾向がある。 いっぱい出来るうち最後のパスだけは Documentと同じAiColorCMYKになるが、あとはAiColorGrayになってしまう。

ColorObjectの振る舞い

Color.Color が該当する Color Enumeration 値でないとき、そもそもそのカラープロパティは無い(nill) 上記のようにGrayになっちゃてるとき、CMYK属性はそもそも存在せず、ましてや CMYK.Cyan なんて nil はそんなメソッド(プロパティ)持って無いといわれる。

アクションの登録と保存

保存、読み込み、置き換え

アクション表示ウィンドウのオプションメニューからアクションの保存ファイル操作。

「置き換え」をすると、デフォルト(初期設定)アクションなども含めて置換されてしまい、 ファイルの保存されていたアクションしかなくなってしまうのに注意。

2003/2/23

Color

Document.DefaultColor なり、各オブジェクトの StrokeColor とか FillColor とかの Colorオブジェクトについて、 その Colorプロパティの AiColor Enumeration に従ったプロパティ(CMYK,...)の色値を設定する。

2003/2/11

テキストを書く

Layer.TextArtItems からテキストを書く。

TextArtItem.Kind を設定すれば、point text、path text、area text、を選べる訳だが、取敢えず point系。

title = lay.TextArtItems.Add
title.Contents = <文字列>
title.ReSize( <width(%)> , <hight(%)> )
title.Position = [ <left> , <top> ]
  1. Layer等の TextArtItems から、TextArtItem を取り(作り)出す、
  2. TextArtItem.Contents に書くべき文字列を代入し、
  3. デフォルトの大きさから適当にサイズを調節(百分率)し、
  4. 描くべき場所に配置する(左上端指定)。

配置位置の計算には、Heigt, Width (どちらも GemotericBounds を基に計算する)を使って微調整出来るだろう。 より詳しくは、VisibleBounds, (GeometricBounds, ControlBounds) を使う事になる。

TextArtItem.Kind

TextArtItem.Kind
AiTextType

テキストのフォント

TextArtItem の TextRangeメソッドで、適用すべきテキストの範囲を選び(設定し)、 その TextRangeオブジェクトの、Fontプロパティに、所要の TextFace オブジェクト値を設定する。

TextFaceオブジェクトを探すのは大変(TextFace, TextFaces の exampleなど参照)

TextFaces.item(itemKey)
itemKey は フォント名称でいいのかな? 未確認

TextFacesコレクションを eachで回して(Count個)、各 TextFace.Name をフォント名にマッチさせる とかすればなんとかなるか?

TextFaces[i] は効くのかな?

TextArtItem.TextRange

TextRange([rangeStart As Long], [rangeEnd As Long])

2003/2/9

パスファインダで交点を求める

線と線(パスとパス)の交点を求めるのに、パスファインダ-アウトライン を使う事が出来る(GUI)。 しかし、スクリプトからは直接これを操作するやり方が解らないので、 あらかじめアクションを定義しておいて、Application.DoScript でアクションを呼ぶ事にする。

DoScript(action As String, from As String, [dialogs As Boolean])
  Plays an action from the Actions palette.
  1. アクションを定義(本体)しておく
    1. 直線 2本をセレクト
    2. 「新規にセットを作成 - 新規にアクションを作成」
      • 英字(所謂半角文字)で名前をつけておく方がスクリプト側からアクセスし易い
    3. 「パスファインダ-アウトライン」を実行
    4. 線の色が消え、太さも細くなるのでその辺を調整。
      • その際は必要なら終端の形状、角の形状も調整する。
    5. 「再生/記録を中止」
    6. アクションメニューからアクションの保存をしたほうが良いでしょう。
  2. Application.DoScript(<アクションの名前>, <アクションの属するセットの名前>)
    1. 適宜パスを選択
      • PathItem.Selected = true
    2. illu.DoScript(<アクションの名前>, <そのセットの名前>)
    3. 結構時間が掛かるので、Application.ActionIsRunning でチェック
      • sleep 1 while illu.ActionIsRunning
  3. GroupItem になってる。
    1. Layer.GroupItems.item(1) (1よりもっと大きいかも知れないけど)
    2. GroupItem.PathItems.item( 1..(GroupItem.PathItems.Count) )
    3. その PathItem.PathPoints.item( 1..(PathItem.PathPoints.Count) ).Anchor をみると、グループ内での分割された線分の順番とか、交点は線分のどっち端とか、基準が良く解らない。 交点の座標が必要なら、これらの頂点(両端点)をすべて比べて同じものを抜き出す事になる。

全点座標を比較検討して交点座標(と交点)を抜き出したり、 適宜グループの名前や分割された線分の名前を設定するメソッドも必要でしょう

パスファインダ-オプション

このオプションはスクリプトから操作出来るような感じがしないので、設定値には十分注意する事。 rubyスクリプト実行前に所要の値になっているかどうか、GUIで確認すべき。

精度

十分小さい値にする事。初期設定値 0.028 でも良さそうだけど、0.01 くらいにしようか。

分割とアウトラインで塗りのないアートワークを削除

今の場合、塗りの無い線の交点を求めるのが目的なので、これはチェックしない

余分なポイントを削除

こっちのほうは目立った影響はないみたい。

2003/2/8

Document.PageOrigin

PageOrigin
The zero-point of the page in the document without margins, relative to the overall height and width.

「プリント可能範囲 」(か「用紙の端」?) の左下端。 描画の基準点ではない

2003/2/6

PathItem.SetEntirePath 不調

SetEntirePath(pathSpecification As Variant Array of Variant Array of 2 Singles)

を使うと直接直線が引ける筈だがうまく行かない。

pathA = lay.PathItems.Add
pathA.setEntirePath( Array[ Array[0,0], Array[100,100] ] )

でエラーになる。

blend.rb:56:in `method_missing': setEntirePath (WIN32OLERuntimeError)
    OLE error code:80070057 in <Unknown>
      the argument is not valid
    HRESULT error code:0x80020009
      例外が発生しました。
        from blend.rb:56

だからって、引数を Array,Array にしたり、0,0,100,100 にしても HRESULT error code:0x8002000e パラメータの数が無効です。 が起こる。

2003/1/26

PathItems.item(1)

PathItems コレクションの要素の item を取り出すメソッド

PathItems.item(itemKey)

itemKey は整数で良かったが、1 から始まる。rubyな 0 始まりで無いのに注意!

恐らく他のコレクションもみんな 1 始まりだろう。要注意。

2003/1/12

Polygon(云々).Rotate(角度).

ずれる。微妙に、1pt程度のズレかも知れないがずれる。 傾いた多角形も自由頂点指定多頂点閉パスとして作成しないと、まさに思った位置には描画できない。

2003/1/11

角っコ(2)

と言う訳でやってみた

./strokeCJ.rb.txt

doc.DefaultStrokeCap = Illu::AiButtEndCap
doc.DefaultStrokeJoin = Illu::AiMiterEndJoin
doc.DefaultStrokeMiterLimit = 5

としておいて下から順に、

  1. そのデフォルト値
  2. デフォルト値だが PointType = Illu::AiSmooth
  3. デフォルト値だが2本のパスで引いてみた
  4. StrokeJoin = AiBevelEndJoin
  5. StrokeJoin = AiMiterEndJoin
  6. StrokeJoin = AiRoundEndJoin

PointTypeは関係無いみたい。

2本のパスで曳くと谷になっちゃう辺り見難かったかな、ちょっと拡大 ./strokeCJ.rb.txt

角っコと端っコ

線の端っコを

パスの終わりで断ち切る
PathItem.StrokeCap = AiButtEndCap : 1
パスの終わりから StrokeWidth(の半分)だけ四角く終端する
PathItem.StrokeCap = AiProjectingEndCap : 3
パスの終わりで丸めて終端する
PathItem.StrokeCap = AiRoundEndCap : 2

折線の交点を

パスの交点の所で断ち切る(わずかにはみでる)
PathItem.StrokeJoin = AiBevelEndJoin : 3
パスの交点の先まで StrokeWidth幅の線の延長に尖らす
PathItem.StrokeJoin = AiMiterEndJoin : 1
パスの交点の所で丸める
PathItem.StrokeJoin = AiRoundEndJoin : 2

何れも丸めるときの半径はStrokeWidthの半分。

AiMiterEndJoin のとき、PathItem.StrokeMiterLimit が十分大きくないと Bevelのように断ち切られる。

StrokeCap, StrokeJoin

StrokeCap: The type of line capping for a path stroke.

StrokeJoin: The type of joints for a path stroke.

<URL:http://partners.adobe.com/asn/developer/scripting/docs/AIJavaScriptReference.pdf> より、 ってわけで

AiStrokeCap

AiButtEndCap : 1
AiProjectingEndCap : 3
AiRoundEndCap : 2

AiStrokeJoin

AiBevelEndJoin : 3
AiMiterEndJoin : 1
AiRoundEndJoin : 2

2003/1/10

角っコ

折線の交点の尖り具合の制御はどうなってるんだろう。 ちょっと尖り過ぎてて、線の向こうに飛び出てしまう。

StrokeCap
AiStrokeCap enumeration
The type of line capping.
StrokeJoin
AiStrokeJoin enumeration
Type of joints for the path.
StrokeMiterLimit
Single
Are joins mitered (pointed) or beveled (squared-off)?

AiStrokeCap, AiStrokeJoin ってなんだろう。

2003/1/5

線の幅

doc = illu.Documents.Add(Illu::AiDocumentCMYKColor, A5::WidthPt, A5::HeightPt)
doc.DefaultStroked = true
doc.DefaultStrokeWidth = 0.03

document単位でのパスを引く時の線の幅の指定。

正直、線幅 0.03point というのは細くし過ぎで、0.1より小さい値では、印字線幅に違いは無い様に見える (Canon BJ F200、それほど解像度の高くない非PSプリンタ)。まあ、0.1未満にしとけばいいのだろう。

閉じたパス

PathItem.Closed = true

Closed Path を作るとき。 PathItem.PathPoints.Add で頂点を付加え、適宜 Anchor座標(とDirection)を指定した後で、 単に PathItem.Closed を true にすれば良い。 たとえば自由頂点の多角形はそうやって作る。

2003/1/3

メソッドの値

結構値を返してくれないメソッドやプロパティ代入(ruby的にはこれもメソッド)が多くてストレスが溜まる。 (これはOLEなら仕方ない事だっけ、それとも Illustrator だけの事?)

PathItem.Rotate(角度)

PathItem.Rotate(角度) は度(degree)

Rotate(Angle As Single, [changePositions As Boolean], [changeFillPatterns As Boolean], [changeFillGradients As Boolean], [changeStrokePattern As Boolean], [rotateAbout As AiTransformation])

PolygonのAnchorのDirection

PathItems.Polygon で得られた PathItem の PathPoints の各点の Left[Right]Direction は自身だった。

pol = paths.Polygon(A5::WidthPt/2, A5::HeightPt/2, size/2, 5)
pol.name = 'Hishi'
pps = pol.PathPoints
puts "\nPolygon"
pps.Count.times do |i|
  pt = pps.item(i+1)
  puts "#{pt.PointType}:#{pt.Anchor[0]},#{pt.Anchor[1]}; L:#{pt.LeftDirection[0]},#{pt.LeftDirection[1]}; R:#{pt.RightDirection[0]},#{pt.RightDirection[1]}"
end
# 是に拠ると Polygon の各頂点の Left[Right]Direction は自身、PointType は勿論 AiCorner

出力

Polygon
2:184.7851563,55.14160156; L:184.7851563,55.14160156; R:184.7851563,55.14160156
2:115.0371094,269.8037109; L:115.0371094,269.8037109; R:115.0371094,269.8037109
2:297.6401367,402.4726563; L:297.6401367,402.4726563; R:297.6401367,402.4726563
2:480.2431641,269.8037109; L:480.2431641,269.8037109; R:480.2431641,269.8037109
2:410.4951172,55.14160156; L:410.4951172,55.14160156; R:410.4951172,55.14160156

PathItems.Polygon の作る正多角形だけど、

PathItems.Polygon の作る正多角形だけど、 作ったあとで回転させるとき、回転中心は、geometric(visible ?) bouds長方形の中心である。 Polygon定義のときに指定した外接円中心ではないのでちょっと混乱した。 また、そういう訳だから、偶数角形のときは大丈夫。

2003/1/2

RectangleのAnchorのDirection

PathItems.Rectangle で得られた PathItem の PathPoints の各点の Left[Right]Direction は自身だった。

rec = paths.Rectangle(left_top[1], left_top[0], size, size)
pps = rec.PathPoints
pps.Count.times do |i|
  pt = pps.item(i+1)
  puts "#{pt.PointType}:#{pt.Anchor[0]},#{pt.Anchor[1]}; L:#{pt.LeftDirection[0]},#{pt.LeftDirection[1]}; R:#{pt.RightDirection[0]},#{pt.RightDirection[1]}"
end
# 是に拠ると Rectangle の各頂点の Left[Right]Direction は自身、PointType は勿論 AiCorner

出力

2:105.6401367,18.47265625; L:105.6401367,18.47265625; R:105.6401367,18.47265625
2:105.6401367,402.4726563; L:105.6401367,402.4726563; R:105.6401367,402.4726563
2:489.6396484,402.4726563; L:489.6396484,402.4726563; R:489.6396484,402.4726563
2:489.6396484,18.47265625; L:489.6396484,18.47265625; R:489.6396484,18.47265625

AiCorner : 2
AiSmooth : 1

PathIems.Ellipse の左上指定

PathIems.Ellipse も左上指定は、上、左 の順。混乱しそう。

Ellipse([top As Single], [left As Single], [Width As Single], [Height As Single], [reversed As Boolean], [inscribed As Boolean])

PathItems.Polygon

PathItems.Polygon は正対した正多角形(外接円中心と外接円半径を指定)のみ

Polygon([centerX As Single], [centerY As Single], [radius As Single], [sides As Long], [reversed As Boolean])

2003/1/1

PathItems.Rectangle の左上指定

PathItems.Rectangle の左上指定が、上、左 の順

Rectangle([top As Single], [left As Single], [Width As Single], [Height As Single], [reversed As Boolean])

X,Y順が直観と反するので凄く混乱した

座標の単位

centimeters 28.346 points = 1 centimeter
inches 72 points = 1 inch
millimeters 2.834645 points = 1 millimeter
picas 12 points = 1 pica
Qs 0.709 point = 1 Q (1 Q equals 0.23 millimeter)

<URL:http://partners.adobe.com/asn/developer/scripting/docs/IllustratorScriptingGuide.pdf#Unit conversion to points>

AdobeIllustrator Constants

Ai constants は <URL:./aiConstants.txt>参照

Illustratorの起動とOLEオブジェクトの作成

こうやって

require 'win32ole'
#illu = WIN32OLE.new('Illustrator.Application')
illu = WIN32OLE.connect('Illustrator.Application')
module Illu; end
WIN32OLE::const_load(illu, Illu)

作るわけだが、Illustratorは既に起動していないと起動できずに(起動中(終盤)に初期設定の読込みの辺りで)エラーになる。 (.new('Illustrator.Application') の場合)

Illustrator が起動していれば、new で OLEオブジェクトを作る事が出来る。 というわけで、どうせ Illustrator が起動中でないといけないのなら、connect で OLEオブジェクトを作る事にしよう。

(Windows98SE 4.10.2222A, ActiveScriptRuby 1.6.8.0, Ruby1.6.8, Win32OLE 0.5.2)
(Adobe Illustrator 10.0.3 Win版)

きっかけ

Illustrator で図を書かねばならない事情が出来た。しかし、マウスで書くのは性に合わず、得意でない。 図は同じ様なものを幾つもいくつも書く必要がある。というわけでスクリプトによる自動処理がしたい。 近くに Mac で AppleScript で自動処理をしている人がいるので可能ではあろう。 是を機会に MacOSX も用意して BSDな人 になるのも一案ではあった。

しかし、調べてみると Visual Basic によるスクリプティングの解説が Adobe自身にあった( <URL:http://partners.adobe.com/asn/developer/scripting/docs/IllustratorScriptingGuide.pdf> AppleScript含む。別に JavaScriptのもある)。 Visual Basic で出来て、VBScript で出来て、JavaScript で出来る: com である。 Windows Active Script なら Illustrator を操作できるわけだ。

そういうわけで「ActiveScriptRuby で Illustrator 10 」。

メモ

ここに書いて行くのは、上記に際して出会った事情のメモである。取敢えずの備忘録を兼ねたメモである。 機会があったら将来また見やすくまとめるかもしれないが、現状では単なる事象の順不同な羅列に過ぎない。


hs9587 2003/1/1-