CTLine或NSAttributedString - 在没有图形上下文的情况下获取图像边界?

时间:2011-10-07 21:23:48

标签: iphone drawing core-text nsattributedstring ctlineref

这可能吗?基本上,我有一堆NSAttributedString对象和相应的CTLine对象。我想在drawRect阶段之前获取图像边界。所以在这一点上,没有什么可以吸引的。然后,我将使用这些图像边界来确定我需要为绘图创建的内容。

编辑:另一种尺寸测量可能会很好。但是,调用具有欺骗性名称的CTLineGetTypographicBounds函数只会返回宽度。如果我传入上升和下降浮点的地址,它们会返回零。

编辑:给定的答案在MacOS中运行良好。任何人都可以在iOS中做到吗?

4 个答案:

答案 0 :(得分:2)

是的,你可以,但不是那么容易。

您应该,通常使用 CTLineGetTypographicBounds(),对我来说,它确实返回 ascent descent leading ,但有点混乱 - '上升'等于总高度(即应该上升+下降)和'下降'始终是字体的最大下降 - 不管你是否有下降的角色。

其他方法是从行( CTLineGetGlyphRuns )中检索 CTRun (s),然后获取字形数组( CTRunGetGlyphs 或< em> CTRunGetGlyphsPtr )然后使用 CTFontGetBoundingRectsForGlyphs CTFontGetAdvancesForGlyphs 构建您需要的信息。

编辑: 我刚刚找到了这个方法:“ - (NSRect)boundingRectWithSize :( NSSize)大小选项:(NSStringDrawingOptions)选项 NSAttributedString 它似乎完全 需要什么。

希望,这很有帮助......

答案 1 :(得分:2)

CTLineGetTypographicBounds()返回的边界与图像边界不同。正如名称(和Иван的回答)所暗示的那样,为字体定义了上升等,并且不会根据字符串进行更改。例如,如果要在多行文本中找到正确的行高,则可以使用它,因为行高通常不应取决于您使用的确切字符。

另一方面,

CTLineGetImageBounds()返回完全适合图像的边界。例如,如果要围绕一行绘制一个框,则这就是您所需要的。

CTLineGetImageBounds()需要一个上下文,因为可能有文本转换和类似的东西。如果您不想担心这一点,只需使用虚拟上下文。例如:

CTLineRef line;

// create the line...

UIGraphicsBeginImageContext(CGSizeMake(1, 1));
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetTextPosition(context, 0, 0);
CGRect bounds = CTLineGetImageBounds(line, context);
UIGraphicsEndImageContext();

// use bounds...

答案 2 :(得分:2)

如果您正在为iOS6 +开发。您可以使用以下方法:

CTLineRef line;
// Create the line...

CGRect bounds = CTLineGetBoundsWithOptions(line, kCTLineBoundsUseGlyphPathBounds);
// use bounds...

假设您在上下文中没有应用变换,但不需要上下文,则此变量与CTLineGetImageBounds()具有相同的边界。对于iOS 5及更低版本,您需要使用Иван描述的方法。

CTLineGetTypographicBounds()给出了与此函数或图像边界不同的宽度。我不知道为什么。返回的上升和下降是字体,而不是CTLineRef.

中显示的字符

答案 3 :(得分:0)

另一种方法是使用CTFontGetGlyphsForCharacters()将字符串转换为字形,然后使用从第一个函数获得的字形数组调用CTFontGetBoundingRectsForGlyphs()。后一个函数返回“字形运行的整个边界矩形”,因此不必担心必须对各个边界值进行处理。如果在iOS中成功使用这两个功能。

如果这样做,请记住字形和字符之间的映射并不总是一对一,尤其是当字符串包含非英文字符时。