3月20日(土)
Xcodeプログラミング入門
注文していた『Xcodeプログラミング入門』という本が届きましたよ。
予想通り、Xcode の“使い方”の本でした。随分と丁寧な解説の Xcode チュートリアルになってます。それから InterfaceBuilder についてもかなり細かい単位で図版とともに説明されています。
そう!これこれ!こういう本がほしかったんですよ。ええと…3ヶ月前にね。
というのも、チュートリアルであってリファレンスではないからです。わからないなりに使っていても習得できるレベルの話なので、それ以上深くは踏み込めません。正直言って今となっては必要ないと言える内容でした。
これね、重い腰を上げて Cocoa の勉強を始めた1月の頭くらいにほしかったです。いや、立ち読みしたかった。
そんなわけで、これから始める人にはとっかかりのチュートリアルとして、よい本だと思います。
それはそれとして1月から Cocoa で始めた HackENT の開発は、それなりに軌道に乗って、ちゃんと動くレベルのものになってきていると思うわけです。
こういう本も大事なんだけど、結局開発のための情報は Web に頼ることが多いです。本には体系的なものを期待してしまうけど、これまでお世話になった Web の情報はほとんどが断片的なものであったり、開発者が悩んで愚痴をこぼしている日記だったりしました。
というわけでそんな情報を、期待している人のために体系的に用意するのではなくて、たまたま Google で引っかかってくる程度には残しておきたいと思いはじめました。
どこまで続くかわからんけど、ちゅうか開始できるかどうかも危ういけど、Cocoa の開発情報の断片を『ココア図書館』というカテゴリでこの日記に追加していくつもりです。

ただ、問題がひとつあって、このロゴを作った段階でもうかなり満足してしまっていて、なんかもうこれでいいやー、みたいな感じにはなっています。
3月22日(月)
ココア図書館 #01 - 縁取り付きの文字列を描画する
CV:斎藤千和で人里離れた山の奥にある小さなサイト。そこにはゆかり姫ラブな管理人と、女医ハック狂いの管理人と、Cocoa の勉強を始めた管理人がいるのです(←なんか失敗っぽい)。
というわけで、Cocoa による HackENT の開発を通して、もしかしたら誰かの役に立つかもしれなかったり、再利用できそうなものをまとめていく『ココア図書館』です。
第一回目の今回はカラオケには必須な縁取り文字の書き方です。
ちょっと気を引くために、こんなネタを選んでみました。

