1

我在 CATextLayer 中绘制一个字符时遇到问题,这样该层就是字符的大小。

我使用下面的代码来获取与字符串中的字符相对应的字形大小。目前我忽略了变音符号,所以我假设字形和字符之间存在一对一的相关性。

对于大小为 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 回答