指定の文字から花文字を作成するAppleScriptです。
「花文字」とは、任意の文字を組み合わせて指定の文字を作成するもので、「祝」という文字とスペースを組み合わせて、
祝 祝 祝祝祝祝祝祝 祝祝祝祝祝 祝 祝祝祝祝祝 祝 祝祝祝 祝祝 祝祝 祝祝祝祝祝祝 祝祝祝祝 祝祝祝 祝祝祝祝祝 祝 祝 祝 祝 祝 祝 祝祝 祝 祝 祝 祝祝 祝祝祝祝 祝 祝 祝
のように組み合わせた文字列のことです。
大昔の大型コンピュータの計算結果をプリンタに印刷する際に、ユーザーごとの計算結果の紙が混ざることを防ぐために、ヘッダーページを印刷するようになっていました。当時はまだアウトラインフォントから大きな文字を印刷する技術がなかったので、花文字のように文字を組み合わせて大きな文字を印刷するようなことを行なっていたようです(たぶん)。
類似の処理にこのようなものがあります。
→ Love
花文字はその名残りで、パソコンのメールなどで文字だけを使って何かを表現するような、原始的なアスキーアートの一種といえばよいのでしょうか。
かつては、花文字作成の専用アプリケーションが存在していました。AppleScript的には、そうしたアプリケーションに「このデータを作ってくれ」と依頼するのが本来のスタイルですが、アプリケーションがない場合には、原理的に別に難しいものではないので、自前で作ってしまえばいいわけです。
(1)指定サイズ、指定フォントで書式つきテキストを作成
(2)書式つきテキストをメモリー上に用意したブランク画像に描画
(3)メモリー上の画像のドットを順次読み取って、塗りつぶされている箇所といない箇所を順次検出
(4)塗りつぶし情報を文字列に表現。空白ドットは空白文字で、描画ドットは指定文字で
(5)文字列を出力
という処理を行なっています。描画時のフォント種別の指定や、結果をCotEditorに出力するあたりは「オマケ」です。
この程度の処理であれば、JEdit Ωやmi、OS標準装備のテキストエディットなどさまざまな(AppleScript対応の)エディタにオープンさせられます(Mac用のテキストエディタでAppleScript非対応というものがあれば、何の迷いもなくゴミ箱行きです)。
AppleScript名:指定文字の花文字テキストを取得する(Retina対応) |
— Created 2017-12-12 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" property NSFont : a reference to current application’s NSFont property NSUUID : a reference to current application’s NSUUID property NSColor : a reference to current application’s NSColor property NSArray : a reference to current application’s NSArray property NSString : a reference to current application’s NSString property NSImage : a reference to current application’s NSImage property NSPredicate : a reference to current application’s NSPredicate property NSDictionary : a reference to current application’s NSDictionary property NSBezierPath : a reference to current application’s NSBezierPath property NSColorSpace : a reference to current application’s NSColorSpace property NSPNGFileType : a reference to current application’s NSPNGFileType property NSFontManager : a reference to current application’s NSFontManager property NSBitmapImageRep : a reference to current application’s NSBitmapImageRep property NSMutableDictionary : a reference to current application’s NSMutableDictionary property NSFontAttributeName : a reference to current application’s NSFontAttributeName property NSKernAttributeName : a reference to current application’s NSKernAttributeName property NSMutableParagraphStyle : a reference to current application’s NSMutableParagraphStyle property NSLigatureAttributeName : a reference to current application’s NSLigatureAttributeName property NSMutableAttributedString : a reference to current application’s NSMutableAttributedString property NSUnderlineStyleAttributeName : a reference to current application’s NSUnderlineStyleAttributeName property NSParagraphStyleAttributeName : a reference to current application’s NSParagraphStyleAttributeName property NSForegroundColorAttributeName : a reference to current application’s NSForegroundColorAttributeName set aString to "あ" set hanaSize to 24 set thisFont to selectAFont(aString) of me if thisFont = false then return –Cancel –花文字文字列を作成 set fRes to getHanamojiStr(hanaSize, thisFont, aString, 0.7, true) of me makeNewDocument given parameter:fRes –花文字文字列を計算して返す on getHanamojiStr(aFontSize as real, aFontName as string, aString as string, aThread as real, incFontName as boolean) if length of aString is not equal to 1 then return false –指定文字コードが指定フォント中に存在するかチェック set fRes to retGlyphsInFont(aFontName, id of aString) of me if fRes = false then return false set aThreadShould to 768 * aThread if (chkMultiByteChar(aString) of me) = false then set spaceChar to string id 12288 –全角スペース(UTF-16) else set spaceChar to string id 32 –半角スペース end if set fillColor to NSColor’s whiteColor –塗り色 set bString to aString & " " –処理内容の帳尻合わせ(そのままだと右端が欠けるのでスペースを入れた) set anAssrStr to makeRTFfromParameters(bString, aFontName, aFontSize, -2, (aFontSize * 1.2)) of me set aSize to anAssrStr’s |size|() if class of aSize = record then set attrStrWidth to width of aSize set attrStrHeight to height of aSize else if class of aSize = list then –macOS 10.13.xのバグ回避 copy aSize to {attrStrWidth, attrStrHeight} end if set {xPos, yPos} to {0, 0} set tmpImg1 to makeImageWithFilledColor(attrStrWidth, attrStrHeight, fillColor) of me set tmpImg2 to drawAttributedStringsOnImage(tmpImg1, anAssrStr, xPos, yPos) of me set aRawimg to NSBitmapImageRep’s imageRepWithData:(tmpImg2’s TIFFRepresentation()) –画像から順次指定座標の色データを拾って花文字listに反映 set strList to {} repeat with y from 1 to attrStrHeight – 1 set strListX to {} repeat with x from 0 to attrStrWidth – 1 set tmpCol to getColorFromRawImage(aRawimg, x, y) of me if tmpCol is not equal to false then if tmpCol is not equal to {255, 255, 255} then copy tmpCol to {tmpR, tmpG, tmpB} if (tmpR + tmpG + tmpB) < aThreadShould then set the end of strListX to aString else set the end of strListX to spaceChar end if else set the end of strListX to spaceChar end if end if end repeat set the end of strList to strListX end repeat –2D List→Text set aRes to list2dToStringByUsingDelimiters(strList, "", return) of me if incFontName = true then set fName to getDisplayedNameOfFont(aFontName) of me set aRes to "■" & fName & return & return & aRes end if return aRes end getHanamojiStr –指定Raw画像中の指定座標のピクセルの色をRGBで取り出す on getColorFromRawImage(aRawimg, x as real, y as real) set aRatio to getImageRatio() of me –Retina Display対応 set origColor to (aRawimg’s colorAtX:(x * aRatio) y:(y * aRatio)) set srgbColSpace to NSColorSpace’s deviceRGBColorSpace if srgbColSpace = missing value then return false set aColor to (origColor’s colorUsingColorSpace:srgbColSpace) set aRed to (aColor’s redComponent()) * 255 set aGreen to (aColor’s greenComponent()) * 255 set aBlue to (aColor’s blueComponent()) * 255 return {aRed as integer, aGreen as integer, aBlue as integer} end getColorFromRawImage –画像のうえに指定のスタイル付きテキストを描画して画像を返す on drawAttributedStringsOnImage(anImage, anAssrStr, xPos as real, yPos as real) anImage’s lockFocus() anAssrStr’s drawAtPoint:(current application’s NSMakePoint(xPos, yPos)) anImage’s unlockFocus() return anImage end drawAttributedStringsOnImage –書式つきテキストを組み立てる on makeRTFfromParameters(aStr as string, fontName as string, aFontSize as real, aKerning as real, aLineSpacing as real) set aVal1 to NSFont’s fontWithName:fontName |size|:aFontSize set aKey1 to (NSFontAttributeName) set aVal2 to NSColor’s blackColor() set aKey2 to (NSForegroundColorAttributeName) set aVal3 to aKerning set akey3 to (NSKernAttributeName) set aVal4 to 0 set akey4 to (NSUnderlineStyleAttributeName) set aVal5 to 2 –all ligature ON set akey5 to (NSLigatureAttributeName) set aParagraphStyle to NSMutableParagraphStyle’s alloc()’s init() aParagraphStyle’s setMinimumLineHeight:(aLineSpacing) aParagraphStyle’s setMaximumLineHeight:(aLineSpacing) set akey7 to (NSParagraphStyleAttributeName) set keyList to {aKey1, aKey2, akey3, akey4, akey5, akey7} set valList to {aVal1, aVal2, aVal3, aVal4, aVal5, aParagraphStyle} set attrsDictionary to NSMutableDictionary’s dictionaryWithObjects:valList forKeys:keyList set attrStr to NSMutableAttributedString’s alloc()’s initWithString:aStr attributes:attrsDictionary return attrStr end makeRTFfromParameters –指定サイズの画像を作成し、背景を指定色で塗る on makeImageWithFilledColor(aWidth as real, aHeight as real, fillColor) set anImage to NSImage’s alloc()’s initWithSize:(current application’s NSMakeSize(aWidth, aHeight)) set aRatio to getImageRatio() of me –Retina Display対応 anImage’s lockFocus() set theRect to {{x:0, y:0}, {width:aWidth * aRatio, height:aHeight * aRatio}} set theNSBezierPath to NSBezierPath’s bezierPath theNSBezierPath’s appendBezierPathWithRect:theRect fillColor’s |set|() theNSBezierPath’s fill() anImage’s unlockFocus() return anImage end makeImageWithFilledColor –2D Listをアイテム間および行間のデリミタを個別に指定してテキスト変換 on list2dToStringByUsingDelimiters(aList as list, itemDelimiter, lineDelimiter) set outList to {} repeat with i in aList set aStr to listToStringUsingTextItemDelimiter(i, itemDelimiter) of me set the end of outList to aStr end repeat set bStr to listToStringUsingTextItemDelimiter(outList, lineDelimiter) of me return bStr end list2dToStringByUsingDelimiters on listToStringUsingTextItemDelimiter(sourceList as list, textItemDelimiter) set CocoaArray to NSArray’s arrayWithArray:sourceList set CocoaString to CocoaArray’s componentsJoinedByString:textItemDelimiter return (CocoaString as string) end listToStringUsingTextItemDelimiter –ユーザー環境にインストールされているすべてのフォントのPostScript名とグリフ数を返す on getEveryFontPSNameANdGlyphsNum(aStr) set aFontList to NSFontManager’s sharedFontManager()’s availableFonts() set thePred to NSPredicate’s predicateWithFormat:"NOT SELF BEGINSWITH ’.’" set aFontList to (aFontList’s filteredArrayUsingPredicate:thePred) as list set aList to {} repeat with i in aFontList set aName to contents of i set aNum to countNumberOfGlyphsInFont(aName) of me set dName to getDisplayedNameOfFont(aName) of me set fRes to retGlyphsInFont(aName, id of aStr) of me if fRes = true then set the end of aList to {fontName:aName, fontNum:aNum, dispName:dName} end if end repeat return aList end getEveryFontPSNameANdGlyphsNum –指定Postscript名称のフォントに定義されている文字数を数えて返す on countNumberOfGlyphsInFont(fontName as string) set aFont to NSFont’s fontWithName:fontName |size|:9.0 if aFont = missing value then return false set aProp to aFont’s numberOfGlyphs() return aProp as number end countNumberOfGlyphsInFont –フォントのPostScript NameからDisplayed Nameを取得 on getDisplayedNameOfFont(aName as string) set aFont to NSFont’s fontWithName:aName |size|:9.0 set aDispName to (aFont’s displayName()) as string return aDispName end getDisplayedNameOfFont –全角文字が存在するか on chkMultiByteChar(checkString as string) set aStr to NSString’s stringWithString:checkString set aRes to aStr’s canBeConvertedToEncoding:(current application’s NSASCIIStringEncoding) return (aRes as boolean) end chkMultiByteChar –指定名称のフォントに指定の文字コードが含まれているかチェック on retGlyphsInFont(fontName as string, strCode as integer) set aFont to NSFont’s fontWithName:fontName |size|:24.0 if aFont = missing value then return false set aSet to aFont’s coveredCharacterSet() set aRes to (aSet’s characterIsMember:strCode) as boolean return aRes as list of string or string –as anything end retGlyphsInFont on selectAFont(aString) set fRes to getEveryFontPSNameANdGlyphsNum(aString) of me set theArray to NSArray’s arrayWithArray:fRes set thePred to NSPredicate’s predicateWithFormat:"fontNum > 10000" set bArray to ((theArray’s filteredArrayUsingPredicate:thePred)’s valueForKeyPath:"dispName") as list set thisFont to choose from list bArray return thisFont end selectAFont –Retina Display対応ルーチン on getImageRatio() set retinaF to detectRetinaDisplay() of me if retinaF = true then return 2.0 as real else return 1.0 as real end if end getImageRatio on detectRetinaDisplay() set dispList to current application’s NSScreen’s screens() set retinaF to false repeat with i in dispList set j to contents of i set aDepth to j’s backingScaleFactor() if aDepth > 1.0 then set retinaF to true end if end repeat return retinaF end detectRetinaDisplay on makeNewDocument given parameter:aStr tell application id "com.coteditor.CotEditor" activate set newDoc to make new document tell newDoc set contents to aStr end tell end tell end makeNewDocument |