我目前已将 NSLayoutManager 与 UITextView 架构中的其他类一起子类化,以实现我自己的文字处理器,如 UITextView。我目前在尝试在字形范围下布局下划线(以实现超链接之类的东西)时遇到问题。为了布局下划线,我在 NSLayoutManager 中覆盖了以下方法。
- (void)drawUnderlineForGlyphRange:(NSRange)glyphRange underlineType (NSUnderlineStyle)underlineVal baselineOffset:(CGFloat)baselineOffset lineFragmentRect:(CGRect)lineRect lineFragmentGlyphRange:(NSRange)lineGlyphRange containerOrigin:(CGPoint)containerOrigin
在上述方法中,我通过字形范围计算从下划线起点到下划线终点的点的下划线距离。查看以下方法:
- (void)getStartLocation:(CGFloat * _Nonnull )startLocation andEndLocation:(CGFloat * _Nonnull)endLocation ofGlyphsInRange:(NSRange)glyphRange {
NSRange characterRange = [self characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL];
(*startLocation) = [self locationForGlyphAtIndex:glyphRange.location].x;
CGGlyph glyphs[self.numberOfGlyphs];
NSUInteger numGlyphs = [self getGlyphsInRange:glyphRange glyphs:&glyphs[0] properties:NULL characterIndexes:NULL bidiLevels:NULL];
CTFontRef ctfont = [self getCTFontForGlyphsInRange:glyphRange];
double advances = CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationDefault, &glyphs[0], NULL, numGlyphs);
(*endLocation) = (*startLocation) + (CGFloat)advances;}
如您所见,我得到了 startLocation,然后通过对 glyphRange 中每个字形的进展求和来得到 endLocation。这种计算似乎工作得相当好,但它似乎会导致某些字符序列的线条过度绘制或绘制不足。我最近注意到 CTFontGetAdvancesForGlyphs 不考虑字体字距调整。任何人都可以帮我处理这段代码吗?我怎样才能有效地将字体字距调整到我的计算中?我曾尝试在给定位置查询我的 NSTextStorage 中的 NSKernAttribute,但我不断返回 nil 值。我已经尝试获取 attributeAtIndex 并尝试在一个范围内枚举属性。
我也知道 NSAttributedString 有下划线选项,但出于各种原因,例如支持自定义样式、颜色等,我想自己绘制下划线。