CoreText 概述

為個(gè)人閱讀快速翻譯, 難免有誤, 見諒, 原文(Apple 文檔)

Core Text 概述

Core Text 是一種強(qiáng)大的底層文本布局和處理字體的技術(shù), Core Text 直接使用 Core Graphics(CG), 通常也叫做 Quartz, 是iOS 和 OSX 底層的高速二維圖像渲染引擎.

注意: Core Text 是為上層文本處理所開發(fā)的框架, 普通開發(fā)者在 iOS 中應(yīng)該使用 Text Kit, OSX 中應(yīng)該使用 Cocoa text system
譯者注: 言外之意就是普通玩家用封裝好的Text Kit, 高玩可嘗試, 不推薦低端用戶使用~

Core Text 協(xié)調(diào)了文本布局, 上層字體框架, Quartz 提供的底層文本和字體框架.
Quartz 框架負(fù)責(zé)字形和位置. Core Text 負(fù)責(zé)從字符到字體的映射, 在調(diào)用Quartz 渲染這些文本之前, 它會(huì)分離出樣式, 字體和其他一些屬性. Quartz 是唯一的底層圖形繪制方法. 因?yàn)?Core Text 已經(jīng)以一定格式提供給Quartz 所有需要的信息. 這樣結(jié)能夠有很高的文本渲染性能.

多線程 : Core Text 支持多線程,是線程安全的, 前提是不在線程之間改變?nèi)魏螀?shù), 比如共享屬性字符串(attributed string)

Core Text 是一系列 C語言平臺(tái)無關(guān)的 API

iOS 和 OS X 平臺(tái)上 Core Text API 基本一致, 到那時(shí) OS X 版本提供了更為豐富的字體管理 API, 包括可變的字體集合. 但是, UIKit 和 AppKit 在不同平臺(tái)上有很大區(qū)別. 比如, 你必須有一個(gè)Quartz圖形上下文來渲染 Core Text 生成的圖形, 和在不同平臺(tái)上獲取的圖像上下文也不一樣. 在 iOS 平臺(tái)上, 一個(gè)視圖對(duì)應(yīng)的是 UIView的子類, 而在 OS X平臺(tái)上, 一個(gè)視圖對(duì)應(yīng)的是NSView 的子類. 你必須清楚, CGRect 對(duì)象傳給 UIView 的 drawRect:方法, 而 OS X 傳遞的是一個(gè)NSRect對(duì)象. 你可以使用NSRectToCGRect方法來講 NSRect轉(zhuǎn)換成CGRect.

圖形上下文由 UIViewUIGraphicsGetCurrentContext 方法返回. 這個(gè)上下文是由 Quartz圖形上下文未經(jīng)修改上下翻轉(zhuǎn)過來的(UIView 返回的上下文原點(diǎn)在左上角), 所以在 iOS 中你必須將其翻轉(zhuǎn)過來, OS X 不需要翻轉(zhuǎn), 詳情可以去Listing 2-1 查看一些示例代碼.

譯者注: Quartz 和 OS X 原點(diǎn)在窗口左下角, 而 iOS 的原點(diǎn)在左上角, 所以需要翻轉(zhuǎn)

Core Text 盡可能的使用系統(tǒng)數(shù)據(jù)類型和服務(wù), 所以你也可以使用 OS X 或者 iOS 的核心框架. 比如, Core Text 使用 Core Foundation 對(duì)象作為輸入輸出參數(shù), 所以你當(dāng)然可以將其存到 Core Foundation 集合類里面. 其他Core Text使用的對(duì)象比如 CGPath, 是由 Core Graphics 框架提供.

Core Text 對(duì)象是一系列 C語言不透明類型(Opaque Types)

在 OS X 和 iOS 中, 許多底層庫為了速度和簡(jiǎn)潔,使用了純 C 編寫. 當(dāng)你使用 Core Text 的時(shí), 你使用一系列 C 函數(shù), 比如CTFramesetterCreateWithAttributedStringCTFramesetterCreateFrame 來替代 Objective-C 類和方法.

Core Text 不透明類型(Opaque Types)

Core Text 布局引擎經(jīng)常跟屬性字符串(CFAttributedStringRef)和圖形路徑(CGPathRef)打交道. 屬性字符串對(duì)象將一個(gè)用于顯示的文本和一些定義格式樣式的屬性封裝起來, 比如字體和顏色. Core Text 使用屬性字符串里的信息來執(zhí)行字符到圖像的轉(zhuǎn)換.

圖形路徑定義一幀文本的形狀. 在 OS X 10.7和 iOS 3.2及更新版本, 這個(gè)路徑可以不是矩形

CFAttributedString 的引用類型 CFAttributedStringRef, 和 Foundation 中的 NSAttributedString 是 toll-free bridged的. 這就意味著 Core Foundation 類型在函數(shù)或方法中可以和bridged Foundation 對(duì)象互相替換的. 因此, 在一個(gè)方法中, NSAttributedString *參數(shù)是可以傳入一個(gè)CFAttributedStringRef類型. 反之, 在CFAttributedStringRef 參數(shù)可以傳入一個(gè)NSAttributedString 實(shí)例(可能需要轉(zhuǎn)換類型來消除編譯器警告) 這個(gè)同樣適用于NSAttributedString的子類.

屬性本質(zhì)就是一系列鍵值對(duì), 定義部分字符的屬性特征, 使用相同屬性的字符根據(jù)range 進(jìn)行分組. 屬性使用CFDictionary對(duì)象傳入屬性字符串,而后被取出來. 應(yīng)用一個(gè)樣式到一個(gè)圖像運(yùn)行器(CTRun 對(duì)象), 創(chuàng)建一個(gè)CFDictionary對(duì)象來存儲(chǔ)你想要應(yīng)用的屬性., 然后創(chuàng)建一個(gè)屬性字符串, 把這個(gè)字典作為參數(shù)傳入. 或者, 你可以應(yīng)用這些屬性到一個(gè)已經(jīng)存在的CFMutableAttributedString對(duì)象中. 即使CFDictionaryRefNSDictionary 是toll-free bridged, 但字典中存儲(chǔ)的屬性對(duì)象可能并不是.

圖 1-1顯示了Core Text 對(duì)象運(yùn)行時(shí)層級(jí). 最上層是一個(gè)framesetter對(duì)象(CTFramesetterRef). 一個(gè)屬性字符串和一個(gè)圖像路徑作為輸入, framesetter可以生成一個(gè)或多個(gè)幀文本(CTFrameRef). 每個(gè)CTFrame對(duì)象代表著一個(gè)段落.

圖 1-1 Core Text 布局引擎架構(gòu)

framesetter 調(diào)用一個(gè)typesetter對(duì)象生成 frame, 在 frame 中放置文本, framesetter將段落樣式應(yīng)用到這個(gè) frame 上, 包括對(duì)齊方式, 制表符, 行間距, 縮進(jìn)和斷句模式. typesetter 將屬性字符串中的字符轉(zhuǎn)換成字形, 并將字形填充到文本框的行中

每個(gè) CTFrame 對(duì)象包括段落的行對(duì)象(CTLine). 每個(gè)行對(duì)象代表著一行文本. 一個(gè) CTFrame對(duì)象可能只包含一行很長(zhǎng)的CTLine 對(duì)象或者很多行. 在framesetting操作過程中, 會(huì)創(chuàng)建行對(duì)象. 這些行對(duì)象跟 frame 一樣, 可以直接將自己繪制到圖像上下文中.

