Общие операции шрифта

В этой главе описываются некоторые общие погрузочно-разгрузочные работы шрифта и показывает, как кодировать их использующий Базовый текст. Эти операции являются тем же на iOS и OS X. Следующие операции с листингами кода включены в эту главу:

Создание дескрипторов шрифта

Функция в качестве примера в Перечислении 3-1 создает дескриптор шрифта из значений параметров, указывающих имя шрифта PostScript и размер точки.

Перечисление 3-1  , Создающее дескриптор шрифта из имени и размера точки

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

Функция в качестве примера в Перечислении 3-2 создает дескриптор шрифта из имени семейства шрифтов и черт шрифта.

Перечисление 3-2  , Создающее дескриптор шрифта из семьи и черт

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);

Создание шрифта от дескриптора шрифта

Перечисление 3-3 показывает, как создать дескриптор шрифта и использовать его для создания шрифта. Когда Вы вызываете CTFontCreateWithFontDescriptor, Вы обычно передаете NULL для параметра матрицы для указания значения по умолчанию (идентификационные данные) матрица. Размер и матрица (второй и третий) параметры CTFontCreateWithFontDescriptor переопределите любого указанного в дескрипторе шрифта, если они не являются неуказанными (0.0 для размера и NULL для матрицы).

Перечисление 3-3  , Создающее шрифт из дескриптора шрифта

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);

Создание связанных шрифтов

Часто полезно преобразовать существующий шрифт в связанный или похожий шрифт. Функция в качестве примера в Перечислении 3-4 показывает, как сделать шрифт полужирным, или неполужирный на основе значения булева параметра передал с вызовом функции. Если у семьи текущего шрифта нет необходимого стиля, функциональных возвратов NULL.

Перечисление 3-4  , Изменяющее черты шрифта

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 преобразовывает данный шрифт в похожий шрифт в другом семействе шрифтов, сохраняя черты, если это возможно. Это может возвратиться NULL. Передача в 0.0 для параметра размера и NULL поскольку параметр матрицы сохраняет размер от исходного шрифта.

Перечисление 3-5  , Преобразовывающее шрифт в другую семью

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

Сериализация шрифта

Функция в качестве примера в Перечислении 3-6 показывает, как создать данные XML для сериализации шрифта, который может быть встроен в документ. Также и предпочтительно, NSArchiver мог использоваться. Это - всего один способ выполнить эту задачу, но это сохраняет все данные от шрифта, должен был воссоздать точный шрифт в более позднее время.

Перечисление 3-6  , Сериализирующее шрифт

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

Создание шрифта от сериализированных данных

Функция в качестве примера в Перечислении 3-7 показывает, как создать ссылку шрифта из сглаженных данных XML. Это показывает, как не сгладить атрибуты шрифта и создать шрифт с теми атрибутами.

Перечисление 3-7  , Создающее шрифт из сериализированных данных

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

Изменение кернинга

Лигатуры и кернинг включены по умолчанию. Для отключения установите kCTKernAttributeName атрибут к 0. Перечисление 3-8 устанавливает размер керна в большое количество для первых нескольких нарисованных символов.

  Кернинг Установки перечисления 3-8

 // 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);

Получение глифов для символов

Перечисление 3-9 показывает, как получить глифы для символов в строке с единственным шрифтом. Большую часть времени необходимо просто использовать объект CTLine получить эту информацию, потому что один шрифт может не закодировать всю строку. Кроме того, простое отображение символа к глифу не получит корректное появление для сложных сценариев. При попытке вывести на экран определенные символы Unicode для шрифта, это простое отображение глифа может быть надлежащим.

Перечисление 3-9  , Получающее глифы для символов

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