mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-23 20:01:11 +00:00
Update documention comment regarding default values for NSMiniFontSize ans NSSmallFontSize.
1574 lines
42 KiB
Objective-C
1574 lines
42 KiB
Objective-C
/** <title>NSFont</title>
|
|
|
|
<abstract>The font class</abstract>
|
|
|
|
Copyright (C) 1996 Free Software Foundation, Inc.
|
|
|
|
Author: Ovidiu Predescu <ovidiu@net-community.com>
|
|
Date: February 1997
|
|
A completely rewritten version of the original source by Scott Christley.
|
|
|
|
This file is part of the GNUstep GUI Library.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; see the file COPYING.LIB.
|
|
If not, see <http://www.gnu.org/licenses/> or write to the
|
|
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#import <Foundation/NSAffineTransform.h>
|
|
#import <Foundation/NSCoder.h>
|
|
#import <Foundation/NSDictionary.h>
|
|
#import <Foundation/NSString.h>
|
|
#import <Foundation/NSUserDefaults.h>
|
|
#import <Foundation/NSSet.h>
|
|
#import <Foundation/NSMapTable.h>
|
|
#import <Foundation/NSException.h>
|
|
#import <Foundation/NSDebug.h>
|
|
#import <Foundation/NSValue.h>
|
|
|
|
#import "AppKit/NSGraphicsContext.h"
|
|
#import "AppKit/NSFont.h"
|
|
#import "AppKit/NSFontDescriptor.h"
|
|
#import "AppKit/NSFontManager.h"
|
|
#import "AppKit/NSView.h"
|
|
#import "GNUstepGUI/GSFontInfo.h"
|
|
|
|
|
|
@interface NSFont (Private)
|
|
- (id) initWithName: (NSString*)name
|
|
matrix: (const CGFloat*)fontMatrix
|
|
screenFont: (BOOL)screenFont
|
|
role: (int)role;
|
|
+ (NSFont*) _fontWithName: (NSString*)aFontName
|
|
size: (CGFloat)fontSize
|
|
role: (int)role;
|
|
@end
|
|
|
|
static int currentVersion = 3;
|
|
|
|
|
|
/*
|
|
Instances of GSFontMapKey are used to find cached font instances in
|
|
globalFontMap.
|
|
*/
|
|
@interface GSFontMapKey : NSObject
|
|
{
|
|
@public
|
|
NSString *name;
|
|
BOOL screenFont;
|
|
int role;
|
|
int matrix[6];
|
|
|
|
unsigned int hash;
|
|
}
|
|
@end
|
|
@implementation GSFontMapKey
|
|
-(NSUInteger) hash
|
|
{
|
|
return hash;
|
|
}
|
|
-(BOOL) isEqual: (id)other
|
|
{
|
|
GSFontMapKey *o;
|
|
if (![other isKindOfClass: object_getClass(self)])
|
|
return NO;
|
|
o = other;
|
|
if (hash != o->hash || screenFont != o->screenFont || role != o->role)
|
|
return NO;
|
|
if (![name isEqualToString: o->name])
|
|
return NO;
|
|
if (matrix[0] != o->matrix[0]
|
|
|| matrix[1] != o->matrix[1]
|
|
|| matrix[2] != o->matrix[2]
|
|
|| matrix[3] != o->matrix[3]
|
|
|| matrix[4] != o->matrix[4]
|
|
|| matrix[5] != o->matrix[5])
|
|
return NO;
|
|
return YES;
|
|
}
|
|
-(void) dealloc
|
|
{
|
|
DESTROY(name);
|
|
[super dealloc];
|
|
}
|
|
@end
|
|
|
|
static GSFontMapKey *
|
|
keyForFont(NSString *name, const CGFloat *matrix,
|
|
BOOL screenFont, int role)
|
|
{
|
|
GSFontMapKey *d;
|
|
d=[GSFontMapKey alloc];
|
|
d->name = [name copy];
|
|
d->screenFont = screenFont;
|
|
d->role = role;
|
|
d->matrix[0] = matrix[0] * 1000;
|
|
d->matrix[1] = matrix[1] * 1000;
|
|
d->matrix[2] = matrix[2] * 1000;
|
|
d->matrix[3] = matrix[3] * 1000;
|
|
d->matrix[4] = matrix[4] * 1000;
|
|
d->matrix[5] = matrix[5] * 1000;
|
|
d->hash = [d->name hash] + screenFont + role * 4
|
|
+ d->matrix[0] + d->matrix[1] + d->matrix[2] + d->matrix[3];
|
|
return d;
|
|
}
|
|
|
|
/**
|
|
<unit>
|
|
<heading>NSFont</heading>
|
|
|
|
<p>The NSFont class allows control of the fonts used for displaying
|
|
text anywhere on the screen. The primary methods for getting a
|
|
particular font are +fontWithName:matrix: and +fontWithName:size: which
|
|
take the name and size of a particular font and return the NSFont object
|
|
associated with that font. In addition there are several convenience
|
|
mathods which make it easier to get certain types of fonts. </p>
|
|
|
|
<p>In particular, there are several methods to get the standard fonts
|
|
used by the Application to display text for a partiuclar purpose. See
|
|
the class methods listed below for more information. These default
|
|
fonts can be set using the user defaults system. The default
|
|
font names available are:
|
|
</p>
|
|
<list>
|
|
<item>NSBoldFont Helvetica-Bold (System bold font)</item>
|
|
<item>NSControlContentFont System font</item>
|
|
<item>NSFont Helvetica (System Font)</item>
|
|
<item>NSLabelFont System font</item>
|
|
<item>NSMenuFont System font</item>
|
|
<item>NSMenuBarFont System font</item>
|
|
<item>NSMessageFont System font</item>
|
|
<item>NSPaletteFont System bold font</item>
|
|
<item>NSTitleBarFont System bold font</item>
|
|
<item>NSToolTipsFont System font</item>
|
|
<item>NSUserFixedPitchFont Courier</item>
|
|
<item>NSUserFont System font</item>
|
|
</list>
|
|
<p>
|
|
The default sizes are:
|
|
</p>
|
|
<list>
|
|
<item>NSBoldFontSize (none)</item>
|
|
<item>NSControlContentFontSize (none)</item>
|
|
<item>NSFontSize 12 (System Font Size)</item>
|
|
<item>NSLabelFontSize (none)</item>
|
|
<item>NSMenuFontSize (none)</item>
|
|
<item>NSMiniFontSize 8</item>
|
|
<item>NSMessageFontSize (none)</item>
|
|
<item>NSPaletteFontSize (none)</item>
|
|
<item>NSSmallFontSize 10</item>
|
|
<item>NSTitleBarFontSize (none)</item>
|
|
<item>NSToolTipsFontSize (none)</item>
|
|
<item>NSUserFixedPitchFontSize (none)</item>
|
|
<item>NSUserFontSize (none)</item>
|
|
</list>
|
|
<p>
|
|
Font sizes list with (none) default to NSFontSize.
|
|
</p>
|
|
|
|
</unit> */
|
|
|
|
@implementation NSFont
|
|
|
|
/* Class variables*/
|
|
|
|
/* See comments in +initialize. */
|
|
static NSFont *placeHolder = nil;
|
|
|
|
/* Fonts that are preferred by the application */
|
|
static NSArray *_preferredFonts;
|
|
|
|
/* Class for fonts */
|
|
static Class NSFontClass = 0;
|
|
|
|
/* Cache all created fonts for reuse. */
|
|
static NSMapTable* globalFontMap = 0;
|
|
|
|
static NSUserDefaults *defaults = nil;
|
|
|
|
|
|
/*
|
|
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,
|
|
RoleMenuBarFont,
|
|
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 , nil /* set by init_font_roles */, nil},
|
|
{@"NSFont" , 0 , nil /* set by init_font_roles */, nil},
|
|
{@"NSUserFixedPitchFont", 0 , nil /* set by init_font_roles */, 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},
|
|
{@"NSMenuBarFont" , RoleSystemFont , nil, nil}
|
|
};
|
|
|
|
|
|
static BOOL did_init_font_roles;
|
|
|
|
/*
|
|
Called by getNSFont, since font_roles is only accessed from that function
|
|
(or fontNameForRole, which is only called by getNSFont). This assures that the
|
|
function is called before the table is used, and that it's called _after_ the
|
|
backend has been loaded (or, if it isn't, the _fontWithName:... calls will
|
|
fail anyway).
|
|
*/
|
|
static void init_font_roles(void)
|
|
{
|
|
GSFontEnumerator *e = [GSFontEnumerator sharedEnumerator];
|
|
|
|
font_roles[RoleSystemFont].defaultFont = [e defaultSystemFontName];
|
|
font_roles[RoleBoldSystemFont].defaultFont = [e defaultBoldSystemFontName];
|
|
font_roles[RoleUserFixedPitchFont].defaultFont = [e defaultFixedPitchFontName];
|
|
}
|
|
|
|
|
|
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(CGFloat fontSize, int role)
|
|
{
|
|
NSString *fontName;
|
|
NSFont *font;
|
|
BOOL defaultSize;
|
|
int i;
|
|
int font_role;
|
|
|
|
NSCAssert(role > RoleExplicit && role < RoleMax, @"Invalid font role.");
|
|
|
|
if (!did_init_font_roles)
|
|
{
|
|
init_font_roles();
|
|
did_init_font_roles = YES;
|
|
}
|
|
|
|
font_role = role * 2;
|
|
|
|
defaultSize = (fontSize <= 0.0);
|
|
if (defaultSize)
|
|
{
|
|
if (font_roles[role].cachedFont)
|
|
return AUTORELEASE(RETAIN(font_roles[role].cachedFont));
|
|
|
|
fontSize = [defaults floatForKey:
|
|
[NSString stringWithFormat: @"%@Size", font_roles[role].key]];
|
|
|
|
if (!fontSize)
|
|
fontSize = [NSFont systemFontSize];
|
|
}
|
|
else
|
|
{
|
|
font_role |= 1;
|
|
}
|
|
|
|
fontName = fontNameForRole(role, &i);
|
|
font = [NSFontClass _fontWithName: fontName
|
|
size: fontSize
|
|
role: font_role];
|
|
|
|
/* That font couldn't be found. */
|
|
if (font == nil)
|
|
{
|
|
/* 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: font_role];
|
|
|
|
if (font == nil)
|
|
{
|
|
/* 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.0
|
|
role: font_role];
|
|
}
|
|
if (font == nil)
|
|
{
|
|
font = [NSFontClass _fontWithName: @"Courier"
|
|
size: 12.0
|
|
role: font_role];
|
|
}
|
|
if (font == nil)
|
|
{
|
|
font = [NSFontClass _fontWithName: @"Fixed"
|
|
size: 12.0
|
|
role: font_role];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (defaultSize)
|
|
ASSIGN(font_roles[role].cachedFont, font);
|
|
|
|
return font;
|
|
}
|
|
|
|
static void setNSFont(NSString *key, NSFont *font)
|
|
{
|
|
int i;
|
|
|
|
[defaults setObject: [font fontName] forKey: key];
|
|
[defaults setObject: [NSNumber numberWithFloat: [font pointSize]]
|
|
forKey: [NSString stringWithFormat: @"%@Size",key]];
|
|
|
|
for (i = 1; i < RoleMax; i++)
|
|
{
|
|
DESTROY(font_roles[i].cachedFont);
|
|
}
|
|
|
|
/* Don't care about errors */
|
|
[defaults synchronize];
|
|
}
|
|
|
|
|
|
//
|
|
// Class methods
|
|
//
|
|
+ (void) initialize
|
|
{
|
|
if (self == [NSFont class])
|
|
{
|
|
NSFontClass = self;
|
|
|
|
/*
|
|
* The placeHolder is a dummy NSFont instance which is never used
|
|
* 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 allocate fonts instances
|
|
* which would immediately have to be released for replacement by
|
|
* a cache object.
|
|
*/
|
|
placeHolder = [self alloc];
|
|
globalFontMap = NSCreateMapTable(NSObjectMapKeyCallBacks,
|
|
NSNonRetainedObjectMapValueCallBacks, 64);
|
|
|
|
if (defaults == nil)
|
|
{
|
|
defaults = RETAIN([NSUserDefaults standardUserDefaults]);
|
|
}
|
|
|
|
_preferredFonts = [defaults objectForKey: @"NSPreferredFonts"];
|
|
[self setVersion: currentVersion];
|
|
}
|
|
}
|
|
|
|
/* Getting the preferred user fonts. */
|
|
|
|
/**<p>Returns the default bold font for use in menus and heading in standard
|
|
gui components. If fontSize is <= 0, the default
|
|
size is used.</p><p>See Also: +fontWithName:size:</p>
|
|
*/
|
|
+ (NSFont*) boldSystemFontOfSize: (CGFloat)fontSize
|
|
{
|
|
return getNSFont(fontSize, RoleBoldSystemFont);
|
|
}
|
|
|
|
/**<p> Returns the default font for use in menus and heading in standard
|
|
gui components. If fontSize is <= 0, the default
|
|
size is used.</p><p>See Also: +boldSystemFontOfSize: userFontOfSize:
|
|
userFixedPitchFontOfSize: +fontWithName:size:</p>
|
|
*/
|
|
+ (NSFont*) systemFontOfSize: (CGFloat)fontSize
|
|
{
|
|
return getNSFont(fontSize, RoleSystemFont);
|
|
}
|
|
|
|
/**<p>Returns the default fixed pitch font for use in locations other
|
|
than standard gui components. If fontSize is <= 0, the default
|
|
size is used.</p><p>See Also: +setUserFixedPitchFont: +userFontOfSize:
|
|
+boldSystemFontOfSize: +systemFontOfSize: +fontWithName:size:</p>
|
|
*/
|
|
+ (NSFont*) userFixedPitchFontOfSize: (CGFloat)fontSize
|
|
{
|
|
return getNSFont(fontSize, RoleUserFixedPitchFont);
|
|
}
|
|
|
|
/**<p> Returns the default font for use in locations other
|
|
than standard gui components. If fontSize is <= 0, the default
|
|
size is used.</p><p>See Also: +setUserFont: +boldSystemFontOfSize:
|
|
systemFontOfSize: userFixedPitchFontOfSize: +fontWithName:size:</p>
|
|
*/
|
|
+ (NSFont*) userFontOfSize: (CGFloat)fontSize
|
|
{
|
|
return getNSFont(fontSize, RoleUserFont);
|
|
}
|
|
|
|
+ (NSFont *) fontWithDescriptor: (NSFontDescriptor *)descriptor
|
|
size: (CGFloat)size
|
|
{
|
|
NSArray *a;
|
|
|
|
descriptor = [descriptor matchingFontDescriptorWithMandatoryKeys:
|
|
[NSSet setWithArray: [[descriptor fontAttributes] allKeys]]];
|
|
|
|
if (descriptor == nil)
|
|
return nil;
|
|
|
|
a = [[NSFontManager sharedFontManager] availableFontNamesMatchingFontDescriptor:
|
|
descriptor];
|
|
if ((a == nil) || ([a count] == 0))
|
|
return nil;
|
|
|
|
return [self fontWithName: [a objectAtIndex: 0]
|
|
size: size];
|
|
}
|
|
|
|
+ (NSFont*) fontWithDescriptor: (NSFontDescriptor*)descriptor
|
|
textTransform: (NSAffineTransform*)transform
|
|
{
|
|
NSArray *a;
|
|
CGFloat fontMatrix[6];
|
|
NSAffineTransformStruct ats;
|
|
|
|
descriptor = [descriptor matchingFontDescriptorWithMandatoryKeys:
|
|
[NSSet setWithArray: [[descriptor fontAttributes] allKeys]]];
|
|
|
|
if (descriptor == nil)
|
|
return nil;
|
|
|
|
a = [[NSFontManager sharedFontManager] availableFontNamesMatchingFontDescriptor:
|
|
descriptor];
|
|
if ((a == nil) || ([a count] == 0))
|
|
return nil;
|
|
|
|
ats = [transform transformStruct];
|
|
fontMatrix[0] = ats.m11;
|
|
fontMatrix[1] = ats.m12;
|
|
fontMatrix[2] = ats.m21;
|
|
fontMatrix[3] = ats.m22;
|
|
fontMatrix[4] = ats.tX;
|
|
fontMatrix[5] = ats.tY;
|
|
|
|
return [self fontWithName: [a objectAtIndex: 0]
|
|
matrix: fontMatrix];
|
|
}
|
|
|
|
+ (NSFont *) fontWithDescriptor: (NSFontDescriptor *)descriptor
|
|
size: (CGFloat)size
|
|
textTransform: (NSAffineTransform *)transform
|
|
{
|
|
if (transform)
|
|
{
|
|
return [self fontWithDescriptor: descriptor
|
|
textTransform: transform];
|
|
}
|
|
else
|
|
{
|
|
return [self fontWithDescriptor: descriptor
|
|
size: size];
|
|
}
|
|
}
|
|
|
|
|
|
/**<p>Returns an array of the names of preferred fonts.</p>
|
|
<p>See Also: +setPreferredFontNames:</p>
|
|
*/
|
|
+ (NSArray*) preferredFontNames
|
|
{
|
|
return _preferredFonts;
|
|
}
|
|
|
|
/* Setting the preferred user fonts*/
|
|
|
|
+ (void) setUserFixedPitchFont: (NSFont*)aFont
|
|
{
|
|
setNSFont (@"NSUserFixedPitchFont", aFont);
|
|
}
|
|
|
|
+ (void) setUserFont: (NSFont*)aFont
|
|
{
|
|
setNSFont (@"NSUserFont", aFont);
|
|
}
|
|
|
|
/** <p>Sets an array of the names of preferred fonts to fontsNames/</p>
|
|
<p>See Also: +preferredFontNames</p>
|
|
*/
|
|
+ (void) setPreferredFontNames: (NSArray*)fontNames
|
|
{
|
|
ASSIGN(_preferredFonts, fontNames);
|
|
// FIXME: Should this store back the preferred fonts in the user defaults?
|
|
}
|
|
|
|
/* Getting various fonts*/
|
|
|
|
+ (NSFont*) controlContentFontOfSize: (CGFloat)fontSize
|
|
{
|
|
return getNSFont(fontSize, RoleControlContentFont);
|
|
}
|
|
|
|
+ (NSFont*) labelFontOfSize: (CGFloat)fontSize
|
|
{
|
|
return getNSFont(fontSize, RoleLabelFont);
|
|
}
|
|
|
|
+ (NSFont*) menuFontOfSize: (CGFloat)fontSize
|
|
{
|
|
return getNSFont(fontSize, RoleMenuFont);
|
|
}
|
|
|
|
+ (NSFont*) menuBarFontOfSize: (CGFloat)fontSize
|
|
{
|
|
return getNSFont(fontSize, RoleMenuBarFont);
|
|
}
|
|
|
|
+ (NSFont*) titleBarFontOfSize: (CGFloat)fontSize
|
|
{
|
|
return getNSFont(fontSize, RoleTitleBarFont);
|
|
}
|
|
|
|
+ (NSFont*) messageFontOfSize: (CGFloat)fontSize
|
|
{
|
|
return getNSFont(fontSize, RoleMessageFont);
|
|
}
|
|
|
|
+ (NSFont*) paletteFontOfSize: (CGFloat)fontSize
|
|
{
|
|
return getNSFont(fontSize, RolePaletteFont);
|
|
}
|
|
|
|
+ (NSFont*) toolTipsFontOfSize: (CGFloat)fontSize
|
|
{
|
|
return getNSFont(fontSize, RoleToolTipsFont);
|
|
}
|
|
|
|
//
|
|
// Font Sizes
|
|
//
|
|
+ (CGFloat) labelFontSize
|
|
{
|
|
CGFloat fontSize = [defaults floatForKey: @"NSLabelFontSize"];
|
|
|
|
if (fontSize == 0)
|
|
{
|
|
return [self systemFontSize];
|
|
}
|
|
|
|
return fontSize;
|
|
}
|
|
|
|
+ (CGFloat) smallSystemFontSize
|
|
{
|
|
CGFloat fontSize = [defaults floatForKey: @"NSSmallFontSize"];
|
|
|
|
if (fontSize == 0)
|
|
{
|
|
fontSize = 10;
|
|
}
|
|
|
|
return fontSize;
|
|
}
|
|
|
|
+ (CGFloat) systemFontSize
|
|
{
|
|
CGFloat fontSize = [defaults floatForKey: @"NSFontSize"];
|
|
|
|
if (fontSize == 0)
|
|
{
|
|
fontSize = 12;
|
|
}
|
|
|
|
return fontSize;
|
|
}
|
|
|
|
+ (CGFloat) systemFontSizeForControlSize: (NSControlSize)controlSize
|
|
{
|
|
switch (controlSize)
|
|
{
|
|
case NSMiniControlSize:
|
|
{
|
|
CGFloat fontSize = [defaults floatForKey: @"NSMiniFontSize"];
|
|
|
|
if (fontSize == 0)
|
|
{
|
|
fontSize = 8;
|
|
}
|
|
|
|
return fontSize;
|
|
}
|
|
case NSSmallControlSize:
|
|
return [self smallSystemFontSize];
|
|
case NSRegularControlSize:
|
|
default:
|
|
return [self systemFontSize];
|
|
}
|
|
}
|
|
|
|
/** <p>Returns an autoreleased font with name aFontName and matrix fontMatrix
|
|
.</p><p>The fontMatrix is a standard size element matrix as used in
|
|
PostScript to describe the scaling of the font, typically it just includes
|
|
the font size as [fontSize 0 0 fontSize 0 0]. You can use the constant
|
|
NSFontIdentityMatrix in place of [1 0 0 1 0 0]. If NSFontIdentityMatrix,
|
|
then the font will automatically flip itself when set in a flipped view.
|
|
</p>
|
|
*/
|
|
+ (NSFont*) fontWithName: (NSString*)aFontName
|
|
matrix: (const CGFloat*)fontMatrix
|
|
{
|
|
NSFont *font;
|
|
|
|
font = [placeHolder initWithName: aFontName
|
|
matrix: fontMatrix
|
|
screenFont: NO
|
|
role: RoleExplicit];
|
|
|
|
return AUTORELEASE(font);
|
|
}
|
|
|
|
/**<p> Returns an autoreleased font with name aFontName and size fontSize.</p>
|
|
* <p>Fonts created using this method will automatically flip themselves
|
|
* when set in a flipped view.</p>
|
|
*/
|
|
+ (NSFont*) fontWithName: (NSString*)aFontName
|
|
size: (CGFloat)fontSize
|
|
{
|
|
return [self _fontWithName: aFontName
|
|
size: fontSize
|
|
role: RoleExplicit];
|
|
}
|
|
|
|
+ (NSFont*) _fontWithName: (NSString*)aFontName
|
|
size: (CGFloat)fontSize
|
|
role: (int)aRole
|
|
{
|
|
NSFont *font;
|
|
CGFloat fontMatrix[6] = { 0, 0, 0, 0, 0, 0 };
|
|
|
|
if (fontSize == 0)
|
|
{
|
|
fontSize = [defaults floatForKey: @"NSUserFontSize"];
|
|
if (fontSize == 0)
|
|
{
|
|
fontSize = 12;
|
|
}
|
|
}
|
|
fontMatrix[0] = fontSize;
|
|
fontMatrix[3] = fontSize;
|
|
|
|
font = [placeHolder initWithName: aFontName
|
|
matrix: fontMatrix
|
|
screenFont: NO
|
|
role: aRole];
|
|
return AUTORELEASE(font);
|
|
}
|
|
|
|
/**
|
|
*/
|
|
+ (void) useFont: (NSString*)aFontName
|
|
{
|
|
[GSCurrentContext() useFont: aFontName];
|
|
}
|
|
|
|
//
|
|
// Instance methods
|
|
//
|
|
- (id) init
|
|
{
|
|
[NSException raise: NSInternalInconsistencyException
|
|
format: @"Called -init on NSFont ... illegal"];
|
|
return self;
|
|
}
|
|
|
|
/*
|
|
Last fallback: If a system font was explicitly requested
|
|
and this font does not exist, try to replace it with the
|
|
corresponding font in the current setup.
|
|
*/
|
|
- (NSString*) _replacementFontName
|
|
{
|
|
if (([fontName isEqualToString: @"Helvetica"] &&
|
|
![font_roles[RoleSystemFont].defaultFont isEqualToString: @"Helvetica"])
|
|
|| ([fontName isEqualToString: @"LucidaGrande"]))
|
|
{
|
|
return font_roles[RoleSystemFont].defaultFont;
|
|
}
|
|
else if (([fontName isEqualToString: @"Helvetica-Bold"] &&
|
|
![font_roles[RoleBoldSystemFont].defaultFont isEqualToString: @"Helvetica-Bold"])
|
|
|| ([fontName isEqualToString: @"LucidaGrande-Bold"]))
|
|
{
|
|
return font_roles[RoleBoldSystemFont].defaultFont;
|
|
}
|
|
else if ([fontName isEqualToString: @"Courier"] &&
|
|
![font_roles[RoleUserFixedPitchFont].defaultFont isEqualToString: @"Courier"])
|
|
{
|
|
return font_roles[RoleUserFixedPitchFont].defaultFont;
|
|
}
|
|
else if ([fontName hasPrefix: @"Helvetica-"] &&
|
|
![font_roles[RoleSystemFont].defaultFont isEqualToString: @"Helvetica"])
|
|
{
|
|
return [NSString stringWithFormat: @"%@-%@",
|
|
font_roles[RoleSystemFont].defaultFont,
|
|
[fontName substringFromIndex: 10]];
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
/** <init />
|
|
* Initializes a newly created font instance from the name and
|
|
* information given in the fontMatrix. The fontMatrix is a standard
|
|
* size element matrix as used in PostScript to describe the scaling
|
|
* of the font, typically it just includes the font size as
|
|
* [fontSize 0 0 fontSize 0 0].<br />
|
|
* This method may destroy the receiver and return a cached instance.
|
|
*/
|
|
- (id) initWithName: (NSString*)name
|
|
matrix: (const CGFloat*)fontMatrix
|
|
screenFont: (BOOL)screen
|
|
role: (int)aRole
|
|
{
|
|
GSFontMapKey *key;
|
|
NSFont *font;
|
|
|
|
/* Should never be called on an initialised font! */
|
|
NSAssert(fontName == nil, NSInternalInconsistencyException);
|
|
|
|
/* Check whether the font is cached */
|
|
key = keyForFont(name, fontMatrix,
|
|
screen, aRole);
|
|
font = (id)NSMapGet(globalFontMap, (void *)key);
|
|
if (font == nil)
|
|
{
|
|
if (self == placeHolder)
|
|
{
|
|
/*
|
|
* If we are initialising the placeHolder, we actually want to
|
|
* leave it be (for later re-use) and initialise a newly created
|
|
* instance instead.
|
|
*/
|
|
self = [NSFontClass alloc];
|
|
}
|
|
fontName = [name copy];
|
|
memcpy(matrix, fontMatrix, sizeof(matrix));
|
|
screenFont = screen;
|
|
role = aRole;
|
|
fontInfo = RETAIN([GSFontInfo fontInfoForFontName: fontName
|
|
matrix: fontMatrix
|
|
screenFont: screen]);
|
|
if ((fontInfo == nil) && (aRole == RoleExplicit))
|
|
{
|
|
NSString *replacementFontName = [self _replacementFontName];
|
|
|
|
if (replacementFontName != nil)
|
|
{
|
|
fontInfo = RETAIN([GSFontInfo fontInfoForFontName: replacementFontName
|
|
matrix: fontMatrix
|
|
screenFont: screen]);
|
|
}
|
|
}
|
|
if (fontInfo == nil)
|
|
{
|
|
DESTROY(fontName);
|
|
DESTROY(key);
|
|
RELEASE(self);
|
|
return nil;
|
|
}
|
|
|
|
/* Cache the font for later use */
|
|
NSMapInsert(globalFontMap, (void *)key, (void *)self);
|
|
}
|
|
else
|
|
{
|
|
if (self != placeHolder)
|
|
{
|
|
RELEASE(self);
|
|
}
|
|
self = RETAIN(font);
|
|
}
|
|
RELEASE(key);
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void) dealloc
|
|
{
|
|
if (fontName != nil)
|
|
{
|
|
GSFontMapKey *key;
|
|
|
|
key = keyForFont(fontName, matrix,
|
|
screenFont, role);
|
|
NSMapRemove(globalFontMap, (void *)key);
|
|
RELEASE(key);
|
|
RELEASE(fontName);
|
|
}
|
|
TEST_RELEASE(fontInfo);
|
|
DESTROY(cachedFlippedFont);
|
|
DESTROY(cachedScreenFont);
|
|
[super dealloc];
|
|
}
|
|
|
|
- (NSString *) description
|
|
{
|
|
NSString *nameWithMatrix;
|
|
NSString *description;
|
|
|
|
nameWithMatrix = [[NSString alloc] initWithFormat:
|
|
@"%@ %.3f %.3f %.3f %.3f %.3f %.3f %c %i", fontName,
|
|
matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5],
|
|
screenFont ? 'S' : 'P',
|
|
role];
|
|
description = [[super description] stringByAppendingFormat: @" %@",
|
|
nameWithMatrix];
|
|
RELEASE(nameWithMatrix);
|
|
return description;
|
|
}
|
|
|
|
- (BOOL) isEqual: (id)anObject
|
|
{
|
|
if (anObject == self)
|
|
return YES;
|
|
if ([anObject isKindOfClass: object_getClass(self)] == NO)
|
|
return NO;
|
|
if ([[anObject fontName] isEqual: fontName] == NO)
|
|
return NO;
|
|
if (memcmp(matrix, [(NSFont*)anObject matrix], sizeof(matrix)) != 0)
|
|
return NO;
|
|
return YES;
|
|
}
|
|
|
|
- (NSUInteger) hash
|
|
{
|
|
int i, sum;
|
|
sum = 0;
|
|
for (i = 0; i < 6; i++)
|
|
sum += matrix[i] * ((i+1) * 17);
|
|
return ([fontName hash] + sum);
|
|
}
|
|
|
|
/**
|
|
* The NSFont class caches instances ... to actually make copies
|
|
* of instances would defeat the whole point of caching, so the
|
|
* effect of copying an NSFont is imply to retain it.
|
|
*/
|
|
- (id) copyWithZone: (NSZone*)zone
|
|
{
|
|
return RETAIN(self);
|
|
}
|
|
|
|
- (NSFont *)_flippedViewFont
|
|
{
|
|
if (cachedFlippedFont == nil)
|
|
{
|
|
CGFloat fontMatrix[6];
|
|
memcpy(fontMatrix, matrix, sizeof(matrix));
|
|
fontMatrix[3] *= -1;
|
|
cachedFlippedFont = [placeHolder initWithName: fontName
|
|
matrix: fontMatrix
|
|
screenFont: screenFont
|
|
role: role];
|
|
}
|
|
return AUTORELEASE(RETAIN(cachedFlippedFont));
|
|
}
|
|
|
|
static BOOL flip_hack;
|
|
+(void) _setFontFlipHack: (BOOL)flip
|
|
{
|
|
flip_hack = flip;
|
|
}
|
|
|
|
//
|
|
// Setting the Font
|
|
//
|
|
/** Sets the receiver as the font used for text drawing operations. If the
|
|
current view is a flipped view, the reciever automatically flips itself
|
|
to display correctly in the flipped view */
|
|
- (void) set
|
|
{
|
|
[self setInContext: GSCurrentContext()];
|
|
}
|
|
|
|
- (void) setInContext: (NSGraphicsContext*)context
|
|
{
|
|
if ([[NSView focusView] isFlipped] || flip_hack)
|
|
[context GSSetFont: [[self _flippedViewFont] fontRef]];
|
|
else
|
|
[context GSSetFont: [self fontRef]];
|
|
|
|
[context useFont: fontName];
|
|
}
|
|
|
|
//
|
|
// Querying the Font
|
|
//
|
|
- (CGFloat) pointSize
|
|
{
|
|
return [fontInfo pointSize];
|
|
}
|
|
|
|
- (NSString*) fontName
|
|
{
|
|
return fontName;
|
|
}
|
|
|
|
- (const CGFloat*) matrix
|
|
{
|
|
return matrix;
|
|
}
|
|
|
|
- (NSAffineTransform*) textTransform
|
|
{
|
|
NSAffineTransform *transform;
|
|
NSAffineTransformStruct tstruct;
|
|
|
|
tstruct.m11 = matrix[0];
|
|
tstruct.m12 = matrix[1];
|
|
tstruct.m21 = matrix[2];
|
|
tstruct.m22 = matrix[3];
|
|
tstruct.tX = matrix[4];
|
|
tstruct.tY = matrix[5];
|
|
|
|
transform = [NSAffineTransform transform];
|
|
[transform setTransformStruct: tstruct];
|
|
return transform;
|
|
}
|
|
|
|
- (NSString*) encodingScheme
|
|
{
|
|
return [fontInfo encodingScheme];
|
|
}
|
|
|
|
- (NSString*) familyName
|
|
{
|
|
return [fontInfo familyName];
|
|
}
|
|
|
|
- (NSRect) boundingRectForFont
|
|
{
|
|
return [fontInfo boundingRectForFont];
|
|
}
|
|
|
|
- (BOOL) isFixedPitch
|
|
{
|
|
return [fontInfo isFixedPitch];
|
|
}
|
|
|
|
- (BOOL) isBaseFont
|
|
{
|
|
return [fontInfo isBaseFont];
|
|
}
|
|
|
|
/* Usually the display name of font is the font name.*/
|
|
- (NSString*) displayName
|
|
{
|
|
return fontName;
|
|
}
|
|
|
|
- (NSDictionary*) afmDictionary
|
|
{
|
|
return [fontInfo afmDictionary];
|
|
}
|
|
|
|
/**<p>This method returns nil in the GNUstep implementation</p>
|
|
*/
|
|
- (NSString*) afmFileContents
|
|
{
|
|
return [fontInfo afmFileContents];
|
|
}
|
|
|
|
- (NSFont*) printerFont
|
|
{
|
|
if (!screenFont)
|
|
return self;
|
|
return AUTORELEASE([placeHolder initWithName: fontName
|
|
matrix: matrix
|
|
screenFont: NO
|
|
role: role]);
|
|
}
|
|
|
|
- (NSFont*) screenFont
|
|
{
|
|
if (screenFont)
|
|
return self;
|
|
/*
|
|
If we haven't already created the real screen font instance, do so now.
|
|
Note that if the font has no corresponding screen font, cachedScreenFont
|
|
will be set to nil.
|
|
*/
|
|
if (cachedScreenFont == nil)
|
|
cachedScreenFont = [placeHolder initWithName: fontName
|
|
matrix: matrix
|
|
screenFont: YES
|
|
role: role];
|
|
return AUTORELEASE(RETAIN(cachedScreenFont));
|
|
}
|
|
|
|
- (NSFont*) screenFontWithRenderingMode: (NSFontRenderingMode)mode
|
|
{
|
|
// FIXME
|
|
return [self screenFont];
|
|
}
|
|
|
|
- (NSFontRenderingMode) renderingMode
|
|
{
|
|
// FIXME
|
|
return NSFontDefaultRenderingMode;
|
|
}
|
|
|
|
- (CGFloat) ascender { return [fontInfo ascender]; }
|
|
- (CGFloat) descender { return [fontInfo descender]; }
|
|
- (CGFloat) capHeight { return [fontInfo capHeight]; }
|
|
- (CGFloat) italicAngle { return [fontInfo italicAngle]; }
|
|
- (NSSize) maximumAdvancement { return [fontInfo maximumAdvancement]; }
|
|
- (NSSize) minimumAdvancement { return [fontInfo minimumAdvancement]; }
|
|
- (CGFloat) underlinePosition { return [fontInfo underlinePosition]; }
|
|
- (CGFloat) underlineThickness { return [fontInfo underlineThickness]; }
|
|
- (CGFloat) xHeight { return [fontInfo xHeight]; }
|
|
- (CGFloat) defaultLineHeightForFont { return [fontInfo defaultLineHeightForFont]; }
|
|
|
|
- (CGFloat) leading
|
|
{
|
|
// FIXME
|
|
return 0.0;
|
|
}
|
|
|
|
/* Computing font metrics attributes*/
|
|
- (CGFloat) widthOfString: (NSString*)string
|
|
{
|
|
return [fontInfo widthOfString: string];
|
|
}
|
|
|
|
- (NSUInteger) numberOfGlyphs
|
|
{
|
|
return [fontInfo numberOfGlyphs];
|
|
}
|
|
|
|
- (NSCharacterSet*) coveredCharacterSet
|
|
{
|
|
return [fontInfo coveredCharacterSet];
|
|
}
|
|
|
|
- (NSFontDescriptor*) fontDescriptor
|
|
{
|
|
return [fontInfo fontDescriptor];
|
|
}
|
|
|
|
/* The following methods have to be implemented by backends */
|
|
|
|
//
|
|
// Manipulating Glyphs
|
|
//
|
|
- (NSSize) advancementForGlyph: (NSGlyph)aGlyph
|
|
{
|
|
return [fontInfo advancementForGlyph: aGlyph];
|
|
}
|
|
|
|
- (NSRect) boundingRectForGlyph: (NSGlyph)aGlyph
|
|
{
|
|
return [fontInfo boundingRectForGlyph: aGlyph];
|
|
}
|
|
|
|
- (BOOL) glyphIsEncoded: (NSGlyph)aGlyph
|
|
{
|
|
return [fontInfo glyphIsEncoded: aGlyph];
|
|
}
|
|
|
|
- (NSMultibyteGlyphPacking) glyphPacking
|
|
{
|
|
return [fontInfo glyphPacking];
|
|
}
|
|
|
|
- (NSGlyph) glyphWithName: (NSString*)glyphName
|
|
{
|
|
return [fontInfo glyphWithName: glyphName];
|
|
}
|
|
|
|
- (NSPoint) positionOfGlyph: (NSGlyph)curGlyph
|
|
precededByGlyph: (NSGlyph)prevGlyph
|
|
isNominal: (BOOL*)nominal
|
|
{
|
|
return [fontInfo positionOfGlyph: curGlyph precededByGlyph: prevGlyph
|
|
isNominal: nominal];
|
|
}
|
|
|
|
- (NSPoint) positionOfGlyph: (NSGlyph)aGlyph
|
|
forCharacter: (unichar)aChar
|
|
struckOverRect: (NSRect)aRect
|
|
{
|
|
return [fontInfo positionOfGlyph: aGlyph
|
|
forCharacter: aChar
|
|
struckOverRect: aRect];
|
|
}
|
|
|
|
- (NSPoint) positionOfGlyph: (NSGlyph)aGlyph
|
|
struckOverGlyph: (NSGlyph)baseGlyph
|
|
metricsExist: (BOOL *)flag
|
|
{
|
|
return [fontInfo positionOfGlyph: aGlyph
|
|
struckOverGlyph: baseGlyph
|
|
metricsExist: flag];
|
|
}
|
|
|
|
- (NSPoint) positionOfGlyph: (NSGlyph)aGlyph
|
|
struckOverRect: (NSRect)aRect
|
|
metricsExist: (BOOL *)flag
|
|
{
|
|
return [fontInfo positionOfGlyph: aGlyph
|
|
struckOverRect: aRect
|
|
metricsExist: flag];
|
|
}
|
|
|
|
- (NSPoint) positionOfGlyph: (NSGlyph)aGlyph
|
|
withRelation: (NSGlyphRelation)relation
|
|
toBaseGlyph: (NSGlyph)baseGlyph
|
|
totalAdvancement: (NSSize *)offset
|
|
metricsExist: (BOOL *)flag
|
|
{
|
|
return [fontInfo positionOfGlyph: aGlyph
|
|
withRelation: relation
|
|
toBaseGlyph: baseGlyph
|
|
totalAdvancement: offset
|
|
metricsExist: flag];
|
|
}
|
|
|
|
- (int) positionsForCompositeSequence: (NSGlyph *)glyphs
|
|
numberOfGlyphs: (int)numGlyphs
|
|
pointArray: (NSPoint *)points
|
|
{
|
|
int i;
|
|
NSGlyph base = glyphs[0];
|
|
|
|
points[0] = NSZeroPoint;
|
|
|
|
for (i = 1; i < numGlyphs; i++)
|
|
{
|
|
BOOL flag;
|
|
// This only places the glyphs relative to the base glyph
|
|
// not to each other
|
|
points[i] = [self positionOfGlyph: glyphs[i]
|
|
struckOverGlyph: base
|
|
metricsExist: &flag];
|
|
if (!flag)
|
|
return i - 1;
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
- (void) getAdvancements: (NSSizeArray)advancements
|
|
forGlyphs: (const NSGlyph*)glyphs
|
|
count: (NSUInteger)count
|
|
{
|
|
// FIXME
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
advancements[i] = [self advancementForGlyph: glyphs[i]];
|
|
}
|
|
}
|
|
|
|
- (void) getAdvancements: (NSSizeArray)advancements
|
|
forPackedGlyphs: (const void*)glyphs
|
|
count: (NSUInteger)count
|
|
{
|
|
// FIXME
|
|
}
|
|
|
|
- (void) getBoundingRects: (NSRectArray)bounds
|
|
forGlyphs: (const NSGlyph*)glyphs
|
|
count: (NSUInteger)count
|
|
{
|
|
// FIXME
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
bounds[i] = [self boundingRectForGlyph: glyphs[i]];
|
|
}
|
|
}
|
|
|
|
- (NSStringEncoding) mostCompatibleStringEncoding
|
|
{
|
|
return [fontInfo mostCompatibleStringEncoding];
|
|
}
|
|
|
|
//
|
|
// NSCoding protocol
|
|
//
|
|
- (Class) classForCoder
|
|
{
|
|
return NSFontClass;
|
|
}
|
|
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
|
{
|
|
if ([aCoder allowsKeyedCoding])
|
|
{
|
|
[aCoder encodeObject: fontName forKey: @"NSName"];
|
|
[aCoder encodeFloat: [self pointSize] forKey: @"NSSize"];
|
|
|
|
switch (role >> 1)
|
|
{
|
|
// FIXME: Many cases still missing
|
|
case RoleControlContentFont:
|
|
[aCoder encodeInt: 16 forKey: @"NSfFlags"];
|
|
break;
|
|
case RoleLabelFont:
|
|
[aCoder encodeInt: 20 forKey: @"NSfFlags"];
|
|
break;
|
|
case RoleTitleBarFont:
|
|
[aCoder encodeInt: 22 forKey: @"NSfFlags"];
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
[aCoder encodeValueOfObjCType: @encode(int) at: &role];
|
|
|
|
if (role == 0)
|
|
{
|
|
float fontMatrix[6];
|
|
BOOL fix = NO;
|
|
|
|
fontMatrix[0] = matrix[0];
|
|
fontMatrix[1] = matrix[1];
|
|
fontMatrix[2] = matrix[2];
|
|
fontMatrix[3] = matrix[3];
|
|
fontMatrix[4] = matrix[4];
|
|
fontMatrix[5] = matrix[5];
|
|
[aCoder encodeObject: fontName];
|
|
[aCoder encodeArrayOfObjCType: @encode(float) count: 6 at: fontMatrix];
|
|
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &fix];
|
|
}
|
|
else if (role & 1)
|
|
{
|
|
float size = matrix[0];
|
|
[aCoder encodeValueOfObjCType: @encode(float) at: &size];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (id) initWithCoder: (NSCoder*)aDecoder
|
|
{
|
|
if ([aDecoder allowsKeyedCoding])
|
|
{
|
|
NSString *name = [aDecoder decodeObjectForKey: @"NSName"];
|
|
float size = [aDecoder decodeFloatForKey: @"NSSize"];
|
|
|
|
DESTROY(self);
|
|
if ([aDecoder containsValueForKey: @"IBIsSystemFont"])
|
|
{
|
|
self = RETAIN([NSFont systemFontOfSize: size]);
|
|
}
|
|
else
|
|
{
|
|
self = RETAIN([NSFont fontWithName: name size: size]);
|
|
}
|
|
if (self == nil)
|
|
{
|
|
if ([aDecoder containsValueForKey: @"NSfFlags"])
|
|
{
|
|
int flags = [aDecoder decodeIntForKey: @"NSfFlags"];
|
|
// FIXME
|
|
if (flags == 16)
|
|
{
|
|
return RETAIN([NSFont controlContentFontOfSize: size]);
|
|
}
|
|
else if (flags == 20)
|
|
{
|
|
return RETAIN([NSFont labelFontOfSize: size]);
|
|
}
|
|
else if (flags == 22)
|
|
{
|
|
return RETAIN([NSFont titleBarFontOfSize: size]);
|
|
}
|
|
}
|
|
self = RETAIN([NSFont systemFontOfSize: size]);
|
|
}
|
|
|
|
return self;
|
|
}
|
|
else
|
|
{
|
|
int version = [aDecoder versionForClassName: @"NSFont"];
|
|
id name;
|
|
float fontMatrix[6];
|
|
CGFloat cgMatrix[6];
|
|
int the_role;
|
|
|
|
if (version == 3)
|
|
{
|
|
[aDecoder decodeValueOfObjCType: @encode(int)
|
|
at: &the_role];
|
|
}
|
|
else
|
|
{
|
|
the_role = RoleExplicit;
|
|
}
|
|
|
|
if (the_role == RoleExplicit)
|
|
{
|
|
/* The easy case: an explicit font, or a font encoded with
|
|
version <= 2. */
|
|
name = [aDecoder decodeObject];
|
|
[aDecoder decodeArrayOfObjCType: @encode(float)
|
|
count: 6
|
|
at: fontMatrix];
|
|
|
|
if (version >= 2)
|
|
{
|
|
BOOL fix;
|
|
[aDecoder decodeValueOfObjCType: @encode(BOOL)
|
|
at: &fix];
|
|
}
|
|
|
|
cgMatrix[0] = fontMatrix[0];
|
|
cgMatrix[1] = fontMatrix[1];
|
|
cgMatrix[2] = fontMatrix[2];
|
|
cgMatrix[3] = fontMatrix[3];
|
|
cgMatrix[4] = fontMatrix[4];
|
|
cgMatrix[5] = fontMatrix[5];
|
|
self = [self initWithName: name
|
|
matrix: cgMatrix
|
|
screenFont: NO
|
|
role: RoleExplicit];
|
|
if (self)
|
|
return self;
|
|
|
|
self = [NSFont userFontOfSize: fontMatrix[0]];
|
|
NSAssert(self != nil, @"Couldn't find a valid font when decoding.");
|
|
return RETAIN(self);
|
|
}
|
|
else
|
|
{
|
|
/* A non-explicit font. */
|
|
float size;
|
|
NSFont *new;
|
|
|
|
if (the_role & 1)
|
|
{
|
|
[aDecoder decodeValueOfObjCType: @encode(float)
|
|
at: &size];
|
|
}
|
|
else
|
|
{
|
|
size = 0.0;
|
|
}
|
|
|
|
switch (the_role >> 1)
|
|
{
|
|
case RoleBoldSystemFont:
|
|
new = [NSFont boldSystemFontOfSize: size];
|
|
break;
|
|
case RoleSystemFont:
|
|
new = [NSFont systemFontOfSize: size];
|
|
break;
|
|
case RoleUserFixedPitchFont:
|
|
new = [NSFont userFixedPitchFontOfSize: size];
|
|
break;
|
|
case RoleTitleBarFont:
|
|
new = [NSFont titleBarFontOfSize: size];
|
|
break;
|
|
case RoleMenuFont:
|
|
new = [NSFont menuFontOfSize: size];
|
|
break;
|
|
case RoleMessageFont:
|
|
new = [NSFont messageFontOfSize: size];
|
|
break;
|
|
case RolePaletteFont:
|
|
new = [NSFont paletteFontOfSize: size];
|
|
break;
|
|
case RoleToolTipsFont:
|
|
new = [NSFont toolTipsFontOfSize: size];
|
|
break;
|
|
case RoleControlContentFont:
|
|
new = [NSFont controlContentFontOfSize: size];
|
|
break;
|
|
case RoleLabelFont:
|
|
new = [NSFont labelFontOfSize: size];
|
|
break;
|
|
case RoleMenuBarFont:
|
|
new = [NSFont menuBarFontOfSize: size];
|
|
break;
|
|
|
|
default:
|
|
NSDebugLLog(@"NSFont", @"unknown role %i", the_role);
|
|
/* fall through */
|
|
case RoleUserFont:
|
|
new = [NSFont userFontOfSize: size];
|
|
break;
|
|
}
|
|
|
|
RELEASE(self);
|
|
if (new)
|
|
return RETAIN(new);
|
|
|
|
new = [NSFont userFontOfSize: size];
|
|
NSAssert(new != nil, @"Couldn't find a valid font when decoding.");
|
|
return RETAIN(new);
|
|
}
|
|
}
|
|
}
|
|
|
|
@end /* NSFont */
|
|
|
|
@implementation NSFont (GNUstep)
|
|
//
|
|
// Private method for NSFontManager and backend
|
|
//
|
|
- (GSFontInfo*) fontInfo
|
|
{
|
|
return fontInfo;
|
|
}
|
|
|
|
- (void *) fontRef
|
|
{
|
|
if (_fontRef == nil)
|
|
_fontRef = fontInfo;
|
|
return _fontRef;
|
|
}
|
|
|
|
// This is a private but popular Cocoa method.
|
|
- (NSGlyph) _defaultGlyphForChar: (unichar)theChar
|
|
{
|
|
return [fontInfo glyphForCharacter: theChar];
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
int NSConvertGlyphsToPackedGlyphs(NSGlyph *glBuf,
|
|
int count,
|
|
NSMultibyteGlyphPacking packing,
|
|
char *packedGlyphs)
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
j = 0;
|
|
// Store the number of glyphs in the first byte.
|
|
packedGlyphs[j++] = count;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
NSGlyph g = glBuf[i];
|
|
|
|
switch (packing)
|
|
{
|
|
case NSOneByteGlyphPacking:
|
|
packedGlyphs[j++] = (char)(g & 0xFF);
|
|
break;
|
|
case NSTwoByteGlyphPacking:
|
|
packedGlyphs[j++] = (char)((g & 0xFF00) >> 8) ;
|
|
packedGlyphs[j++] = (char)(g & 0xFF);
|
|
break;
|
|
case NSFourByteGlyphPacking:
|
|
packedGlyphs[j++] = (char)((g & 0xFF000000) >> 24) ;
|
|
packedGlyphs[j++] = (char)((g & 0xFF0000) >> 16);
|
|
packedGlyphs[j++] = (char)((g & 0xFF00) >> 8) ;
|
|
packedGlyphs[j++] = (char)(g & 0xFF);
|
|
break;
|
|
case NSJapaneseEUCGlyphPacking:
|
|
case NSAsciiWithDoubleByteEUCGlyphPacking:
|
|
default:
|
|
// FIXME
|
|
break;
|
|
}
|
|
}
|
|
|
|
return j;
|
|
}
|