Added code that handles all the attribute stuff for a CTFontRef AND CTFontDescriptorRef for us; we'll use this throughout the various font style files instead of doing everything ourselves.
This commit is contained in:
parent
be6a07755b
commit
4e7fb5e264
|
@ -25,6 +25,263 @@
|
||||||
// because the descriptors returned by Core Text's own font
|
// because the descriptors returned by Core Text's own font
|
||||||
// matching won't have any.
|
// matching won't have any.
|
||||||
|
|
||||||
|
@implementation fontStyleData
|
||||||
|
|
||||||
|
- (id)initWithFont:(CTFontRef)f
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
self->font = f;
|
||||||
|
CFRetain(self->font);
|
||||||
|
self->desc = CTFontCopyDescriptor(self->font);
|
||||||
|
if (![self prepare]) {
|
||||||
|
[self release];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithDescriptor:(CTFontDescriptorRef)d
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
self->font = NULL;
|
||||||
|
self->desc = d;
|
||||||
|
CFRetain(self->desc);
|
||||||
|
if (![self prepare]) {
|
||||||
|
[self release];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
#define REL(x) if (x != NULL) { CFRelease(x); x = NULL; }
|
||||||
|
REL(self->variationAxes);
|
||||||
|
REL(self->familyName);
|
||||||
|
REL(self->preferredFamilyName);
|
||||||
|
REL(self->fullName);
|
||||||
|
REL(self->subFamilyName);
|
||||||
|
REL(self->preferredSubFamilyName);
|
||||||
|
REL(self->postScriptName);
|
||||||
|
REL(self->variations);
|
||||||
|
REL(self->styleName);
|
||||||
|
REL(self->traits);
|
||||||
|
CFRelease(self->desc);
|
||||||
|
REL(self->font);
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)prepare
|
||||||
|
{
|
||||||
|
CFNumberRef num;
|
||||||
|
|
||||||
|
self->traits = NULL;
|
||||||
|
self->symbolic = 0;
|
||||||
|
self->weight = 0;
|
||||||
|
self->width = 0;
|
||||||
|
self->didStyleName = NO;
|
||||||
|
self->styleName = NULL;
|
||||||
|
self->didVariations = NO;
|
||||||
|
self->variations = NULL;
|
||||||
|
self->didRegistrationScope = NO;
|
||||||
|
self->hasRegistrationScope = NO;
|
||||||
|
self->registrationScope = 0;
|
||||||
|
self->didPostScriptName = NO;
|
||||||
|
self->postScriptName = NULL;
|
||||||
|
self->didFontFormat = NO;
|
||||||
|
self->fontFormat = 0;
|
||||||
|
self->didPreferredSubFamilyName = NO;
|
||||||
|
self->preferredSubFamilyName = NULL;
|
||||||
|
self->didSubFamilyName = NO;
|
||||||
|
self->subFamilyName = NULL;
|
||||||
|
self->didFullName = NO;
|
||||||
|
self->fullName = NULL;
|
||||||
|
self->didPreferredFamilyName = NO;
|
||||||
|
self->preferredFamilyName = NULL;
|
||||||
|
self->didFamilyName = NO;
|
||||||
|
self->familyName = NULL;
|
||||||
|
self->didVariationAxes = NO;
|
||||||
|
self->variationAxes = NULL;
|
||||||
|
|
||||||
|
self->traits = (CFDictionaryRef) CTFontDescriptorCopyAttribute(self->desc, kCTFontTraitsAttribute);
|
||||||
|
if (self->traits == NULL)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
num = (CFNumberRef) CFDictionaryGetValue(self->traits, kCTFontSymbolicTrait);
|
||||||
|
if (num == NULL)
|
||||||
|
return NO;
|
||||||
|
if (CFNumberGetValue(num, kCFNumberSInt32Type, &(self->symbolic)) == false)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
num = (CFNumberRef) CFDictionaryGetValue(self->traits, kCTFontWeightTrait);
|
||||||
|
if (num == NULL)
|
||||||
|
return NO;
|
||||||
|
if (CFNumberGetValue(num, kCFNumberDoubleType, &(self->weight)) == false)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
num = (CFNumberRef) CFDictionaryGetValue(self->traits, kCTFontWidthTrait);
|
||||||
|
if (num == NULL)
|
||||||
|
return NO;
|
||||||
|
if (CFNumberGetValue(num, kCFNumberDoubleType, &(self->width)) == false)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)ensureFont
|
||||||
|
{
|
||||||
|
if (self->font != NULL)
|
||||||
|
return;
|
||||||
|
self->font = CTFontCreateWithFontDescriptor(self->desc, 0.0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CTFontSymbolicTraits)symbolicTraits
|
||||||
|
{
|
||||||
|
return self->symbolic;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (double)weight
|
||||||
|
{
|
||||||
|
return self->weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (double)width
|
||||||
|
{
|
||||||
|
return self->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CFStringRef)styleName
|
||||||
|
{
|
||||||
|
if (!self->didStyleName) {
|
||||||
|
self->didStyleName = YES;
|
||||||
|
self->styleName = (CFStringRef) CTFontDescriptorCopyAttribute(self->desc, kCTFontStyleNameAttribute);
|
||||||
|
// The code we use this for (guessItalicOblique() below) checks if this is NULL or not, so we're good.
|
||||||
|
}
|
||||||
|
return self->styleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CFDictionaryRef)variations
|
||||||
|
{
|
||||||
|
if (!self->didVariations) {
|
||||||
|
self->didVariations = YES;
|
||||||
|
self->variations = (CFDictionaryRef) CTFontDescriptorCopyAttribute(self->desc, kCTFontVariationsAttribute);
|
||||||
|
// This being NULL is used to determine whether a font uses variations at all, so we don't need to worry now.
|
||||||
|
}
|
||||||
|
return self->variations;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasRegistrationScope
|
||||||
|
{
|
||||||
|
if (!self->didRegistrationScope) {
|
||||||
|
CFNumberRef num;
|
||||||
|
|
||||||
|
self->didRegistrationScope = YES;
|
||||||
|
num = (CFNumberRef) CTFontDescriptorCopyAttribute(desc, kCTFontRegistrationScopeAttribute);
|
||||||
|
self->hasRegistrationScope = num != NULL;
|
||||||
|
if (self->hasRegistrationScope) {
|
||||||
|
if (CFNumberGetValue(num, kCFNumberSInt32Type, &(self->registrationScope)) == false) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
CFRelease(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self->hasRegistrationScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CTFontManagerScope)registrationScope
|
||||||
|
{
|
||||||
|
[self hasRegistrationScope];
|
||||||
|
return self->registrationScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CFStringRef)postScriptName
|
||||||
|
{
|
||||||
|
if (!self->didPostScriptName) {
|
||||||
|
self->didPostScriptName = YES;
|
||||||
|
[self ensureFont];
|
||||||
|
self->postScriptName = CTFontCopyPostScriptName(self->font);
|
||||||
|
}
|
||||||
|
return self->postScriptName;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CFDataRef)table:(CTFontTableTag)tag
|
||||||
|
{
|
||||||
|
[self ensureFont];
|
||||||
|
return CTFontCopyTable(self->font, tag, kCTFontTableOptionNoOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CTFontFormat)fontFormat
|
||||||
|
{
|
||||||
|
if (!self->didFontFormat) {
|
||||||
|
CFNumberRef num;
|
||||||
|
|
||||||
|
self->didFontFormat = YES;
|
||||||
|
num = (CFNumberRef) CTFontDescriptorCopyAttribute(self->desc, kCTFontFormatAttribute);
|
||||||
|
if (num == NULL) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
if (CFNumberGetValue(num, kCFNumberSInt32Type, &(self->fontFormat)) == false) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
CFRelease(num);
|
||||||
|
}
|
||||||
|
return self->fontFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't need to worry if this or any of the functions that use it return NULL, because the code that uses it (libFontRegistry.dylib bug workarounds in fonttraits.m) checks for NULL.
|
||||||
|
- (CFStringRef)fontName:(CFStringRef)key
|
||||||
|
{
|
||||||
|
[self ensureFont];
|
||||||
|
return CTFontCopyName(self->font, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FONTNAME(sel, did, var, key) \
|
||||||
|
- (CFString)sel \
|
||||||
|
{ \
|
||||||
|
if (!did) { \
|
||||||
|
did = YES; \
|
||||||
|
var = [self fontName:key]; \
|
||||||
|
} \
|
||||||
|
return var; \
|
||||||
|
}
|
||||||
|
FONTNAME(preferredSubFamilyName,
|
||||||
|
self->didPreferredSubFamilyName,
|
||||||
|
self->preferredSubFamilyName,
|
||||||
|
kCTFontPreferredSubFamilyNameKey)
|
||||||
|
FONTNAME(subFamilyName,
|
||||||
|
self->didSubFamilyName,
|
||||||
|
self->subFamilyName,
|
||||||
|
kCTFontSubFamilyNameKey)
|
||||||
|
FONTNAME(fullName,
|
||||||
|
self->didFullName,
|
||||||
|
self->fullName,
|
||||||
|
kCTFontFullNameKey)
|
||||||
|
FONTNAME(preferredFamilyName,
|
||||||
|
self->didPreferredFamilyName,
|
||||||
|
self->preferredFamilyName,
|
||||||
|
kCTFontPreferredFamilyNameKey)
|
||||||
|
FONTNAME(familyName,
|
||||||
|
self->didFamilyName,
|
||||||
|
self->familyName,
|
||||||
|
kCTFontFamilyNameKey)
|
||||||
|
|
||||||
|
- (CFArrayRef)variationAxes
|
||||||
|
{
|
||||||
|
if (!self->didVariationAxes) {
|
||||||
|
self->didVariationAxes = YES;
|
||||||
|
[self ensureFont];
|
||||||
|
self->variationAxes = CTFontCopyVariationAxes(self->font);
|
||||||
|
// We don't care about the return value because we call this only on fonts that we know have variations anyway.
|
||||||
|
}
|
||||||
|
return self->variationAxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
struct closeness {
|
struct closeness {
|
||||||
CFIndex index;
|
CFIndex index;
|
||||||
double weight;
|
double weight;
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
// 3 november 2017
|
||||||
|
|
||||||
|
// fontstyle.m
|
||||||
|
@interface fontStyleData : NSObject {
|
||||||
|
CTFontRef font;
|
||||||
|
CTFontDescriptorRef desc;
|
||||||
|
CFDictionaryRef traits;
|
||||||
|
CTFontSymbolicTraits symbolic;
|
||||||
|
double weight;
|
||||||
|
double width;
|
||||||
|
BOOL didStyleName;
|
||||||
|
CFStringRef styleName;
|
||||||
|
BOOL didVariations;
|
||||||
|
CFDictionaryRef variations;
|
||||||
|
BOOL didRegistrationScope;
|
||||||
|
BOOL hasRegistrationScope;
|
||||||
|
CTFontManagerScope registrationScope;
|
||||||
|
BOOL didPostScriptName;
|
||||||
|
CFStringRef postScriptName;
|
||||||
|
BOOL didFontFormat;
|
||||||
|
CTFontFormat fontFormat;
|
||||||
|
BOOL didPreferredSubFamilyName;
|
||||||
|
CFStringRef preferredSubFamilyName;
|
||||||
|
BOOL didSubFamilyName;
|
||||||
|
CFStringRef subFamilyName;
|
||||||
|
BOOL didFullName;
|
||||||
|
CFStringRef fullName;
|
||||||
|
BOOL didPreferredFamilyName;
|
||||||
|
CFStringRef preferredFamilyName;
|
||||||
|
BOOL didFamilyName;
|
||||||
|
CFStringRef familyName;
|
||||||
|
BOOL didVariationAxes;
|
||||||
|
CFArrayRef variationAxes;
|
||||||
|
}
|
||||||
|
- (id)initWithFont:(CTFontRef)f;
|
||||||
|
- (id)initWithDescriptor:(CTFontDescriptorRef)d;
|
||||||
|
- (BOOL)prepare;
|
||||||
|
- (void)ensureFont;
|
||||||
|
- (CTFontSymbolicTraits)symbolicTraits;
|
||||||
|
- (double)weight;
|
||||||
|
- (double)width;
|
||||||
|
- (CFStringRef)styleName;
|
||||||
|
- (CFDictionaryRef)variations;
|
||||||
|
- (BOOL)hasRegistrationScope;
|
||||||
|
- (CTFontManagerScope)registrationScope;
|
||||||
|
- (CFStringRef)postScriptName;
|
||||||
|
- (CFDataRef)table:(CTFontTableTag)tag;
|
||||||
|
- (CTFontFormat)fontFormat;
|
||||||
|
- (CFStringRef)fontName:(CFStringRef)key;
|
||||||
|
- (CFStringRef)preferredSubFamilyName;
|
||||||
|
- (CFStringRef)subFamilyName;
|
||||||
|
- (CFStringRef)fullName;
|
||||||
|
- (CFStringRef)preferredFamilyName;
|
||||||
|
- (CFStringRef)familyName;
|
||||||
|
- (CFArrayRef)variationAxes;
|
||||||
|
@end
|
Loading…
Reference in New Issue