[an error occurred while processing this directive]
@nifty のメールって、ne.jp に移行したころだったと思うけど、XXX99999 という ID とは別に、別名のアドレスを使えるようになったんですが、旧 NIFTY-Serve 会員はなんか変な命名規約で 任意名.本名@nifty.ne.jp みたいのにされて、ずっと変えられなかったのです。
その制限がようやく緩和されたみたい。
@nifty のメールといえば最近使い始めた「迷惑メールフォルダ」が便利です。
SPAMフィルタで迷惑メールに分類されたメールを隔離して、メーラで受信しないようにしてくれるものです。隔離するだけで、勝手に消されるわけではないので安心です。Web メールの画面から削除したり、通常のメールボックスに戻したりできます。
mac.com のフィルタもかなり性能がいいようですけど、これもなかなかよくって、一日百数十通来ていた迷惑メールのうち、メーラに漏れてくるのは2、3通になりました!
あと、これの面白いところは、SPAM フィルタの学習度が視覚的にわかるというところです。
わかったからといって何の役にも立たないのですが、なんかおもろいのでつい確認してしまいます。
こんな時代だから、SPAM を受け取らない工夫も必要ですが、SPAM を配信させない仕組みのほうも、なんとかならないものですかね。
SPAM といえばスパムおにぎり。
4月中旬の第四次下地島帰省が楽しみでしょうがないです。それだけが今のモチベーションを維持している感じです。
というわけで、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];
フォント属性を中身と縁とで分けて設定します。なんかこの辺の使い方は設計ミスった気もするなぁ。
そんなわけでいつまで続くかはめちゃめちゃ不安ですが、とりあえず『ココア図書館』スタートさせます。
今後は、今回みたいなまとまったものじゃなくて、うちの覚え書きみたいなものになっていくと思っていますが、共有できるものはどんどん共有していきたいものですね。とりあえず次回も文字描画がらみかなぁ?
この期におよんでさらに速くなったようで、魔法みたいですね。普段バッチでしか使わないのであまり速度は意識してないんだけど、確かに速くなってます。
今回、面白いなと思ったのが、XDVD(eXtended DVD) フォーマットでのエンコード。1GOP に含まれるフレーム数を DVD の規定の 18 フレームから、60 フレーム以上に設定することで、圧縮率を上げようというものです。
GOP(Group of Pictures)というのは、再生に必要な全部の情報を含んだフレームで始まって、その差分のフレームが続いて、1GOP を構成します。この一連の画像のグループが連続して、映像になっているわけですが、この XDVD というのは GOP の長さを長くするんですね。つまり、差分で構成されるフレームを多くして、圧縮率を上げるという理屈なのでしょう。
このフォーマットで作成した DVDを焼くには、TMPGEnc DVD Author が必要なんだけど、その縛りに目をつぶればなかなか使えると思いました。今まで、一枚の DVD-R に4〜5話しか焼けなかったのが、今、お試し中の設定だと6〜7話焼けるということで、お得ですね。26話を7枚に焼くか4枚に焼くかって、作業時間的にも結構でかいしね。
ちなみにこの XDVDフォーマットの MPEG は、QuickTime MPEG2 Decoder でも再生できたので、普段の視聴環境には影響ないみたいです。しばらく様子見ながらずっと使って行くかどうか決めたい!
ちゅうか、びっくりしたー前回のココア図書館の記事に 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 の初期もこの方法で書いていましたよ。
ね、これも案外わるくないでしょ。ただ、大量に処理すると時間がかかっちゃうのですよね。しっかし、能登麻美子はいいよねぇ。
ただ、カラオケを気持ちよく歌うためには、文字の見やすさがどうしても必要で、背景の動画やスクリーンセイバーに負けない、しっかりした縁取りが重要ってことで、やっぱ時間がかかっても、苦労してでも、きれいな縁取りを描画していきたい、と思うのでした。
はい、それでは、脳内能登麻美子とバーンナップしてくるので、この辺で失礼します。また次回。
トポステに胸毛が生えてきたというお話。その原因を探るべく、長老に話を聞きにいくハレたちなのですが…。
長老の胸毛がですね、ちゅうかなんだその、胸毛の中の長老がですね。ふつーにしてるんですよ。何事もなかったかのように。いつも通り、こんなのっておかしいぞ!と思うのはハレだけという世界。
長老の胸毛はじめて物語がスタート。古い長老の写真の中に入り込んで、若かりし頃の長老の姿をカメラに収めるグゥ様。
喜べ、お宝写真いっぱい撮れたぞ。さてネットにアップするか。
とか言ってるし!
ところが、長老の胸毛が爆発的に増殖する瞬間のシャッターチャンスを逃してしまいます。でもグゥ様は
しかたない、(ピー)X で落とすか。
と、まったくあわてません。最近のジャングルはすごいですね。ファイル共有もありなんですね。
でも一番面白かったのはやっぱ長老の中の人を想像したとき。玄田哲章が長老の声当ててると思うだけでおもろくておもろくて。
アイキャッチの後は唐突に話が変わって、ラヴェンナのおつかい話。
全編ラヴェンナにフォーカスしていて、ハレもグゥもほとんど出てきません。普段日の当たらないラヴェンナですが、出ずっぱりでしゃべりっぱなしなのです。
白鳥由里声で、もともとかわいらしい感じだったけど、心にはあんまり残ってませんでした。でも、なんか気に入ってきましたよ。相当かわいいです。単純ですね。
あと、映像特典としてアフレコ風景を脚色した寸劇が入ってました。愛河里花子の動きがおもろいです。これも次回に続くようでめちゃめちゃ楽しみ。
詳しくはかすみを参照してほしいわけですけど、この一年、毎週のように女医ハックをしていながら、これまで気づけなかったのですよね、この方法。
背面の「入力1」という赤白端子にステレオ入力をするのですけど、この時点で本家の待機中の音楽はまだ鳴っています。これが落とし穴でしたー!
それでも気にすることなくハックの音楽を再生すればよかったんです。そうすると、入力端子の横にある「自動切替感度」というつまみの設定値(うちらは中にしています)に従って、入力1の音声を感知して、その音声に切り替えてくれるのです。
これまでは、前面の司会用マイク端子にモノラル入力していました。HyperJOY V1 だと司会用端子にはエフェクトがかからないのですが、V2 からはエフェクトかかってしまうようになりました。そういうわけで困っていたところだったのです。もしかして他の持ち込みカラオケグループのみなさんは知ってたですか?
ちゅうかステレオ最高!すごい迫力です。カラオケ部屋の音響で、原音のまま歌えるわけですから!HackENT の表示のきれいさに加えて、音も劇的に変わったのです!
この方法は、クロ@ロボ部とえぎょによって確立されました。今や DMNG メンバーのみならず、ロボ部内でも女医ハックは行われているようです。
公開するにはもう少し練らないといけないけど(てゆか今年になって0から作り直し始めちゃったしNE!)、すこしづつ輪が広がっているのも開発者としてはうれしいものですね。
さて、この方法、一個だけ難点があって、ハック側の音声がなくなると、本家の待機中の音楽に戻っちゃうということ。そんで切り替えの検知には1秒弱かかるので、ハック側で再生する曲の頭がちょっと欠けてしまいます。
だけど、女医ハックの仕組みはうちらが作っているわけだからどうにでもできるでしょう。今は、カラオケ再生開始のときの曲名の表示時に、人間には聞こえない周波数の音を流して、強制的に入力端子のほうに切り替えさせようとしています。
2004年3月中旬のだめちゅんにっき