3

いくつかの投稿では、CTFramesetterSuggestFrameSizeWithConstraints から正確な高さを取得することの難しさを指摘しており、ここ(framesetter 投稿)では、@Chris DeSalvo が決定的な修正のように見えるものを示しています: 正しい行間調整で段落スタイル設定を追加します。

DeSalvo は、UIFont のアセンダーとディセンダーを lineHeight から削除することで、「リード」を取得します。と比べてどうだろうと思いましたCTFontGetLeading

次のように作成されたフォントを使用しました。

CTFontRef fontr = CTFontCreateWithName((CFStringRef)@"Helvetica Neue", 16.0f, NULL);
UIFont *font = [UIFont fontWithName:@"Helvetica Neue" size:16.0f];

値はかなり異なっていました。

  • 0.448 CTFontGetLeading
  • 2.360 DeSalvo の式: UIFont lineHeight - アセンダー + ディセンダー

その他の UIFont 値は次のとおりです。

  • 21.000 UIFont の lineHeight
  • 15.232 UIFont のアセンダー (ベースラインからの Y 座標)
  • -3.408 UIFont のディセンダー (ベースラインからの Y 座標)
  • 08.368 UIFont の xHeight

Ken Thomases が問い合わせた CTFont 値は次のとおりです。

  • 11.568001 CTFontGetCapHeight
  • 08.368 CTFontGetXHeight
  • -15.216001、-7.696001、38.352001、24.928001 CTFontGetBoundingBox
  • 15.232 CTFontGetAscent
  • 03.408 CTFontGetDescent (クラス ref は、「フォント参照のポイント サイズとマトリックスに従ってスケーリングされた、スケーリングされた font-descent メトリック」と述べています。これは明らかに、ベースラインからの Y 座標の絶対値であることを意味しますか?)

UIFont には以前は「リーディング」専用のプロパティがありましたが、廃止されたため、lineHeight代わりに使用することをお勧めします。UIFontは、同じフォントに対してLeading が21であり、CTFontRef .448であると見なしますか? 何かがおかしい。

3 つの質問:

  1. kCTParagraphStyleSpecifierLineSpacingAdjustment が意味するのは本当に「先頭」ですか?
  2. もしそうなら、それを得るためにどの方法/式を使用すればよいですか?
  3. そうでない場合、行間調整には何を使用すればよいですか?
4

2 に答える 2

2

私もこれに遭遇しましたが、実際のプロジェクトで機能したコードは次のとおりです。

// When you create an attributed string the default paragraph style has a leading 
// of 0.0. Create a paragraph style that will set the line adjustment equal to
// the leading value of the font. This logic will ensure that the measured
// height for a given paragraph of attributed text will be accurate wrt the font.

- (void) applyParagraphAttributes:(CFMutableAttributedStringRef)mAttributedString
{
  CGFloat leading = CTFontGetLeading(self.plainTextFont);

  CTParagraphStyleSetting paragraphSettings[1] = {
    kCTParagraphStyleSpecifierLineSpacingAdjustment, sizeof (CGFloat), &leading
  };

  CTParagraphStyleRef  paragraphStyle = CTParagraphStyleCreate(paragraphSettings, 1);

  CFRange textRange = CFRangeMake(0, [self length]);

  CFStringRef keys[] = { kCTParagraphStyleAttributeName };
  CFTypeRef values[] = { paragraphStyle };

  CFDictionaryRef attrValues = CFDictionaryCreate(kCFAllocatorDefault,
                                                  (const void**)&keys,
                                                  (const void**)&values,
                                                  sizeof(keys) / sizeof(keys[0]),
                                                  &kCFTypeDictionaryKeyCallBacks,
                                                  &kCFTypeDictionaryValueCallBacks);

  BOOL clearOtherAttributes = FALSE;
  CFAttributedStringSetAttributes(mAttributedString, textRange, attrValues, (Boolean)clearOtherAttributes);
  CFRelease(attrValues);

  CFRelease(paragraphStyle);

  self.stringRange = textRange;

  return;
}
于 2013-06-28T22:12:30.127 に答える
0

上記の 3 つの質問に対する回答:

  1. はい、kCTParagraphStyleSpecifierLineSpacingAdjustment の意味するところを「リード」します。またはとにかく、期待どおりに動作します。
  2. フォントの通常の行送りを取得するために使用CTFontGetLeading(fontRef)するか、選択した任意の値 (CGFloat として) をプラグインします。
  3. 該当なし。

回答 1 と 2 は機能します。属性付き文字列の paragraphStyle 属性に先頭の値を指定すると、Core-Text フレームセッターがその高さを正確に計算できるようになります。

2 つの注意事項があります。

  1. 一度に 1 つの文字列で高さを段階的に計算しようとすると、各文字列に最初の改行が含まれている場合、framesetter はその改行が行頭だけでなく行全体を表すと見なします。連結された文字列の高さが必要な場合は、その連結をフレームセッターにフィードする必要があります。もちろん、増分の高さの違いを追跡することはできますが、framesetter が以前の文字列の寸法を再計算することを避ける方法はありません。
  2. CATextLayer は、間隔の調整 (およびその他の属性) を無視します。正確な文字列の高さごとのフレーミングが問題になる場合は、CALayer に直接描画する必要があります。

謎が 1 つあります。UIFont の非推奨の先頭はどうなっているのでしょうか。Leading と lineHeight は 2 つの異なるものです。

于 2012-04-14T17:11:28.983 に答える