如何获得 CFAttributedString 的 *real* 高度

How to get *real* height of CFAttributedString

我用 Futura-Bold 字体和大小 100px 创建了一个简单的 CFAttributedString:

let font = NSFont(name: "Futura-Bold", size: 100.0)!

当我在 CGContext(使用 CTFramesetterCreateFrame)上呈现该字符串时,我得到以下图像:

现在的问题是如何得到这段文字的真实高度?正如您在上面的示例中看到的,我们正在查看 85px。

当查询 font 对象的各种属性时,我得到以下值:

font.pointSize  // 100.0
font.ascender   // 103.90
font.descender  // -25.99
font.capHeight  // 75.40
font.leading    // 2.99
font.boundingRectForFont // (-22.7, -34.3994140625, 168.6, 144.29931640625)

有谁知道如何计算渲染字符串的实际像素大小?

一种可以为您提供所需价值的解决方案是使用 NSString boundingRect(with:options:attributes:) 方法。通过传递正确的选项,您可以获得所需的结果:

let font = NSFont(name: "Futura-Bold", size: 100)!
let text: NSString = "Hello World!"
let rect = text.boundingRect(with: NSSize(width: 0, height: 0), options: [ .usesDeviceMetrics ], attributes: [ .font: font ], context: nil)
print("Height of \"\(text)\" is \(rect.height)")

输出:

Height of "Hello World!" is 85.1

这也适用于 NSAttributedString

let font = NSFont(name: "Futura-Bold", size: 100)!
let attrStr = NSAttributedString(string: "Hello World!", attributes: [ .font: font ])
let rect2 = attrStr.boundingRect(with: NSSize(width: 0, height: 0), options: [ .usesDeviceMetrics ])
print("Height of \"\(attrStr)\" is \(rect2.height)")

输出:

Height of "Hello World!{
NSFont = "\"Futura-Bold 100.00 pt. P [] (0x7ff6eae563b0) fobj=0x7ff6eaf1ea50, spc=34.00\"";
}" is 85.1

如果需要,您可以将 CFAttributedString 转换为 NSAttributedString

let attrStr: CFAttributedString = ... // some CFAttributedString
let rect2 = (attrStr as NSAttributedString).boundingRect(with: NSSize(width: 0, height: 0), options: [ .usesDeviceMetrics ])

除了 rmaddys 的出色回答之外,我自己找到了另一种解决方案,它也给出了预期的结果。诀窍是使用 CTLineGetImageBounds.

let font = NSFont(name: "Futura-Bold", size: 100.0)!
let text = NSAttributedString(string: "Hello World!", attributes: [.font:font])
let line = CTLineCreateWithAttributedString(text)

print(CTLineGetImageBounds(line, textContext))

其中 textContext 是您呈现文本的 CGContext。根据 Apple 文档:

This is required because the context could have settings in it that would cause changes in the image bounds.

以上代码给出以下结果:

(7.9, -2.1, 664.2, 85.1)
                   ^^^^