Migrated fonttraits.m to use the new fontStyleData class.

This commit is contained in:
Pietro Gagliardi 2017-11-03 18:52:15 -04:00
parent 51f0e3dbe5
commit 72d31285c1
2 changed files with 48 additions and 128 deletions

View File

@ -25,6 +25,10 @@
// 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.
// TODO explicitly mark these as undocumented
extern const CFStringRef kCTFontPreferredSubFamilyNameKey;
extern const CFStringRef kCTFontPreferredFamilyNameKey;
@implementation fontStyleData @implementation fontStyleData
- (id)initWithFont:(CTFontRef)f - (id)initWithFont:(CTFontRef)f

View File

@ -1,5 +1,6 @@
// 1 november 2017 // 1 november 2017
#import "uipriv_darwin.h" #import "uipriv_darwin.h"
#import "fontstyle.h"
// This is the part of the font style matching and normalization code // This is the part of the font style matching and normalization code
// that handles fonts that use a traits dictionary. // that handles fonts that use a traits dictionary.
@ -18,76 +19,30 @@
// what. We'll just convert Core Text's values into libui constants // what. We'll just convert Core Text's values into libui constants
// and use those for matching. // and use those for matching.
static BOOL fontRegistered(CTFontDescriptorRef desc) static BOOL fontRegistered(fontStyleData *d)
{ {
CFNumberRef scope; if (![d hasRegistrationScope])
CTFontManagerScope val;
scope = (CFNumberRef) CTFontDescriptorCopyAttribute(desc, kCTFontRegistrationScopeAttribute);
if (scope == NULL)
// header says this should be treated as the same as not registered // header says this should be treated as the same as not registered
return NO; return NO;
if (CFNumberGetValue(scope, kCFNumberSInt32Type, &val) == false) {
// TODO
CFRelease(scope);
return NO;
}
CFRelease(scope);
// examination of Core Text shows this is accurate // examination of Core Text shows this is accurate
return val != kCTFontManagerScopeNone; return [d registrationScope] != kCTFontManagerScopeNone;
}
static BOOL getTraits(CTFontDescriptorRef desc, CTFontSymbolicTraits *symbolic, double *weight, double *width)
{
CFDictionaryRef traits = NULL;
CFNumberRef num = NULL;
traits = (CFDictionaryRef) CTFontDescriptorCopyAttribute(desc, kCTFontTraitsAttribute);
if (traits == NULL)
return NO;
num = (CFNumberRef) CFDictionaryGetValue(traits, kCTFontSymbolicTrait);
if (num == NULL)
goto fail;
if (CFNumberGetValue(num, kCFNumberSInt32Type, symbolic) == false)
goto fail;
num = (CFNumberRef) CFDictionaryGetValue(traits, kCTFontWeightTrait);
if (num == NULL)
goto fail;
if (CFNumberGetValue(num, kCFNumberDoubleType, weight) == false)
goto fail;
num = (CFNumberRef) CFDictionaryGetValue(traits, kCTFontWidthTrait);
if (num == NULL)
goto fail;
if (CFNumberGetValue(num, kCFNumberDoubleType, width) == false)
goto fail;
CFRelease(traits);
return YES;
fail:
CFRelease(traits);
return NO;
} }
// Core Text doesn't seem to differentiate between Italic and Oblique. // Core Text doesn't seem to differentiate between Italic and Oblique.
// Pango's Core Text code just does a g_strrstr() (backwards case-sensitive search) for "Oblique" in the font's style name (see https://git.gnome.org/browse/pango/tree/pango/pangocoretext-fontmap.c); let's do that too I guess // Pango's Core Text code just does a g_strrstr() (backwards case-sensitive search) for "Oblique" in the font's style name (see https://git.gnome.org/browse/pango/tree/pango/pangocoretext-fontmap.c); let's do that too I guess
static uiDrawTextFontItalic guessItalicOblique(CTFontDescriptorRef desc) static uiDrawTextFontItalic guessItalicOblique(fontStyleData *d)
{ {
CFStringRef styleName; CFStringRef styleName;
BOOL isOblique; BOOL isOblique;
isOblique = NO; // default value isOblique = NO; // default value
styleName = (CFStringRef) CTFontDescriptorCopyAttribute(desc, kCTFontStyleNameAttribute); styleName = [d styleName];
if (styleName != NULL) { if (styleName != NULL) {
CFRange range; CFRange range;
range = CFStringFind(styleName, CFSTR("Oblique"), kCFCompareBackwards); range = CFStringFind(styleName, CFSTR("Oblique"), kCFCompareBackwards);
if (range.location != kCFNotFound) if (range.location != kCFNotFound)
isOblique = YES; isOblique = YES;
CFRelease(styleName);
} }
if (isOblique) if (isOblique)
return uiDrawFontItalicOblique; return uiDrawFontItalicOblique;
@ -120,9 +75,8 @@ static const CFStringRef exceptions[] = {
NULL, NULL,
}; };
static void trySecondaryOS2Values(CTFontDescriptorRef desc, uiDrawFontDescriptor *out, BOOL *hasWeight, BOOL *hasWidth) static void trySecondaryOS2Values(fontStyleData *d, uiDrawFontDescriptor *out, BOOL *hasWeight, BOOL *hasWidth)
{ {
CTFontRef font;
CFDataRef os2; CFDataRef os2;
uint16_t usWeightClass, usWidthClass; uint16_t usWeightClass, usWidthClass;
CFStringRef psname; CFStringRef psname;
@ -132,17 +86,13 @@ static void trySecondaryOS2Values(CTFontDescriptorRef desc, uiDrawFontDescriptor
*hasWidth = NO; *hasWidth = NO;
// only applies to unregistered fonts // only applies to unregistered fonts
if (fontRegistered(desc)) if (fontRegistered(d))
return; return;
font = CTFontCreateWithFontDescriptor(desc, 0.0, NULL); os2 = [d table:kCTFontTableOS2];
if (os2 == NULL)
os2 = CTFontCopyTable(font, kCTFontTableOS2, kCTFontTableOptionNoOptions);
if (os2 == NULL) {
// no OS2 table, so no secondary values // no OS2 table, so no secondary values
CFRelease(font);
return; return;
}
if (CFDataGetLength(os2) > 77) { if (CFDataGetLength(os2) > 77) {
const UInt8 *b; const UInt8 *b;
@ -176,49 +126,32 @@ static void trySecondaryOS2Values(CTFontDescriptorRef desc, uiDrawFontDescriptor
CFRelease(os2); CFRelease(os2);
// don't use secondary weights in the event of special predefined names // don't use secondary weights in the event of special predefined names
psname = CTFontCopyPostScriptName(font); psname = [d postScriptName];
for (ex = exceptions; *ex != NULL; ex++) for (ex = exceptions; *ex != NULL; ex++)
if (CFEqual(psname, *ex)) { if (CFEqual(psname, *ex)) {
*hasWeight = NO; *hasWeight = NO;
break; break;
} }
CFRelease(psname);
CFRelease(font);
} }
// TODO explicitly mark these as undocumented static BOOL testTTFOTFSubfamilyName(CFStringRef name, CFStringRef want)
extern const CFStringRef kCTFontPreferredSubFamilyNameKey; {
extern const CFStringRef kCTFontPreferredFamilyNameKey; CFRange range;
static const CFStringRef subfamilyKeys[] = { if (name == NULL)
kCTFontSubFamilyNameKey, return NO;
kCTFontPreferredSubFamilyNameKey, range.location = 0;
kCTFontFullNameKey, range.length = CFStringGetLength(name);
kCTFontPreferredFamilyNameKey, return CFStringFindWithOptions(name, want, range,
kCTFontFamilyNameKey, (kCFCompareCaseInsensitive | kCFCompareBackwards | kCFCompareNonliteral), NULL) != false;
NULL, }
};
static BOOL testTTFOTFSubfamilyNames(fontStyleData *d, CFStringRef want)
static BOOL testTTFOTFSubfamilyNames(CTFontDescriptorRef desc, CFStringRef want)
{ {
CFNumberRef num;
CTFontFormat type;
CGFontRef font; CGFontRef font;
CFString *key; CFString *key;
num = (CFNumberRef) CTFontDescriptorCopyAttribute(desc, kCTFontFormatAttribute); switch ([d fontFormat]) {
if (num == NULL) {
// TODO
return NO;
}
if (CFNumberGetValue(num, kCFNumberSInt32Type, &type) == false) {
// TODO
CFRelease(num);
return NO;
}
CFRelease(num);
switch (type) {
case kCTFontFormatOpenTypePostScript: case kCTFontFormatOpenTypePostScript:
case kCTFontFormatOpenTypeTrueType: case kCTFontFormatOpenTypeTrueType:
case kCTFontFormatTrueType: case kCTFontFormatTrueType:
@ -227,26 +160,15 @@ static BOOL testTTFOTFSubfamilyNames(CTFontDescriptorRef desc, CFStringRef want)
return NO; return NO;
} }
font = CTFontCreateWithFontDescriptor(desc, 0.0, NULL); if (testTTFOTFSubfamilyName([d preferredSubFamilyName], want))
for (key = subfamilyKeys; *key != NULL; key++) {
CFStringRef val;
CFRange range;
val = CTFontCopyName(font, *key);
if (val == NULL)
continue;
range.location = 0;
range.length = CFStringGetLength(val);
if (CFStringFindWithOptions(val, want, range,
(kCFCompareCaseInsensitive | kCFCompareBackwards | kCFCompareNonliteral), NULL) != false) {
CFRelease(val);
CFRelease(font);
return YES; return YES;
} if (testTTFOTFSubfamilyName([d subFamilyName], want))
CFRelease(val); return YES;
} if (testTTFOTFSubfamilyName([d fullName], want))
CFRelease(font); return YES;
return NO; if (testTTFOTFSubfamilyName([d preferredFamilyName], want))
return YES;
return testTTFOTFSubfamilyName([d familyName], want);
} }
// work around a bug in libFontRegistry.dylib // work around a bug in libFontRegistry.dylib
@ -261,27 +183,21 @@ static BOOL shouldReallyBeSemiCondensed(CTFontDescriptorRef desc)
return testTTFOTFSubfamilyNames(desc, CFSTR("Semi Condensed")); return testTTFOTFSubfamilyNames(desc, CFSTR("Semi Condensed"));
} }
void processFontTraits(CTFontDescriptorRef desc, uiDrawFontDescriptor *out) void processFontTraits(fontStyleData *d, uiDrawFontDescriptor *out)
{ {
CTFontSymbolicTraits symbolic; double weight, width;
double weight;
double width;
BOOL hasWeight, hasWidth; BOOL hasWeight, hasWidth;
uint16_t usWeightClasss, usWidthClass;
CTFontRef font;
if (!getTraits(desc, &symbolic, &weight, &width)) {
// TODO
goto fail;
}
out->Italic = uiDrawTextItalicNormal; out->Italic = uiDrawTextItalicNormal;
if ((symbolic & kCTFontItalicTrait) != 0) if (([d symbolicTraits] & kCTFontItalicTrait) != 0)
out->Italic = guessItalicOblique(desc); out->Italic = guessItalicOblique(d);
hasWeight = NO; hasWeight = NO;
hasWidth = NO; hasWidth = NO;
trySecondaryOS2Values(desc, out, &hasWeight, &hasWidth); trySecondaryOS2Values(d, out, &hasWeight, &hasWidth);
weight = [d weight];
width = [d width];
if (!hasWeight) if (!hasWeight)
// TODO this scale is a bit lopsided // TODO this scale is a bit lopsided
@ -293,7 +209,7 @@ void processFontTraits(CTFontDescriptorRef desc, uiDrawFontDescriptor *out)
out->Weight = uiDrawTextWeightLight; out->Weight = uiDrawTextWeightLight;
else if (weight <= -0.23) { else if (weight <= -0.23) {
out->Weight = uiDrawTextWeightBook; out->Weight = uiDrawTextWeightBook;
if (shouldReallyBeThin(desc)) if (shouldReallyBeThin(d))
out->Weight = uiDrawTextWeightThin; out->Weight = uiDrawTextWeightThin;
} else if (weight <= 0.0) } else if (weight <= 0.0)
out->Weight = uiDrawTextWeightNormal; out->Weight = uiDrawTextWeightNormal;
@ -314,7 +230,7 @@ void processFontTraits(CTFontDescriptorRef desc, uiDrawFontDescriptor *out)
// TODO this scale is a bit lopsided // TODO this scale is a bit lopsided
if (width <= -0.7) { if (width <= -0.7) {
out->Stretch = uiDrawTextStretchUltraCondensed; out->Stretch = uiDrawTextStretchUltraCondensed;
if (shouldReallyBeSemiCondensed(desc)) if (shouldReallyBeSemiCondensed(d))
out->Stretch = uiDrawTextStretchSemiCondensed; out->Stretch = uiDrawTextStretchSemiCondensed;
} else if (width <= -0.5) } else if (width <= -0.5)
out->Stretch = uiDrawTextStretchExtraCondensed; out->Stretch = uiDrawTextStretchExtraCondensed;