Font caching rewrite

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@14590 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2002-09-27 12:25:02 +00:00
parent 898e2814df
commit 4658c7dc35
3 changed files with 252 additions and 194 deletions

View file

@ -1,3 +1,10 @@
2002-09-27 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSFont.m: Rewrote code dealing with creation and destruction
of font objects to remove holes in the original caching scheme and to
optimimise font creation/destruction somewhat. All font objects
should now be handled by the cache, no matter how they are created.
2002-09-27 Richard Frith-Macdonald <rfm@gnu.org> 2002-09-27 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSFont.m: Replace caching code which never released fonts * Source/NSFont.m: Replace caching code which never released fonts

View file

@ -31,6 +31,7 @@
#include <Foundation/NSUserDefaults.h> #include <Foundation/NSUserDefaults.h>
#include <Foundation/NSSet.h> #include <Foundation/NSSet.h>
#include <Foundation/NSMapTable.h> #include <Foundation/NSMapTable.h>
#include <Foundation/NSException.h>
#include <AppKit/NSGraphicsContext.h> #include <AppKit/NSGraphicsContext.h>
#include <AppKit/NSFont.h> #include <AppKit/NSFont.h>
@ -45,14 +46,31 @@ static BOOL systemCacheNeedsRecomputing = NO;
static BOOL boldSystemCacheNeedsRecomputing = NO; static BOOL boldSystemCacheNeedsRecomputing = NO;
static BOOL userCacheNeedsRecomputing = NO; static BOOL userCacheNeedsRecomputing = NO;
static BOOL userFixedCacheNeedsRecomputing = NO; static BOOL userFixedCacheNeedsRecomputing = NO;
static NSFont *placeHolder = nil;
@interface NSFont (Private) @interface NSFont (Private)
- (id) initWithName: (NSString*)name - (id) initWithName: (NSString*)name
matrix: (const float*)fontMatrix; matrix: (const float*)fontMatrix
fix: (BOOL)explicitlySet;
@end @end
static int currentVersion = 2; static int currentVersion = 2;
/*
* Just to ensure that we use a standard name in the cache.
*/
static NSString*
newNameWithMatrix(NSString *name, const float *matrix, BOOL fix)
{
NSString *nameWithMatrix;
nameWithMatrix = [[NSString alloc] initWithFormat:
@"%@ %.3f %.3f %.3f %.3f %.3f %.3f %c", name,
matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5],
(fix == NO) ? 'N' : 'Y'];
return nameWithMatrix;
}
/** /**
<unit> <unit>
<heading>NSFont</heading> <heading>NSFont</heading>
@ -161,6 +179,17 @@ setNSFont(NSString* key, NSFont* font)
if (self == [NSFont class]) if (self == [NSFont class])
{ {
NSFontClass = self; 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 allocete fonts instances
* which would immediately have to be released for replacement by
* a cache object.
*/
placeHolder = [self alloc];
globalFontMap = NSCreateMapTable(NSObjectMapKeyCallBacks, globalFontMap = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSNonRetainedObjectMapValueCallBacks, 64); NSNonRetainedObjectMapValueCallBacks, 64);
@ -470,40 +499,35 @@ setNSFont(NSString* key, NSFont* font)
return fontSize; return fontSize;
} }
/** Creates a new font with name aFontName and matrix fontMatrix. The /**
fontMatrix is a standard size element matrix as used in PostScript * Returns an autoreleased font with name aFontName and matrix fontMatrix.<br />
to describe the scaling of the font, typically it just includes * The fontMatrix is a standard size element matrix as used in PostScript
the font size as [fontSize 0 0 fontSize 0 0]. You can use the constant * to describe the scaling of the font, typically it just includes
NSFontIdentityMatrix in place of [1 0 0 1 0 0]. If NSFontIdentityMatrix, * the font size as [fontSize 0 0 fontSize 0 0]. You can use the constant
then the font will automatically flip itself when set in a * NSFontIdentityMatrix in place of [1 0 0 1 0 0]. If NSFontIdentityMatrix,
flipped view */ * then the font will automatically flip itself when set in a flipped view.
*/
+ (NSFont*) fontWithName: (NSString*)aFontName + (NSFont*) fontWithName: (NSString*)aFontName
matrix: (const float*)fontMatrix matrix: (const float*)fontMatrix
{ {
NSFont *font; NSFont *font;
NSString *nameWithMatrix; BOOL fix;
nameWithMatrix = [NSString stringWithFormat: if (fontMatrix == NSFontIdentityMatrix)
@"%@ %.3f %.3f %.3f %.3f %.3f %.3f", aFontName, fix = NO;
fontMatrix[0], fontMatrix[1], fontMatrix[2], else
fontMatrix[3], fontMatrix[4], fontMatrix[5]]; fix = YES;
/* Check whether the font is cached */ font = [placeHolder initWithName: aFontName matrix: fontMatrix fix: fix];
font = RETAIN((id)NSMapGet(globalFontMap, (void*)nameWithMatrix));
if (font == nil)
{
font = [[NSFontClass alloc] initWithName: aFontName
matrix: fontMatrix];
/* Cache the font for later use */
NSMapInsert(globalFontMap, (void*)nameWithMatrix, (void*)font);
}
return AUTORELEASE(font); return AUTORELEASE(font);
} }
/** Creates a new font with name aFontName and size fontSize. Fonts created /**
using this method will automatically flip themselves when set in a flipped * Returns an autoreleased font with name aFontName and size fontSize.<br />
view */ * Fonts created using this method will automatically flip themselves
* when set in a flipped view.
*/
+ (NSFont*) fontWithName: (NSString*)aFontName + (NSFont*) fontWithName: (NSString*)aFontName
size: (float)fontSize size: (float)fontSize
{ {
@ -521,9 +545,8 @@ setNSFont(NSString* key, NSFont* font)
fontMatrix[0] = fontSize; fontMatrix[0] = fontSize;
fontMatrix[3] = fontSize; fontMatrix[3] = fontSize;
font = [self fontWithName: aFontName matrix: fontMatrix]; font = [placeHolder initWithName: aFontName matrix: fontMatrix fix: NO];
font->matrixExplicitlySet = NO; return AUTORELEASE(font);
return font;
} }
+ (void) useFont: (NSString*)aFontName + (void) useFont: (NSString*)aFontName
@ -534,46 +557,89 @@ setNSFont(NSString* key, NSFont* font)
// //
// Instance methods // Instance methods
// //
/** <init /> Initializes a newly created font class from the name and - (id) init
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].
*/
- (id) initWithName: (NSString*)name matrix: (const float*)fontMatrix
{ {
[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 float*)fontMatrix
fix: (BOOL)explicitlySet
{
NSString *nameWithMatrix;
NSFont *font;
/* Should never be called on an initialised font! */
NSAssert(fontName == nil, NSInternalInconsistencyException);
/* Check whether the font is cached */
nameWithMatrix = newNameWithMatrix(name, fontMatrix, explicitlySet);
font = (id)NSMapGet(globalFontMap, (void*)nameWithMatrix);
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]; fontName = [name copy];
memcpy(matrix, fontMatrix, sizeof(matrix)); memcpy(matrix, fontMatrix, sizeof(matrix));
if (fontMatrix == NSFontIdentityMatrix) matrixExplicitlySet = explicitlySet;
matrixExplicitlySet = NO;
else
matrixExplicitlySet = YES;
fontInfo = RETAIN([GSFontInfo fontInfoForFontName: fontName fontInfo = RETAIN([GSFontInfo fontInfoForFontName: fontName
matrix: fontMatrix]); matrix: fontMatrix]);
/* Cache the font for later use */
NSMapInsert(globalFontMap, (void*)nameWithMatrix, (void*)self);
}
else
{
RELEASE(self);
self = RETAIN(font);
}
RELEASE(nameWithMatrix);
return self; return self;
} }
- (void) dealloc - (void) dealloc
{ {
NSString *nameWithMatrix = [NSString alloc]; if (fontName != nil)
{
NSString *nameWithMatrix;
nameWithMatrix = [nameWithMatrix initWithFormat: nameWithMatrix = newNameWithMatrix(fontName, matrix, matrixExplicitlySet);
@"%@ %.3f %.3f %.3f %.3f %.3f %.3f", fontName,
matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]];
NSMapRemove(globalFontMap, (void*)nameWithMatrix); NSMapRemove(globalFontMap, (void*)nameWithMatrix);
RELEASE(nameWithMatrix); RELEASE(nameWithMatrix);
RELEASE(fontName); RELEASE(fontName);
RELEASE(fontInfo); }
TEST_RELEASE(fontInfo);
[super dealloc]; [super dealloc];
} }
/* FIXME - appropriate description */
/*
- (NSString *) description - (NSString *) description
{ {
return [self fontName]; NSString *nameWithMatrix;
NSString *description;
nameWithMatrix = newNameWithMatrix(fontName, matrix, matrixExplicitlySet);
description = [[super description] stringByAppendingFormat: @" %@",
nameWithMatrix];
RELEASE(nameWithMatrix);
return description;
} }
*/
- (BOOL) isEqual: (id)anObject - (BOOL) isEqual: (id)anObject
{ {
@ -601,23 +667,14 @@ setNSFont(NSString* key, NSFont* font)
return ([fontName hash] + sum); return ([fontName hash] + sum);
} }
// /**
// NSCopying Protocol * 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 - (id) copyWithZone: (NSZone*)zone
{ {
NSFont*new_font; return RETAIN(self);
if (NSShouldRetainWithZone(self, zone))
{
new_font = RETAIN(self);
}
else
{
new_font = (NSFont*)NSCopyObject(self, 0, zone);
new_font->fontName = [fontName copyWithZone: zone];
new_font->fontInfo = [fontInfo copyWithZone: zone];
}
return new_font;
} }
- (NSFont *)_flippedViewFont - (NSFont *)_flippedViewFont
@ -808,36 +865,30 @@ setNSFont(NSString* key, NSFont* font)
- (id) initWithCoder: (NSCoder*)aDecoder - (id) initWithCoder: (NSCoder*)aDecoder
{ {
int version = [aDecoder versionForClassName: int version = [aDecoder versionForClassName: @"NSFont"];
@"NSFont"];
if (version == currentVersion)
{
id name; id name;
float fontMatrix[6]; float fontMatrix[6];
BOOL fix;
name = [aDecoder decodeObject]; name = [aDecoder decodeObject];
[aDecoder decodeArrayOfObjCType: @encode(float) [aDecoder decodeArrayOfObjCType: @encode(float)
count: 6 count: 6
at: fontMatrix]; at: fontMatrix];
self = [self initWithName: name matrix: fontMatrix]; if (version == currentVersion)
{
[aDecoder decodeValueOfObjCType: @encode(BOOL) [aDecoder decodeValueOfObjCType: @encode(BOOL)
at: &matrixExplicitlySet]; at: &fix];
} }
else else
{ {
id name;
float fontMatrix[6];
name = [aDecoder decodeObject];
[aDecoder decodeArrayOfObjCType: @encode(float)
count: 6
at: fontMatrix];
self = [self initWithName: name matrix: fontMatrix];
if (fontMatrix[0] == fontMatrix[3] if (fontMatrix[0] == fontMatrix[3]
&& fontMatrix[1] == 0.0 && fontMatrix[1] == 0.0 && fontMatrix[2] == 0.0)
&& fontMatrix[2] == 0.0) fix = NO;
matrixExplicitlySet = NO; else
fix = YES;
} }
self = [self initWithName: name matrix: fontMatrix fix: fix];
return self; return self;
} }