每個(gè)行對(duì)象包含一個(gè)數(shù)組的glyph run(CTRun)對(duì)象. 一個(gè)glyph run 每一行對(duì)象都包含一系列連續(xù)不斷的字形,這些字形都包含相同的屬性和方向. typesetter會(huì)在從字符產(chǎn)生行時(shí)創(chuàng)建glyph run對(duì)象. 這就意味著, 一個(gè)行對(duì)象是由一個(gè)或多個(gè)glyphs run 構(gòu)成. glyphs run 可以將自己繪入圖像上下文中, 若非必要時(shí),大多數(shù)客戶端不需要直接跟 glyph run 打交道.

字體對(duì)象

字體對(duì)象為字形之間的布局提供支持, 然后將當(dāng)前字體繪入圖像上下文. Core Text 字體不透明對(duì)象, CTFont, 是一個(gè)特殊的字體實(shí)例, 封裝了許多實(shí)例. CTFontRef為其引用類型, 和 iOS 中的 UIFont, OS X 的 NSFont 是 oll-free bridged, 你可以指定字體大小和變換矩陣, 給這字體實(shí)例具體特征. 對(duì)于大小特定的字體, 你可以從字體對(duì)象中查詢到很多關(guān)于字體相關(guān)的信息, 比如字符到字形的映射, 編碼, 字體度量信息, 和字形信息等等. 字體度量是一些參數(shù), 比如, 升序, 降序, 開頭, 頭高等等. 字形信息包含參數(shù)比如, 矩形邊界和字形步進(jìn).

Core Text 字體對(duì)象是不可變的, 所以可以被多個(gè)操作, 工作隊(duì)列或者線程使用. 有很多方式創(chuàng)建字體對(duì)象. 首選方法是從一個(gè)字體描述符創(chuàng)建一個(gè)字體對(duì)象CTFontCreateWithFontDescriptor, 還有其他很多方便的 API, 具體使用哪個(gè)要看你的目的. 比如, 你可以使用字形的 PostScript 名字(CTFontCreateWithName
)或者 一個(gè) Core Graphics 字體引用(CTFontCreateWithGraphicsFont
), CTFontCreateUIFontForLanguage 在所使用的應(yīng)用本地創(chuàng)建一個(gè)用戶接口字體引用.

Core Text 字體引用提供了一個(gè)復(fù)雜的自動(dòng)字體替換機(jī)制, 叫做字體串聯(lián).
根據(jù)字體的特征挑選合適的字體來替換一個(gè)找不到的字體, 字體串聯(lián)基于串聯(lián)的列表, 是一系列有序的字體描述符. 在一個(gè)字體創(chuàng)建的時(shí)候, 會(huì)指定一個(gè)系統(tǒng)默認(rèn)的串聯(lián)列表(根據(jù)用戶的語言設(shè)置和當(dāng)前字體有不同的表現(xiàn))和一個(gè)字體串聯(lián)列表. 串聯(lián)機(jī)制可以使用字體描述符的信息, 根據(jù)樣式為字符匹配字體 CTFontCreateForString 函數(shù)可以使用串聯(lián)列表來挑選合適的字體去編碼對(duì)應(yīng)的字符串. 使用kCTFontCascadeListAttribute 屬性來指定和檢索字體串聯(lián)列表.

字體描述符

字體描述符, 用CTFontDescriptor 不透明類型表示, 提供了完全從一個(gè)屬性字典描述字體的機(jī)制, 和易用的創(chuàng)建新字體的設(shè)施. 你可以根據(jù)字體描述符創(chuàng)建字體, 也可以從一個(gè)字體對(duì)象中獲取字體描述符, 然后用其來創(chuàng)建一個(gè)新的字體對(duì)象. 你可以創(chuàng)建字體描述符來部分創(chuàng)建字體, 比如, 只是字體簇名稱或者比重, 然后就可以找到系統(tǒng)中與之匹配的所有字體.iOS 中的UIFontDescriptor , OS X 中的NSFontDescriptorCTFontDescriptorRef 類型是toll-free bridged.

