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 绘制。