3

I have currently subclassed NSLayoutManager along with other classes in the UITextView architecture in order to implement my own Word Processor like UITextView. I am currently facing a problem when trying to layout underlines under ranges of glyphs (to implement something like hyperlink). In order to layout the underlines I have overrode the following method in NSLayoutManager.

- (void)drawUnderlineForGlyphRange:(NSRange)glyphRange underlineType (NSUnderlineStyle)underlineVal baselineOffset:(CGFloat)baselineOffset lineFragmentRect:(CGRect)lineRect lineFragmentGlyphRange:(NSRange)lineGlyphRange containerOrigin:(CGPoint)containerOrigin

In the above method I compute the underline distance in points from origin of the underline to the end of the underline via the glyph range. View the following method:

- (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;}

As you can see I get the startLocation, and then I get the endLocation by summing the advances for each glyph in the glyphRange. This computation seems to work reasonably well but it seems to result in a overdrawn or underdrawn line for some sequences of characters. It has recently come to my attention that CTFontGetAdvancesForGlyphs does NOT account for font kerning. Can anyone help me with this code? How can I incorporate font kerning effectively into my computation? I have tried querying the NSKernAttribute in my NSTextStorage at the given location but I keep getting back nil values. I have tried both getting the attributeAtIndex and tried enumerating for the attribute over a range.

I am also aware NSAttributedString has underline options but I want to draw the underline myself for various reasons such as supporting custom defined styles, colors, and more.

AyBayBay
  • 1,726
  • 4
  • 18
  • 37
  • You can use NSAttributedString to draw the underlines of text, and show the attributed string in the textview. – EricXuan May 20 '16 at 03:23
  • 1
    @EricXuan yes I know thats an option but I want to be in complete control of how I draw the underline. I dont want NSAttributedString to do it for me thats why I overrode the method in LayoutManager. I allow people to add custom colors and non-iOS type styles so I need control over that – AyBayBay May 20 '16 at 06:16

0 Answers0