Skip to content

damoyan/TextKitDemo

Repository files navigation

Introduction

This is a demo project for TextKit learning.

This demo is built on XCode7.1 with Swift2.0

Basic Concepts

Glyph

Image Of Glyph Metrics

可以通过CGContextShowGlyphsAtPositions()来直接画glyph. 但是有几个点需要注意:

  1. CGContextShowGlyphsAtPositions()里的position参数是指glyphorigin. (这里的origin是在上图里面的origin. 可以理解为坐标原点.)
  2. 这个方法在画glyph的时候, 是以position为原点, 在glyph的boundingRect区域去画glyph的.

NSLayoutManager

TextKit通过这个类提供文字的排版服务, 但是这个类有几个方法和属性的值有问题

numberOfGlyphs

这个属性应该返回文本对应的glyph的数量, 但是在实践中发现, 实际上返回的是文本的长度. 也就是说当glyph和文字不是一一对应的时候, 这个属性的值是错误的.

boundingRectForGlyphRange()

返回的rect是相对于textContainer的坐标系原点的rect(即textContainer的左上角). 需要注意的是, 这个值并不包括textViewtextContainerInsets. 这个函数返回的rect实际上并不是glyph的实际占用大小. (它返回的宽度是advance, 高度是行高. ) 所以要获取glyph的实际占用大小, 还是要用CoreText的API.

locationForGlyphAtIndex()

返回的location是glyphorigin(上面Glyph Metric图里面的)相对于glyph所在行的origin(左上角)的偏移. 需要注意的是, 这个location已经包含了lineFragmentPadding了, 所以使用时不需要再转换一次了.

characterRangeForGlyphRange()/glyphRangeForCharacterRange()

和上面的numberOfGlyphs一样, 这两个函数的返回值一样有问题. 只适用于glyphcharacter是一一对应的这种情况. 当不是一一对应时, 返回值都有问题. 两个函数返回的rangelength实际上都是glyph对应的characterlength. 比如在Zapfino字体中, the对应一个glyph, 返回的glyphrangelength应该是1, 但是实际是3. 但是用layoutManager.CGGlyphAtIndex(glyphRange.location)函数去获取glyph的时候, 拿到的glyph是对的.

usedRectForTextContainer()/boundingRectForGlyphRange:InTextContainer()

如果都是获取textContainer里面所有glyphrect, 这两个函数的返回值是不一定相等的. boundingRect...函数的width实际上是textContainer.size.width - 2 * lineFragmentPadding. 而usedRect...width通常比这个值要大. 因为glyph很可能会画到boundingRect的外面. (你可以通过给UILabel设置一种Italic的字体看出来, 首字母会被切断.) 而usedRect...拿到的就是文本所占据的size.

Tips

  1. textStorage发生变化的时候会trigger layoutManager重新layout. 比如textStorage.setAttributedString()等类似操作

  2. invalidateLayoutForCharacterRange也会trigger layoutManager重新layout

Lisence

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages