スクリプトでGlyphsを動かす、パート2

広告

原文: Scripting Glyphs

チュートリアル

スクリプト

執筆者: Rafał Buchner & Rainer Scheichelbauer

en zh

2022年8月18日更新(初版公開:2012年6月28日)

最初のパートでは、フォントとグリフの情報を出力する方法を学びました。今回は、一歩進んで、実際にフォントを操作してみたいと思います。お気に入りのフォントのコピーを作成し、Pythonの筋肉を温めておいてください。

このチュートリアルは、「スクリプトでGlyphsを動かす、パート1」を先に読んでいることを前提としています。

グリフレイヤー

まず、Glyphsが文字をどのように整理しているかを思い出しましょう。文字を描いたり編集したりするときに扱うパス、アンカー、ガイドラインなど、これらすべては単にグリフのプロパティではありません。むしろ、それらはグリフが持つことができるレイヤーの1つに属しています。レイヤーには、手動で挿入したレイヤーとマスターレイヤー(補間に使用されるもの)の両方があります。

選択されたレイヤー

さて、何かをする前に、どのレイヤーが選択されているかを判断する必要があります。方法はこうです。マクロパネルを表示し、次のように入力します。

print( Glyphs.font.selectedLayers )

すると、次のようなものが表示されます。

(
    "GSLayer <0x7fe471526320>: [Bold Italic] (A)",
    "GSLayer <0x7fe47152fbb0>: [Bold Italic] (B)",
    "GSLayer <0x7fe471530d30>: [Bold Italic] (C)"
)

ここで何をしたのでしょうか?まず、Glyphsオブジェクトを取り、そのfontプロパティを要求しました。これは現在の、つまり最前面にあるフォントを返すはずです。フォントが開かれていない場合はエラーが出ます。確かに、結果(「GSLayer…」)はあまり情報量が多くありませんが、これがGlyphsがレイヤーを呼ぶ方法です。16進数の識別コード、それに続くレイヤー名、そしてそれぞれのグリフ名です。

幸いなことに、私たちはこれらのことを直接扱う必要はあまりありません。Pythonにその仕事をさせることができます。そこで、最初の行はこうなります。

myLayers = Glyphs.font.selectedLayers

パスへのアクセス

これを少し拡張してみましょう。

myLayers = Glyphs.font.selectedLayers
for thisLayer in myLayers:
    print( thisLayer.parent.name )
    print( thisLayer.paths )

これをマクロパネルで実行すると、次のような答えが得られます。

A
(<GSPath 57 nodes and 29 segments>, <GSPath 10 nodes and 4 segments>)
B
(<GSPath 53 nodes and 23 segments>, <GSPath 42 nodes and 16 segments>)
C
(<GSPath 57 nodes and 23 segments>)

何が起こったのでしょうか?fontからselectedLayersを取得したので、ユーザーが選択したすべてのレイヤーが得られ、それをmyLayersという変数に渡しました。

2行目では、myLayersにあるすべてのレイヤーをループ処理しています。レイヤーを1つずつ、まずthisLayerと名付け、次にthisLayerにそのparentの名前を尋ねてマクロパネルに出力し、最後にthisLayerにそのパスを尋ねてその答えもマクロパネルに出力します。その後、ループはmyLayersの次のレイヤーに進み、全体が再び始まります。これはmyLayersの最後のレイヤーが処理されるまで続きます。

ここでこっそり入れたものがあります。parentです。オブジェクトのサブオブジェクトにアクセスするには、ピリオドとそのサブオブジェクトの名前を追加すればよかったのを覚えていますか?Glyphsで現在開かれているすべてのフォントを知りたい場合は、Glyphs.fontsと入力します。最初に開かれているフォントのファミリー名を知りたい場合は、Glyphs.fonts[0].familyNameと入力します。この方法で、オブジェクトツリーを下に掘り下げることができます。しかし、時にはすでにオブジェクトがあり、オブジェクト階層を1つ上に掘り上げる必要がある場合があります。これを行うには、オブジェクトのparentを参照します。

この場合、thisLayerに格納されているレイヤーがあり、そのレイヤーがどのグリフに属しているかを知りたいので、レイヤーにその親を尋ねます。thisLayer.parentです。そして最後に、その親グリフに名前を尋ね、thisLayer.parent.nameとし、その結果をprintコマンドに渡します。

