本文主要來介紹如何使用Cocoa文字系統,在某些情況下你可能需要對想顯示在螢幕上的文字做更多的控制,而不是僅僅使用NSTextField或者NSTextView,有時候你需要更高效地在螢幕上畫文字,而不想使用NSStringDrawing方法。還可能你需要在CGContext上畫文字,再有可能你想在一個Carbon程式中畫文字。
這個時候,你就可能會考慮CoreText了,不過你還可能想相容Mac OS X 10.4。這裡又一個簡單的方法可以滿足你全部的需要。
Cocoa文字系統
這個辦法就是使用Cocoa文字系統。Cocoa文字系統是一組類,NSTextView、NSTextField和NSStringDrawing都會用它們在螢幕上顯示字元。如果你閱讀過蘋果的文檔,可能你會被嚇到,因為蘋果的文檔寫的非常複雜,包括了非常多的類,諸如:NSLayoutManagers, NSTextStorages, NSTextContainers, NSGlyphGenerators, NSTypesetters…不過別怕,實際使用起來還是挺簡單的。
蘋果其實已經在Drawing Text with NSLayoutManager這篇文檔中提供了一個很好的關於如何顯示文字的介紹。
如果你讀過上面的文檔,你可能會發現,你實際上僅僅需要使用三個類就可以在螢幕上顯示任何帶有效果的Unicode字串,這些字串包含在一個由NSLayoutManager控制的方框內。你希望顯示的文字和文字的屬性儲存在NSTextStorage中,需要顯示的位置是由NSTextContainer指定的。另外,如果你建立了這些對象,你還可以將它們緩衝,這樣可以明顯加快顯示速度。
你可以像通常一樣使用+alloc/-init方法建立這些對象,然後告訴layout manager保管這些文字的外觀,告訴text storage保管layout manager。蘋果的例子大概是這樣的:
- NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:@"This is the text string."];
- NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
- NSTextContainer *textContainer = [[NSTextContainer alloc] init];
- [layoutManager addTextContainer:textContainer];
- [textContainer release];
- [textStorage addLayoutManager:layoutManager];
- [layoutManager release];
- // Use the objects.
- [textStorage release];
想在螢幕上顯示這個字串的話,你可以指定顯示的位置,然後告訴layout manager使用drawGlyphsForGlyphRange在螢幕的特定位置顯示。
- [textContainer setContainerSize: rect.size];
- NSRange glyphRange = [layoutManager glyphRangeForTextContainer: textContainer];
- [layoutManager drawGlyphsForGlyphRange: glyphRange atPoint: rect.origin];
還是很簡單的,對吧?有兩件事情需要注意:當你改變文字容器的尺寸時,文字需要重新排列和折行,這些操作可以通過緩衝來加速。另外,你可以直接調用glyphRangeForTextContainer:方法來手動控制文字重排。
如果想在文字中添加特殊風格或者圖片,也很簡單,因為NSTextStorage是NSMutableAttibutedString的子類,所以指定風格、字型都很容易。
測量文字
比如你希望測量一段文字要佔螢幕多大位置,可以先將文字容器的一個屬性:寬或者高設定成一個定值,然後將另外一個屬性設定成一個很大的數值,比如FLT_MAX,然後調用-glyphRangeForTextContainer:方法重排文字,然後就可以通過-usedRectForTextContainer:方法擷取到這段文字實際需要佔多大的螢幕空間了:
- [textContainer setContainerSize: NSMakeSize([self bounds].size.width, FLT_MAX)];
- (NSRange) [layoutManager glyphRangeForTextContainer: textContainer]; // Cause re-layout.
- NSRect neededBox = [layoutManager usedRectForTextContainer: textContainer];
在Quartz或Carbon中使用Cocoa文字系統
Carbon直接使用Quartz的API。另外,在OpenGL材質中、PDF中和其他特殊地方顯示文字也都直接使用Quartz。那麼,如何才能在Quartz中使用上面所說的方法呢?你無法擷取到NSGraphicsContext,你只有CGContext,怎麼辦呢?其實不難,NSGraphicsContext中都帶有一個CGContext,而且可以互相轉換。這樣,比如你擷取到一個叫做inContext的CGContextRef變數,你可以用下面的方法實現文字顯示:
- [NSGraphicsContext saveGraphicsState];
- NSGraphicsContext
- * context = [NSGraphicsContext graphicsContextWithGraphicsPort: inContext flipped: true];
- [NSGraphicsContext setCurrentContext: context];
- // Do Cocoa drawing here.
- [NSGraphicsContext restoreGraphicsState];
這樣做的好處是Cocoa文字系統不僅僅比ATSUI簡單,而且它的設計非常類似CoreText。因此如果你希望在你的軟體未來的某個版本中使用CoreText,你可以現在就用這種方式顯示文字,那麼將來的轉換會非常方便。
小結:關於如何使用Cocoa文字系統的內容介紹完了,希望通過本文的學習對你有所協助!