TextEdit.app でアウトライン

バージョンが上がるごとに地道な改良が加え続けられている TextEdit.app。ちょっとした書類なら TextEdit.app だけで十分ということも多い。Mac OS X 10.7 に付属している TextEdit はついに縦書きにも対応した。

TextEdit を使ってどのような表現ができるかは、ちゃんと知りたいテキストエディット.appとリッチテキストの使い方 - ザリガニが見ていた...。に詳しい。

だけど、(個人的には)一つだけ問題があった。

それはアウトラインについて。袋文字ともいうようだけど、TextEdit ではアウトラインにした文字列の中の色を指定することができない。

TextEdit_Outline_001.jpg

このように通常は現在の文字色でアウトライン化され、文字の内側の色は白以外指定することができない。袋文字 - Wikipediaなのだからこれでいいともいえるのだけど、アウトラインの外側と内側の色の両方を個別に指定したい。

いろいろと調べたのだけど、TextEdit.app で作成する方法が見つからない。こういう要望って少ないのでしょうか?

AS Hole(AppleScriptの穴) By Piyomaru Software » Keynote上でコピーされたテキストオブジェクトの内容をTextEditで解析してIllustratorで白フチ文字を作成してKeynoteにペースト v2 » Blog Archiveといった方法は見つかったのだけど、これはなかなか敷居が高い。そもそも Illustrator 持ってないし。

...はたと気がつく。RTF なんだから、中身のデータそのものをいじってしまえばいいのでは?そもそも RTF の中身なんて文字列なんだし。

ようやく探し当てたのが Attributed String Programming Guide: RTF Files and Attributed Strings

さすが Apple。ちゃんと用意していました。上記の文書を読むと、strokewidth が文字列をアウトライン化するのに使われている制御コード。この strokewidth にマイナスの値を適用すれば文字列の内側にも色を付けられるようです。実際に TextEdit.app で作成した RTF ファイルをテキストエディタで開き、strokewidth の値をいじっていたらできました。

TextEdit_Outline_002.jpg

「書式」メニューの「スタイルをコピー」、「スタイルをペースト」メニューを使えば、他の Cocoa アプリケーションでも同じスタイルを使い回すことができます。例えば、Keynote や Pages や Numbers。もちろん Apple のアプリケーションでなくても使えます。

しかし、RTF ファイルをテキストエディタで開いて中身の制御コードをいじるというのはなかなか面倒なもの。そこで、アウトラインの内側の色と外側の色を指定して RTF ファイルをつくるスクリプトを。

Script Editor で開く

on run
    set template to "{\\rtf1\\ansi\\ansicpg1252\\cocoartf1138\\cocoasubrtf470
{\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;$innerColor;$outerColor;} \paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0 \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
\f0\fs192 \cf2 \outl0\strokewidth-60 \strokec3 Outline Text}"
    -- cf number = character color
    -- strokec number = stroke color

    display dialog "文字の内側の色を選択" with icon 1 giving up after 3
    set innerColor to my color2RTFColor(choose color)
    display dialog "文字の外側の色を選択" with icon 1 giving up after 3

    set outerColor to my color2RTFColor(choose color)

    set template to my substitution(template, "$innerColor", innerColor)
    set template to my substitution(template, "$outerColor", outerColor)

    set theFile to (path to desktop as text) & "Outline Text.rtf"

    my writeFile(theFile, template)

    tell application "Finder" to open file theFile using (path to application "TextEdit")
end run

on color2Hex(colorList)
    repeat with thisColor in colorList
        set contents of thisColor to ((thisColor as integer) * (255 / 65535)) as integer
    end repeat

    return colorList
end color2Hex

on color2RTFColor(colorList)
    color2Hex(colorList)
    set {r, g, b} to colorList
    set theList to {"\\red" & r as text, "\\green" & g as text, "\\blue" & b as text}

    return (theList as text)
end color2RTFColor

on substitution(theText, fromText, toText)
    tell (a reference to text item delimiters)
        set {tid, contents} to {contents, fromText}
        set {theList, contents} to {every text item of theText, toText}
        set {replacedText, contents} to {theList as text, tid}
    end tell

    return replacedText
end substitution

on writeFile(theFile, theText)
    try
        set fh to open for access file theFile with write permission
        set eof fh to 0
        write theText to fh starting at eof as «class utf8»
        close access fh
        return true
    on error eMsg number eNum
        try
            close access fh
        end try
        return false
    end try
end writeFile

ぶっちゃけ文字列を置き換えているだけだったりしますが。