Migrated fonttraits.m to use the new fontStyleData class.
This commit is contained in:
parent
51f0e3dbe5
commit
72d31285c1
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue