/* NSImage.m Load, manipulate and display images Copyright (C) 1996 Free Software Foundation, Inc. This file is part of the mySTEP Library and is provided under the terms of the GNU Library General Public License. */ #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import "NSBackendPrivate.h" // Class variables static NSMutableDictionary *__nameToImageDict = nil; @implementation NSImage + (void) initialize { __nameToImageDict = [[NSMutableDictionary alloc] initWithCapacity: 10]; [NSBitmapImageRep class]; // initialize NSBitmapImageRep class now } + (id) imageNamed:(NSString*)aName { // locate by name or load from main bundle NSImage *image; if([aName length] == 0) return nil; // there is no unnamed image... if([aName isEqualToString:NSApplicationIcon]) { // try to load application icon NSString *subst=[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIconFile"]; // replace from Info.plist if([subst length] > 0) aName=subst; // try to load } if((image = [__nameToImageDict objectForKey:aName])) { // found a record in cache if([image isKindOfClass:[NSNull class]]) return nil; // we know that we don't know... return image; } image=[self _imageNamed:aName inBundle:[NSBundle mainBundle]]; if(!image) { #if 0 NSLog(@"could not find NSImage -imageNamed:%@", aName); #endif [__nameToImageDict setObject:[NSNull null] forKey:aName]; // save a tag that we don't know the image } return image; } + (id) _imageNamed:(NSString*)aName inBundle:(NSBundle *) bundle; { // locate in specific bundle (e.g. a loaded bundle) and then in AppKit.framework NSString *name; NSString *path; NSEnumerator *e; NSString *ext; NSArray *fileTypes; NSImage *image; #if 0 NSLog(@"load imageNamed %@ inBundle %@", aName, bundle); #endif ext = [aName pathExtension]; // dict search for it fileTypes = [NSImageRep imageFileTypes]; #if 0 NSLog(@"ext = %@ imageFileTypes = %@", ext, fileTypes); #endif if([fileTypes containsObject:ext]) { // known extension name = [aName stringByDeletingPathExtension]; // has a supported extension path = [bundle pathForResource:name ofType:ext]; // look up #if 0 NSLog(@"name = %@", name); NSLog(@"ext = %@", ext); NSLog(@"path = %@", path); #endif } else { // keep full name name = aName; path = nil; } if(!path) { // name does not have a supported ext: search for the image locally (mainBundle) id o; ext=nil; // ignore extension e = [fileTypes objectEnumerator]; while((o = [e nextObject])) { #if 0 NSLog(@"try %@: %@.%@", [bundle bundlePath], name, o); #endif if((path = [bundle pathForResource:name ofType:o])) break; } } if(!path) { // If not found in app bundle search for image in system bundle=[NSBundle bundleForClass:[self class]]; // look up in AppKit.framework if(ext) path = [bundle pathForResource:name ofType:ext]; else { // try all extensions we know id o; e = [fileTypes objectEnumerator]; while((o = [e nextObject])) { #if 0 NSLog(@"try %@: %@.%@", [bundle bundlePath], name, o); #endif if((path = [bundle pathForResource:name ofType:o])) break; } } } #if 0 NSLog(@"found %@ at path=%@ in bundle %@", aName, path, bundle); #endif image=nil; if(path && (image = [[NSImage alloc] initByReferencingFile:path])) { // file really exists [image setName:aName]; // will save in __nameToImageDict - and increment retain count #if 0 NSLog(@"NSImage: -imageNamed:%@ -> %@", aName, image); #endif [image autorelease]; // don't leak if everything is released - unfortunately we are never deleted from the image cache } return image; } + (BOOL) canInitWithPasteboard:(NSPasteboard*)pasteboard { // FIX ME: Implement NSArray *array = [NSImageRep registeredImageRepClasses]; int i, count = [array count]; for (i = 0; i < count; i++) if ([[array objectAtIndex: i] canInitWithPasteboard: pasteboard]) return YES; return NO; } + (NSArray*) imageFileTypes { return [NSImageRep imageFileTypes]; } + (NSArray*) imageUnfilteredFileTypes { return [NSImageRep imageUnfilteredFileTypes]; } + (NSArray*) imagePasteboardTypes { return [NSImageRep imagePasteboardTypes]; } + (NSArray*) imageUnfilteredPasteboardTypes { return [NSImageRep imageUnfilteredPasteboardTypes]; } - (id) init { return [self initWithSize: NSZeroSize]; } - (id) initWithSize:(NSSize)aSize // Designated init { if((self=[super init])) { _reps = [NSMutableArray new]; if(aSize.width && aSize.height) { _size = aSize; _alignmentRect = (NSRect) { NSZeroPoint, _size }; _img.sizeWasExplicitlySet = YES; } _img.prefersColorMatch = YES; _img.multipleResolutionMatching = YES; #if 0 NSLog(@"NSImage initWithSize"); #endif _backgroundColor=[[NSColor clearColor] retain]; // default background is transparent #if 0 NSLog(@"NSImage initWithSize color=%@", _backgroundColor); #endif } return self; } - (id) initByReferencingFile:(NSString*)fileName { // must have explicitly an extension NSString *e = [fileName pathExtension]; #if 0 NSLog(@"NSImage initByReferencingFile:%@", fileName); #endif if (!e || ([[NSImageRep imageFileTypes] indexOfObject:e] == NSNotFound)) { // no extension or is not recognized by type [self release]; return nil; } if((self=[self initWithSize:NSZeroSize])) { _img.dataRetained = YES; _imageFilePath = [fileName retain]; } #if 0 NSLog(@"NSImage initByReferencingFile -> %@", self); #endif return self; } - (id) initWithContentsOfFile:(NSString*)fileName { if((self=[self initByReferencingFile:fileName])) { if(![self isValid]) { // wasn't able to load [self release]; return nil; } } return self; } - (id) initWithData:(NSData*)data { if((self=[self initWithSize: NSZeroSize])) { _data=[data retain]; if(![self isValid]) { // wasn't able to load [self release]; return nil; } } return self; } - (id) initWithPasteboard:(NSPasteboard*)pasteboard { return NIMP } - (void) dealloc { [_data release]; [_reps release]; [_cache release]; if(_name && self == [__nameToImageDict objectForKey: _name]) [__nameToImageDict removeObjectForKey:_name]; // only if we are not a copy with the same name [_name release]; [_backgroundColor release]; [super dealloc]; } - (id) copyWithZone:(NSZone *) zone { NSImage *copy = [isa allocWithZone:zone]; if(!_img.isValid) { } // copy instance variables copy->_name = [_name retain]; copy->_imageFilePath = [_imageFilePath retain]; copy->_reps = [_reps mutableCopy]; copy->_backgroundColor = [_backgroundColor retain]; copy->_size = _size; copy->_alignmentRect = _alignmentRect; copy->_delegate = [_delegate retain]; copy->_img = _img; // copy all image flags [copy recache]; return copy; } - (void) lockFocus { // lock focus on cache NSGraphicsContext *ctxt; #if 1 NSLog(@"lockFocus: %@", self); #endif // here we should also check the caching mode settings if(!_cache) { // create cache _cache=[[NSCachedImageRep alloc] initWithSize:_size depth:0 separate:_img.cacheSeparately alpha:YES]; if(!_cache) [NSException raise:NSImageCacheException format:@"can't create cached image representation"]; [[_cache window] _allocateGraphicsContext]; } [NSGraphicsContext saveGraphicsState]; ctxt=[[_cache window] graphicsContext]; [NSGraphicsContext setCurrentContext:ctxt]; // [ctxt _setCTM: ...] define CTM so that we really draw into the cache tile, i.e. move the origin - any maybe we need to flip [ctxt _addClip:[NSBezierPath bezierPathWithRect:[_cache rect]] reset:YES]; } - (void) lockFocusOnRepresentation:(NSImageRep *) imageRep; { // this method should have been called -lockFocusAndDrawRepresentation: [self lockFocus]; [imageRep drawInRect:(NSRect) { NSZeroPoint, [self size]}]; // draw (if specified) } - (void) unlockFocus { [NSGraphicsContext restoreGraphicsState]; } - (void) setMatchesOnMultipleResolution:(BOOL)flag { _img.multipleResolutionMatching = flag; } - (BOOL) matchesOnMultipleResolution { return _img.multipleResolutionMatching; } - (BOOL) setName:(NSString*)string { if(!string || [__nameToImageDict objectForKey: string]) return NO; // if already in dictionary ASSIGN(_name, string); [__nameToImageDict setObject:self forKey:_name]; // save in dictionary return YES; } - (NSString*) name { return _name; } - (void) setPrefersColorMatch:(BOOL)flag { _img.prefersColorMatch = flag; } - (void) setCachedSeparately:(BOOL)flag { _img.cacheSeparately = flag; } - (void) setDataRetained:(BOOL)flag { _img.dataRetained = flag; } - (void) setFlipped:(BOOL)flag { _img.flipDraw = flag; } - (BOOL) prefersColorMatch { return _img.prefersColorMatch; } - (BOOL) isCachedSeparately { return _img.cacheSeparately; } - (BOOL) isDataRetained { return _img.dataRetained; } - (BOOL) isFlipped { return _img.flipDraw; } - (BOOL) cacheDepthMatchesImageDepth { return _img.unboundedCacheDepth;} - (BOOL) scalesWhenResized { return _img.scalable; } - (void) setScalesWhenResized:(BOOL)flag { _img.scalable = flag; } - (NSString *) description; { return [NSString stringWithFormat:@"NSImage: name=%@ size=%@ %@%@%@", _name, NSStringFromSize(_size), _img.scalable?@" scalable":@"", _img.isValid?@" valid":@"", _img.flipDraw?@" flipped":@"", _img.scalable?@" scalesWhenResized":@"", _img.cacheSeparately?@" cachedSeparately":@"", _img.dataRetained?@" dataRetained":@"", nil ]; } - (void) setCacheDepthMatchesImageDepth:(BOOL)flag { _img.unboundedCacheDepth = flag; } - (void) recache { [_cache release]; _cache=nil; } - (NSImageRep *) _cachedOrBestRep; { // return the image rep - cached if necessary NSImageRep *bestRep; if(_cache) return _cache; // we have a cached rep bestRep=[self bestRepresentationForDevice:nil]; if(!bestRep) return nil; // can't cache switch(_img.cacheMode) { case NSImageCacheDefault: case NSImageCacheNever: return (NSCachedImageRep *) bestRep; // use the original case NSImageCacheBySize: // check size: // case NSImageCacheDefault: case NSImageCacheAlways: default: break; } if([bestRep isKindOfClass:[NSCachedImageRep class]]) _cache=[bestRep retain]; // just save the reference else { // draw into new cache [self lockFocusOnRepresentation:bestRep]; // render into cache window [self unlockFocus]; } return _cache; } - (void) setBackgroundColor:(NSColor*)color { ASSIGN(_backgroundColor, color); } - (NSColor*) backgroundColor { return _backgroundColor; } - (NSArray*) representations { return _reps; } - (void) setDelegate:(id)anObject { ASSIGN(_delegate, anObject); } - (id) delegate { return _delegate; } - (void) setSize:(NSSize)aSize { #if 0 NSLog(@"setSize:%@", NSStringFromSize(aSize)); #endif if(NSEqualSizes(_size, aSize)) return; // effectively unchanged _size = aSize; _alignmentRect = (NSRect) { NSZeroPoint, _size }; _img.sizeWasExplicitlySet = YES; if(_data) _img.isValid=NO; // reload from data since it is still available [self recache]; // recache } - (NSSize) size { if(!_img.sizeWasExplicitlySet && _size.width == 0) { // determine from best representation if possible NSImageRep *best; if(!_img.isValid) [self isValid]; // try to load reps first // FIXME: we should determine from all reps not only the best for an unknown device best=[self bestRepresentationForDevice: nil]; if(best) { _size = [best size]; _alignmentRect = (NSRect) { NSZeroPoint, _size }; } else NSLog(@"there is no best representation"); #if 0 NSLog(@"image %@ best %@: size=%@", _name, best, NSStringFromSize(_size)); #endif } return _size; } - (void) drawAtPoint:(NSPoint)point fromRect:(NSRect)src operation:(NSCompositingOperation)op fraction:(float)fraction; { [self drawInRect:(NSRect){point, src.size} // not scaled fromRect:src operation:op fraction:fraction]; } - (void) drawInRect:(NSRect)dest fromRect:(NSRect)src operation:(NSCompositingOperation)op fraction:(float)fraction; { // contrary to composite: we don't ignore rotation here! NSGraphicsContext *ctx=[NSGraphicsContext currentContext]; NSAffineTransform *atm=[NSAffineTransform transform]; static NSBezierPath *unitSquare=nil; NSCompositingOperation co; if(!_img.isValid) [self isValid]; // Make sure we have the image reps loaded in - if possible if(src.size.width <= 0.0 || src.size.height <= 0.0) src.size=_size; // use image size if(dest.size.width <= 0.0 || dest.size.height <= 0.0) dest.size=_size; // use image size [ctx saveGraphicsState]; co=[ctx compositingOperation]; // save [ctx setCompositingOperation:op]; [ctx _setFraction:fraction]; if(_img.flipDraw) { // scaleXBy:1.0 yBy:-1.0 NSLog(@"should flip drawInRect: %@", self); } [atm translateXBy:dest.origin.x-src.origin.x yBy:dest.origin.y-src.origin.y]; [atm scaleXBy:dest.size.width yBy:dest.size.height]; // will draw to unit square if(!NSEqualSizes(src.size, _size)) [atm scaleXBy:_size.width/src.size.width yBy:_size.height/src.size.height]; // additional scaling [ctx _concatCTM:atm]; // add to CTM as needed if(!unitSquare) unitSquare=[[NSBezierPath bezierPathWithRect:NSMakeRect(0.0, 0.0, 1.0, 1.0)] retain]; [ctx _addClip:unitSquare reset:NO]; // set CTM as needed // [ctx _draw:[self bestRepresentationForDevice:nil]]; [ctx _draw:[self _cachedOrBestRep]]; [ctx setCompositingOperation:co]; [ctx restoreGraphicsState]; } - (void) dissolveToPoint:(NSPoint)p fraction:(float)f { [self compositeToPoint:p fromRect:(NSRect){{0,0},_size} operation:NSCompositeSourceOver fraction:f]; } - (void) dissolveToPoint:(NSPoint)p fromRect:(NSRect)s fraction:(float)f { [self compositeToPoint:p fromRect:s operation:NSCompositeSourceOver fraction:f]; } - (void) compositeToPoint:(NSPoint)pnt // Draw the Image operation:(NSCompositingOperation)op { [self compositeToPoint:pnt fromRect:(NSRect){{0,0},_size} operation:op fraction:1.0]; } - (void) compositeToPoint:(NSPoint)pnt // Draw the Image operation:(NSCompositingOperation)op fraction:(float)fraction; { [self compositeToPoint:pnt fromRect:(NSRect){{0,0},_size} operation:op fraction:fraction]; } - (void) compositeToPoint:(NSPoint)pnt fromRect:(NSRect)rect operation:(NSCompositingOperation)op { [self compositeToPoint:pnt fromRect:(NSRect){{0,0},_size} operation:op fraction:1.0]; } - (void) compositeToPoint:(NSPoint)pnt fromRect:(NSRect)src operation:(NSCompositingOperation)op fraction:(float)fraction { // this is the most generic composite/dissolve method - modify CTM before calling this method to translate to point // for maximum compatibility, this function has to ignore rotation and scaling of the CTM! // see e.g.: http://www.stone.com/The_Cocoa_Files/Cocoamotion.html static NSBezierPath *unitSquare=nil; NSGraphicsContext *ctx=[NSGraphicsContext currentContext]; NSAffineTransform *atm=[NSAffineTransform transform]; NSCompositingOperation co; if(!_img.isValid) [self isValid]; // Make sure we have the image reps loaded in - if possible if(src.size.width <= 0.0 || src.size.height <= 0.0) src.size=_size; // use image size [ctx saveGraphicsState]; co=[ctx compositingOperation]; // save [ctx setCompositingOperation:op]; [ctx _setFraction:fraction]; if(_img.flipDraw) NSLog(@"should flip compositeToPoint: %@", self); ; // FIXME: scaleXBy:1.0 yBy:-1.0 // FIXME: do we have to scale src.origin? [atm translateXBy:pnt.x-src.origin.x yBy:pnt.y-src.origin.y]; [atm scaleXBy:src.size.width yBy:src.size.height]; // will draw the src rect to unit square [ctx _concatCTM:atm]; // add to CTM as needed // FIXME: somehow remove any rotation if(!unitSquare) unitSquare=[[NSBezierPath bezierPathWithRect:NSMakeRect(0.0, 0.0, 1.0, 1.0)] retain]; [ctx _addClip:unitSquare reset:NO]; // set CTM as needed // [ctx _draw:[self bestRepresentationForDevice:nil]]; [ctx _draw:[self _cachedOrBestRep]]; [ctx setCompositingOperation:co]; // restore [ctx restoreGraphicsState]; } - (BOOL) drawRepresentation:(NSImageRep*)imageRep inRect:(NSRect)rect { #if 0 NSLog(@"%@ drawRepresentation:%@ inRect:%@", self, imageRep, NSStringFromRect(rect)); #endif if(!_img.scalable) { if([imageRep drawAtPoint:rect.origin]) return YES; rect.size = _size; } else if([imageRep drawInRect:rect]) return YES; if(_delegate && [_delegate respondsToSelector:@selector(imageDidNotDraw:inRect:)]) { NSImage *a; if ((a = [_delegate imageDidNotDraw:self inRect:rect])) { NSImageRep *rp = [a bestRepresentationForDevice:nil]; // FIXME return [a drawRepresentation:rp inRect:rect]; } } return NO; } - (void) addRepresentation:(NSImageRep *)imageRep { [_reps addObject:imageRep]; } - (void) addRepresentations:(NSArray *)imageRepArray { if (imageRepArray) [_reps addObjectsFromArray:imageRepArray]; } - (void) removeRepresentation:(NSImageRep *)imageRep { [_reps removeObjectIdenticalTo:imageRep]; } - (BOOL) isValid { if(!_img.isValid) { NSArray *reps=nil; #if 0 NSLog(@"load image representation(s) (at path: %@)", _imageFilePath); #endif if(_imageFilePath) { // (re)load from path if possible reps = [NSImageRep imageRepsWithContentsOfFile:_imageFilePath]; if(!reps) NSLog(@"could not load image at path: %@", _imageFilePath); } else if(_data) { // (re)load from data Class rep = [NSImageRep imageRepClassForData:_data]; // find appropriate handler class if(rep) { if([rep respondsToSelector: @selector(imageRepsWithData:)]) reps = [rep imageRepsWithData:_data]; // returns multiple reps else { // single rep NSImageRep *image; if((image = [rep imageRepWithData:_data])) reps=[NSArray arrayWithObject:image]; } } if(!_img.dataRetained) { // free [_data release]; _data=nil; } } else // we have been created by -initWithSize: - create a cached image to draw into reps=[NSArray arrayWithObject:[[[NSCachedImageRep alloc] initWithSize:_size depth:0 separate:_img.cacheSeparately alpha:YES] autorelease]]; if(!reps) { if(_imageFilePath) NSLog(@"could not load representations from file %@", _imageFilePath); else NSLog(@"could not load representations from NSData"); return NO; } [self addRepresentations:reps]; if(_img.sizeWasExplicitlySet) { NSEnumerator *e=[reps objectEnumerator]; NSImageRep *r; while((r=[e nextObject])) [r setSize:_size]; // resize representation(s) } if([_reps count]) _img.isValid = YES; // any valid representation have been loaded } #if 0 NSLog(@"image valid %d", _img.isValid); #endif return _img.isValid; } - (int) _scoreRepresentation:(NSImageRep *) r forDevice:(NSDictionary *) deviceDescription; { int score=0; int imageResolution, deviceResolution; int bpp; // bits per plane if([r isKindOfClass:[NSCachedImageRep class]]) return -1; // ignore in scoring process if(!_img.prefersColorMatch) ; // reverse rule 1 and 2 by reversing the high scores #if 0 NSLog(@"score %@: %@", NSStringFromClass([r class]), r); #endif // Rule 1: if(![r respondsToSelector:@selector(numberOfPlanes)]) { // not a bitmap rep - assume we are an EPS if(!_img.usesEPSOnResolutionMismatch) return -1; // never use EPS as best one score=1; // use EPS if nothing else works } if([(NSBitmapImageRep *) r numberOfPlanes] < 3) { // b&w image rep score += 0; } else { // prefer color image rep over b&w unless we know that we have a b&w display score += 100; // we assume to have a color display... } // Rule 2: // FIXME: imageResolution is MIN([r pixelsWide]/size.width, [r pixelsHigh]/size.height) imageResolution=300; // how to get that from ImageRep??? deviceResolution=72; // get from deviceDescription if(imageResolution%deviceResolution == 0 && _img.multipleResolutionMatching) score += 500000; // Jackpot else if(imageResolution == deviceResolution) score += 500000; // exact match score += 10*imageResolution; // score better resolution higher // Rule 3: bpp=[(NSBitmapImageRep *) r bitsPerPixel]; if(bpp == 8) score += 50; // depth match else score += bpp; // score higher depth better return score; } - (NSImageRep *) bestRepresentationForDevice:(NSDictionary *) deviceDescription { int highScore; NSEnumerator *e; NSImageRep *r; NSImageRep *_bestRep; // best representation of all if(!_img.isValid && ![self isValid]) return nil; // Make sure we have the image reps loaded in - if possible #if 0 NSLog(@"representations: %@ %@", self, _reps); #endif _bestRep=nil; highScore=-1; // use any -1 score if no other is found e=[_reps reverseObjectEnumerator]; while((r=[e nextObject])) { int newScore=[self _scoreRepresentation:r forDevice:deviceDescription]; #if 0 NSLog(@"score %d for %@", newScore, r); #endif if(newScore > highScore) { // found a better one than before _bestRep=r; highScore=newScore; } } if(!_img.sizeWasExplicitlySet && _bestRep) { _size = [_bestRep size]; _alignmentRect = (NSRect) { NSZeroPoint, _size }; } #if 0 NSLog(@"_bestRep: %@ size:%@", _bestRep, NSStringFromSize(_size)); #endif if(!_bestRep) NSLog(@"no best rep found for %@ in %@", deviceDescription, _reps); return _bestRep; } - (NSData *) TIFFRepresentation { return [self TIFFRepresentationUsingCompression:NSTIFFCompressionLZW factor:0.0]; } - (NSData *) TIFFRepresentationUsingCompression:(NSTIFFCompression)comp factor:(float)aFloat { // forward to best rep? // check if we have any bitmap rep // then, get TIFF from there // else get TIFF from cached rep return NIMP; } - (NSRect) alignmentRect; { return _alignmentRect; } - (NSImageCacheMode) cacheMode; { return _img.cacheMode; } - (BOOL) isTemplate; { return _img.isTemplate; } - (BOOL) usesEPSOnResolutionMismatch; { return _img.usesEPSOnResolutionMismatch; } - (void) setAlignmentRect:(NSRect) rect; { _alignmentRect=rect; } - (void) setCacheMode:(NSImageCacheMode) mode; { _img.cacheMode=mode; } - (void) setTemplate:(BOOL) flag; { _img.isTemplate=flag; } - (void) setUsesEPSOnResolutionMismatch:(BOOL)flag; { _img.usesEPSOnResolutionMismatch=flag; } - (id) initByReferencingURL:(NSURL*)url; { return NIMP; } - (id) initWithContentsOfURL:(NSURL*)url; { return NIMP; } - (void) cancelIncrementalLoad; { return; // ignored } - (id) awakeAfterUsingCoder:(NSCoder*)aDecoder { if(_name && [__nameToImageDict objectForKey:_name]) { // [self release]; --- we are always named and stored in the nameToImageDict return [__nameToImageDict objectForKey:_name]; } return self; } - (void) encodeWithCoder:(NSCoder*)coder { NIMP; } // NSCoding Protocol - (id) initWithCoder:(NSCoder*)coder { if([coder allowsKeyedCoding]) { unsigned int iflags=[coder decodeIntForKey:@"NSImageFlags"]; #define SCALABLE ((iflags&0x8000000) != 0) _img.scalable=SCALABLE; #define SIZESET ((iflags&0x2000000) != 0) _img.sizeWasExplicitlySet=SIZESET; #define USEEPS ((iflags&0x0200000) != 0) _img.usesEPSOnResolutionMismatch=USEEPS; #define COLORMATCHPREFERRED ((iflags&0x0100000) != 0) _img.prefersColorMatch=COLORMATCHPREFERRED; #define MULTIRESMATCH ((iflags&0x0080000) != 0) _img.multipleResolutionMatching=MULTIRESMATCH; #define FLIPPED ((iflags&0x0008000) != 0) _img.flipDraw=FLIPPED; #define ALIASED ((iflags&0x0004000) != 0) #define CACHEMODE ((iflags&0x0001800) >> 11) _img.cacheMode=CACHEMODE; _size=[coder decodeSizeForKey:@"NSSize"]; _alignmentRect = (NSRect) { NSZeroPoint, _size }; _backgroundColor=[[coder decodeObjectForKey:@"NSColor"] retain]; if([coder containsValueForKey:@"NSReps"]) { _reps=[[coder decodeObjectForKey:@"NSReps"] retain]; // load array of reps // FIXME: we should only ignore cached image reps // sometimes a NIB encodes a TIFFRepresentation #if 0 NSLog(@"NSImage initWithCoder ignores archived reps _reps=%@", _reps); #endif [_reps release]; _reps = [NSMutableArray new]; // _img.isValid=YES; // [self release]; // return nil; // IB stores the Image Reps of Checkbox icons explicitly } else _reps = [NSMutableArray new]; return self; } NSLog(@"NSImage: can't initWithCoder"); [self release]; return nil; } @end