2

私は現在、UITextView のような独自のワード プロセッサを実装するために、UITextView アーキテクチャの他のクラスと共に NSLayoutManager をサブクラス化しています。現在、グリフの範囲の下に下線を配置しようとするときに問題に直面しています (ハイパーリンクのようなものを実装するため)。下線をレイアウトするために、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 に下線オプションがあることも認識していますが、カスタム定義のスタイル、色などをサポートするなど、さまざまな理由で自分で下線を引きたいと思っています。

4

0 に答える 0