Apple 的相關博客:
Text Programming Guide for iOS
Core Text Programming Guide
CoreText 框架位置
唐巧博客
基于 CoreText 的排版引擎:基礎
《Core Text Tutorial for iOS: Making a Magazine App》
基于 CoreText 的開源庫
OHAttribtuedLabel
DTCoreText
Nimbus
YYText
M80AttributedLabel
CoreText 引擎的架構
iOS/OSX中用于描述富文本的類是NSAttributedString。NSAttributedString 的 attributes 可以配置字符串中任意區域的,字體顏色,下劃線,斜體,背景顏色。
CoreText 中最重要的兩個概念就是 CTFrameSetter 和 CTFrame。
- 用 NSAttributedString 生成 CTFrameSetter
- CTFrameSetter 是 CTFrame 的工廠,專門用來生產 CTFrame(用 CTFrameSetter 來 生產 CTFrame )
- 用 CTFrame 繪制到 context 上。
(CTLine 和 CTRun 是由屬性文本自動處理的,要進行精細化配置的時候才需要自己處理 CTRun)
CoreText 的簡單使用
使用 CoreText 進行圖文混排其實不是最根本的目的。
CoreText 使用,主要是用來顯示字符串的。
小目標 —— 顯示字符串
下列代碼寫在一個自定義的 UIView 的子類中。
override func draw(_ rect: CGRect) {
super.draw(rect)
// 1. 獲取當前的圖形上下文
let context = UIGraphicsGetCurrentContext()
// 2. 翻轉坐標
context!.textMatrix = CGAffineTransform.identity
context!.translateBy(x: 0, y: self.bounds.size.height);
context!.scaleBy(x: 1.0, y: -1.0);
// 3. 文本繪制的范圍
let path = CGMutablePath()
// 繪制字符串的范圍可以自己通過路徑自己指定
path.addRect(rect)
// 4. 創建屬性字符串
let str: String = "Hello World!"
let attributedString = NSMutableAttributedString(string: str)
// 5. 創建 framesetter
let framesetter = CTFramesetterCreateWithAttributedString(attributedString as CFAttributedString )
// 6. 創建 frame
let frame = CTFramesetterCreateFrame(framesetter, CFRange(location: 0, length: 0), path, nil)
// 7. 繪制
CTFrameDraw(frame, context!)
}
** 文本繪制的過程 **
整個流程大概是:
獲取上下文 ——> 翻轉坐標系 (翻轉坐標主要是由于 UIKit 的坐標系和 CG 框架的坐標系是不一樣的 ) ——> 創建 NSAttributedString ——> 根據NSAttributedString創建CTFramesetter ——>創建繪制區域CGPathRef ——> 根據CTFramesetter 和 CGPath 創建 CTFrame ——> CTFrameDraw 繪制。
**CoreText 視窗組合圖 **
UIGraphicsGetCurrentContext() 獲取的 context 相對于 Quartz ,可以理解為一個畫板。
CTFrame 相對于 CoreText , 也可以理解為一個圖文畫板。最終的目的也就是將 CTFrame 畫板上繪制的圖文 再繪制到 context 上,顯示出來給用戶看。
我們要使用 CoreText 的目的還是要控制 CTFrame 畫板上圖文的繪制。
根據視窗結構圖體現,CTFrame 主要有 CTLine 組成, CTLine 又主要由 CTRun 組成。
注意到上面的示例代碼,發現我們沒有創建 CTLine 和 CTRun,CoreText 會根據 NSAttributedString 的屬性來自動創建 CTRun,CTRun 又組合為CTLine, 每個CTRun對象對應不同的屬性,正因此,你可以自由的控制字體、顏色、字間距等等信息。
在實際的使用中最終步驟:
創建 NSAttributedString ——> 根據NSAttributedString創建CTFramesetter ——>創建繪制區域CGPath ——> 根據CTFramesetter 和 CGPath 創建 CTFrame ——> CTFrameDraw 繪制。