Rewrite handling of standard fonts to provide better behavior.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@17089 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Alexander Malmberg 2003-07-02 15:46:32 +00:00
parent 42b6ef6744
commit d4fff8ae12
2 changed files with 177 additions and 254 deletions

View file

@ -1,3 +1,9 @@
2003-07-02 16:38 Alexander Malmberg <alexander@malmberg.org>
* Source/NSFont.m: (Mostly) rewrite handling of standard fonts to
provide better behavior, especially when only some fonts are set in
the defaults. Updated documentation.
2003-07-01 Serg Stoyan <stoyan@hologr.com> 2003-07-01 Serg Stoyan <stoyan@hologr.com>
* Source/NSBrowser.m (_createColumn): * Source/NSBrowser.m (_createColumn):

View file

@ -42,42 +42,6 @@
#include "gnustep/gui/GSFusedSilicaContext.h" #include "gnustep/gui/GSFusedSilicaContext.h"
/*
The valid font roles. Note that these values are used when encoding and
decoding, so entries may never be removed. Entries may be added after the
last entry, and entries don't have to actually be handled.
Note that these values are multiplied by two before they are used since the
lowest bit is used to indicate an explicit size. If the lowest bit is set,
the size is explicitly specified and encoded.
*/
enum FontRoles
{
RoleExplicit=0,
RoleBoldSystemFont,
RoleSystemFont,
RoleUserFixedPitchFont,
RoleUserFont,
RoleTitleBarFont,
RoleMenuFont,
RoleMessageFont,
RolePaletteFont,
RoleToolTipsFont,
RoleControlContentFont,
RoleLabelFont
};
/* We cache all the 4 default fonts after we first get them.
But when a default font is changed, the variable is set to YES
so all default fonts are forced to be recomputed. */
static BOOL systemCacheNeedsRecomputing = NO;
static BOOL boldSystemCacheNeedsRecomputing = NO;
static BOOL userCacheNeedsRecomputing = NO;
static BOOL userFixedCacheNeedsRecomputing = NO;
static NSFont *placeHolder = nil;
@interface NSFont (Private) @interface NSFont (Private)
- (id) initWithName: (NSString*)name - (id) initWithName: (NSString*)name
matrix: (const float*)fontMatrix matrix: (const float*)fontMatrix
@ -127,17 +91,17 @@ newNameWithMatrix(NSString *name, const float *matrix, BOOL fix,
font names available are: font names available are:
</p> </p>
<list> <list>
<item>NSBoldFont Helvetica-Bold</item> <item>NSBoldFont Helvetica-Bold (System bold font)</item>
<item>NSControlContentFont Helvetica</item> <item>NSControlContentFont System font</item>
<item>NSFont Helvetica (System Font)</item> <item>NSFont Helvetica (System Font)</item>
<item>NSLabelFont Helvetica</item> <item>NSLabelFont System font</item>
<item>NSMenuFont Helvetica</item> <item>NSMenuFont System font</item>
<item>NSMessageFont Helvetica</item> <item>NSMessageFont System font</item>
<item>NSPaletteFont Helvetica-Bold</item> <item>NSPaletteFont System bold font</item>
<item>NSTitleBarFont Helvetica-Bold</item> <item>NSTitleBarFont System bold font</item>
<item>NSToolTipsFont Helvetica</item> <item>NSToolTipsFont System font</item>
<item>NSUserFixedPitchFont Courier</item> <item>NSUserFixedPitchFont Courier</item>
<item>NSUserFont Helvetica</item> <item>NSUserFont System font</item>
</list> </list>
<p> <p>
The default sizes are: The default sizes are:
@ -146,7 +110,7 @@ newNameWithMatrix(NSString *name, const float *matrix, BOOL fix,
<item>NSBoldFontSize (none)</item> <item>NSBoldFontSize (none)</item>
<item>NSControlContentFontSize (none)</item> <item>NSControlContentFontSize (none)</item>
<item>NSFontSize 12 (System Font Size)</item> <item>NSFontSize 12 (System Font Size)</item>
<item>NSLabelFontSize 12</item> <item>NSLabelFontSize (none)</item>
<item>NSMenuFontSize (none)</item> <item>NSMenuFontSize (none)</item>
<item>NSMessageFontSize (none)</item> <item>NSMessageFontSize (none)</item>
<item>NSPaletteFontSize (none)</item> <item>NSPaletteFontSize (none)</item>
@ -166,6 +130,9 @@ newNameWithMatrix(NSString *name, const float *matrix, BOOL fix,
/* Class variables*/ /* Class variables*/
/* See comments in +initialize. */
static NSFont *placeHolder = nil;
/* Fonts that are preferred by the application */ /* Fonts that are preferred by the application */
static NSArray *_preferredFonts; static NSArray *_preferredFonts;
@ -177,90 +144,196 @@ static NSMapTable* globalFontMap = 0;
static NSUserDefaults *defaults = nil; static NSUserDefaults *defaults = nil;
static NSFont *
getNSFont(NSString* key, NSString* defaultFontName, float fontSize, int role) /*
The valid font roles. Note that these values are used when encoding and
decoding, so entries may never be removed. Entries may be added after the
last entry, and entries don't have to actually be handled.
Note that these values are multiplied by two before they are used since the
lowest bit is used to indicate an explicit size. If the lowest bit is set,
the size is explicitly specified and encoded.
*/
enum FontRoles
{
RoleExplicit=0,
RoleBoldSystemFont,
RoleSystemFont,
RoleUserFixedPitchFont,
RoleUserFont,
RoleTitleBarFont,
RoleMenuFont,
RoleMessageFont,
RolePaletteFont,
RoleToolTipsFont,
RoleControlContentFont,
RoleLabelFont,
RoleMax
};
typedef struct
{
/* Defaults key for this font. */
NSString *key;
/* If there's no defaults key, fall back to the font for this role. */
int fallback;
/* If there's no other role to fall back to, use this font. */
NSString *defaultFont;
/* Cached font for the default size of this role. */
NSFont *cachedFont;
} font_role_info_t;
/*
This table, through getNSFont, controls the behavior of getting the standard
fonts, and must match the table in the documentation above. Each entry should
have a fallback or a defaultFont. There must be a default font for the system
font. Bad Things will happen if entries are invalid.
*/
static font_role_info_t font_roles[RoleMax]={
{nil , 0 , nil , nil},
{@"NSBoldFont" , 0 , @"Helvetica-Bold", nil},
{@"NSFont" , 0 , @"Helvetica" , nil},
{@"NSUserFixedPitchFont", 0 , @"Courier" , nil},
{@"NSUserFont" , RoleSystemFont , nil , nil},
{@"NSTitleBarFont" , RoleBoldSystemFont, nil , nil},
{@"NSMenuFont" , RoleSystemFont , nil , nil},
{@"NSMessageFont" , RoleSystemFont , nil , nil},
{@"NSPaletteFont" , RoleBoldSystemFont, nil , nil},
{@"NSToolTipsFont" , RoleSystemFont , nil , nil},
{@"NSControlContentFont", RoleSystemFont , nil , nil},
{@"NSLabelFont" , RoleSystemFont , nil , nil}
};
static NSString *fontNameForRole(int role, int *actual_entry)
{
int i;
NSString *fontName;
i = role;
while (1)
{
fontName = [defaults stringForKey: font_roles[i].key];
if (fontName)
{
break;
}
else if (font_roles[i].fallback)
{
i = font_roles[i].fallback;
}
else if (font_roles[i].defaultFont)
{
fontName = font_roles[i].defaultFont;
break;
}
else
{
NSCAssert(NO, @"Invalid font role table entry.");
}
}
if (actual_entry)
*actual_entry = i;
return fontName;
}
static NSFont *getNSFont(float fontSize, int role)
{ {
NSString *fontName; NSString *fontName;
NSFont *font; NSFont *font;
BOOL defaultSize;
int i;
int font_role;
role *= 2; NSCAssert(role > RoleExplicit && role < RoleMax, @"Invalid font role.");
fontName = [defaults objectForKey: key];
if (fontName == nil)
{
fontName = defaultFontName;
}
if (fontSize == 0) font_role = role * 2;
defaultSize = (fontSize == 0.0);
if (defaultSize)
{ {
font_role |= 1;
if (font_roles[role].cachedFont)
return font_roles[role].cachedFont;
fontSize = [defaults floatForKey: fontSize = [defaults floatForKey:
[NSString stringWithFormat: @"%@Size", key]]; [NSString stringWithFormat: @"%@Size", font_roles[role].key]];
}
else if (!fontSize)
{ fontSize = [NSFont systemFontSize];
role |= 1;
} }
font = [NSFontClass _fontWithName: fontName size: fontSize role: role]; fontName = fontNameForRole(role, &i);
font = [NSFontClass _fontWithName: fontName
size: fontSize
role: font_role];
/* That font couldn't be found (?). */ /* That font couldn't be found. */
if (font == nil) if (font == nil)
{ {
/* Try the same size, but the defaultFontName. */ /* Warn using the role that specified the invalid font. */
font = [NSFontClass _fontWithName: defaultFontName NSLog(@"The font specified for %@, %@, can't be found.",
font_roles[i].key, fontName);
/* Try the system font. */
fontName = fontNameForRole(RoleSystemFont, NULL);
font = [NSFontClass _fontWithName: fontName
size: fontSize size: fontSize
role: role]; role: font_role];
if (font == nil) if (font == nil)
{ {
/* Try the default font name and size. */ /* Try the default system font and size. */
fontSize = [defaults floatForKey: fontName = font_roles[RoleSystemFont].defaultFont;
[NSString stringWithFormat: @"%@Size", key]]; font = [NSFontClass _fontWithName: fontName
size: 12.0
font = [NSFontClass _fontWithName: defaultFontName role: font_role];
size: fontSize
role: role];
/* It seems we can't get any font here! Try some well known /* It seems we can't get any font here! Try some well known
* fonts as a last resort. */ * fonts as a last resort. */
if (font == nil) if (font == nil)
{ {
font = [NSFontClass _fontWithName: @"Helvetica" font = [NSFontClass _fontWithName: @"Helvetica"
size: 12. size: 12.0
role: role]; role: font_role];
} }
if (font == nil) if (font == nil)
{ {
font = [NSFontClass _fontWithName: @"Courier" font = [NSFontClass _fontWithName: @"Courier"
size: 12. size: 12.0
role: role]; role: font_role];
} }
if (font == nil) if (font == nil)
{ {
font = [NSFontClass _fontWithName: @"Fixed" font = [NSFontClass _fontWithName: @"Fixed"
size: 12. size: 12.0
role: role]; role: font_role];
} }
} }
} }
ASSIGN(font_roles[role].cachedFont, font);
return font; return font;
} }
void static void setNSFont(NSString *key, NSFont *font)
setNSFont(NSString* key, NSFont* font)
{ {
int i;
[defaults setObject: [font fontName] forKey: key]; [defaults setObject: [font fontName] forKey: key];
systemCacheNeedsRecomputing = YES; for (i = 1; i < RoleMax; i++)
boldSystemCacheNeedsRecomputing = YES; DESTROY(font_roles[i].cachedFont);
userCacheNeedsRecomputing = YES;
userFixedCacheNeedsRecomputing = YES;
/* Don't care about errors */ /* Don't care about errors */
[defaults synchronize]; [defaults synchronize];
} }
// //
// Class methods // Class methods
// //
@ -275,7 +348,7 @@ setNSFont(NSString* key, NSFont* font)
* as a font ... the initialiser knows that whenever it gets the * as a font ... the initialiser knows that whenever it gets the
* placeHolder it should either return a cached font or return a * placeHolder it should either return a cached font or return a
* newly allocated font to replace it. This mechanism stops the * newly allocated font to replace it. This mechanism stops the
* +fontWithName:... methods from having to allocete fonts instances * +fontWithName:... methods from having to allocate fonts instances
* which would immediately have to be released for replacement by * which would immediately have to be released for replacement by
* a cache object. * a cache object.
*/ */
@ -301,21 +374,7 @@ setNSFont(NSString* key, NSFont* font)
*/ */
+ (NSFont*) boldSystemFontOfSize: (float)fontSize + (NSFont*) boldSystemFontOfSize: (float)fontSize
{ {
static NSFont *font = nil; return getNSFont(fontSize, RoleBoldSystemFont);
if (fontSize != 0)
{
return getNSFont (@"NSBoldFont", @"Helvetica-Bold", fontSize, RoleBoldSystemFont);
}
else
{
if ((font == nil) || (boldSystemCacheNeedsRecomputing == YES))
{
ASSIGN (font, getNSFont (@"NSBoldFont", @"Helvetica-Bold", 0, RoleBoldSystemFont));
boldSystemCacheNeedsRecomputing = NO;
}
return font;
}
} }
/** /**
@ -325,21 +384,7 @@ setNSFont(NSString* key, NSFont* font)
*/ */
+ (NSFont*) systemFontOfSize: (float)fontSize + (NSFont*) systemFontOfSize: (float)fontSize
{ {
static NSFont *font = nil; return getNSFont(fontSize, RoleSystemFont);
if (fontSize != 0)
{
return getNSFont (@"NSFont", @"Helvetica", fontSize, RoleSystemFont);
}
else
{
if ((font == nil) || (systemCacheNeedsRecomputing == YES))
{
ASSIGN (font, getNSFont (@"NSFont", @"Helvetica", 0, RoleSystemFont));
systemCacheNeedsRecomputing = NO;
}
return font;
}
} }
/** /**
@ -348,21 +393,7 @@ setNSFont(NSString* key, NSFont* font)
*/ */
+ (NSFont*) userFixedPitchFontOfSize: (float)fontSize + (NSFont*) userFixedPitchFontOfSize: (float)fontSize
{ {
static NSFont *font = nil; return getNSFont(fontSize, RoleUserFixedPitchFont);
if (fontSize != 0)
{
return getNSFont (@"NSUserFixedPitchFont", @"Courier", fontSize, RoleUserFixedPitchFont);
}
else
{
if ((font == nil) || (userFixedCacheNeedsRecomputing == YES))
{
ASSIGN (font, getNSFont (@"NSUserFixedPitchFont", @"Courier", 0, RoleUserFixedPitchFont));
userFixedCacheNeedsRecomputing = NO;
}
return font;
}
} }
/** /**
@ -371,21 +402,7 @@ setNSFont(NSString* key, NSFont* font)
*/ */
+ (NSFont*) userFontOfSize: (float)fontSize + (NSFont*) userFontOfSize: (float)fontSize
{ {
static NSFont *font = nil; return getNSFont(fontSize, RoleUserFont);
if (fontSize != 0)
{
return getNSFont (@"NSUserFont", @"Helvetica", fontSize, RoleUserFont);
}
else
{
if ((font == nil) || (userCacheNeedsRecomputing == YES))
{
ASSIGN (font, getNSFont (@"NSUserFont", @"Helvetica", 0, RoleUserFont));
userCacheNeedsRecomputing = NO;
}
return font;
}
} }
/** /**
@ -417,137 +434,37 @@ setNSFont(NSString* key, NSFont* font)
+ (NSFont*) controlContentFontOfSize: (float)fontSize + (NSFont*) controlContentFontOfSize: (float)fontSize
{ {
static NSFont *font = nil; return getNSFont(fontSize, RoleControlContentFont);
if (fontSize != 0)
{
return getNSFont (@"NSControlContentFont", @"Helvetica", fontSize, RoleControlContentFont);
}
else
{
if ((font == nil) || (userCacheNeedsRecomputing == YES))
{
ASSIGN (font, getNSFont (@"NSControlContentFont", @"Helvetica", 0, RoleControlContentFont));
userCacheNeedsRecomputing = NO;
}
return font;
}
} }
+ (NSFont*) labelFontOfSize: (float)fontSize + (NSFont*) labelFontOfSize: (float)fontSize
{ {
static NSFont *font = nil; return getNSFont(fontSize, RoleLabelFont);
if (fontSize != 0)
{
return getNSFont (@"NSLabelFont", @"Helvetica", fontSize, RoleLabelFont);
}
else
{
if ((font == nil) || (userCacheNeedsRecomputing == YES))
{
ASSIGN (font, getNSFont (@"NSLabelFont", @"Helvetica", 0, RoleLabelFont));
userCacheNeedsRecomputing = NO;
}
return font;
}
} }
+ (NSFont*) menuFontOfSize: (float)fontSize + (NSFont*) menuFontOfSize: (float)fontSize
{ {
static NSFont *font = nil; return getNSFont(fontSize, RoleMenuFont);
if (fontSize != 0)
{
return getNSFont (@"NSMenuFont", @"Helvetica", fontSize, RoleMenuFont);
}
else
{
if ((font == nil) || (userCacheNeedsRecomputing == YES))
{
ASSIGN (font, getNSFont (@"NSMenuFont", @"Helvetica", 0, RoleMenuFont));
userCacheNeedsRecomputing = NO;
}
return font;
}
} }
+ (NSFont*) titleBarFontOfSize: (float)fontSize + (NSFont*) titleBarFontOfSize: (float)fontSize
{ {
static NSFont *font = nil; return getNSFont(fontSize, RoleTitleBarFont);
if (fontSize != 0)
{
return getNSFont (@"NSTitleBarFont", @"Helvetica-Bold", fontSize, RoleTitleBarFont);
}
else
{
if ((font == nil) || (boldSystemCacheNeedsRecomputing == YES))
{
ASSIGN (font, getNSFont (@"NSTitleBarFont", @"Helvetica-Bold", 0, RoleTitleBarFont));
boldSystemCacheNeedsRecomputing = NO;
}
return font;
}
} }
+ (NSFont*) messageFontOfSize: (float)fontSize + (NSFont*) messageFontOfSize: (float)fontSize
{ {
static NSFont *font = nil; return getNSFont(fontSize, RoleMessageFont);
if (fontSize != 0)
{
return getNSFont (@"NSMessageFont", @"Helvetica", fontSize, RoleMessageFont);
}
else
{
if ((font == nil) || (userCacheNeedsRecomputing == YES))
{
ASSIGN (font, getNSFont (@"NSMessageFont", @"Helvetica", 0, RoleMessageFont));
userCacheNeedsRecomputing = NO;
}
return font;
}
} }
+ (NSFont*) paletteFontOfSize: (float)fontSize + (NSFont*) paletteFontOfSize: (float)fontSize
{ {
// Not sure on this one. return getNSFont(fontSize, RolePaletteFont);
static NSFont *font = nil;
if (fontSize != 0)
{
return getNSFont (@"NSPaletteFont", @"Helvetica-Bold", fontSize, RolePaletteFont);
}
else
{
if ((font == nil) || (boldSystemCacheNeedsRecomputing == YES))
{
ASSIGN (font, getNSFont (@"NSPaletteFont", @"Helvetica-Bold", 0, RolePaletteFont));
boldSystemCacheNeedsRecomputing = NO;
}
return font;
}
} }
+ (NSFont*) toolTipsFontOfSize: (float)fontSize + (NSFont*) toolTipsFontOfSize: (float)fontSize
{ {
// Not sure on this one. return getNSFont(fontSize, RoleToolTipsFont);
static NSFont *font = nil;
if (fontSize != 0)
{
return getNSFont (@"NSToolTipsFont", @"Helvetica", fontSize, RoleToolTipsFont);
}
else
{
if ((font == nil) || (userCacheNeedsRecomputing == YES))
{
ASSIGN (font, getNSFont (@"NSToolTipsFont", @"Helvetica", 0, RoleToolTipsFont));
userCacheNeedsRecomputing = NO;
}
return font;
}
} }
// //
@ -559,7 +476,7 @@ setNSFont(NSString* key, NSFont* font)
if (fontSize == 0) if (fontSize == 0)
{ {
fontSize = 12; return [self systemFontSize];
} }
return fontSize; return fontSize;