こんな感じに縁取りされた文字を書くのは結構難儀なんですよ。
-(void) writeBorderString: (NSString *) string
AtPoint: (NSPoint) point
withAttribute: (NSMutableDictionary *) fontAttribute
andBorderAttribute: (NSMutableDictionary *) fontBorderAttribute
borderWidth: (float) width
/*
string:描画する文字列
point:描画開始位置
fontAttribute:塗りつぶしの属性(NSFontAttributeName、NSForegroundColorAttributeNameのみ)
fontBorderAttribute:縁取りの属性(NSForegroundColorAttributeNameのみ)
width:縁取りの幅
*/
{
NSBezierPath *path = [[NSBezierPath bezierPath] autorelease];
NSTextStorage *textStorage = [[[NSTextStorage alloc] initWithString:string
attributes:fontAttribute] autorelease];
NSLayoutManager *layoutManager = [[[NSLayoutManager alloc] init] autorelease];
NSTextContainer *textContainer = [[[NSTextContainer alloc] init] autorelease];
NSRange range;
float x = point.x;
float y = point.y;
unsigned glyphLength;
/* NSLayoutManager(グリフのレイアウトおよび描画、生成)の準備 */
[layoutManager addTextContainer:textContainer];
/* NSTextStorage(文字列を保持している)に、レイアウトを適用する */
[textStorage addLayoutManager:layoutManager];
/* NSTextContainer(テキストの描画範囲) */
range = [layoutManager glyphRangeForTextContainer:textContainer];
/* グリフ番号の配列を作成 */
NSGlyph glyph[range.length];
glyphLength = [layoutManager getGlyphs:glyph range:range];
/* 縁取りの描画 */
/* ベジェパスの開始位置を設定 */
/*(descender:g,j,p,q,yなどベースラインより下に伸びている部分を補正する) */
[path moveToPoint:NSMakePoint(x,y-[[fontAttribute objectForKey:NSFontAttributeName] descender])];
/* 縁取りの太さを設定 */
[path setLineWidth:borderWidth];
/* 縁取りの角の丸め */
[path setLineJoinStyle:NSRoundLineJoinStyle];
/* 縁取りの色を設定 */
[[fontBorderAttribute objectForKey:NSForegroundColorAttributeName] set];
/* 得たグリフ番号の配列からベジェパスを作成 */
[path appendBezierPathWithGlyphs:glyph count:glyphLength
inFont:[fontAttribute objectForKey:NSFontAttributeName]];
/* ベジェパスを描画 */
[path stroke];
/* 中身の塗りつぶし */
/* ベジェパスの開始位置を再度設定(ペン位置を戻す) */
[path moveToPoint:NSMakePoint(x,y-[[fontAttribute objectForKey:NSFontAttributeName] descender])];
/* 塗りつぶしの色を設定 */
[[fontAttribute objectForKey:NSForegroundColorAttributeName] set];
/* ベジェパス内を塗りつぶし */
[path fill];
}キャッチーなネタを選んだら内容が重たくなってしまいました。NSTextStorage に属性付き文字列を格納して、NSLayoutManager でその文字列をグリフ(文字の輪郭とでも言ったらいいのでしょうかね)に変換してレイアウトして、NSTextContainer で描画範囲を確定します。
グリフ番号の配列をもとにしてグリフを得るのですが、最初 NSTextStorage のフォント属性と、描画したいグリフのフォント属性を間違えて設定していたために随分苦労しちゃった。フォントが違えばグリフ番号が違うのも当たり前みたいですね。
さて、この関数ですけど、こんな感じで使います。
[theImage lockFocus];
/* フォント種類とサイズを指定 */
[fontAttribute setObject:[NSFont fontWithName:@"Osaka" size:fontSize] forKey:NSFontAttributeName];
/* フォントの塗りつぶし色を指定 */
[fontAttribute setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName];
/* フォントの縁取り色を指定 */
[fontBorderAttribute setObject:[NSColor blackColor] forKey:NSForegroundColorAttributeName];
[self writeBorderString:string AtPoint:NSMakePoint(0,0)
withAttribute:fontAttribute andBorderAttribute:fontBorderAttribute borderWidth:10.0];
[theImage unlockFocus];
フォント属性を中身と縁とで分けて設定します。なんかこの辺の使い方は設計ミスった気もするなぁ。
そんなわけでいつまで続くかはめちゃめちゃ不安ですが、とりあえず『ココア図書館』スタートさせます。
今後は、今回みたいなまとまったものじゃなくて、うちの覚え書きみたいなものになっていくと思っていますが、共有できるものはどんどん共有していきたいものですね。とりあえず次回も文字描画がらみかなぁ?
3月25日(木)
ココア図書館 #02 - 縁取り付きの文字列を描画する その2
CV:斎藤千和で人里離れた山の奥にある小さなサイト。そこにはゆかり姫ラブな管理人と、女医ハック狂いの管理人と、Cocoa の勉強を始めた管理人がいるのです(←どうやらこの口上が毎回言いたいらしい)。
ちゅうか、びっくりしたー前回のココア図書館の記事に mkino@HAPPY Macintosh Developing TIME!さんがうちの掲示板で反応してくれてました。うれすぃ…。
mkinoさんといえば、Cocoa の世界では大御所じゃないですか。そんな人がこんな人里離れた山の奥にある小さな図書館(やっぱりこれが言いたいらしい)に足を運んでくれるとは!すげいでよ!あひーっ!
はい、それで、本題なんですけど、
NSAttributedStringに、NSStrokeWidthAttributeNameとNSStrokeColorAttributeName を設定してdrawAtPoint:するのも、簡単でいいと思うんですが、どうでしょう?
NSAttributedStringだと、storkeWidthを使うと中身が塗りつぶされないですよね。だから、始めに通常の文字を描いて、重ね書きをするといいと思います。
とのことでした。
そうなんです。楽な方がいいに決まってます。
/* NSStrokeWidthAttributeName は縁取りの幅を指定 */
[fontBorderAttr setObject:[[NSNumber alloc]initWithFloat:10.0]
forKey:NSStrokeWidthAttributeName];
/* NSStrokeColorAttributeName は縁取りの色を指定 */
[fontBorderAttr setObject:[NSColor whiteColor] forKey: NSStrokeColorAttributeName];
[writeStr drawAtPoint:NSMakePoint(x,y) withAttributes:fontBorderAttr];
[writeStr drawAtPoint:NSMakePoint(x,y) withAttributes:fontAttribute];としてあげますと、ちゃんと縁取りで書いてくれますよ。簡単だし、こっちを多用するのがいいと思います。実はこの方法も HackENT の初期段階では使っていました。
だけどカラオケという意味だとこれで書いた文字列がいまいちだったので、前回のまわりくどい方法にたどり着いたんですよ。前回(右側)のと比較してみるとよくわかります。

