美文网首页程序员
CoreText编程指南(常用字体操作)

CoreText编程指南(常用字体操作)

作者: 癫癫的恋了 | 来源:发表于2016-03-26 11:39 被阅读597次

    Common Font Operations(常用字体操作)

    这一章描述了一个常用的字体处理操作,并展示了怎么用CoreText代码来实现它们。这些操作在iOS和OS X中是一样的。本章包含下面的操作列表:

    • 创建一个字体描述符
    • 从字体描述符创建一个字体
    • 创建相关的字体
    • 解析字体
    • 用字体解析数据创建一个字体
    • 调整字距
    • 从字符中获得符号

    Creating Font Descriptors(创建字体描述符)

    清单3-1中示例函数用PostScrpt font name和字号作为参数创建一个字体描述符。

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

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

    清单3-2中的示例函数从font family namefont traits创建一个字体描述符。

    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(从字体描述符创建字体)

    清单3-3展示了怎么创建一个字体描述符并用它创建一个字体。当你调用CTFontCreateWithFontDescriptor时,你通常传NULLmatrix参数来制定一个默认(identity)的矩阵。CTFontCreateWithFontDescriptorsizematrix(第二个和第三个)参数会覆盖制定的字体描述符中指定的值,除非(字体描述符中)他们没有被指定(size为0,matrixNULL)。

    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(创建相关字体)

    把一个已经存在的字体转化成一个相关或类似的字体经常是有用的。清单3-4中的示例函数展示了怎么根据函数调用时传的Boolean参数的值,来生成一个粗体或者非粗体的字体。如果当前字体family没有需要的样式,这个函数返回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);
    }
    

    清单3-8中的示例函数把所给的字体转换成另一个字体family中相似的字体,尽可能的保留特征。它可能返回NULLsize参数传0,matrix参数传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(解析字体)

    清单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(从解析数据创建字体)

    清单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来关闭它。清单3-8在前几个字符绘制的时候把字间距设置成一个大的数字。

    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(从字符中获取符号)

    清单3-9展示了怎么用一个字体从stringcharacters中获取glyphs。大部分时间有应该只从CTLine对象中获取这些信息,因为整个string可能不止用了一个字体。而且,对于复杂的文本简单的character-to-glyph mapping不会得到正确的外观。这个简单的glyph mapping可能在你尝试用一个字体显示特定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);
    }
    

    相关文章

      网友评论

        本文标题:CoreText编程指南(常用字体操作)

        本文链接:https://www.haomeiwen.com/subject/qwddlttx.html