Last active
July 1, 2023 10:53
-
-
Save macprog-guy/156d33bfefef570a7efb to your computer and use it in GitHub Desktop.
NSFont Category to make it easy to add or remove traits.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
A small category on NSFont to make it easy to manipulate fonts. | |
The header file is pretty self explanitory. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
\category NSFont(CFTraits) | |
\brief Adds a number of facilities to simplify working with fonts. | |
\details It's not always easy to get the bold or italic variant of a font | |
if it even exists. This category adds properties to NSFont that | |
indicate whether a font is bold, italic, condensed, monospaced | |
and more. Other properties can tell you if a bold or italic variant | |
exist. Finally, some methods return the bold or italic variations | |
of the font. | |
\author Eric Methot | |
\date 2012-04-10 | |
\copyright Copyleft 2012 Eric Methot. | |
*/ | |
#import <Cocoa/Cocoa.h> | |
@interface NSFont (CFTraits) | |
/// Returns YES if this font exists in a bold variant and NO otherwise. | |
@property (readonly) BOOL fontInFamilyExistsInBold; | |
/// Returns YES if this font exists in an italic variant and NO otherwise. | |
@property (readonly) BOOL fontInFamilyExistsInItalic; | |
/// Returns YES if this font is bold. | |
@property (readonly) BOOL isBold; | |
/// Returns YES if this font is italic. | |
@property (readonly) BOOL isItalic; | |
/// Returns YES if this font is condensed. | |
@property (readonly) BOOL isCondensed; | |
/// Returns YES if this font is expanded. | |
@property (readonly) BOOL isExpanded; | |
/// Returns YES if this font is monospaced. | |
@property (readonly) BOOL isMonospaced; | |
/// Returns YES if this font is vertical. | |
//@property (readonly) BOOL isVertical; | |
/// Returns YES if this font is UI optimized. | |
@property (readonly) BOOL isUIOptimized; | |
/// Returns the font size for this font instance. | |
@property (readonly) float fontSize; | |
/// Returns the bold variation of the font or the font itself | |
/// if such a variation does not exist. | |
@property (readonly) NSFont *fontVariationBold; | |
/// Returns the italic variation of the font or the font itself | |
/// if such a variation does not exist. | |
@property (readonly) NSFont *fontVariationItalic; | |
/// Returns the bold-italic variation of the font or the font itself | |
/// if such a variation does not exist. | |
@property (readonly) NSFont *fontVariationBoldItalic; | |
/// Returns the regular variation of the font or the font itself | |
/// if such a variation does not exist. | |
@property (readonly) NSFont *fontVariationRegular; | |
/// Returns the same font with new size. | |
- (NSFont*) fontVariationOfSize:(double)size; | |
/// Returns the value of the spc attribute in the fonts description. | |
@property (readonly) double spacing; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
\category NSFont(CFTraits) | |
\author Eric Methot | |
\date 2012-04-10 | |
\copyright Copyleft 2012 Eric Methot. | |
*/ | |
#import "NSFont+CFTraits.h" | |
#import <objc/runtime.h> | |
/// Some traits are cached globally by fontName. | |
static NSMutableDictionary *gNSFontCachedCustomTraits = nil; | |
/// Some traits are | |
const uint64_t kNUFontTraitInFamilyExistsInBold = 0x0000000100000000ULL; | |
const uint64_t kNUFontTraitInFamilyExistsInItalic = 0x0000000200000000ULL; | |
@implementation NSFont (CFTraits) | |
- (BOOL) checkForCachedFontTrait:(NSUInteger)trait | |
{ | |
// We use the cached traits if we have them. | |
NSNumber *cachedTraits = [gNSFontCachedCustomTraits objectForKey:self.fontName]; | |
if (cachedTraits == nil) { | |
// We use the traits in the fontDescriptor | |
NSFontSymbolicTraits traits = self.fontDescriptor.symbolicTraits; | |
// Then we look at the other members of that font family to see if there are any bold or italic variations. | |
NSArray *members = [[NSFontManager sharedFontManager] availableMembersOfFontFamily:self.familyName]; | |
uint64_t customTraits = traits; | |
for (NSArray *member in members) { | |
int memberTrait = [[member objectAtIndex:3] intValue]; | |
if (memberTrait & NSBoldFontMask) | |
customTraits |= kNUFontTraitInFamilyExistsInBold; | |
if (memberTrait & NSItalicFontMask) | |
customTraits |= kNUFontTraitInFamilyExistsInItalic; | |
} | |
cachedTraits = @(customTraits); | |
static dispatch_once_t onceToken; | |
dispatch_once(&onceToken, ^{ | |
gNSFontCachedCustomTraits = [NSMutableDictionary dictionaryWithCapacity:512]; | |
}); | |
@synchronized(gNSFontCachedCustomTraits) { | |
[gNSFontCachedCustomTraits setObject:cachedTraits forKey:self.fontName]; | |
} | |
} | |
uint64_t flag = cachedTraits.unsignedIntegerValue & trait; | |
return (BOOL)(flag != 0); | |
} | |
- (BOOL) fontInFamilyExistsInBold | |
{ | |
return [self checkForCachedFontTrait:kNUFontTraitInFamilyExistsInBold]; | |
} | |
- (BOOL) fontInFamilyExistsInItalic | |
{ | |
return [self checkForCachedFontTrait:kNUFontTraitInFamilyExistsInItalic]; | |
} | |
- (BOOL) isBold | |
{ | |
return [self checkForCachedFontTrait:NSFontBoldTrait]; | |
} | |
- (BOOL) isItalic | |
{ | |
return [self checkForCachedFontTrait:NSFontItalicTrait]; | |
} | |
- (BOOL) isCondensed | |
{ | |
return [self checkForCachedFontTrait:NSFontCondensedTrait]; | |
} | |
- (BOOL) isExpanded | |
{ | |
return [self checkForCachedFontTrait:NSFontExpandedTrait]; | |
} | |
- (BOOL) isMonospaced | |
{ | |
return [self checkForCachedFontTrait:NSFontMonoSpaceTrait]; | |
} | |
//- (BOOL) isVertical | |
//{ | |
// return [self checkForCachedFontTrait:NSFontVerticalTrait]; | |
//} | |
- (BOOL) isUIOptimized | |
{ | |
return [self checkForCachedFontTrait:NSFontUIOptimizedTrait]; | |
} | |
- (float) fontSize | |
{ | |
return [[self.fontDescriptor objectForKey:NSFontSizeAttribute] floatValue]; | |
} | |
- (NSFont*) fontVariationWithTraits:(NSFontTraitMask)traitMask | |
{ | |
NSFontManager *fontManager = [NSFontManager sharedFontManager]; | |
return [fontManager convertFont:self toHaveTrait:traitMask]; | |
} | |
- (NSFont*) fontVariationBold | |
{ | |
return [self fontVariationWithTraits:NSBoldFontMask]; | |
} | |
- (NSFont*) fontVariationItalic | |
{ | |
return [self fontVariationWithTraits:NSItalicFontMask]; | |
} | |
- (NSFont*) fontVariationBoldItalic | |
{ | |
return [self fontVariationWithTraits:NSBoldFontMask | NSItalicFontMask]; | |
} | |
- (NSFont*) fontVariationRegular | |
{ | |
return [self fontVariationWithTraits:NSUnboldFontMask | NSUnitalicFontMask]; | |
} | |
- (NSFont*) fontVariationOfSize:(double)size | |
{ | |
return [NSFont fontWithName:self.fontName size:size]; | |
} | |
- (double) spacing | |
{ | |
NSString *descr = self.description; | |
NSRange range = [descr rangeOfString:@"spc="]; | |
return [descr substringFromIndex:range.location + range.length].doubleValue; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
looks like this fails on font family "Arial Black" when calling " fontInFamilyExistsInItalic"
"Arial Black" does not exists in Italic trait. Font book says "Arial Black" has only normal trait.
checkForCachedFontTrait gets a cached trait of 0x380000002
which is tested against trait kNUFontTraitInFamilyExistsInItalic = 0x0000000200000000ULL;
resulting flag = YES which looks wrong to me..
could some one explain what is wrong in my experience
Thanks to all
LD