我們使用創(chuàng)建一個(gè)包含PostScript 名字, font family, 樣式以及其他特性(比如, 粗體或斜體)等的字體屬性字典來作為CTFontDescriptor 對(duì)象. 你可以使用字體描述符創(chuàng)建一個(gè)CTFont 對(duì)象. 字體描述符可以被序列化并存儲(chǔ)到文檔中來進(jìn)行持久化.
圖 1- 2描述了字體系統(tǒng)使用字體描述符創(chuàng)建指定字體實(shí)例

圖 1-2 從字體描述符創(chuàng)建字體

你可以認(rèn)為字體描述符就是字體系統(tǒng)中的查詢條件, 你可以創(chuàng)建一個(gè)不完整的字體描述符, 屬性字典里只是一部分的值. 比如, 如果你指定了 font family, 不指定字體的所有特性, 你就能獲取到該 font family 的所有字體, 但是如果你指定了kCTFontTraitsAttribute的值為kCTFontTraitBold, 那么就能查詢到該 font family 下的所有粗體. 通過CTFontDescriptorCreateMatchingFontDescriptors提供可以提供一個(gè)跟查詢匹配的完整的字體描述符列表.

在 iOS 6.0及以后版本, 應(yīng)用可以使用CTFontDescriptorMatchFontDescriptorsWithProgressHandler下載所需未安裝的字體, 下載的字體并不是安裝后永遠(yuǎn)不變的, 系統(tǒng)可能會(huì)在一定情況下將其移除, 支持下載的字體被列在iOS 6: Font listiOS 7: Font list. DownloadFont(在 iOS 開發(fā)庫中)說明了下載技術(shù). 在 OS X 中, 按需下載字體不是必須的, 因?yàn)樗锌捎米煮w都已經(jīng)安裝到系統(tǒng)中了.

字體集合

字體集合是一系列字體組成的組作為一個(gè)單獨(dú)的對(duì)象. CTFontCollection不透明來行代表一個(gè)字體集合. 字體集合提供字體枚舉, 訪問全局和自定義字體集合, 以及訪問包含該字體集合的字體描述符的能力. 舉個(gè)例子, 通過CTFontCollectionCreateFromAvailableFonts創(chuàng)建一個(gè)包含所有可用字體描述符的集合, 你可以使用這個(gè)集合獲取所有字體描述符.

.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌考余,老刑警劉巖饲窿,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異捆交,居然都是意外死亡淑翼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門品追,熙熙樓的掌柜王于貴愁眉苦臉地迎上來玄括,“玉大人,你說我怎么就攤上這事肉瓦≡饩” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵泞莉,是天一觀的道長(zhǎng)哪雕。 經(jīng)常有香客問我,道長(zhǎng)鲫趁,這世上最難降的妖魔是什么斯嚎? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮挨厚,結(jié)果婚禮上堡僻,老公的妹妹穿的比我還像新娘。我一直安慰自己疫剃,他們只是感情好钉疫,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著慌申,像睡著了一般陌选。 火紅的嫁衣襯著肌膚如雪理郑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天咨油,我揣著相機(jī)與錄音您炉,去河邊找鬼。 笑死役电,一個(gè)胖子當(dāng)著我的面吹牛赚爵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播法瑟,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼冀膝,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了霎挟?” 一聲冷哼從身側(cè)響起窝剖,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎酥夭,沒想到半個(gè)月后赐纱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡熬北,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年疙描,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讶隐。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡起胰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出巫延,到底是詐尸還是另有隱情效五,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布烈评,位于F島的核電站火俄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏讲冠。R本人自食惡果不足惜瓜客,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望竿开。 院中可真熱鬧谱仪,春花似錦、人聲如沸否彩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽列荔。三九已至敬尺,卻和暖如春枚尼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背砂吞。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工署恍, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蜻直。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓盯质,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親概而。 傳聞我的和親對(duì)象是個(gè)殘疾皇子呼巷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容