Core Text框架详细解析(五) —— Core Text字体操作

版本记录

版本号 时间
V1.0 2017.10.22

前言

Core Text框架主要用来做文字处理,是的iOS3.2+OSX10.5+中的文本引擎,让您精细的控制文本布局和格式。它位于在UIKit中和CoreGraphics/Quartz之间的最佳点。接下来这几篇我们就主要解析该框架。感兴趣的可以前面几篇。
1. Core Text框架详细解析(一) —— 基本概览
2. Core Text框架详细解析(二) —— 关于Core Text
3. Core Text框架详细解析(三) —— Core Text总体概览
4. Core Text框架详细解析(四) —— Core Text文本布局操作

字体操作

本章介绍一些常见的字体处理操作,并显示如何使用Core Text进行编码。 这些操作在iOS和OS X上是相同的。本章包含以下代码列表操作:

  • Creating Font Descriptors
  • Creating a Font from a Font Descriptor
  • Creating Related Fonts
  • Serializing a Font
  • Creating a Font from Serialized Data
  • Changing Kerning
  • Getting Glyphs for Characters

Creating Font Descriptors - 创建字体描述符

Listing 3-1中的示例函数从指定PostScript字体名称和点大小的参数值创建一个字体描述符。

// Listing 3-1  Creating a font descriptor from a name and point size

CTFontDescriptorRef CreateFontDescriptorFromName(CFStringRef postScriptName,
                                                  CGFloat size)
{
    return CTFontDescriptorCreateWithNameAndSize(postScriptName, size);
}

Listing 3-2中的示例函数从字体系列名称和字体特征中创建一个字体描述符。

// Listing 3-2  Creating a font descriptor from a family and traits

NSString* familyName = @"Papyrus";
CTFontSymbolicTraits symbolicTraits = kCTFontTraitCondensed;
CGFloat size = 24.0;
 
NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
[attributes setObject:familyName forKey:(id)kCTFontFamilyNameAttribute];
 
// The attributes dictionary contains another dictionary, the traits dictionary,
// which in this example specifies only the symbolic traits.
NSMutableDictionary* traits = [NSMutableDictionary dictionary];
[traits setObject:[NSNumber numberWithUnsignedInt:symbolicTraits]
                                           forKey:(id)kCTFontSymbolicTrait];
 
[attributes setObject:traits forKey:(id)kCTFontTraitsAttribute];
[attributes setObject:[NSNumber numberWithFloat:size]
                                         forKey:(id)kCTFontSizeAttribute];
 
CTFontDescriptorRef descriptor =
             CTFontDescriptorCreateWithAttributes((CFDictionaryRef)attributes);
CFRelease(descriptor);

Creating a Font from a Font Descriptor - 从字体描述符创建字体

Listing 3-3 显示了如何创建一个字体描述符并使用它来创建一个字体。 当您调用CTFontCreateWithFontDescriptor时,通常会为矩阵参数传递NULL,以指定默认(identity)矩阵。 CTFontCreateWithFontDescriptor的大小和矩阵(第二和第三个)参数将覆盖字体描述符中指定的任何内容,除非它们未指定(大小为0.0,矩阵为NULL)。

// Listing 3-3  Creating a font from a font descriptor

NSDictionary *fontAttributes =
                  [NSDictionary dictionaryWithObjectsAndKeys:
                          @"Courier", (NSString *)kCTFontFamilyNameAttribute,
                          @"Bold", (NSString *)kCTFontStyleNameAttribute,
                          [NSNumber numberWithFloat:16.0],
                          (NSString *)kCTFontSizeAttribute,
                          nil];
// Create a descriptor.
CTFontDescriptorRef descriptor =
          CTFontDescriptorCreateWithAttributes((CFDictionaryRef)fontAttributes);
 
// Create a font using the descriptor.
CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, 0.0, NULL);
CFRelease(descriptor);

Creating Related Fonts - 创建相关字体

将现有字体转换为相关或相似的字体通常很有用。 Listing 3-4 中的示例函数显示了如何使用函数调用传递的布尔参数的值使粗体或粗体字体粗体显示。 如果当前的字体系列没有请求的样式,则该函数返回NULL。

// Listing 3-4  Changing traits of a font

CTFontRef CreateBoldFont(CTFontRef font, Boolean makeBold)
{
    CTFontSymbolicTraits desiredTrait = 0;
    CTFontSymbolicTraits traitMask;
 
    // If requesting that the font be bold, set the desired trait
    // to be bold.
    if (makeBold) desiredTrait = kCTFontBoldTrait;
 
    // Mask off the bold trait to indicate that it is the only trait
    // to be modified. As CTFontSymbolicTraits is a bit field,
    // could change multiple traits if desired.
    traitMask = kCTFontBoldTrait;
 
    // Create a copy of the original font with the masked trait set to the
    // desired value. If the font family does not have the appropriate style,
    // returns NULL.
 
    return CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, desiredTrait, traitMask);
}

Listing 3-5中的示例函数将给定字体转换为另一个字体系列中的类似字体,如果可能,将保留特征。 它可能返回NULL。 传递大小参数为0.0和矩阵参数为NULL以保留原始字体的大小。

// Listing 3-5  Converting a font to another family