最後の行も同様に重要です。なぜなら、私たちは聖杯、つまり私たちのフォントを構成するまさにそのパスにたどり着いたからです。次のステップでパスにひどいことをするので、フォントのコピーで作業していることを願っています。警告はしましたよ。

パスとノード

さて、選択したレイヤーに何かクレイジーなことをしたいと思います。すべてのノードをランダムに左右に散らしてみましょう。そこで行うことはこれです。Pythonにランダムな正または負の数値を生成させ、それを最初の選択されたレイヤーの最初のパスの最初のノードのx座標に加えます。そして、これを他のすべてのノード、パス、レイヤーで繰り返します。

Pythonには乱数生成器がありますが、私たちのパーティーには特別な招待が必要です。これをモジュールのインポートまたはライブラリのインポートと呼びます。そこで、乱数生成器をインポートすることから始めます。

import random

そして、ここだけの話ですが、import randomするたびに、randomのseed関数を呼び出すのが良い考えです。

random.seed()

seedという単語の後ろにある括弧に気づきましたか?括弧は、いわゆるメソッドを示します。そうです、オブジェクトは他のオブジェクトを持つことができますが、メソッド(または「関数」)も持つことができます。メソッドは、それが付随しているオブジェクトに対して何かをします。seed()関数は、乱数生成器に本当にランダムであること、そしてそれについてぐずぐずしないように伝えます。これをしないと、乱数生成器が同じ結果を2回返す可能性があり、それは絶対に避けたいことです。

さて、それではすべての選択されたレイヤー、そのすべてのパス、そしてすべてのノードを順に処理し、それらに必要なことをしていきましょう。

import random
random.seed()

myLayers = Glyphs.font.selectedLayers
for thisLayer in myLayers:
    for thisPath in thisLayer.paths:
        for thisNode in thisPath.nodes:
            thisNode.x += random.randint( -50, 50 )

最後の行を除いて、すべてが明確なはずです。変数thisNodeは、パス上のオンカーブまたはオフカーブの点を保持しています。前の行ですべてのノードを反復処理しています。プロパティxは、もちろん、その点のx座標です。

演算子+=は、「右側にあるものを左側の変数に加える」という意味です。例えば、x+=5はxを5だけ増やします。そのため、+=インクリメント演算子とも呼ばれます。これはx=x+5と言うよりも短く、効率的な方法です。

プロのヒント

クラスがどのメソッドやオブジェクトをサポートしているかを確認するには、Pythonの組み込みhelp()関数をそれに実行します。例えば、import randomした後に、help(random)を実行できます。help()関数は、その括弧の間に置いたものの技術的な説明を出力します。

help(random)からの出力の膨大な量に圧倒された場合は、randintについて具体的なヘルプを得るために、代わりにhelp(random.randint)を実行してみてください。

さて、ランダムな部分です。まず、数行前にインポートしたモジュールrandomを取ります。次に、そのメソッドの1つ、すなわちランダムな整数の略であるrandint()を取得します。すべてのメソッドと同様に、randint()の最後には括弧があります。その括弧の中に、入力値を渡すことができ、その入力に基づいて結果が得られます。メソッドrandint()は、コンマで区切られた2つの値、最小値最大値を取り、最小値と最大値の間のランダムな整数を返します。私たちはrandint()に最小値として-50、最大値として50を渡し、ランダムな数が返されることを期待します。

つまり、要するに、最後の行はこれを行います。それぞれの点のx座標を取り、それに-50から50の間のランダムな数を加えます。理にかなっていますか?

ここまですべて明確ですか?はい?では、次は何でしょうか?このスクリプトを「スクリプト」メニューの項目に変えて、いつでも好きなときにアクセスできるようにしましょう。どうやって?「スクリプトでGlyphsを動かす、パート3」でそのすべてを読んでください。


更新履歴 2014-10-04: パート1と3へのリンクを追加。

更新履歴 2016-12-08: いくつかのフォーマットを修正、古い警告を削除、help()に関するプロのヒントを追加。

更新履歴 2019-02-06: テキストとフォーマットの軽微な調整。

更新履歴 2019-02-12: 誤字を修正。

更新履歴 2020-12-02: Python3向けに更新。

更新履歴 2022-18-08: タイトル、関連記事、軽微なフォーマットを更新。

関連記事

すべてのチュートリアルを見る →

スクリプト

スクリプト

スクリプト

コメント

タイトルとURLをコピーしました