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