CTFontRef CreateFontConvertedToFamily(CTFontRef font, CFStringRef family)
{
    // Create a copy of the original font with the new family. This call
    // attempts to preserve traits, and may return NULL if that is not possible.
    // Pass in 0.0 and NULL for size and matrix to preserve the values from
    // the original font.
 
    return CTFontCreateCopyWithFamily(font, 0.0, NULL, family);
}

Serializing a Font - 序列化字体

Listing 3-6中的示例函数显示了如何创建XML数据以序列化可以嵌入到文档中的字体。 或者,并且优选地,可以使用NSArchiver。 这只是完成此任务的一种方法,但它会保留以后重新创建确切字体所需字体的所有数据。

// Listing 3-6  Serializing a font

CFDataRef CreateFlattenedFontData(CTFontRef font)
{
    CFDataRef           result = NULL;
    CTFontDescriptorRef descriptor;
    CFDictionaryRef     attributes;
 
    // Get the font descriptor for the font.
    descriptor = CTFontCopyFontDescriptor(font);
 
    if (descriptor != NULL) {
        // Get the font attributes from the descriptor. This should be enough
        // information to recreate the descriptor and the font later.
        attributes = CTFontDescriptorCopyAttributes(descriptor);
 
        if (attributes != NULL) {
            // If attributes are a valid property list, directly flatten
            // the property list. Otherwise we may need to analyze the attributes
            // and remove or manually convert them to serializable forms.
            // This is left as an exercise for the reader.
           if (CFPropertyListIsValid(attributes, kCFPropertyListXMLFormat_v1_0)) {
                result = CFPropertyListCreateXMLData(kCFAllocatorDefault, attributes);
            }
        }
    }
    return result;
}

Creating a Font from Serialized Data - 从序列化数据中创建字体

Listing 3-7中的示例函数显示了如何从展平的XML数据创建字体引用。 它显示如何折叠字体属性并利用这些属性创建字体。

// Listing 3-7  Creating a font from serialized data

CTFontRef CreateFontFromFlattenedFontData(CFDataRef iData)
{
    CTFontRef           font = NULL;
    CFDictionaryRef     attributes;
    CTFontDescriptorRef descriptor;
 
    // Create our font attributes from the property list.
    // For simplicity, this example creates an immutable object.
    // If you needed to massage or convert certain attributes
    // from their serializable form to the Core Text usable form,
    // do it here.
    attributes =
          (CFDictionaryRef)CFPropertyListCreateFromXMLData(
                               kCFAllocatorDefault,
                               iData, kCFPropertyListImmutable, NULL);
    if (attributes != NULL) {
        // Create the font descriptor from the attributes.
        descriptor = CTFontDescriptorCreateWithAttributes(attributes);
        if (descriptor != NULL) {
            // Create the font from the font descriptor. This sample uses
            // 0.0 and NULL for the size and matrix parameters. This
            // causes the font to be created with the size and/or matrix
            // that exist in the descriptor, if present. Otherwise default
            // values are used.
            font = CTFontCreateWithFontDescriptor(descriptor, 0.0, NULL);
        }
    }
    return font;
}

Changing Kerning - 改变字距

默认情况下启用连接和字距调整。 如果要禁用,请将kCTKernAttributeName属性设置为0。Listing 3-8将前几个字符的kern大小设置为很大的数字。

// Listing 3-8  Setting kerning

 // Set the color of the first 13 characters to red
 // using a previously defined red CGColor object.
 CFAttributedStringSetAttribute(attrString, CFRangeMake(0, 13),
                                      kCTForegroundColorAttributeName, red);
 
 // Set kerning between the first 18 chars to be 20
 CGFloat otherNum = 20;
 CFNumberRef otherCFNum = CFNumberCreate(NULL, kCFNumberCGFloatType, &otherNum);
 CFAttributedStringSetAttribute(attrString, CFRangeMake(0,18),
                                           kCTKernAttributeName, otherCFNum);

Getting Glyphs for Characters - 获取字符的字形

Listing 3-9显示了如何使用单个字体获取字符串中的字符的字形。 大多数时候你应该只使用一个CTLine对象获取这个信息,因为一个字体可能不会对整个字符串进行编码。 此外,简单的字符到字形映射将无法获得复杂脚本的正确外观。 如果您尝试为字体显示特定的Unicode字符,则这种简单的字形映射可能是适当的。

Listing 3-9  Getting glyphs for characters
void GetGlyphsForCharacters(CTFontRef font, CFStringRef string)
{
    // Get the string length.
    CFIndex count = CFStringGetLength(string);
 
    // Allocate our buffers for characters and glyphs.
    UniChar *characters = (UniChar *)malloc(sizeof(UniChar) * count);
    CGGlyph *glyphs = (CGGlyph *)malloc(sizeof(CGGlyph) * count);
 
    // Get the characters from the string.
    CFStringGetCharacters(string, CFRangeMake(0, count), characters);
 
    // Get the glyphs for the characters.
    CTFontGetGlyphsForCharacters(font, characters, glyphs, count);
 
    // Do something with the glyphs here. Characters not mapped by this font will be zero.
    // ...
 
    // Free the buffers
    free(characters);
    free(glyphs);
}

后记

未完,待续~~~

Core Text框架详细解析(五) —— Core Text字体操作_第1张图片

你可能感兴趣的:(Core Text框架详细解析(五) —— Core Text字体操作)