我试图使用各种技术在MacOS X / iOS中获取角色的边界框.我现在正在展示我的所有尝试.到目前为止,如果我想获得像“Ä”这样的变音字符的大小,代码就会失败.
使用CTFontGetBoundingRectsForGlyphs
-(void) resizeLayer1:(CATextLayer *)l toString:(Nsstring *)string
{
// need to set CGFont explicitly to convert font property to a CGFontRef
CGFontRef layerFont = CGFontCreateWithFontName((CFStringRef)@"Helvetica");
l.font = layerFont;
string = l.string;
NSUInteger len = [string length];
// 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,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);
}
结果它有点工作,但有一些填充正在进行,因为字形由CATextLayer呈现
使用CTFramesetterSuggestFrameSizeWithConstraints
-(void) resizeLayer2:(CATextLayer *)l toString:(Nsstring *)string
{
// need to set CGFont explicitly to convert font property to a CGFontRef
CGFontRef layerFont = CGFontCreateWithFontName((CFStringRef)@"Helvetica");
l.font = layerFont;
string = l.string;
NSUInteger len = [string length];
// get characters from Nsstring
UniChar *characters = (UniChar *)malloc(sizeof(UniChar)*len);
CFStringGetCharacters((__bridge CFStringRef)l.string,NULL);
CFMutableAttributedStringRef attrStr = CFAttributedStringCreateMutable(kcfAllocatorDefault,0);
CFAttributedStringReplaceString(attrStr,0),(__bridge CFStringRef)string);
CTTextAlignment alignment = kCTJustifiedTextAlignment;
CTParagraphStyleSetting _settings[] = { {kCTParagraphStyleSpecifierAlignment,sizeof(alignment),&alignment} };
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(_settings,sizeof(_settings) / sizeof(_settings[0]));
CFAttributedStringSetAttribute(attrStr,CFAttributedStringGetLength(attrStr)),kCTParagraphStyleAttributeName,paragraphStyle);
CFAttributedStringSetAttribute(attrStr,kCTFontAttributeName,coreTextFont);
CFRelease(paragraphStyle);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrStr);
CFRelease(attrStr);
CFRange range;
CGFloat maxWidth = CGFLOAT_MAX;
CGFloat maxHeight = 10000.f;
CGSize constraint = CGSizeMake(maxWidth,maxHeight);
// checking frame sizes
CGSize coreTextSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,len),nil,constraint,&range);
// allocate glyphs and bounding Box arrays for holding the result
// assuming that each character is only one glyph,len);
CFRelease(coreTextFont);
bb[0].origin = l.bounds.origin;
coreTextSize.width = ceilf(coreTextSize.width);
coreTextSize.height = ceilf(coreTextSize.height);
bb[0].size = coreTextSize;
l.position = CGPointMake(200.f,100.f);
// after setting the bounds the layer gets transparent
l.bounds = bb[0];
l.opaque = YES;
return;
l.backgroundColor = CGColorCreateGenericRGB(0.f,1.f);
free(characters);
free(glyphs);
free(bb);
}
结果字符串的边界框是正确的.变音符号存在问题:Ä缺少其点,因为边界框不够高.
使用CTLineGetTypographicBounds
-(void) resizeLayer3:(CATextLayer *)l toString:(Nsstring *)string
{
// need to set CGFont explicitly to convert font property to a CGFontRef
CGFontRef layerFont = CGFontCreateWithFontName((CFStringRef)@"Helvetica");
l.font = layerFont;
string = l.string;
NSUInteger len = [string length];
// get characters from Nsstring
UniChar *characters = (UniChar *)malloc(sizeof(UniChar)*len);
CFStringGetCharacters((__bridge CFStringRef)l.string,(__bridge CFStringRef)string);
CFAttributedStringSetAttribute(attrStr,coreTextFont);
CTLineRef line = CTLineCreateWithAttributedString(attrStr);
CGFloat ascent;
CGFloat descent;
CGFloat width = CTLineGetTypographicBounds(line,&ascent,&descent,NULL);
CGFloat height = ascent+descent;
CGSize coreTextSize = CGSizeMake(width,height);
// get bounding Boxes for glyphs
CGRect *bb = (CGRect *)malloc(sizeof(CGRect)*len);
CFRelease(coreTextFont);
bb[0].origin = CGPointZero;
coreTextSize.width = ceilf(coreTextSize.width);
coreTextSize.height = ceilf(coreTextSize.height);
bb[0].size = coreTextSize;
l.position = CGPointMake(200.f,1.f);
free(characters);
free(bb);
}
结果字符串的边界框是正确的.变音符号存在问题:Ä缺少其点,因为边界框不够高.
使用CTFontGetBoundingRectsForGlyphs
-(void) resizeLayer4:(CATextLayer *)l toString:(Nsstring *)string
{
// need to set CGFont explicitly to convert font property to a CGFontRef
CGFontRef layerFont = CGFontCreateWithFontName((CFStringRef)@"Helvetica");
l.font = layerFont;
string = l.string;
NSUInteger len = [string length];
// get characters from Nsstring
UniChar *characters = (UniChar *)malloc(sizeof(UniChar)*len);
CFStringGetCharacters((__bridge CFStringRef)l.string,len);
CGPathRef glyPHPath = CTFontCreatePathForGlyph(coreTextFont,glyphs[1],NULL);
CGRect rect = CGPathGetBoundingBox(glyPHPath);
// get bounding Boxes for glyphs
CGRect *bb = (CGRect *)malloc(sizeof(CGRect)*len);
CTFontGetBoundingRectsForGlyphs(coreTextFont,100.f);
l.bounds = rect;
l.backgroundColor = CGColorCreateGenericRGB(0.f,1.f);
free(characters);
free(glyphs);
free(bb);
}
结果字符串的边界框是正确的.由于变音符号本身是一个字形,而字符是另一个字形意味着Ä由两个字形组成,因此变音符号存在问题.怎么可以使用它?
还有其他可能性我忽略了并值得尝试吗?
编辑
CTLineGetTypographicBounds的第三个选项似乎有效.然而,我正在运行一个不同的问题,即CATextLayer中的第一行缺少其变音符号.第一行不知何故不够高.这意味着我在这里咆哮错误的树.
解决方法
在第一个示例中,您似乎忽略了这样一个事实,即字形的边界矩形很可能是负y源.返回的rect通常将y = 0视为文本的基线.因此,您可以在bounds rect中设置偏移量,这也可能是图层在文本中具有偏移量的原因. (没试过但是这么认为)
如果您对特定文本的边界不感兴趣,但选择包含各种文本的高度,您可能还想使用CTFontGetBoundingBox.