【发布时间】:2011-06-16 04:11:34
【问题描述】:
CoreText 是否有任何工具可以选择字体的 SmallCaps 变体,或者如果字体没有该功能,则可以合成小型大写字母?尽管有处理字体变化/功能的设施,但我在 CoreText 文档中找不到任何关于小型大写字母的内容。有没有人做过类似的事情?
【问题讨论】:
CoreText 是否有任何工具可以选择字体的 SmallCaps 变体,或者如果字体没有该功能,则可以合成小型大写字母?尽管有处理字体变化/功能的设施,但我在 CoreText 文档中找不到任何关于小型大写字母的内容。有没有人做过类似的事情?
【问题讨论】:
答案似乎是肯定的。它支持具有 Small Caps 功能的字体,但不支持在没有该功能的字体中合成 Small Caps。可以通过创建具有kCTFontFeatureSettingsAttribute 属性的CTFontDescriptor 来启用此功能,该属性映射到一组功能字典。对于 Letter Case,kCTFontFeatureTypeIdentifierKey 键必须设置为 3,对于 Small Caps,kCTFontFeatureSelectorIdentifierKey 必须设置为 3。 <ATS/SFNTLayoutTypes.h> 包含标识各种值的常量,尽管此标头在 iOS SDK 中不可用。
在 iPad 上可用的字体中,以下支持 Small Caps:
注意,Didot 系列中的斜体/粗体字体不支持小型大写字母。
【讨论】:
通常使用CTFontDescriptorCreateCopyWithFeature 是最简单的。正如您在自己的回答中提到的,这仅适用于实际实现您请求的功能的字体。
【讨论】:
CTFontDescriptorCreateCopyWithFeature 使用起来稍微容易一些。
扩展凯文巴拉德的答案。值 '3' 和 '3' 适用于系统字体,但似乎不是通用的。我正在使用外部字体,但这些值不起作用。
您可以通过以下方式注销所有可用属性:
UIFont *font = [UIFont fontWithName: fontName size: fontSize];
CFArrayRef fontProperties = CTFontCopyFeatures ( ( __bridge CTFontRef ) font ) ;
NSLog(@"properties = %@", fontProperties);
CFRelease(fontProperties);
并确定启用小型大写字母或其他字体功能所需的字体功能和选择器。
【讨论】:
我决定在这里回答,以便为任何试图解决此问题的人提供更完整的解决方案,因为这里的信息不完整。
此解决方案使用 iOS 7 UIFontDescriptor,因为我现在放弃了对 iOS 6 的支持。
正如 Anthony Mattox 指出的那样,系统字体值(列为 3 和 3 但应注意实际上是 kLetterCaseType 和 kSmallCapsSelector,您不应该通过其编号来引用枚举),不会为自定义字体工作。我不确定所有自定义字体是否都是这种情况,或者只是一些,但我发现我的情况就是这样。
当深入研究这两个枚举值的声明时,您实际上可以看到它们无论如何都已被弃用,并且可能仅适用于支持小型大写字母的少数系统字体。在记录 Anthony 概述的自定义字体的可用属性后,我找到了用于自定义字体的 2 个正确属性。他们是kLowerCaseType 和kLowerCaseSmallCapsSelector。我相信这种组合是唯一的其他选择,因此对于您尝试使用的任何字体,它都是其中之一。
我写了一些分类方法来封装这两种情况的功能:
- (UIFont *) smallCapSystemFont
{
UIFontDescriptor *descriptor = [self fontDescriptor];
NSArray *array = @[@{UIFontFeatureTypeIdentifierKey : @(kLetterCaseType),
UIFontFeatureSelectorIdentifierKey : @(kSmallCapsSelector)}];
descriptor = [descriptor fontDescriptorByAddingAttributes:@{UIFontDescriptorFeatureSettingsAttribute : array}];
return [UIFont fontWithDescriptor:descriptor size:0];
}
- (UIFont *) smallCapCustomFont
{
UIFontDescriptor *descriptor = [self fontDescriptor];
NSArray *array = @[@{UIFontFeatureTypeIdentifierKey : @(kLowerCaseType),
UIFontFeatureSelectorIdentifierKey : @(kLowerCaseSmallCapsSelector)}];
descriptor = [descriptor fontDescriptorByAddingAttributes:@{UIFontDescriptorFeatureSettingsAttribute : array}];
return [UIFont fontWithDescriptor:descriptor size:0];
}
您可以通过创建具有正确名称和大小的字体,然后在其上调用其中一种方法来使用这些方法,这将返回该字体的小型大写字母版本。您需要找出正确的方法来使用您决定使用的任何小型大写字体。
可能有一种聪明的方法可以通过检查可用类型(即使只是分析该字体属性数组的结果)来确定在运行时以编程方式使用哪个类型,但我并没有这样做,因为我只是使用几种不同的字体和手动检查适合我。
我注意到的一件事是数字是分开处理的。如果您也希望数字的上限也很小(在大多数支持它的字体的情况下,这实际上似乎被称为“旧式数字”),您将需要明确地将其作为属性。
看起来支持系统字体和自定义字体都是一样的,不像字母。
您只需将此字典添加到上面的每个数组中:
@{UIFontFeatureTypeIdentifierKey : @(kNumberCaseType),
UIFontFeatureSelectorIdentifierKey : @(kLowerCaseNumbersSelector)}
再一次,字体本身实际上需要支持这个属性。
【讨论】:
smallCapsSystemFont 那个,你会看到它的作用。
CTFontCopyFeatures)。这将列出给定字体的属性,您可以查看小型大写字母是否是其中之一。 (很明显是哪一个)
由于这里没有人提供 Swift 4 示例,所以我将包含游乐场代码以在 UILabel 中显示一些小型大写字母:
//: Playground - noun: a place where people can play
import UIKit
import CoreGraphics
let pointSize : CGFloat = 24
let fontDescriptor = UIFont(name: "HoeflerText-Regular", size: pointSize)!.fontDescriptor
let fractionFontDesc = fontDescriptor.addingAttributes(
[
UIFontDescriptor.AttributeName.featureSettings: [
[
UIFontDescriptor.FeatureKey.featureIdentifier: kLetterCaseType,
UIFontDescriptor.FeatureKey.typeIdentifier: kSmallCapsSelector
]
]
] )
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 500, height: 100))
label.font = UIFont(descriptor: fractionFontDesc, size:pointSize)
label.text = "Montpelier, Vermont"
【讨论】: