如何用CoreText加载与AppKit的NSFont效果一致的字体?
用CoreText加载与AppKit一致字体的问题
我尝试使用CTFontCreateWithFontDescriptor()加载字体,但其表现与NSFont()加载的字体存在差异,目标是用CoreText加载出与AppKit完全一致的字体。
NSTextField表现差异
将两种字体用于NSTextField时,文本偏移和渲染效果不匹配:
let familyName = "Helvetica" let fontSize: CGFloat = 30 let string = "Hello, World! gÖ,|#" // 用AppKit加载字体 let font1 = NSFont(name: familyName, size: fontSize)! // 用CoreText API加载字体 let font2 = CTFontCreateWithFontDescriptor(CTFontDescriptorCreateWithAttributes([ kCTFontFamilyNameAttribute: familyName, kCTFontSizeAttribute: fontSize, ] as [CFString : Any] as CFDictionary), 0, nil) as NSFont // 设置文本框 let field1 = NSTextField() let field2 = NSTextField() field1.setAsLabel() field2.setAsLabel() field1.font = font1 field2.font = font2 field1.stringValue = string field2.stringValue = string
NSTextField结果预览
NSAttributedString边界框差异
将两种字体用于NSAttributedString时,文本的边界框高度不同:
let bounds1 = NSAttributedString(string: string, attributes: [ .font: font1 ]).boundingRect(with: .infinity) let bounds2 = NSAttributedString(string: string, attributes: [ .font: font2 ]).boundingRect(with: .infinity) print(bounds1) // 输出: (0.0, -7.0, 252.3486328125, 37.0) print(bounds2) // 输出: (0.0, -7.0, 252.3486328125, 31.0)
调查过程
我对比了字体、字体属性、特性、功能设置甚至二进制字体表,未发现差异,推测是内部因素改变了表现。
我发现若为NSAttributedString的边界框获取方法添加.usesDeviceMetrics选项,两者返回结果一致,但帧也完全不同:
let bounds1 = NSAttributedString(string: "Hello, World! gÖ,|#", attributes: [.font: font1]).boundingRect(with: .infinity, options: [.usesDeviceMetrics]) let bounds2 = NSAttributedString(string: "Hello, World! gÖ,|#", attributes: [.font: font2]).boundingRect(with: .infinity, options: [.usesDeviceMetrics]) print(bounds1) // 输出: (2.3583984375, -6.6357421875, 249.9609375, 33.837890625) print(bounds2) // 输出: (2.3583984375, -6.6357421875, 249.9609375, 33.837890625)
问题
如何用CoreText加载出与NSFont效果一致的字体?
次要问题:为何NSTextField会将其帧原点设为-2.0?
附:代码中使用的扩展
extension CGSize { public static var infinity: Self { .init(width: CGFloat.infinity, height: CGFloat.infinity) } } extension NSTextField { func setAsLabel() { translatesAutoresizingMaskIntoConstraints = false isBezeled = false isBordered = false isEditable = false isSelectable = false drawsBackground = false } }
内容的提问来源于stack exchange,提问作者Marcel Kiss
相关产品推荐
相关产品推荐

