Cocoaには、より高度なテキスト描画のために、NSTextStorage、NSTextContainer、NSLayoutManagerという3つのクラスがあります。
NSTextStorageはNSMutableAttributedStringのサグクラスで、描画する文字列を格納します。NSTextContainerはテキストを描画する領域を計算します。そして、それら情報をもとにNSLayoutManagerが、テキストの描画処理を行います。特に、NSLayoutManagerは、テキスト描画の際に一度行われた計算結果などをキャッシュするため、テキストの描画に関して高いパフォーマンスを誇ります。
また、これらのクラスを応用することで、曲線に沿って文字を並べたり、図形の周囲にテキストを回り込ませたりといった、特殊なレイアウトも可能になります。
NSStringでdrawAtPoint:withAttributes:を使うと、内部でNSLayoutManagerなど3つのオブジェクトが生成されて、テキストの描画が実行されます。しかし、NSStringは描画が終わるとこれら3つのオブジェクトを破棄してしまうので、描画効率は悪いです。もし、テキストの編集などで、頻繁に再描画が繰り返されるなら、NSStringよりもNSLayoutManagerを使った方がよいでしょう。
NSLayoutManagerを使ってテキストの描画を行うには、まずNSTextStorage、NSTextContainer、NSLayoutManagerの3つのオブジェクトを生成し初期化します。
NSTextStorage* textStorage; NSTextContainer* textContainer; NSLayoutManager* layoutManager; textStorage = [[NSTextStorage alloc] initWithString:@"Hello"]; NSSize viewSize = [self bounds].size; textContainer = [[NSTextContainer alloc] initWithContainerSize:viewSize]; layoutManager = [[NSLayoutManager alloc] init]; [textStorage addLayoutManager:layoutManager]; [layoutManager addTextContainer:textContainer]; [textContainer release]; [layoutManager release];
そして、drawRect:メソッド内などで、NSLayoutManagerのdrawGlyphsForGlyphRange:atPoint:メソッドを呼びます。
NSRange range = [layoutManager glyphRangeForTextContainer:textContainer]; NSPoint point = NSMakePoint(10.0, 10.0); [layoutManager drawGlyphsForGlyphRange:range atPoint:point];
drawGlyphsForGlyphRange:atPoint:は、テキストを描画する座標に加えて、描画するグリフの範囲を指定します。グリフとは文字のドットパターンのことで、日本語文字の場合、1文字=1グリフとなります。NSTextContainerで示された領域内の全てのグリフを描画範囲として指定するには、[layoutManager glyphRangeForTextContainer:textContainer]の戻り値を使います。