mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-25 18:30:56 +00:00
discussion with Steve Naroff (before he left Apple) it was decided that the isa pointer should be regarded as an implementation detail and not part of the language, so direct references to it are deprecated (on OS X). This gives the runtime a bit more freedom to do secret isa-swizzling tricks. I've had these changes sitting in my copy for ages - no idea why they weren't committed. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@33111 72102866-910b-0410-8b05-ffd578937521
1546 lines
42 KiB
Objective-C
1546 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
|
|
fix: (BOOL)explicitlySet
|
|
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 fix;
|
|
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
|
|
|| fix != o->fix)
|
|
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 fix,
|
|
BOOL screenFont, int role)
|
|
{
|
|
GSFontMapKey *d;
|
|
d=[GSFontMapKey alloc];
|
|
d->name = [name copy];
|
|
d->screenFont = screenFont;
|
|
d->role = role;
|
|
d->fix = fix;
|
|
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 + fix * 2
|
|
+ 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 6</item>
|
|
<item>NSMessageFontSize (none)</item>
|
|
<item>NSPaletteFontSize (none)</item>
|
|
<item>NSSmallFontSize 9</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 = 9;
|
|
}
|
|
|
|
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 = 6;
|
|
}
|
|
|
|
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;
|
|
BOOL fix;
|
|
|
|
if (fontMatrix == NSFontIdentityMatrix)
|
|
fix = NO;
|
|
else
|
|
fix = YES;
|
|
|
|
font = [placeHolder initWithName: aFontName
|
|
matrix: fontMatrix
|
|
fix: fix
|
|
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
|
|
fix: NO
|
|
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;
|
|
}
|
|
|
|
/** <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
|
|
fix: (BOOL)explicitlySet
|
|
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, explicitlySet,
|
|
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));
|
|
matrixExplicitlySet = explicitlySet;
|
|
screenFont = screen;
|
|
role = aRole;
|
|
fontInfo = RETAIN([GSFontInfo fontInfoForFontName: fontName
|
|
matrix: fontMatrix
|
|
screenFont: screen]);
|
|
if ((fontInfo == nil) && (aRole == RoleExplicit))
|
|
{
|
|
/*
|
|
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.
|
|
*/
|
|
if (([fontName isEqualToString: @"Helvetica"] &&
|
|
![font_roles[RoleSystemFont].defaultFont isEqualToString: @"Helvetica"])
|
|
|| ([fontName isEqualToString: @"LucidaGrande"]))
|
|
{
|
|
fontInfo = RETAIN([GSFontInfo fontInfoForFontName:
|
|
font_roles[RoleSystemFont].defaultFont
|
|
matrix: fontMatrix
|
|
screenFont: screen]);
|
|
}
|
|
else if (([fontName isEqualToString: @"Helvetica-Bold"] &&
|
|
![font_roles[RoleBoldSystemFont].defaultFont isEqualToString: @"Helvetica-Bold"])
|
|
|| ([fontName isEqualToString: @"LucidaGrande-Bold"]))
|
|
{
|
|
fontInfo = RETAIN([GSFontInfo fontInfoForFontName:
|
|
font_roles[RoleBoldSystemFont].defaultFont
|
|
matrix: fontMatrix
|
|
screenFont: screen]);
|
|
}
|
|
else if ([fontName isEqualToString: @"Courier"] &&
|
|
![font_roles[RoleUserFixedPitchFont].defaultFont isEqualToString: @"Courier"])
|
|
{
|
|
fontInfo = RETAIN([GSFontInfo fontInfoForFontName:
|
|
font_roles[RoleUserFixedPitchFont].defaultFont
|
|
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,
|
|
matrixExplicitlySet, 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 %c %i", fontName,
|
|
matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5],
|
|
(matrixExplicitlySet == NO) ? 'N' : 'Y',
|
|
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
|
|
fix: YES
|
|
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, as long as the font was created
|
|
without explicitly setting the font matrix */
|
|
- (void) set
|
|
{
|
|
[self setInContext: GSCurrentContext()];
|
|
}
|
|
|
|
- (void) setInContext: (NSGraphicsContext*)context
|
|
{
|
|
if (matrixExplicitlySet == NO
|
|
&& ([[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
|
|
fix: matrixExplicitlySet
|
|
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
|
|
fix: matrixExplicitlySet
|
|
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]; }
|
|
|
|
/* 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;
|
|
}
|
|
|
|
- (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];
|
|
|
|
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: &matrixExplicitlySet];
|
|
}
|
|
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);
|
|
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];
|
|
BOOL fix;
|
|
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)
|
|
{
|
|
[aDecoder decodeValueOfObjCType: @encode(BOOL)
|
|
at: &fix];
|
|
}
|
|
else
|
|
{
|
|
if (fontMatrix[0] == fontMatrix[3]
|
|
&& fontMatrix[1] == 0.0 && fontMatrix[2] == 0.0)
|
|
fix = NO;
|
|
else
|
|
fix = YES;
|
|
}
|
|
|
|
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
|
|
fix: fix
|
|
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;
|
|
}
|