もう『レモネード』最高なわけですが、縦に並べてみるとこんな感じ。


普通の縁取り効果がほしかったら前者のほうがかっこいいのですが、ことカラオケとなるとやはりボーダーの存在意義が変わってきますよね。
まず角を丸くしたいときは、NSStrokeWidthAttributeName じゃできないんじゃないかと思って早々にあきらめちゃって、最終的に NSGlyph にたどり着いたのですよ。
ちなみに、REALbasic 時代はどうやっていたかといいますと、いわゆる東西南北法(←いま命名)を使ってました。
要は、文字列を書く前に、縁取りしたい色で文字列の東、西、南、北、北東、北西、南東、南西にずらして文字を書いておいて、最後にその上から中身の色で文字列を書いてました。だから1行書くのに都合9回も描画処理するんです。
そうやって描いた文字列はこんな感じです。Cocoa 化した直後、HackENT の初期もこの方法で書いていましたよ。

ね、これも案外わるくないでしょ。ただ、大量に処理すると時間がかかっちゃうのですよね。しっかし、能登麻美子はいいよねぇ。
ただ、カラオケを気持ちよく歌うためには、文字の見やすさがどうしても必要で、背景の動画やスクリーンセイバーに負けない、しっかりした縁取りが重要ってことで、やっぱ時間がかかっても、苦労してでも、きれいな縁取りを描画していきたい、と思うのでした。
はい、それでは、脳内能登麻美子とバーンナップしてくるので、この辺で失礼します。また次回。
3月31日(水)
1年越しの夢かなう〜ステレオハック開始
えぎょ@霞み電波発信所(読めねい)によるとはあひーっ!女医ハックがステレオでできるようになったでよ。これはすげいてすよ(←やめれ)。
詳しくはかすみを参照してほしいわけですけど、この一年、毎週のように女医ハックをしていながら、これまで気づけなかったのですよね、この方法。
背面の「入力1」という赤白端子にステレオ入力をするのですけど、この時点で本家の待機中の音楽はまだ鳴っています。これが落とし穴でしたー!
それでも気にすることなくハックの音楽を再生すればよかったんです。そうすると、入力端子の横にある「自動切替感度」というつまみの設定値(うちらは中にしています)に従って、入力1の音声を感知して、その音声に切り替えてくれるのです。
これまでは、前面の司会用マイク端子にモノラル入力していました。HyperJOY V1 だと司会用端子にはエフェクトがかからないのですが、V2 からはエフェクトかかってしまうようになりました。そういうわけで困っていたところだったのです。もしかして他の持ち込みカラオケグループのみなさんは知ってたですか?
ちゅうかステレオ最高!すごい迫力です。カラオケ部屋の音響で、原音のまま歌えるわけですから!HackENT の表示のきれいさに加えて、音も劇的に変わったのです!
この方法は、クロ@ロボ部とえぎょによって確立されました。今や DMNG メンバーのみならず、ロボ部内でも女医ハックは行われているようです。
公開するにはもう少し練らないといけないけど(てゆか今年になって0から作り直し始めちゃったしNE!)、すこしづつ輪が広がっているのも開発者としてはうれしいものですね。
さて、この方法、一個だけ難点があって、ハック側の音声がなくなると、本家の待機中の音楽に戻っちゃうということ。そんで切り替えの検知には1秒弱かかるので、ハック側で再生する曲の頭がちょっと欠けてしまいます。
だけど、女医ハックの仕組みはうちらが作っているわけだからどうにでもできるでしょう。今は、カラオケ再生開始のときの曲名の表示時に、人間には聞こえない周波数の音を流して、強制的に入力端子のほうに切り替えさせようとしています。


