CoreText.framework

框架说明

官方文档

CoreText是一个底层的、高效的图文绘制排版框架。

CoreText 框架中最常用的几个类:

  • CTFont CoreText字体对象
  • CTFontCollection CoreText字体集
  • CTFontDescriptor 字体描述,包含字体的各种属性
  • CTFrame 一个包含多行字符的frame
  • CTFramesetter 产生CTFrame的对象工厂
  • CTGlyphInfo 该类型让用户可以重载字体的Unicode到GlyphID的对应关系
  • CTLine 一行字符
  • CTParagraphStyle AttributedString的段落属性
  • CTRun 一行字符中代表一段连续的具有相同属性的字符
  • CTRunDelegate CTRun的delegate,用于控制排版上的一些特征,包括ascent,descent,width
  • CTTextTab 代表段落中的Tab
  • CTTypesetter 排字机,决定行布局
CoreText.framework_第1张图片
对象关系图

CTFrame作为一个整体的画布(Canvas),其中由行(CTLine)组成,而每行可以分为一个或多个小方块(CTRun)。

CoreText.framework_第2张图片
示意图

注意:你不需要自己创建CTRun,Core Text将根据NSAttributedString的属性来自动创建CTRun。每个CTRun对象对应不同的属性,正因此,你可以自由的控制字体、颜色、字间距等等信息。

字体的基本知识

CoreText.framework_第3张图片
CoreText.framework_第4张图片

字体(Font) 是一系列字号、样式和磅值相同的字符(例如:10磅黑体Palatino)
字面(Face) 是所有字号的磅值和格式的综合
字体集(Font family) 是一组相关字体(例如:Franklin family包括Franklin Gothic、Fran-klinHeavy和Franklin Compressed)
磅值(Weight) 用于描述字体粗度。典型的磅值,从最粗到最细,有极细、细、book、中等、半粗、粗、较粗、极粗
样式(Style) 字形有三种形式:Roman type是直体;oblique type是斜体;utakuc type是斜体兼曲线(比Roman type更像书法体)。
x高度(x-height) 指小写字母的平均高度(以x为基准)。磅值相同的两字母,x高度越大的字母看起来比x高度小的字母要大
Cap高度(Cap height) 与x高度相似。指大写字母的平均高度(以C为基准)
上行字母(Ascender) x高度以上的部分(比如字母b)叫做上伸部分
下行字母(Descender) 例如在字母q中,基线以下的字母部分叫下伸部分
基线(Baseline) 通常在x、v、b、m下的那条线
描边(Stroke) 组成字符的线或曲线。可以加粗或改变字符形状
衬线(Serif) 用来使字符更可视的一条水平线。如字母左上角和下部的水平线。
无衬线(Sans Serif) 可以让排字员不使用衬线装饰。
方形字(Block) 这种字体的笔画使字符看起来比无衬线字更显眼,但还不到常见的衬线字的程度。例如Lubalin Graph就是方形字,这种字看起来好像是木头块刻的一样
手写体脚本(Calligraphic script) 是一种仿效手写体的字体。例如Murray Hill或者Fraktur字体
艺术字(Decorative) 像绘画般的字体
Pi符号(Pisymbol) 非标准的字母数字字符的特殊符号。例如Wingdings和Mathematical Pi
连写(Ligature) 是一系列连写字母如fi、fl、ffi或ffl。由于字些字母形状的原因经常被连写,故排字员已习惯将它们连写。

CoreText.framework_第5张图片
字体中的属性(附)

字符属性名称

const CFStringRef kCTCharacterShapeAttributeName;              
//字体形状属性  必须是CFNumberRef对象默认为0,非0则对应相应的字符形状定义,如1表示传统字符形状
const CFStringRef kCTFontAttributeName;                        
//字体属性   必须是CTFont对象
const CFStringRef kCTKernAttributeName;                        
//字符间隔属性 必须是CFNumberRef对象
const CFStringRef kCTLigatureAttributeName;                 
//设置是否使用连字属性,设置为0,表示不使用连字属性。标准的英文连字有FI,FL.默认值为1,既是使用标准连字。也就是当搜索到f时候,会把fl当成一个文字。必须是CFNumberRef 默认为1,可取0,1,2
const CFStringRef kCTForegroundColorAttributeName;             
//字体颜色属性  必须是CGColor对象,默认为black
const CFStringRef kCTForegroundColorFromContextAttributeName; 
 //上下文的字体颜色属性 必须为CFBooleanRef 默认为False,
