这可能只是一个
UnsafeRawPointer
问题,但我不太知道。
在我基于 Swift 的应用程序中,我已将 OpenType/TrueType 字体加载到 CoreText 字体对象中。
然后,我要求为所有字体的表标签提供一个数组,每个标签都是一个
FourCharCode
(UInt32
),其中每个字节都是可打印的 ASCII 字符,按大端顺序排列。 CoreText 的答案是 CFArray
,我想对其进行迭代,如下所示:
allTableTags = CTFontCopyAvailableTables(theFont!, CTFontTableOptions(rawValue: 0))
guard allTableTags != nil else { return }
let numTags = CFArrayGetCount(allTableTags) // 13
for i in 0..<numTags {
let tagPtr = CFArrayGetValueAtIndex(allTableTags, i) // UnsafeRawPointer?
if tagPtr != nil {
let tag = tagPtr!.load(as: FourCharCode.self) // Crashes here
let str = Utility.tagToString(tag)
debugPrint("tag: \(str)")
}
}
但是当我尝试将指针读取为 4 字节整数时,它崩溃了。这是哪里出了问题?
allTableTags[]
中的数组值不是指针,它们是存储为八字节值的实际4字节标签(每个标签占用与指针相同的空间)。
据我所知,Apple 的 CoreText
文档没有以任何令人满意的方式解释这一点。与官方标头中的声明相反,在这种
CoreText
情况下,
CFArrayGetValueAtIndex()
并不总是返回
UnsafeRawPointer?
。所以而不是
let tag = tagPtr!.load(as: FourCharCode.self)
用这个:
let tag = CTFontTableTag( Int(bitPattern: tagPtr) )
这也意味着您不必检查返回的数组值是否为 nil 指针,这在合法字体中无论如何都不会发生。它不是一个指针。所以最终的代码是:
let allTags = CTFontCopyAvailableTables(theFont!, CTFontTableOptions(rawValue: 0))
guard allTags != nil else { return }
let numTags = CFArrayGetCount(allTags)
for i in 0..<numTags {
let notPtr = CFArrayGetValueAtIndex(allTags, i) // Not an UnsafeRawPointer?
let tag = CTFontTableTag( Int(bitPattern: notPtr) ) // Get low-order 4 bytes
Swift.print("tag: \(Utility.tagToString(tag))")
}
对于 theFont
中具有 13 个表的特定 NSont,运行上述结果为:
CFF
DSIG
GDEF
GPOS
GSUB
OS/2
cmap
head
hhea
hmtx
maxp
name
post
所以它显然可以工作,因为这些是标准的四 ASCII 字节 OpenType/TrueType 字体表标签。