CoreText 支持小型大写字母吗?

发布于 2024-10-14 14:42:42 字数 128 浏览 4 评论 0原文

CoreText 是否有任何工具可以选择字体的 SmallCaps 变体,或者如果字体没有该功能,则可以合成小型大写字母?尽管有处理字体变化/功能的工具,但我在 CoreText 文档中找不到任何有关小型大写字母的内容。有人做过类似的事情吗?

Does CoreText have any facility for selecting a SmallCaps variant of a font, or for synthesizing small caps if the font doesn't have that feature? I can't find anything in the CoreText documentation that talks about small caps, though there are facilities for dealing with font variations/features. Has anyone done anything similar to this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

你曾走过我的故事 2024-10-21 14:42:42

答案似乎是合格的“是”。它支持具有小型大写字母功能的字体,但不支持在不具有该功能的字体中合成小型大写字母。可以通过使用 kCTFontFeatureSettingsAttribute 属性创建一个 CTFontDescriptor 来启用此功能,该属性映射到功能字典数组。对于字母大小写,kCTFontFeatureTypeIdentifierKey 键必须设置为 3,对于小型大写字母,kCTFontFeatureSelectorIdentifierKey 键必须设置为 3。 包含标识各种值的常量,但此标头在 iOS SDK 中不可用。

在 iPad 上可用的字体中,以下字体支持小型大写字母:

  • HoeflerText-Regular
  • HoeflerText-Italic
  • HoeflerText-Black
  • HoeflerText-BlackItalic
  • Didot

请注意,Didot 系列中的斜体/粗体字体不支持小型大写字母。

The answer appears to be a qualified Yes. It supports fonts that have a Small Caps feature, but it doesn't support synthesizing Small Caps in fonts that don't have the feature. This feature can be enabled by creating a CTFontDescriptor with the kCTFontFeatureSettingsAttribute attribute, which maps to an array of feature dicts. The kCTFontFeatureTypeIdentifierKey key must be set to 3 for Letter Case, and the kCTFontFeatureSelectorIdentifierKey must be set to 3 for Small Caps. <ATS/SFNTLayoutTypes.h> contains constants that identify the various values, though this header isn't available in the iOS SDK.

Of the fonts available on the iPad, the following support Small Caps:

  • HoeflerText-Regular
  • HoeflerText-Italic
  • HoeflerText-Black
  • HoeflerText-BlackItalic
  • Didot

Note, the Italic/Bold fonts in the Didot family don't support small caps.

呆橘 2024-10-21 14:42:42

通常,使用 CTFontDescriptorCreateCopyWithFeature 最简单。正如您在自己的答案中提到的,这仅适用于实际实现您所请求的功能的字体。

It's generally easiest to use CTFontDescriptorCreateCopyWithFeature. As you mentioned in your own answer, this will only work for fonts that actually implement the feature you are requesting.

眼眸印温柔 2024-10-21 14:42:42

我决定在这里回答,以便为尝试解决此问题的任何人提供更完整的解决方案,因为此处的信息不完整。

该解决方案使用 iOS 7 UIFontDescriptor,因为我现在放弃了对 iOS 6 的支持。

正如 Anthony Mattox 指出的,系统字体值(列为 3 和 3,但应注意实际上是 < code>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)}

再一次,要使其工作,字体本身实际上需要支持此属性。

I decided to answer here to provide a more complete solution to anyone trying to solve this issue, as the info here is incomplete.

This solution uses the iOS 7 UIFontDescriptor as I am now dropping support for iOS 6.

As Anthony Mattox pointed out, the system font values (which are listed as 3 and 3 but should be noted to actually be kLetterCaseType and kSmallCapsSelector, you should not refer to an enum by its number), will not work for custom fonts. I am not sure whether this is the case for all custom fonts or just some, but I found this to be the case with mine.

When digging into the declaration of both of these enum values, you can actually see that they are deprecated anyway and presumably only work for the few system fonts that support small caps. After logging the available attributes for my custom font as outlined by Anthony, I found the 2 correct attributes to use for custom fonts. They are kLowerCaseType and kLowerCaseSmallCapsSelector. I believe that this combination is the only other option so for any font you attempt to use, it will be one or the other.

I wrote some category methods to encapsulate this functionality for both cases:

- (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];
}

You use these by creating a font with the correct name and size and then calling one of these methods on it which will return a small cap version of that font. You will need to figure out the correct method to use for whatever small caps font you decide to use.

There is probably a clever way to figure out which one to use programmatically at runtime by checking for available types (even by just analyzing the results of that font properties array), but I have not bothered to do so as I am only using a few different fonts and a manual check is suitable for me.

Edit:

One thing I noticed is that numbers are handled separately. If you want numbers to be small capped too (which actually seems to be called "Old-style numbers" in the case of most fonts that support it), you will need that explicitly as an attribute.

Looks like it is the same for both supporting system fonts and custom fonts, unlike letters.

You would just add this dictionary to each of the arrays above:

@{UIFontFeatureTypeIdentifierKey : @(kNumberCaseType),
                         UIFontFeatureSelectorIdentifierKey : @(kLowerCaseNumbersSelector)}

Once again, for this to work the font itself actually needs to support this attribute.

苯莒 2024-10-21 14:42:42

扩展凯文巴拉德的答案。值“3”和“3”适用于系统字体,但似乎并不通用。我使用的是外部字体,这些值不起作用。

您可以使用类似以下内容注销所有可用属性:

UIFont *font = [UIFont fontWithName: fontName size: fontSize];
CFArrayRef  fontProperties  =  CTFontCopyFeatures ( ( __bridge CTFontRef ) font ) ;
NSLog(@"properties = %@", fontProperties);
CFRelease(fontProperties);

并确定启用小型大写字母或其他字体功能所需的字体功能和选择器。

To extend Kevin Ballard's answer. The values '3' and '3' work for the system fonts, but don't seem to be universal. I'm using an external font and these values did not work.

You can log out all of the available properties with something like this:

UIFont *font = [UIFont fontWithName: fontName size: fontSize];
CFArrayRef  fontProperties  =  CTFontCopyFeatures ( ( __bridge CTFontRef ) font ) ;
NSLog(@"properties = %@", fontProperties);
CFRelease(fontProperties);

and determine what font feature and selector you'll need to enable small caps or other font features.

那片花海 2024-10-21 14:42:42

由于这里没有人提供 Swift 4 示例,因此我将添加 Playground 代码以在 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" 

As no one here has provided a Swift 4 sample, I'm just going to include playground code to display some small caps text in a 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" 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文