const CFStringRef kCTParagraphStyleAttributeName;              
//段落样式属性 必须是CTParagraphStyle对象 默认为NIL
const CFStringRef kCTStrokeWidthAttributeName;              
//笔画线条宽度 必须是CFNumberRef对象,默为0.0f,标准为3.0f
const CFStringRef kCTStrokeColorAttributeName;              
//笔画的颜色属性 必须是CGColorRef 对象,默认为前景色
const CFStringRef kCTSuperscriptAttributeName;              
//设置字体的上下标属性 必须是CFNumberRef对象 默认为0,可为-1为下标,1为上标,需要字体支持才行。如排列组合的样式Cn1
const CFStringRef kCTUnderlineColorAttributeName;           
//字体下划线颜色属性 必须是CGColorRef对象,默认为前景色
const CFStringRef kCTUnderlineStyleAttributeName;           
//字体下划线样式属性 必须是CFNumberRef对象,默为kCTUnderlineStyleNone 可以通过CTUnderlineStypleModifiers 进行修改下划线风格
const CFStringRef kCTVerticalFormsAttributeName;
//文字的字形方向属性 必须是CFBooleanRef 默认为false,false表示水平方向,true表示竖直方向
const CFStringRef kCTGlyphInfoAttributeName;
//字体信息属性 必须是CTGlyphInfo对象
const CFStringRef kCTRunDelegateAttributeName
//CTRun 委托属性 必须是CTRunDelegate对象

使用的基本步骤

新建一个UIView, 在view的drawRect函数中按步骤写入下面的代码

// 1. 获取当前上下文
let context = UIGraphicsGetCurrentContext()

// 2. 转换坐标系
CGContextSetTextMatrix(context, CGAffineTransformIdentity)
CGContextTranslateCTM(context, 0, self.bounds.size.height)
CGContextScaleCTM(context, 1.0, -1.0)

// 3. 初始化路径
let path = CGPathCreateWithRect(self.bounds, nil)

// 4. 初始化字符串
let attrString = NSMutableAttributedString(string: "Hello CoreText")

// 5. 初始化framesetter
let framesetter = CTFramesetterCreateWithAttributedString(attrString)

// 6. 绘制frame
let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, attrString.length), path, nil)
CTFrameDraw(frame, context!)

简单的富文本Label

上面简单的绘制步骤中, 最后一步绘制frame, 是将整个frame当做一块绘制, 至于什么换行, 行中的样式什么的都是系统自己决定了。在开始之前, 我们将这个绘制frame改成我们自己一行一行, 甚至一个run一个run的绘制

按行绘制

// 1. 获得CTLine数组
let lines = CTFrameGetLines(frame)

// 2. 获得行数
let numberOfLines = CFArrayGetCount(lines)

// 3. 获得每一行的origin, CoreText的origin是在字形的baseLine处的, 请参考字形图
var lineOrigins = [CGPoint](count: numberOfLines, repeatedValue: CGPointZero)
CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), &lineOrigins)

// 4. 遍历每一行进行绘制
for index in 0..

将最后一步改成按行绘制, 最终得到的效果也和按frame绘制一样的, 接下来看下按Run绘制

// 画一行
func drawLine(line: CTLine, context: CGContext) {
   let runs = CTLineGetGlyphRuns(line) as Array
 
   runs.forEach { run in
       CTRunDraw(run as! CTRun, context, CFRangeMake(0, 0))
       }
   }
}

相关资料

  1. Text Programming Guide for iOS
  2. Cocoa Text Architecture Guide
  3. CoreText基础概念(扫盲篇)

你可能感兴趣的:(CoreText.framework)