mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-06-04 15:50:42 +00:00
Reorganize image caching code to make it easier to understand and
change. And a bit faster too. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@27286 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
a4ca53d72e
commit
545799e46c
2 changed files with 336 additions and 303 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2008-12-13 Fred Kiefer <FredKiefer@gmx.de>
|
||||||
|
|
||||||
|
* Source/NSImage.m: Reorganize the image caching code to make it
|
||||||
|
easier to understand and change.
|
||||||
|
|
||||||
2008-12-12 19:36-EST Gregory John Casamento <greg_casamento@yahoo.com>
|
2008-12-12 19:36-EST Gregory John Casamento <greg_casamento@yahoo.com>
|
||||||
|
|
||||||
* Source/NSOutlineView.m: Added change suggested by Doug in
|
* Source/NSOutlineView.m: Added change suggested by Doug in
|
||||||
|
|
154
Source/NSImage.m
154
Source/NSImage.m
|
@ -167,8 +167,8 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
- (BOOL) _useFromFile: (NSString *)fileName;
|
- (BOOL) _useFromFile: (NSString *)fileName;
|
||||||
- (BOOL) _loadFromData: (NSData *)data;
|
- (BOOL) _loadFromData: (NSData *)data;
|
||||||
- (BOOL) _loadFromFile: (NSString *)fileName;
|
- (BOOL) _loadFromFile: (NSString *)fileName;
|
||||||
- (NSImageRep*) _cacheForRep: (NSImageRep*)rep;
|
- (GSRepData*) _cacheForRep: (NSImageRep*)rep;
|
||||||
- (NSImageRep*) _doImageCache;
|
- (NSCachedImageRep*) _doImageCache: (NSImageRep *)rep;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation NSImage
|
@implementation NSImage
|
||||||
|
@ -661,6 +661,7 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,20 +729,24 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
operation: op
|
operation: op
|
||||||
fraction: 1.0];
|
fraction: 1.0];
|
||||||
#else
|
#else
|
||||||
NSImageRep *rep = nil;
|
|
||||||
|
|
||||||
NS_DURING
|
NS_DURING
|
||||||
{
|
{
|
||||||
if ([GSCurrentContext() isDrawingToScreen] == YES)
|
NSImageRep *rep = [self bestRepresentationForDevice: nil];
|
||||||
rep = [self _doImageCache];
|
NSCachedImageRep *cache = nil;
|
||||||
if (rep
|
|
||||||
&&_cacheMode != NSImageCacheNever
|
if (rep == nil)
|
||||||
&& [rep isKindOfClass: cachedClass])
|
return;
|
||||||
|
|
||||||
|
if (([GSCurrentContext() isDrawingToScreen] == YES)
|
||||||
|
&& _cacheMode != NSImageCacheNever)
|
||||||
|
cache = [self _doImageCache: rep];
|
||||||
|
|
||||||
|
if (cache != nil)
|
||||||
{
|
{
|
||||||
NSRect rect;
|
NSRect rect;
|
||||||
float y = aPoint.y;
|
float y = aPoint.y;
|
||||||
|
|
||||||
rect = [(NSCachedImageRep *)rep rect];
|
rect = [cache rect];
|
||||||
NSDebugLLog(@"NSImage", @"composite rect %@ in %@",
|
NSDebugLLog(@"NSImage", @"composite rect %@ in %@",
|
||||||
NSStringFromRect(rect), NSStringFromRect(aRect));
|
NSStringFromRect(rect), NSStringFromRect(aRect));
|
||||||
// Move the drawing rectangle to the origin of the image rep
|
// Move the drawing rectangle to the origin of the image rep
|
||||||
|
@ -751,12 +756,12 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
rect = NSIntersectionRect(aRect, rect);
|
rect = NSIntersectionRect(aRect, rect);
|
||||||
|
|
||||||
PScomposite(NSMinX(rect), NSMinY(rect), NSWidth(rect), NSHeight(rect),
|
PScomposite(NSMinX(rect), NSMinY(rect), NSWidth(rect), NSHeight(rect),
|
||||||
[[(NSCachedImageRep *)rep window] gState], aPoint.x, y, op);
|
[[cache window] gState], aPoint.x, y, op);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSRect rect;
|
NSRect rect;
|
||||||
rep = [self bestRepresentationForDevice: nil];
|
|
||||||
rect = NSMakeRect(aPoint.x, aPoint.y, _size.width, _size.height);
|
rect = NSMakeRect(aPoint.x, aPoint.y, _size.width, _size.height);
|
||||||
[self drawRepresentation: rep inRect: rect];
|
[self drawRepresentation: rep inRect: rect];
|
||||||
}
|
}
|
||||||
|
@ -796,19 +801,23 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
operation: (NSCompositingOperation)op
|
operation: (NSCompositingOperation)op
|
||||||
fraction: (float)delta
|
fraction: (float)delta
|
||||||
{
|
{
|
||||||
NSImageRep *rep = nil;
|
|
||||||
|
|
||||||
NS_DURING
|
NS_DURING
|
||||||
{
|
{
|
||||||
if ([GSCurrentContext() isDrawingToScreen] == YES)
|
NSImageRep *rep = [self bestRepresentationForDevice: nil];
|
||||||
rep = [self _doImageCache];
|
NSCachedImageRep *cache = nil;
|
||||||
if (rep
|
|
||||||
&&_cacheMode != NSImageCacheNever
|
if (rep == nil)
|
||||||
&& [rep isKindOfClass: cachedClass])
|
return;
|
||||||
|
|
||||||
|
if (([GSCurrentContext() isDrawingToScreen] == YES)
|
||||||
|
&& _cacheMode != NSImageCacheNever)
|
||||||
|
cache = [self _doImageCache: rep];
|
||||||
|
|
||||||
|
if (cache != nil)
|
||||||
{
|
{
|
||||||
NSRect rect;
|
NSRect rect;
|
||||||
|
|
||||||
rect = [(NSCachedImageRep *)rep rect];
|
rect = [cache rect];
|
||||||
NSDebugLLog(@"NSImage", @"composite rect %@ in %@",
|
NSDebugLLog(@"NSImage", @"composite rect %@ in %@",
|
||||||
NSStringFromRect(rect), NSStringFromRect(srcRect));
|
NSStringFromRect(rect), NSStringFromRect(srcRect));
|
||||||
// Move the drawing rectangle to the origin of the image rep
|
// Move the drawing rectangle to the origin of the image rep
|
||||||
|
@ -817,8 +826,7 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
srcRect.origin.y += rect.origin.y;
|
srcRect.origin.y += rect.origin.y;
|
||||||
rect = NSIntersectionRect(srcRect, rect);
|
rect = NSIntersectionRect(srcRect, rect);
|
||||||
|
|
||||||
[GSCurrentContext() GScomposite:
|
[GSCurrentContext() GScomposite: [[cache window] gState]
|
||||||
[[(NSCachedImageRep *)rep window] gState]
|
|
||||||
toPoint: aPoint
|
toPoint: aPoint
|
||||||
fromRect: rect
|
fromRect: rect
|
||||||
operation: op
|
operation: op
|
||||||
|
@ -827,7 +835,7 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSRect rect;
|
NSRect rect;
|
||||||
rep = [self bestRepresentationForDevice: nil];
|
|
||||||
rect = NSMakeRect(aPoint.x, aPoint.y, _size.width, _size.height);
|
rect = NSMakeRect(aPoint.x, aPoint.y, _size.width, _size.height);
|
||||||
[self drawRepresentation: rep inRect: rect];
|
[self drawRepresentation: rep inRect: rect];
|
||||||
}
|
}
|
||||||
|
@ -870,27 +878,31 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
operation: NSCompositeSourceOver
|
operation: NSCompositeSourceOver
|
||||||
fraction: aFloat];
|
fraction: aFloat];
|
||||||
#else
|
#else
|
||||||
NSImageRep *rep = nil;
|
|
||||||
|
|
||||||
NS_DURING
|
NS_DURING
|
||||||
{
|
{
|
||||||
if ([GSCurrentContext() isDrawingToScreen] == YES)
|
NSImageRep *rep = [self bestRepresentationForDevice: nil];
|
||||||
rep = [self _doImageCache];
|
NSCachedImageRep *cache = nil;
|
||||||
if (rep
|
|
||||||
&&_cacheMode != NSImageCacheNever
|
if (rep == nil)
|
||||||
&& [rep isKindOfClass: cachedClass])
|
return;
|
||||||
|
|
||||||
|
if (([GSCurrentContext() isDrawingToScreen] == YES)
|
||||||
|
&& _cacheMode != NSImageCacheNever)
|
||||||
|
cache = [self _doImageCache: rep];
|
||||||
|
|
||||||
|
if (cache != nil)
|
||||||
{
|
{
|
||||||
NSRect rect;
|
NSRect rect;
|
||||||
float y = aPoint.y;
|
float y = aPoint.y;
|
||||||
|
|
||||||
rect = [(NSCachedImageRep *)rep rect];
|
rect = [cache rect];
|
||||||
// Move the drawing rectangle to the origin of the image rep
|
// Move the drawing rectangle to the origin of the image rep
|
||||||
// and intersect the two rects.
|
// and intersect the two rects.
|
||||||
aRect.origin.x += rect.origin.x;
|
aRect.origin.x += rect.origin.x;
|
||||||
aRect.origin.y += rect.origin.y;
|
aRect.origin.y += rect.origin.y;
|
||||||
rect = NSIntersectionRect(aRect, rect);
|
rect = NSIntersectionRect(aRect, rect);
|
||||||
PSdissolve(NSMinX(rect), NSMinY(rect), NSWidth(rect), NSHeight(rect),
|
PSdissolve(NSMinX(rect), NSMinY(rect), NSWidth(rect), NSHeight(rect),
|
||||||
[[(NSCachedImageRep *)rep window] gState], aPoint.x, y, aFloat);
|
[[cache window] gState], aPoint.x, y, aFloat);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -898,7 +910,6 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
|
|
||||||
/* FIXME: Here we are supposed to composite directly from the source
|
/* FIXME: Here we are supposed to composite directly from the source
|
||||||
but how do you do that? */
|
but how do you do that? */
|
||||||
rep = [self bestRepresentationForDevice: nil];
|
|
||||||
rect = NSMakeRect(aPoint.x, aPoint.y, _size.width, _size.height);
|
rect = NSMakeRect(aPoint.x, aPoint.y, _size.width, _size.height);
|
||||||
[self drawRepresentation: rep inRect: rect];
|
[self drawRepresentation: rep inRect: rect];
|
||||||
}
|
}
|
||||||
|
@ -1201,7 +1212,7 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
|
|
||||||
- (void) lockFocusOnRepresentation: (NSImageRep *)imageRep
|
- (void) lockFocusOnRepresentation: (NSImageRep *)imageRep
|
||||||
{
|
{
|
||||||
// FIXME: THis should rather use
|
// FIXME: This should rather use
|
||||||
// [NSGraphicsContext graphicsContextWithBitmapImageRep:]
|
// [NSGraphicsContext graphicsContextWithBitmapImageRep:]
|
||||||
if (_cacheMode != NSImageCacheNever)
|
if (_cacheMode != NSImageCacheNever)
|
||||||
{
|
{
|
||||||
|
@ -1211,8 +1222,8 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
if (imageRep == nil)
|
if (imageRep == nil)
|
||||||
imageRep = [self bestRepresentationForDevice: nil];
|
imageRep = [self bestRepresentationForDevice: nil];
|
||||||
|
|
||||||
imageRep = [self _cacheForRep: imageRep];
|
repd = [self _cacheForRep: imageRep];
|
||||||
repd = repd_for_rep(_reps, imageRep);
|
imageRep = repd->rep;
|
||||||
|
|
||||||
window = [(NSCachedImageRep *)imageRep window];
|
window = [(NSCachedImageRep *)imageRep window];
|
||||||
_lockedView = [window contentView];
|
_lockedView = [window contentView];
|
||||||
|
@ -1818,16 +1829,14 @@ iterate_reps_for_types(NSArray* imageReps, SEL method)
|
||||||
// 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
|
- (NSCachedImageRep *) _doImageCache: (NSImageRep *)rep
|
||||||
{
|
{
|
||||||
NSImageRep *rep = [self bestRepresentationForDevice: nil];
|
|
||||||
|
|
||||||
if (_cacheMode != NSImageCacheNever)
|
|
||||||
{
|
|
||||||
GSRepData *repd;
|
GSRepData *repd;
|
||||||
|
|
||||||
rep = [self _cacheForRep: rep];
|
repd = [self _cacheForRep: rep];
|
||||||
repd = repd_for_rep(_reps, rep);
|
rep = repd->rep;
|
||||||
|
if ([rep isKindOfClass: cachedClass] == NO)
|
||||||
|
return nil;
|
||||||
|
|
||||||
NSDebugLLog(@"NSImage", @"Cached image rep is %p", rep);
|
NSDebugLLog(@"NSImage", @"Cached image rep is %p", rep);
|
||||||
/*
|
/*
|
||||||
|
@ -1859,22 +1868,27 @@ iterate_reps_for_types(NSArray* imageReps, SEL method)
|
||||||
{
|
{
|
||||||
[rep setOpaque: [repd->original isOpaque]];
|
[rep setOpaque: [repd->original isOpaque]];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSDebugLLog(@"NSImage", @"Rendered rep %p on background %@",
|
NSDebugLLog(@"NSImage", @"Rendered rep %p on background %@",
|
||||||
rep, repd->bg);
|
rep, repd->bg);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return rep;
|
return (NSCachedImageRep *)rep;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSImageRep*) _cacheForRep: (NSImageRep*)rep
|
- (GSRepData*) _cacheForRep: (NSImageRep*)rep
|
||||||
{
|
{
|
||||||
|
if ([rep isKindOfClass: cachedClass] == YES)
|
||||||
|
{
|
||||||
|
return repd_for_rep(_reps, rep);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* If this is not a cached image rep - create a cache to be used to
|
* If this is not a cached image rep - try to find the cache rep
|
||||||
|
* for this image rep. If none is found 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: cachedClass] == NO)
|
|
||||||
{
|
|
||||||
NSImageRep *cacheRep = nil;
|
NSImageRep *cacheRep = nil;
|
||||||
unsigned count = [_reps count];
|
unsigned count = [_reps count];
|
||||||
|
|
||||||
|
@ -1906,18 +1920,21 @@ iterate_reps_for_types(NSArray* imageReps, SEL method)
|
||||||
{
|
{
|
||||||
if (repd->bg == nil)
|
if (repd->bg == nil)
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"NSImage", @"Invalid %@ ... %@ %d", repd->bg, _color, repd->rep);
|
NSDebugLLog(@"NSImage", @"Invalid %@ ... %@ %d",
|
||||||
|
repd->bg, _color, repd->rep);
|
||||||
invalidCache = repd;
|
invalidCache = repd;
|
||||||
}
|
}
|
||||||
else if (opaque == YES || [repd->bg isEqual: _color] == YES)
|
else if (opaque == YES || [repd->bg isEqual: _color] == YES)
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"NSImage", @"Exact %@ ... %@ %d", repd->bg, _color, repd->rep);
|
NSDebugLLog(@"NSImage", @"Exact %@ ... %@ %d",
|
||||||
|
repd->bg, _color, repd->rep);
|
||||||
validCache = repd;
|
validCache = repd;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"NSImage", @"Partial %@ ... %@ %d", repd->bg, _color, repd->rep);
|
NSDebugLLog(@"NSImage", @"Partial %@ ... %@ %d",
|
||||||
|
repd->bg, _color, repd->rep);
|
||||||
partialCache = repd;
|
partialCache = repd;
|
||||||
partialCount++;
|
partialCount++;
|
||||||
}
|
}
|
||||||
|
@ -1926,7 +1943,7 @@ NSDebugLLog(@"NSImage", @"Partial %@ ... %@ %d", repd->bg, _color, repd->rep);
|
||||||
|
|
||||||
if (validCache != nil)
|
if (validCache != nil)
|
||||||
{
|
{
|
||||||
if (NSImageForceCaching == NO && [rep isOpaque] == NO)
|
if (NSImageForceCaching == NO && opaque == NO)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If the image rep is not opaque and we are drawing
|
* If the image rep is not opaque and we are drawing
|
||||||
|
@ -1941,6 +1958,8 @@ NSDebugLLog(@"NSImage", @"Partial %@ ... %@ %d", repd->bg, _color, repd->rep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cacheRep = validCache->rep;
|
cacheRep = validCache->rep;
|
||||||
|
if (cacheRep != nil)
|
||||||
|
return validCache;
|
||||||
}
|
}
|
||||||
else if (partialCache != nil && partialCount > 2)
|
else if (partialCache != nil && partialCount > 2)
|
||||||
{
|
{
|
||||||
|
@ -1949,7 +1968,7 @@ NSDebugLLog(@"NSImage", @"Partial %@ ... %@ %d", repd->bg, _color, repd->rep);
|
||||||
* a few partial matches - otherwise we fall default to
|
* a few partial matches - otherwise we fall default to
|
||||||
* creating a new cache.
|
* creating a new cache.
|
||||||
*/
|
*/
|
||||||
if (NSImageForceCaching == NO && [rep isOpaque] == NO)
|
if (NSImageForceCaching == NO && opaque == NO)
|
||||||
{
|
{
|
||||||
if (invalidCache != nil)
|
if (invalidCache != nil)
|
||||||
{
|
{
|
||||||
|
@ -1966,15 +1985,19 @@ NSDebugLLog(@"NSImage", @"Partial %@ ... %@ %d", repd->bg, _color, repd->rep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cacheRep = partialCache->rep;
|
cacheRep = partialCache->rep;
|
||||||
|
if (cacheRep != nil)
|
||||||
|
return partialCache;
|
||||||
}
|
}
|
||||||
else if (invalidCache != nil)
|
else if (invalidCache != nil)
|
||||||
{
|
{
|
||||||
cacheRep = invalidCache->rep;
|
cacheRep = invalidCache->rep;
|
||||||
|
if (cacheRep != nil)
|
||||||
|
return invalidCache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cacheRep == nil)
|
if (cacheRep == nil)
|
||||||
{
|
{
|
||||||
NSScreen *cur = [NSScreen mainScreen];
|
|
||||||
NSSize imageSize;
|
NSSize imageSize;
|
||||||
GSRepData *repd;
|
GSRepData *repd;
|
||||||
|
|
||||||
|
@ -1982,20 +2005,25 @@ NSDebugLLog(@"NSImage", @"Partial %@ ... %@ %d", repd->bg, _color, repd->rep);
|
||||||
if (imageSize.width == 0 || imageSize.height == 0)
|
if (imageSize.width == 0 || imageSize.height == 0)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
cacheRep = [[cachedClass alloc] initWithSize: _size
|
// Create a new cached image rep without any contents.
|
||||||
depth: [cur depth]
|
cacheRep = [[cachedClass alloc]
|
||||||
|
initWithSize: _size
|
||||||
|
depth: [[NSScreen mainScreen] depth]
|
||||||
separate: NO
|
separate: NO
|
||||||
alpha: NO];
|
alpha: NO];
|
||||||
[self addRepresentation: cacheRep];
|
repd = [GSRepData new];
|
||||||
RELEASE(cacheRep); /* Retained in _reps array. */
|
repd->rep = cacheRep;
|
||||||
repd = repd_for_rep(_reps, cacheRep);
|
|
||||||
repd->original = rep;
|
repd->original = rep;
|
||||||
}
|
[_reps addObject: repd];
|
||||||
return cacheRep;
|
RELEASE(repd); /* Retained in _reps array. */
|
||||||
|
|
||||||
|
return repd;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return rep;
|
// I don't think we ever reach this line.
|
||||||
|
return repd_for_rep(_reps, cacheRep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue