如何在 Swift 中迭代加载的 OpenType 字体的所有 FourCharCode 表标签?

问题描述 投票:0回答:1

这可能只是一个

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 字节整数时,它崩溃了。这是哪里出了问题?

swift tags core-text opentype
1个回答
0
投票

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 字体表标签。

© www.soinside.com 2019 - 2024. All rights reserved.