This is a demo project for TextKit learning.
This demo is built on XCode7.1 with Swift2.0
可以通过CGContextShowGlyphsAtPositions()
来直接画glyph
. 但是有几个点需要注意:
CGContextShowGlyphsAtPositions()
里的position
参数是指glyph
的origin
. (这里的origin
是在上图里面的origin
. 可以理解为坐标原点.)- 这个方法在画
glyph
的时候, 是以position
为原点, 在glyph
的boundingRect区域去画glyph
的.
TextKit通过这个类提供文字的排版服务, 但是这个类有几个方法和属性的值有问题
这个属性应该返回文本对应的glyph
的数量, 但是在实践中发现, 实际上返回的是文本的长度. 也就是说当glyph
和文字不是一一对应的时候, 这个属性的值是错误的.
返回的rect是相对于textContainer
的坐标系原点的rect(即textContainer
的左上角). 需要注意的是, 这个值并不包括textView
的textContainerInsets
.
这个函数返回的rect实际上并不是glyph
的实际占用大小. (它返回的宽度是advance
, 高度是行高. ) 所以要获取glyph
的实际占用大小, 还是要用CoreText的API.
返回的location是glyph
的origin
(上面Glyph Metric图里面的)相对于glyph
所在行的origin
(左上角)的偏移. 需要注意的是, 这个location
已经包含了lineFragmentPadding
了, 所以使用时不需要再转换一次了.
和上面的numberOfGlyphs
一样, 这两个函数的返回值一样有问题. 只适用于glyph
和character
是一一对应的这种情况. 当不是一一对应时, 返回值都有问题. 两个函数返回的range
的length
实际上都是glyph
对应的character
的length
. 比如在Zapfino
字体中, the
对应一个glyph
, 返回的glyphrange
的length
应该是1, 但是实际是3. 但是用layoutManager.CGGlyphAtIndex(glyphRange.location)
函数去获取glyph
的时候, 拿到的glyph
是对的.
如果都是获取textContainer
里面所有glyph
的rect
, 这两个函数的返回值是不一定相等的. boundingRect...
函数的width
实际上是textContainer.size.width
- 2 * lineFragmentPadding
. 而usedRect...
的width
通常比这个值要大. 因为glyph
很可能会画到boundingRect
的外面. (你可以通过给UILabel设置一种Italic的字体看出来, 首字母会被切断.) 而usedRect...
拿到的就是文本所占据的size
.
-
当
textStorage
发生变化的时候会triggerlayoutManager
重新layout. 比如textStorage.setAttributedString()
等类似操作 -
invalidateLayoutForCharacterRange
也会triggerlayoutManager
重新layout
MIT