2012-05-06 3 views
1

CATextLayerに文字を描画して、レイヤーが文字のサイズに正確になるようにする問題があります。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; 
} 

これは私が上記のコードから得た結果です。サイズは正しいと思われますが、キャラクターの周りに何らかのパディングがあります。

Result of the B on a CATextLayer

私の質問

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

多分私はここで明白な点を見逃しています。レイヤーのサイズとフォントを設定した後、定義された方法で文字を囲むようにレイヤーをラップする(CSSのようなオプションのパディングを使用していることを意味します) CTFontCreatePathForGlyphでグリフからCGPathを作成し、CGPathGetBoundingBoxとのバウンディングボックスを得ることについて


答えて

3

どのように?

代わりに、CTRunを作成し、「タイト」バウンディングボックスも返すCTRunGetImageBounds関数を使用しますが、これは前述のアプローチよりも多くのコード行を必要とするため、グラフィックスコンテキスト。

+0

これは興味深いアプローチです。これは、原点座標がゼロより小さいバウンディングボックスの問題を解決する。だから、灰色のコンテキストでパスを描画し、文字列プロパティを設定するCATextLayerのメカニズムをバイパスしますか? – GorillaPatch

+0

私は描画部分について本当に考えていませんでしたが、あなたが 'CATextLayer'の他の機能を必要としない限り、確かにそれを行うことができます。 – omz

+0

そこにはもう一つの問題があります:私はベースラインに従って複数のテキストレイヤーを揃えたいので、パディングを含む文字の全体サイズを取得したいと思います。 – GorillaPatch

1

これは、文字の周囲の組み込みスペースと関係があると仮定します。それらの境界ボックスには通常、グリフを1行にまとめると、一般的な間隔として使用されるいくつかのスペースが含まれます。これらはカーニングテーブルで最適化されます。

はい、実際のベジェパスを抽出することは、タイトな境界ボックスを取得する非常に良い方法です。 CATextLayersを使った経験はありませんが、私は何年もそれをやっています。

+0

OK、ベジェパスを使うと、パディングなしのグリフのサイズがわかります。しかし、それを表示するために、CoreGraphicsを直接使用する必要があります。私は、CoreText APIを調べて、Glyphの測定にスペースを含めることができるかどうか調べます。 – GorillaPatch

関連する問題