1

レイヤーが文字のサイズとまったく同じになるように、CATextLayer で文字を描画する際に問題があります。

以下のコードを使用して、文字列内の文字に対応するグリフのサイズを取得します。現時点では、分音符号を無視しているため、グリフと文字の間には 1 対 1 の相関関係があると想定しています。

サイズ 128pt の Helvetica フォントのいくつかの文字のバウンディング ボックスの値も取得します。

Character | x   | y     | width | height |
B         | 9.4 |   0.0 | 70.8  | 91.8   |
y         | 1.3 | -27.4 | 61.2  | 96.0   |

座標を表す座標系の原点がどこにあるのかわかりません。(0,0) が一番左にあり、フォントのベースラインに垂直に配置されていると想定しています。そのため、'y' の y の値は負になります。

このコードを使用して、大文字の B のサイズを計算し、それに応じて CATextLayer のサイズを変更しています。

- (CATextLayer *) testTextLayer
{
    CATextLayer *l = [CATextLayer layer];
    l.string = @"B";
    NSUInteger len = [l.string length];
    l.fontSize =128.f;
    CGColorRef blackColor = CGColorCreateGenericGray(0.f, 1.f);
    l.foregroundColor = blackColor;
    CGColorRelease(blackColor);

    // need to set CGFont explicitly to convert font property to a CGFontRef
    CGFontRef layerFont = CGFontCreateWithFontName((CFStringRef)@"Helvetica");
    l.font = layerFont;

    // get characters from NSString
    UniChar *characters = (UniChar *)malloc(sizeof(UniChar)*len);
    CFStringGetCharacters((__bridge CFStringRef)l.string, CFRangeMake(0, [l.string length]), characters);

    // Get CTFontRef from CGFontRef
    CTFontRef coreTextFont = CTFontCreateWithGraphicsFont(layerFont, l.fontSize, NULL, NULL);

    // allocate glyphs and bounding box arrays for holding the result
    // assuming that each character is only one glyph, which is wrong
    CGGlyph *glyphs = (CGGlyph *)malloc(sizeof(CGGlyph)*len);
    CTFontGetGlyphsForCharacters(coreTextFont, characters, glyphs, len);

    // get bounding boxes for glyphs
    CGRect *bb = (CGRect *)malloc(sizeof(CGRect)*len);
    CTFontGetBoundingRectsForGlyphs(coreTextFont, kCTFontDefaultOrientation, glyphs, bb, len);
    CFRelease(coreTextFont);

    l.position = CGPointMake(200.f, 100.f);

    l.bounds = bb[0];

    l.backgroundColor = CGColorCreateGenericRGB(0.f, .5f, .9f, 1.f);

    free(characters);
    free(glyphs);
    free(bb);

    return l;
}

これは、上記のコードから取得した結果です。サイズは正しいように見えますが、キャラクターの周りに何らかのパディングが行われています。

CATextLayer の B の結果

私の質問

  1. グリフのバウンディングボックスの起源の仮定は正しいですか?
  2. このパディングなしで、レイヤーにきちんと収まるように文字を描くにはどうすればよいでしょうか? あるいは、このパディングをどのように制御できますか?

多分私はここで明らかな点を見逃しています。レイヤーのサイズとフォントを設定した後、定義された方法でキャラクターの周りにレイヤーをシュリンクラップする方法はありますか(CSSのようにオプションのパディングを使用することを意味します)?


4

2 に答える 2

3

CGPathでグリフからを作成し、CTFontCreatePathForGlyphでその境界ボックスを取得するのはCGPathGetBoundingBoxどうですか?

CTRun別の方法として、何らかの方法で を作成しCTRunGetImageBounds、「タイトな」バウンディング ボックスを返す関数を使用することもできますが、これにはおそらく前述のアプローチよりも多くのコード行が必要であり、グラフィックス コンテキストが必要になります。

于 2012-05-06T20:23:43.747 に答える
1

これは、文字の周りに組み込まれているスペースに関係していると思います。それらのバウンディング ボックスには通常、グリフを一列に並べる場合の一般的な間隔として機能するある程度のスペースが含まれています。これらはカーニング テーブルで最適化されます。

はい、実際のベジエ パスを抽出することは、タイトなバウンディング ボックスを取得するための非常に優れた方法です。CATextLayers を使用した経験はありませんが、私は何年もそれを行ってきました。

于 2012-05-06T21:32:30.177 に答える