Hatena::Groupiphone-dev

iOS プログラミングメモ

2008-12-26 (Fri)

カスタムフォントの組み込み 12:24  カスタムフォントの組み込み - iOS プログラミングメモ を含むブックマーク

SkyBook の情報を追っかけている人はご存知でしょうが、明朝フォントの組み込みが出来ました。なぜか日本語で解説したサンプルがなくて四苦八苦しましたが、なんとか実現する事が出来ました。以下やり方を書いておきますので、他の青空文庫ビューワでも早晩対応されるでしょう。逆に言うと、対応されない青空文庫ビューワには将来はないと断言しておきます。

まずプロジェクトに適当なフォントファイルを追加します。例えば、IPA 明朝フォントの ipam.ttf を追加したとして話を進めます。

そんでもってコードのサンプルです。以下のコードは UIView を継承したクラスに書く事になると思います。とりあえずの動作チェックとして、drawRect の中に書けば良いでしょう。

// [フォントデータの読み込み]
// bundle ディレクトリがデータを読み込みます
NSString *fontPath = [[NSBundle mainBundle] pathForResource:@"ipam" ofType:@"ttf"];
CGDataProviderRef fontDataProvider = CGDataProviderCreateWithFilename([fontPath UTF8String]);
CGFontRef _cgFont = CGFontCreateWithDataProvider(fontDataProvider);
CGDataProviderRelease(fontDataProvider);
// この時点で、メモリ使用量が7メガほどになります。
// 複数のカスタムフォントを読み込むと多分死にます。

// [フォントの指定]
// View の context に対してフォントの設定を行ないます。
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFont(context, _cgFont);
CGContextSetFontSize(context, 20);

// [回転]
// iPhone の座標系と Core Graphics の描画処理に相違があって
// そのまま描画をすると反転してしまうので、CGContextSetTextMatrix で反転させています。
// → 参考: http://idlysphere.blog66.fc2.com/blog-entry-153.html
CGAffineTransform transform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
CGContextSetTextMatrix(context, transform);

// [テキストの描画]
// テキストを unicode 文字列に分解してさらにグリフコードを取得します。
// グリフコードは各フォント毎に異なるので、その変換です。
// 最後に、指定したポジションに文字列を描画しています。
NSString *str = @"テスト文字列だよ";
CGGlyph _glyphs[[str length]];
unichar _chars[[str length]];
int i;
for(i = 0; i < [str length]; i++) {
   _chars[i] = [str characterAtIndex:i];
}
CGFontGetGlyphsForUnichars(_cgFont, _chars, _glyphs, [str length]);
CGContextShowGlyphsAtPoint(context, 0, 20, _glyphs, [str length]);

// [フォントデータの開放]
// これを忘れるともの凄いメモリリークになるので注意!
CGFontRelease(_cgFont);

// 以上で終わり

実は CGFontGetGlyphsForUnichars はヘッダファイルにも書いてない undocumented な関数なので、このままやると warning が出ます。適当なヘッダファイルとかに以下のコードを入れておけば warning は出なくなります。

bool CGFontGetGlyphsForUnichars(CGFontRef, unichar[], CGGlyph[], size_t);

文字の色に関しては、CGContextSetFillColorWithColor とか使って出来ない事もないですが、普通に UIColor を使った方が簡単だと思いますしおすすめです。

本当は、商業的な理由により SkyBook の新バージョンがストアに並んでから書こうと思ってたんですが、ネイティブアプリスレ で試行錯誤中のようなので、もう書く事にしました。規制中なのであっちに書き込む事が出来なくて歯がゆいわけですが。●買えば規制中でも書き込み出来んの?

クラス化のすすめ

コードのコメントにも書いてありますが、iPhone 的に見てメモリ圧迫量がいささか大きいです。しかもフォントの読み込みの部分は若干重い処理になるので、CGFontRef の生成は別のクラスに任せておいて、View にそのオブジェクトを渡してフォントのオブジェクトはコントローラで扱うって言うのがオブジェクト指向的にも良いんじゃないでしょうか。

例えば、こんなん。

// SomeViewController
CustomFont *custom = [[CustomFont alloc] init];
[[SomeView alloc] initWithFont:custom]

この辺のサンプルプロジェクトは、多分誰かが作る。

米国に挑む人 18:42  米国に挑む人 - iOS プログラミングメモ を含むブックマーク

こんな集まりがあったなんて全然耳に入ってこなかったなー。iPhone Developer Japan か。入ってみようかと思ったけど、クローズドなのはちょっと…。

ohnoohno2008/12/30 04:21どうもohnoです。
その節はありがとうございました〜。

既にご存知でしたらすいません、長音記号の横から縦への変換についてです。
「ー」を縦にしたい場合、横のグリフコード660を7891に変換すれば縦書きになります。
ただ、あくまでもフォントに縦書き長音記号がある場合となります。

Adobe-Japan1-6に対応しているフォントならOKかと。
http://www.adobe.com/devnet/font/pdfs/5078.Adobe-Japan1-6.pdf

失礼いたしましたー。

ktakayamaktakayama2008/12/31 23:15ありがとうございます。
これで縦書き用の文字使えそうです。

トラックバック - http://iphone-dev.g.hatena.ne.jp/ktakayama/20081226