Image cache tidyup

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@5345 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 1999-12-01 13:49:47 +00:00
parent f2bcb34b09
commit 804630d3ae
3 changed files with 277 additions and 306 deletions

View file

@ -94,12 +94,9 @@ static NSString* NSImage_PATH = @"Images";
- (void) dealloc - (void) dealloc
{ {
if (fileName) TEST_RELEASE(fileName);
[fileName release]; TEST_RELEASE(rep);
if (rep) TEST_RELEASE(bg);
[rep release];
if (bg)
[bg release];
NSDeallocateObject(self); NSDeallocateObject(self);
} }
@end @end
@ -134,6 +131,9 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
- (BOOL) loadFromData: (NSData *)data; - (BOOL) loadFromData: (NSData *)data;
- (BOOL) loadFromFile: (NSString *)fileName; - (BOOL) loadFromFile: (NSString *)fileName;
- (NSImageRep *) lastRepresentation; - (NSImageRep *) lastRepresentation;
- (NSImageRep*) cacheForRep: (NSImageRep*)rep
onDevice: (NSDictionary*)deviceDescription;
- (NSImageRep*) _doImageCache: (NSDictionary*)deviceDescription;
@end @end
@implementation NSImage @implementation NSImage
@ -141,6 +141,8 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
/* Class variables and functions for class methods */ /* Class variables and functions for class methods */
static NSMutableDictionary *nameDict = nil; static NSMutableDictionary *nameDict = nil;
static NSDictionary *nsmapping = nil; static NSDictionary *nsmapping = nil;
static NSColor *clearColor = nil;
static Class cacheClass = 0;
+ (void) initialize + (void) initialize
{ {
@ -156,13 +158,14 @@ static NSDictionary* nsmapping = nil;
// initialize the class variables // initialize the class variables
nameDict = [[NSMutableDictionary alloc] initWithCapacity: 10]; nameDict = [[NSMutableDictionary alloc] initWithCapacity: 10];
if (path) if (path)
nsmapping = [[[NSString stringWithContentsOfFile: path] nsmapping = RETAIN([[NSString stringWithContentsOfFile: path]
propertyListFromStringsFileFormat] propertyListFromStringsFileFormat]);
retain]; clearColor = RETAIN([NSColor clearColor]);
cacheClass = [NSCachedImageRep class];
} }
} }
+ imageNamed: (NSString *)aName + (id) imageNamed: (NSString *)aName
{ {
NSString *realName = [nsmapping objectForKey: aName]; NSString *realName = [nsmapping objectForKey: aName];
@ -252,7 +255,7 @@ static NSDictionary* nsmapping = nil;
if (image) if (image)
{ {
[image setName: aName]; [image setName: aName];
[image release]; // Retained in dictionary. RELEASE(image); // Retained in dictionary.
} }
return image; return image;
} }
@ -272,10 +275,10 @@ static NSDictionary* nsmapping = nil;
} }
// Designated initializer for nearly everything. // Designated initializer for nearly everything.
- initWithSize: (NSSize)aSize - (id) initWithSize: (NSSize)aSize
{ {
[super init]; [super init];
_reps = [[NSMutableArray arrayWithCapacity: 2] retain]; _reps = [[NSMutableArray alloc] initWithCapacity: 2];
if (aSize.width && aSize.height) if (aSize.width && aSize.height)
{ {
_size = aSize; _size = aSize;
@ -302,7 +305,7 @@ static NSDictionary* nsmapping = nil;
_flags.dataRetained = NO; _flags.dataRetained = NO;
if (![self useFromFile: fileName]) if (![self useFromFile: fileName])
{ {
[self release]; RELEASE(self);
return nil; return nil;
} }
} }
@ -318,7 +321,7 @@ static NSDictionary* nsmapping = nil;
_flags.dataRetained = YES; _flags.dataRetained = YES;
if (![self useFromFile: fileName]) if (![self useFromFile: fileName])
{ {
[self release]; RELEASE(self);
return nil; return nil;
} }
} }
@ -333,14 +336,14 @@ static NSDictionary* nsmapping = nil;
{ {
if (![self loadFromData: data]) if (![self loadFromData: data])
{ {
[self release]; RELEASE(self);
return nil; return nil;
} }
} }
return self; return self;
} }
- initWithPasteboard: (NSPasteboard *)pasteboard - (id) initWithPasteboard: (NSPasteboard *)pasteboard
{ {
[self notImplemented: _cmd]; [self notImplemented: _cmd];
return nil; return nil;
@ -357,6 +360,7 @@ static NSDictionary* nsmapping = nil;
if (_size.width == 0) if (_size.width == 0)
{ {
NSImageRep *rep = [self bestRepresentationForDevice: nil]; NSImageRep *rep = [self bestRepresentationForDevice: nil];
_size = [rep size]; _size = [rep size];
} }
return _size; return _size;
@ -365,30 +369,29 @@ static NSDictionary* nsmapping = nil;
- (void) dealloc - (void) dealloc
{ {
[self representations]; [self representations];
[_repList release]; RELEASE(_repList);
[_reps release]; RELEASE(_reps);
/* Make sure we don't remove name from the nameDict if we are just a copy /* Make sure we don't remove name from the nameDict if we are just a copy
of the named image, not the original image */ of the named image, not the original image */
if (name && self == [nameDict objectForKey: name]) if (name && self == [nameDict objectForKey: name])
[nameDict removeObjectForKey: name]; [nameDict removeObjectForKey: name];
[name release]; RELEASE(name);
[super dealloc]; [super dealloc];
} }
- copyWithZone: (NSZone *)zone - (id) copyWithZone: (NSZone *)zone
{ {
NSImage *copy; NSImage *copy;
// FIXME: maybe we should retain if _flags.dataRetained = NO // FIXME: maybe we should retain if _flags.dataRetained = NO
copy = (NSImage*)NSCopyObject (self, 0, zone); copy = (NSImage*)NSCopyObject (self, 0, zone);
[name retain]; RETAIN(name);
copy->_reps = [NSMutableArray new]; copy->_reps = [NSMutableArray new];
copy->_repList = [NSMutableArray new]; copy->_repList = [NSMutableArray new];
[_color retain]; RETAIN(_color);
_lockedView = nil; _lockedView = nil;
[copy addRepresentations: [[[self representations] copyWithZone: zone] [copy addRepresentations: [self representations]];
autorelease]];
return copy; return copy;
} }
@ -396,15 +399,12 @@ static NSDictionary* nsmapping = nil;
- (BOOL) setName: (NSString *)string - (BOOL) setName: (NSString *)string
{ {
if (!nameDict) if (!nameDict)
nameDict = [[NSMutableDictionary dictionaryWithCapacity: 2] retain]; nameDict = [[NSMutableDictionary alloc] initWithCapacity: 2];
if (!string || [nameDict objectForKey: string]) if (!string || [nameDict objectForKey: string])
return NO; return NO;
[string retain]; ASSIGN(name, string);
if (name)
[name release];
name = string;
[nameDict setObject: self forKey: name]; [nameDict setObject: self forKey: name];
return YES; return YES;
@ -492,15 +492,18 @@ static NSDictionary* nsmapping = nil;
GSRepData *repd = (GSRepData*)[_reps objectAtIndex: i]; GSRepData *repd = (GSRepData*)[_reps objectAtIndex: i];
if (repd->bg != nil if (repd->bg != nil
|| [repd->rep isKindOfClass: [NSCachedImageRep class]] == NO) || [repd->rep isKindOfClass: cacheClass] == NO)
{
valid = YES; valid = YES;
break;
}
} }
return valid; return valid;
} }
- (void) recache - (void) recache
{ {
int i, count; unsigned i, count;
count = [_reps count]; count = [_reps count];
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
@ -510,8 +513,7 @@ static NSDictionary* nsmapping = nil;
repd = (GSRepData*)[_reps objectAtIndex: i]; repd = (GSRepData*)[_reps objectAtIndex: i];
if (repd->bg != nil) if (repd->bg != nil)
{ {
[repd->bg release]; DESTROY(repd->bg);
repd->bg = nil;
} }
} }
} }
@ -528,18 +530,13 @@ static NSDictionary* nsmapping = nil;
- (void) setBackgroundColor: (NSColor *)aColor - (void) setBackgroundColor: (NSColor *)aColor
{ {
if (_color != aColor) ASSIGN(_color, aColor);
{
if (_color)
[_color release];
_color = [aColor retain];
}
} }
- (NSColor *) backgroundColor - (NSColor *) backgroundColor
{ {
if (_color == nil) if (_color == nil)
_color = [[NSColor clearColor] retain]; _color = RETAIN(clearColor);
return _color; return _color;
} }
@ -575,39 +572,24 @@ static NSDictionary* nsmapping = nil;
// a cache and no cache exists, create one and draw the representation in it // a cache and no cache exists, create one and draw the representation in it
// If a cache exists, but is not valid, redraw the cache from the original // If a cache exists, but is not valid, redraw the cache from the original
// image (if there is one). // image (if there is one).
- (NSImageRep *)_doImageCache - (NSImageRep *)_doImageCache: (NSDictionary*)deviceDesc
{ {
NSImageRep *rep = nil; NSImageRep *rep = nil;
GSRepData *repd; GSRepData *repd;
repd = repd_for_rep(_reps, [self bestRepresentationForDevice: nil]); repd = repd_for_rep(_reps, [self bestRepresentationForDevice: deviceDesc]);
rep = repd->rep; rep = repd->rep;
if (doesCaching) if (doesCaching == YES)
{ {
/* /*
* If this is not a cached image rep - create a cache to be used to * If this is not a cached image rep - create a cache to be used to
* render the image rep into, and switch to the cached rep. * render the image rep into, and switch to the cached rep.
*/ */
if ([rep isKindOfClass: [NSCachedImageRep class]] == NO) if ([rep isKindOfClass: cacheClass] == NO)
{ {
NSScreen *cur = [NSScreen mainScreen]; rep = [self cacheForRep: rep onDevice: deviceDesc];
NSCachedImageRep *cachedRep; repd = repd_for_rep(_reps, rep);
NSSize imageSize;
imageSize = [self size];
if (imageSize.width == 0 || imageSize.height == 0)
return nil;
cachedRep = [[NSCachedImageRep alloc] initWithSize: _size
depth: [cur depth]
separate: NO
alpha: NO];
[self addRepresentation: cachedRep];
[cachedRep release]; /* Retained in _reps array. */
repd = repd_for_rep(_reps, cachedRep);
repd->original = rep;
rep = repd->rep;
} }
/* /*
@ -620,21 +602,16 @@ static NSDictionary* nsmapping = nil;
NSRect bounds; NSRect bounds;
[self lockFocusOnRepresentation: rep]; [self lockFocusOnRepresentation: rep];
/*
* If this is not a cache - the lockFocus will have created a
* cache that we can use instead.
*/
if (repd->original == nil)
{
repd = repd_for_rep(_reps, [self lastRepresentation]);
}
bounds = [_lockedView bounds]; bounds = [_lockedView bounds];
if (_color != nil && [_color isEqual: clearColor] == NO)
{
[_color set]; [_color set];
NSEraseRect(bounds); NSEraseRect(bounds);
}
[self drawRepresentation: repd->original [self drawRepresentation: repd->original
inRect: NSMakeRect(0, 0, _size.width, _size.height)]; inRect: NSMakeRect(0, 0, _size.width, _size.height)];
[self unlockFocus]; [self unlockFocus];
repd->bg = [_color copy]; repd->bg = _color ? [_color copy] : [clearColor copy];
} }
} }
@ -662,7 +639,7 @@ static NSDictionary* nsmapping = nil;
// xxx If fromRect specifies something other than full image // xxx If fromRect specifies something other than full image
// then we need to construct a subimage to draw // then we need to construct a subimage to draw
rep = [self _doImageCache]; rep = [self _doImageCache: nil];
[self drawRepresentation: rep inRect: rect]; [self drawRepresentation: rep inRect: rect];
} }
@ -684,7 +661,7 @@ static NSDictionary* nsmapping = nil;
// xxx If fromRect specifies something other than full image // xxx If fromRect specifies something other than full image
// then we need to construct a subimage to draw // then we need to construct a subimage to draw
rep = [self _doImageCache]; rep = [self _doImageCache: nil];
[self drawRepresentation: rep inRect: rect]; [self drawRepresentation: rep inRect: rect];
} }
@ -751,9 +728,9 @@ static NSDictionary* nsmapping = nil;
if ([array indexOfObject: ext] == NSNotFound) if ([array indexOfObject: ext] == NSNotFound)
return NO; return NO;
repd = [GSRepData new]; repd = [GSRepData new];
repd->fileName = [fileName retain]; repd->fileName = RETAIN(fileName);
[_reps addObject: repd]; [_reps addObject: repd];
[repd release]; RELEASE(repd);
_flags.syncLoad = YES; _flags.syncLoad = YES;
return YES; return YES;
} }
@ -777,31 +754,12 @@ static NSDictionary* nsmapping = nil;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
repd = [GSRepData new]; repd = [GSRepData new];
repd->rep = [[imageRepArray objectAtIndex: i] retain]; repd->rep = RETAIN([imageRepArray objectAtIndex: i]);
[_reps addObject: repd]; [_reps addObject: repd];
[repd release]; RELEASE(repd);
} }
} }
- (BOOL) useCacheWithDepth: (int)depth
{
NSSize imageSize;
NSCachedImageRep* rep;
imageSize = [self size];
if (!imageSize.width || !imageSize.height)
return NO;
// FIXME: determine alpha? separate?
rep = [[NSCachedImageRep alloc] initWithSize: _size
depth: depth
separate: NO
alpha: NO];
[self addRepresentation: rep];
return YES;
}
- (void) removeRepresentation: (NSImageRep *)imageRep - (void) removeRepresentation: (NSImageRep *)imageRep
{ {
unsigned i; unsigned i;
@ -824,45 +782,31 @@ static NSDictionary* nsmapping = nil;
- (void) lockFocus - (void) lockFocus
{ {
NSScreen *cur = [NSScreen mainScreen];
NSImageRep *rep; NSImageRep *rep;
if (!(rep = [self bestRepresentationForDevice: nil])) if (!(rep = [self bestRepresentationForDevice: nil]))
{ {
[self useCacheWithDepth: [cur depth]]; if ([rep isKindOfClass: cacheClass] == NO)
rep = [self lastRepresentation]; {
rep = [self cacheForRep: rep onDevice: nil];
}
} }
[self lockFocusOnRepresentation: rep]; [self lockFocusOnRepresentation: rep];
} }
- (void) lockFocusOnRepresentation: (NSImageRep *)imageRep - (void) lockFocusOnRepresentation: (NSImageRep *)imageRep
{ {
NSScreen *cur = [NSScreen mainScreen]; if (imageRep == nil)
NSWindow *window;
if (!imageRep)
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
format: @"Cannot lock focus on nil rep"]; format: @"Cannot lock focus on nil rep"];
if (doesCaching) if (doesCaching == YES)
{ {
if (![imageRep isKindOfClass: [NSCachedImageRep class]]) NSWindow *window;
{
GSRepData *cached;
int depth;
if (_flags.unboundedCacheDepth) if ([imageRep isKindOfClass: cacheClass] == NO)
depth = [cur depth]; // FIXME: get depth correctly
else
depth = [cur depth];
if (![self useCacheWithDepth: depth])
{ {
[NSException raise: NSImageCacheException imageRep = [self cacheForRep: imageRep onDevice: nil];
format: @"Unable to create cache"];
}
cached = repd_for_rep(_reps, [self lastRepresentation]);
cached->original = imageRep;
imageRep = cached->rep;
} }
window = [(NSCachedImageRep *)imageRep window]; window = [(NSCachedImageRep *)imageRep window];
_lockedView = [window contentView]; _lockedView = [window contentView];
@ -872,10 +816,12 @@ static NSDictionary* nsmapping = nil;
- (void) unlockFocus - (void) unlockFocus
{ {
if (_lockedView) if (_lockedView != nil)
{
[_lockedView unlockFocus]; [_lockedView unlockFocus];
_lockedView = nil; _lockedView = nil;
} }
}
- (NSImageRep *) lastRepresentation - (NSImageRep *) lastRepresentation
{ {
@ -902,8 +848,7 @@ static NSDictionary* nsmapping = nil;
/* /*
* What's the best representation? FIXME * What's the best representation? FIXME
* At the moment we take the last bitmap we find, or the first * At the moment we take the last bitmap we find.
* rep of any type if we don't find a bitmap.
*/ */
[_reps getObjects: reps]; [_reps getObjects: reps];
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
@ -914,21 +859,27 @@ static NSDictionary* nsmapping = nil;
{ {
rep = repd->rep; rep = repd->rep;
} }
else if (rep == nil)
{
rep = repd->rep;
} }
} }
return rep;
}
/* - (NSImageRep*) cacheForRep: (NSImageRep*)rep
* If we got a representation - see if we already have it cached. onDevice: (NSDictionary*)deviceDescription
*/
if (doesCaching)
{ {
if (rep != nil) if (doesCaching == YES)
{
NSImageRep *cacheRep = nil;
unsigned count = [_reps count];
if (count > 0)
{ {
GSRepData *invalidCache = nil; GSRepData *invalidCache = nil;
GSRepData *validCache = nil; GSRepData *validCache = nil;
GSRepData *reps[count];
unsigned i;
[_reps getObjects: reps];
/* /*
* Search the cached image reps for any whose original is our * Search the cached image reps for any whose original is our
@ -954,7 +905,7 @@ static NSDictionary* nsmapping = nil;
} }
} }
if (validCache) if (validCache != nil)
{ {
/* /*
* If the image rep has transparencey and we are drawing * If the image rep has transparencey and we are drawing
@ -963,23 +914,43 @@ static NSDictionary* nsmapping = nil;
* transparency on top of anything. So we invalidate * transparency on top of anything. So we invalidate
* the cache by removing the background color information. * the cache by removing the background color information.
*/ */
if ([rep hasAlpha] if ([rep hasAlpha] && [validCache->bg isEqual: clearColor])
&& [validCache->bg isEqual: [NSColor clearColor]])
{ {
[validCache->bg release]; DESTROY(validCache->bg);
validCache->bg = nil;
} }
rep = validCache->rep; cacheRep = validCache->rep;
} }
else if (invalidCache) else if (invalidCache != nil)
{ {
rep = invalidCache->rep; cacheRep = invalidCache->rep;
} }
} }
if (cacheRep == nil)
{
NSScreen *cur = [NSScreen mainScreen];
NSSize imageSize;
GSRepData *repd;
imageSize = [self size];
if (imageSize.width == 0 || imageSize.height == 0)
return nil;
cacheRep = [[cacheClass alloc] initWithSize: _size
depth: [cur depth]
separate: NO
alpha: NO];
[self addRepresentation: cacheRep];
RELEASE(cacheRep); /* Retained in _reps array. */
repd = repd_for_rep(_reps, cacheRep);
repd->original = rep;
} }
return cacheRep;
} }
else
{
return rep; return rep;
} }
}
- (NSArray *) representations - (NSArray *) representations
{ {

View file

@ -131,7 +131,7 @@
// nada // nada
break; break;
case NSImageFramePhoto: case NSImageFramePhoto:
// what does this one look like? TODO (in sync with the rest of the code) // FIXME
break; break;
case NSImageFrameGrayBezel: case NSImageFrameGrayBezel:
NSDrawGrayBezel(cellFrame, NSZeroRect); NSDrawGrayBezel(cellFrame, NSZeroRect);
@ -235,8 +235,8 @@ static inline NSSize scaleProportionally(NSSize imageSize, NSRect canvasRect)
NSDebugLLog(@"NSImageCell", @"NSScaleNone"); NSDebugLLog(@"NSImageCell", @"NSScaleNone");
[image setScalesWhenResized:NO]; [image setScalesWhenResized:NO];
// don't let the image size overrun the space available // don't let the image size overrun the space available
if( _original_image_size.width > cellFrame.size.width || if (_original_image_size.width > cellFrame.size.width
_original_image_size.height > cellFrame.size.height ) || _original_image_size.height > cellFrame.size.height)
[image setSize: cellFrame.size]; [image setSize: cellFrame.size];
else else
[image setSize: _original_image_size]; [image setSize: _original_image_size];
@ -304,7 +304,7 @@ static inline NSSize scaleProportionally(NSSize imageSize, NSRect canvasRect)
borderSize = [NSCell sizeForBorderType: NSNoBorder]; borderSize = [NSCell sizeForBorderType: NSNoBorder];
break; break;
case NSImageFramePhoto: case NSImageFramePhoto:
// what does this one look like? TODO (in sync with the rest of the code) // FIXME
borderSize = [NSCell sizeForBorderType: NSNoBorder]; borderSize = [NSCell sizeForBorderType: NSNoBorder];
break; break;
case NSImageFrameGrayBezel: case NSImageFrameGrayBezel: