【问题标题】:Does CoreText support Small Caps?CoreText 是否支持小型大写字母?
【发布时间】:2011-06-16 04:11:34
【问题描述】:

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

【问题讨论】:

    标签: ios core-text


    【解决方案1】:

    答案似乎是肯定的。它支持具有 Small Caps 功能的字体,但不支持在没有该功能的字体中合成 Small Caps。可以通过创建具有kCTFontFeatureSettingsAttribute 属性的CTFontDescriptor 来启用此功能,该属性映射到一组功能字典。对于 Letter Case,kCTFontFeatureTypeIdentifierKey 键必须设置为 3,对于 Small Caps,kCTFontFeatureSelectorIdentifierKey 必须设置为 3。 <ATS/SFNTLayoutTypes.h> 包含标识各种值的常量,尽管此标头在 iOS SDK 中不可用。

    在 iPad 上可用的字体中,以下支持 Small Caps:

    • HoeflerText-Regular
    • Hoefler 文本-斜体
    • HoeflerText-黑色
    • HoeflerText-BlackItalic
    • 迪多特

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

    【讨论】:

    • 我认为这个标头现在在 iOS 5 SDK 中可用
    【解决方案2】:

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

    【讨论】:

    • 就我而言,我还需要选择性地支持斜体/粗体,所以我确实需要使用更通用的属性版本。但你是对的,对于小型大写字母的简单切换,CTFontDescriptorCreateCopyWithFeature 使用起来稍微容易一些。
    【解决方案3】:

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

    您可以通过以下方式注销所有可用属性:

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

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

    【讨论】:

      【解决方案4】:

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

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

      正如 Anthony Mattox 指出的那样,系统字体值(列为 3 和 3 但应注意实际上是 kLetterCaseTypekSmallCapsSelector,您不应该通过其编号来引用枚举),不会为自定义字体工作。我不确定所有自定义字体是否都是这种情况,或者只是一些,但我发现我的情况就是这样。

      当深入研究这两个枚举值的声明时,您实际上可以看到它们无论如何都已被弃用,并且可能仅适用于支持小型大写字母的少数系统字体。在记录 Anthony 概述的自定义字体的可用属性后,我找到了用于自定义字体的 2 个正确属性。他们是kLowerCaseTypekLowerCaseSmallCapsSelector。我相信这种组合是唯一的其他选择,因此对于您尝试使用的任何字体,它都是其中之一。

      我写了一些分类方法来封装这两种情况的功能:

      - (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)}
      

      再一次,字体本身实际上需要支持这个属性。

      【讨论】:

      • 此方法不适用于 iOS 7 系统字体(Helvetica Neue)。
      • @Legoless 澄清一下,它不适用于 Helvetica Neue,因为该字体没有小型大写字母模式。这仅适用于已将其烘焙到其中的字体。在这个问题的另一个答案中有这些字体的列表。可以使用的系统字体的一个示例是“Didot”。试试smallCapsSystemFont 那个,你会看到它的作用。
      • 如果你想在 Helvetica Neue 中使用小型大写字母,你要么需要找到其他人制作的内置字体版本,要么通过绘制较小尺寸的大写字符来伪造它.
      • 提到这些字体的答案是从 2011 年开始的,我认为从那时起字体可能会发生变化。但根据我的研究,OS X 和 iOS 都有相同的 Helvetica Neue 字体。那么为什么 Photoshop 可以在 Helvetica Neue 中轻松渲染 Small Caps 而 iOS 却不能呢?
      • 再一次,您可以在上面的答案中使用日志记录功能(CTFontCopyFeatures)。这将列出给定字体的属性,您可以查看小型大写字母是否是其中之一。 (很明显是哪一个)
      【解决方案5】:

      由于这里没有人提供 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" 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-04
        • 2011-02-03
        相关资源
        最近更新 更多