diff --git a/ChangeLog b/ChangeLog index 498ca52ab..74801c85d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2003-07-02 16:38 Alexander Malmberg + + * 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 * Source/NSBrowser.m (_createColumn): diff --git a/Source/NSFont.m b/Source/NSFont.m index 28bdd6833..ee0b061e5 100644 --- a/Source/NSFont.m +++ b/Source/NSFont.m @@ -42,42 +42,6 @@ #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) - (id) initWithName: (NSString*)name matrix: (const float*)fontMatrix @@ -127,17 +91,17 @@ newNameWithMatrix(NSString *name, const float *matrix, BOOL fix, font names available are:

- NSBoldFont Helvetica-Bold - NSControlContentFont Helvetica + NSBoldFont Helvetica-Bold (System bold font) + NSControlContentFont System font NSFont Helvetica (System Font) - NSLabelFont Helvetica - NSMenuFont Helvetica - NSMessageFont Helvetica - NSPaletteFont Helvetica-Bold - NSTitleBarFont Helvetica-Bold - NSToolTipsFont Helvetica + NSLabelFont System font + NSMenuFont System font + NSMessageFont System font + NSPaletteFont System bold font + NSTitleBarFont System bold font + NSToolTipsFont System font NSUserFixedPitchFont Courier - NSUserFont Helvetica + NSUserFont System font

The default sizes are: @@ -146,7 +110,7 @@ newNameWithMatrix(NSString *name, const float *matrix, BOOL fix, NSBoldFontSize (none) NSControlContentFontSize (none) NSFontSize 12 (System Font Size) - NSLabelFontSize 12 + NSLabelFontSize (none) NSMenuFontSize (none) NSMessageFontSize (none) NSPaletteFontSize (none) @@ -166,6 +130,9 @@ newNameWithMatrix(NSString *name, const float *matrix, BOOL fix, /* Class variables*/ +/* See comments in +initialize. */ +static NSFont *placeHolder = nil; + /* Fonts that are preferred by the application */ static NSArray *_preferredFonts; @@ -177,90 +144,196 @@ static NSMapTable* globalFontMap = 0; 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; NSFont *font; + BOOL defaultSize; + int i; + int font_role; - role *= 2; - - fontName = [defaults objectForKey: key]; - if (fontName == nil) - { - fontName = defaultFontName; - } + NSCAssert(role > RoleExplicit && role < RoleMax, @"Invalid font role."); - 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: - [NSString stringWithFormat: @"%@Size", key]]; - } - else - { - role |= 1; + [NSString stringWithFormat: @"%@Size", font_roles[role].key]]; + + if (!fontSize) + fontSize = [NSFont systemFontSize]; } - 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) { - /* Try the same size, but the defaultFontName. */ - font = [NSFontClass _fontWithName: defaultFontName + /* Warn using the role that specified the invalid font. */ + 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 - role: role]; + role: font_role]; if (font == nil) { - /* Try the default font name and size. */ - fontSize = [defaults floatForKey: - [NSString stringWithFormat: @"%@Size", key]]; - - font = [NSFontClass _fontWithName: defaultFontName - size: fontSize - role: role]; + /* Try the default system font and size. */ + fontName = font_roles[RoleSystemFont].defaultFont; + font = [NSFontClass _fontWithName: fontName + size: 12.0 + role: font_role]; /* It seems we can't get any font here! Try some well known * fonts as a last resort. */ if (font == nil) { font = [NSFontClass _fontWithName: @"Helvetica" - size: 12. - role: role]; + size: 12.0 + role: font_role]; } if (font == nil) { font = [NSFontClass _fontWithName: @"Courier" - size: 12. - role: role]; + size: 12.0 + role: font_role]; } if (font == nil) { font = [NSFontClass _fontWithName: @"Fixed" - size: 12. - role: role]; + size: 12.0 + role: font_role]; } } } + ASSIGN(font_roles[role].cachedFont, font); + return font; } -void -setNSFont(NSString* key, NSFont* font) +static void setNSFont(NSString *key, NSFont *font) { + int i; [defaults setObject: [font fontName] forKey: key]; - systemCacheNeedsRecomputing = YES; - boldSystemCacheNeedsRecomputing = YES; - userCacheNeedsRecomputing = YES; - userFixedCacheNeedsRecomputing = YES; + for (i = 1; i < RoleMax; i++) + DESTROY(font_roles[i].cachedFont); /* Don't care about errors */ [defaults synchronize]; } + // // Class methods // @@ -275,7 +348,7 @@ setNSFont(NSString* key, NSFont* font) * as a font ... the initialiser knows that whenever it gets the * placeHolder it should either return a cached font or return a * 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 * a cache object. */ @@ -301,21 +374,7 @@ setNSFont(NSString* key, NSFont* font) */ + (NSFont*) boldSystemFontOfSize: (float)fontSize { - static NSFont *font = nil; - - 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; - } + return getNSFont(fontSize, RoleBoldSystemFont); } /** @@ -325,21 +384,7 @@ setNSFont(NSString* key, NSFont* font) */ + (NSFont*) systemFontOfSize: (float)fontSize { - static NSFont *font = nil; - - 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; - } + return getNSFont(fontSize, RoleSystemFont); } /** @@ -348,21 +393,7 @@ setNSFont(NSString* key, NSFont* font) */ + (NSFont*) userFixedPitchFontOfSize: (float)fontSize { - static NSFont *font = nil; - - 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; - } + return getNSFont(fontSize, RoleUserFixedPitchFont); } /** @@ -371,21 +402,7 @@ setNSFont(NSString* key, NSFont* font) */ + (NSFont*) userFontOfSize: (float)fontSize { - static NSFont *font = nil; - - 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; - } + return getNSFont(fontSize, RoleUserFont); } /** @@ -417,137 +434,37 @@ setNSFont(NSString* key, NSFont* font) + (NSFont*) controlContentFontOfSize: (float)fontSize { - static NSFont *font = nil; - - 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; - } + return getNSFont(fontSize, RoleControlContentFont); } + (NSFont*) labelFontOfSize: (float)fontSize { - static NSFont *font = nil; - - 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; - } + return getNSFont(fontSize, RoleLabelFont); } + (NSFont*) menuFontOfSize: (float)fontSize { - static NSFont *font = nil; - - 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; - } + return getNSFont(fontSize, RoleMenuFont); } + (NSFont*) titleBarFontOfSize: (float)fontSize { - static NSFont *font = nil; - - 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; - } + return getNSFont(fontSize, RoleTitleBarFont); } + (NSFont*) messageFontOfSize: (float)fontSize { - static NSFont *font = nil; - - 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; - } + return getNSFont(fontSize, RoleMessageFont); } + (NSFont*) paletteFontOfSize: (float)fontSize { - // Not sure on this one. - 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; - } + return getNSFont(fontSize, RolePaletteFont); } + (NSFont*) toolTipsFontOfSize: (float)fontSize { - // Not sure on this one. - 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; - } + return getNSFont(fontSize, RoleToolTipsFont); } // @@ -559,7 +476,7 @@ setNSFont(NSString* key, NSFont* font) if (fontSize == 0) { - fontSize = 12; + return [self systemFontSize]; } return fontSize;