Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: third_party/icon_family/IconFamily.m

Issue 9380039: Add IconFamily library to third_party (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/icon_family/IconFamily.h ('k') | third_party/icon_family/LICENSE » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // IconFamily.m
2 // IconFamily class implementation
3 // by Troy Stephens, Thomas Schnitzer, David Remahl, Nathan Day, Ben Haller, Sve n Janssen, Peter Hosey, Conor Dearden, Elliot Glaysher, and Dave MacLachlan
4 // version 0.9.4
5 //
6 // Project Home Page:
7 // http://iconfamily.sourceforge.net/
8 //
9 // Problems, shortcomings, and uncertainties that I'm aware of are flagged with "NOTE:". Please address bug reports, bug fixes, suggestions, etc. to the projec t Forums and bug tracker at https://sourceforge.net/projects/iconfamily/
10
11 /*
12 Copyright (c) 2001-2010 Troy N. Stephens
13 Portions Copyright (c) 2007 Google Inc.
14
15 Use and distribution of this source code is governed by the MIT License, who se terms are as follows.
16
17 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal i n the Software without restriction, including without limitation the rights to u se, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in a ll copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I MPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR C OPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #import "IconFamily.h"
25 #import "NSString+CarbonFSRefCreation.h"
26
27
28 @interface NSFileManager (IconFamilyCompatibility)
29
30 - (NSDictionary *) iconfamily_attributesAtPath:(NSString *)path;
31 - (BOOL) iconfamily_setAttributes:(NSDictionary *)attributes atPath:(NSString *) path;
32 - (BOOL) iconfamily_removeItemAtPath:(NSString *)path;
33
34 @end
35
36
37 @interface NSImage (IconFamilyCompatibility)
38
39 - (NSImageRep *) iconfamily_bestRepresentation;
40
41 @end
42
43
44 #if MAC_OS_X_VERSION_MAX_ALLOWED <= 1050
45 // Methods defined in 10.6 and beyond
46 @interface NSImage (SnowLeopard)
47
48 - (NSImageRep *)bestRepresentationForRect:(NSRect)rect context:(NSGraphicsContex t *)referenceContext hints:(NSDictionary *)hints;
49
50 @end
51 #endif
52
53
54 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
55 // This is defined in 10.5 and beyond in IconStorage.h
56 enum {
57 kIconServices512PixelDataARGB = 'ic09' /* non-premultiplied 512x512 ARGB bitma p*/
58 };
59
60 // Methods defined in 10.5 and beyond
61 @interface NSFileManager (Leopard)
62
63 - (NSDictionary *)attributesOfItemAtPath:(NSString *)path error:(NSError **)erro r;
64 - (BOOL)setAttributes:(NSDictionary *)attributes ofItemAtPath:(NSString *)path e rror:(NSError **)error;
65 - (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error;
66
67 @end
68 #endif
69
70 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_3
71 // This is defined in 10.4 and beyond in IconStorage.h
72 enum {
73 kIconServices256PixelDataARGB = 'ic08' /* non-premultiplied 256x256 ARGB bitma p*/
74 };
75 #endif
76
77 // Necessary on 10.5 for Preview's "New with Clipboard" menu item to see the Ico nFamily data.
78 #define ICONFAMILY_UTI @"com.apple.icns"
79 // Determined by using Pasteboard Manager to put com.apple.icns data on the clip board. Alternatively, you can determine this by copying an application to the cl ipboard using the Finder (select an application and press cmd-C).
80 #define ICONFAMILY_PBOARD_TYPE @"'icns' (CorePasteboardFlavorType 0x69636E73)"
81
82 @interface IconFamily (Internals)
83
84 + (NSImage*) resampleImage:(NSImage*)image toIconWidth:(int)width usingImageInte rpolation:(NSImageInterpolation)imageInterpolation;
85
86 + (Handle) get32BitDataFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requ iredPixelSize:(int)requiredPixelSize;
87
88 + (Handle) get8BitDataFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requi redPixelSize:(int)requiredPixelSize;
89
90 + (Handle) get8BitMaskFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requi redPixelSize:(int)requiredPixelSize;
91
92 + (Handle) get1BitMaskFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requi redPixelSize:(int)requiredPixelSize;
93
94 - (BOOL) addResourceType:(OSType)type asResID:(int)resID;
95
96 @end
97
98 @implementation IconFamily
99
100 + (IconFamily*) iconFamily
101 {
102 return [[[IconFamily alloc] init] autorelease];
103 }
104
105 + (IconFamily*) iconFamilyWithContentsOfFile:(NSString*)path
106 {
107 return [[[IconFamily alloc] initWithContentsOfFile:path] autorelease];
108 }
109
110 + (IconFamily*) iconFamilyWithIconOfFile:(NSString*)path
111 {
112 return [[[IconFamily alloc] initWithIconOfFile:path] autorelease];
113 }
114
115 + (IconFamily*) iconFamilyWithIconFamilyHandle:(IconFamilyHandle)hNewIconFamily
116 {
117 return [[[IconFamily alloc] initWithIconFamilyHandle:hNewIconFamily] autorel ease];
118 }
119
120 + (IconFamily*) iconFamilyWithSystemIcon:(int)fourByteCode
121 {
122 return [[[IconFamily alloc] initWithSystemIcon:fourByteCode] autorelease];
123 }
124
125 + (IconFamily*) iconFamilyWithThumbnailsOfImage:(NSImage*)image
126 {
127 return [[[IconFamily alloc] initWithThumbnailsOfImage:image] autorelease];
128 }
129
130 + (IconFamily*) iconFamilyWithThumbnailsOfImage:(NSImage*)image usingImageInterp olation:(NSImageInterpolation)imageInterpolation
131 {
132 return [[[IconFamily alloc] initWithThumbnailsOfImage:image usingImageInterp olation:imageInterpolation] autorelease];
133 }
134
135 // This is IconFamily's designated initializer. It creates a new IconFamily tha t initially has no elements.
136 //
137 // The proper way to do this is to simply allocate a zero-sized handle (not to b e confused with an empty handle) and assign it to hIconFamily. This technique w orks on Mac OS X 10.2 as well as on 10.0.x and 10.1.x. Our previous technique o f allocating an IconFamily struct with a resourceSize of 0 no longer works as of Mac OS X 10.2.
138 - init
139 {
140 self = [super init];
141 if (self) {
142 hIconFamily = (IconFamilyHandle) NewHandle( 0 );
143 if (hIconFamily == NULL) {
144 [self autorelease];
145 return nil;
146 }
147 }
148 return self;
149 }
150
151 - initWithData:(NSData *)data
152 {
153 self = [self init];
154 if (self) {
155 Handle storageMem = NULL;
156
157 OSStatus err = PtrToHand([data bytes], &storageMem, (long)[data length]) ;
158 if( err != noErr )
159 {
160 [self release];
161 return nil;
162 }
163
164 hIconFamily = (IconFamilyHandle)storageMem;
165 }
166 return self;
167 }
168
169 - initWithContentsOfFile:(NSString*)path
170 {
171 FSRef ref;
172 OSStatus result;
173
174 self = [self init];
175 if (self) {
176 if (hIconFamily) {
177 DisposeHandle( (Handle)hIconFamily );
178 hIconFamily = NULL;
179 }
180 if (![path getFSRef:&ref createFileIfNecessary:NO]) {
181 [self autorelease];
182 return nil;
183 }
184 result = ReadIconFromFSRef( &ref, &hIconFamily );
185 if (result != noErr) {
186 [self autorelease];
187 return nil;
188 }
189 }
190 return self;
191 }
192
193 - initWithIconFamilyHandle:(IconFamilyHandle)hNewIconFamily
194 {
195 self = [self init];
196 if (self) {
197 if (hIconFamily) {
198 DisposeHandle( (Handle)hIconFamily );
199 hIconFamily = NULL;
200 }
201 hIconFamily = hNewIconFamily;
202 }
203 return self;
204 }
205
206 - initWithIconOfFile:(NSString*)path
207 {
208 IconRef iconRef;
209 OSStatus result;
210 SInt16 label;
211 FSRef ref;
212
213 self = [self init];
214 if (self)
215 {
216 if (hIconFamily)
217 {
218 DisposeHandle( (Handle)hIconFamily );
219 hIconFamily = NULL;
220 }
221
222 if( ![path getFSRef:&ref createFileIfNecessary:NO] )
223 {
224 [self autorelease];
225 return nil;
226 }
227
228 result = GetIconRefFromFileInfo(
229 &ref,
230 /*inFileNameLength*/ 0,
231 /*inFileName*/ NULL,
232 kFSCatInfoNone,
233 /*inCatalogInfo*/ NULL,
234 kIconServicesNormalUsageFlag,
235 &iconRef,
236 &label );
237
238 if (result != noErr)
239 {
240 [self autorelease];
241 return nil;
242 }
243
244 result = IconRefToIconFamily(
245 iconRef,
246 kSelectorAllAvailableData,
247 &hIconFamily );
248
249 ReleaseIconRef( iconRef );
250
251 if (result != noErr || !hIconFamily)
252 {
253 [self autorelease];
254 return nil;
255 }
256 }
257 return self;
258 }
259
260 - initWithSystemIcon:(int)fourByteCode
261 {
262 IconRef iconRef;
263 OSErr result;
264
265 self = [self init];
266 if (self)
267 {
268 if (hIconFamily)
269 {
270 DisposeHandle( (Handle)hIconFamily );
271 hIconFamily = NULL;
272 }
273
274 result = GetIconRef(kOnSystemDisk, kSystemIconsCreator, fourByteCode, &i conRef);
275
276 if (result != noErr)
277 {
278 [self autorelease];
279 return nil;
280 }
281
282 result = IconRefToIconFamily(
283 iconRef,
284 kSelectorAllAvailableData,
285 &hIconFamily );
286
287 if (result != noErr || !hIconFamily)
288 {
289 [self autorelease];
290 return nil;
291 }
292
293 ReleaseIconRef( iconRef );
294 }
295 return self;
296 }
297
298 - initWithThumbnailsOfImage:(NSImage*)image
299 {
300 // The default is to use a high degree of antialiasing, producing a smooth i mage.
301 return [self initWithThumbnailsOfImage:image usingImageInterpolation:NSImage InterpolationHigh];
302 }
303
304 - initWithThumbnailsOfImage:(NSImage*)image usingImageInterpolation:(NSImageInte rpolation)imageInterpolation
305 {
306 NSImage* iconImage512x512;
307 NSImage* iconImage256x256;
308 NSImage* iconImage128x128;
309 NSImage* iconImage32x32;
310 NSImage* iconImage16x16;
311 NSImage* bitmappedIconImage512x512;
312 NSBitmapImageRep* iconBitmap512x512;
313 NSBitmapImageRep* iconBitmap256x256;
314 NSBitmapImageRep* iconBitmap128x128;
315 NSBitmapImageRep* iconBitmap32x32;
316 NSBitmapImageRep* iconBitmap16x16;
317
318 // Start with a new, empty IconFamily.
319 self = [self init];
320 if (self == nil)
321 return nil;
322
323 // Resample the given image to create a 512x512 pixel, 32-bit RGBA
324 // version, and use that as our "thumbnail" (512x512) icon and mask.
325 //
326 // Our +resampleImage:toIconWidth:... method, in its present form,
327 // returns an NSImage that contains an NSCacheImageRep, rather than
328 // an NSBitmapImageRep. We convert to an NSBitmapImageRep, so that
329 // our methods can scan the image data, using initWithFocusedViewRect:.
330 iconImage512x512 = [IconFamily resampleImage:image toIconWidth:512 usingImag eInterpolation:imageInterpolation];
331 if (!iconImage512x512) {
332 [self autorelease];
333 return nil;
334 }
335
336 [iconImage512x512 lockFocus];
337 iconBitmap512x512 = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMak eRect(0, 0, 512, 512)] autorelease];
338 [iconImage512x512 unlockFocus];
339 if (!iconBitmap512x512) {
340 [self release];
341 return nil;
342 }
343 // Create an NSImage with the iconBitmap512x512 NSBitmapImageRep, that we
344 // can resample to create the smaller icon family elements. (This is
345 // most likely more efficient than resampling from the original image again,
346 // particularly if it is large. It produces a slightly different result, bu t
347 // the difference is minor and should not be objectionable...)
348
349 bitmappedIconImage512x512 = [[NSImage alloc] initWithSize:NSMakeSize(512, 51 2)];
350 [bitmappedIconImage512x512 addRepresentation:iconBitmap512x512];
351
352 if (!bitmappedIconImage512x512) {
353 [self autorelease];
354 return nil;
355 }
356
357 [self setIconFamilyElement:kIconServices512PixelDataARGB fromBitmapImageRep: iconBitmap512x512];
358
359 iconImage256x256 = [IconFamily resampleImage:bitmappedIconImage512x512 toIco nWidth:256 usingImageInterpolation:imageInterpolation];
360 if (iconImage256x256) {
361 [iconImage256x256 lockFocus];
362 iconBitmap256x256 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMa keRect(0, 0, 256, 256)];
363 [iconImage256x256 unlockFocus];
364 if (iconBitmap256x256) {
365 [self setIconFamilyElement:kIconServices256PixelDataARGB fromBitmapImage Rep:iconBitmap256x256];
366 [iconBitmap256x256 release];
367 }
368 }
369
370 iconImage128x128 = [IconFamily resampleImage:bitmappedIconImage512x512 toIco nWidth:128 usingImageInterpolation:imageInterpolation];
371 if (iconImage128x128) {
372 [iconImage128x128 lockFocus];
373 iconBitmap128x128 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMa keRect(0, 0, 128, 128)];
374 [iconImage128x128 unlockFocus];
375
376 if (iconBitmap128x128) {
377 [self setIconFamilyElement:kThumbnail32BitData fromBitmapImageRep:iconBi tmap128x128];
378 [self setIconFamilyElement:kThumbnail8BitMask fromBitmapImageRep:iconBi tmap128x128];
379 [iconBitmap128x128 release];
380 }
381 }
382
383 // Resample the 512x512 image to create a 32x32 pixel, 32-bit RGBA version,
384 // and use that as our "large" (32x32) icon and 8-bit mask.
385 iconImage32x32 = [IconFamily resampleImage:bitmappedIconImage512x512 toIconW idth:32 usingImageInterpolation:imageInterpolation];
386 if (iconImage32x32) {
387 [iconImage32x32 lockFocus];
388 iconBitmap32x32 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMake Rect(0, 0, 32, 32)];
389 [iconImage32x32 unlockFocus];
390 if (iconBitmap32x32) {
391 [self setIconFamilyElement:kLarge32BitData fromBitmapImageRep:iconBitmap 32x32];
392 [self setIconFamilyElement:kLarge8BitData fromBitmapImageRep:iconBitmap3 2x32];
393 [self setIconFamilyElement:kLarge8BitMask fromBitmapImageRep:iconBitmap3 2x32];
394 [self setIconFamilyElement:kLarge1BitMask fromBitmapImageRep:iconBitmap3 2x32];
395 [iconBitmap32x32 release];
396 }
397 }
398
399 // Resample the 512x512 image to create a 16x16 pixel, 32-bit RGBA version,
400 // and use that as our "small" (16x16) icon and 8-bit mask.
401 iconImage16x16 = [IconFamily resampleImage:bitmappedIconImage512x512 toIconW idth:16 usingImageInterpolation:imageInterpolation];
402 if (iconImage16x16) {
403 [iconImage16x16 lockFocus];
404 iconBitmap16x16 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMake Rect(0, 0, 16, 16)];
405 [iconImage16x16 unlockFocus];
406 if (iconBitmap16x16) {
407 [self setIconFamilyElement:kSmall32BitData fromBitmapImageRep:iconBitmap 16x16];
408 [self setIconFamilyElement:kSmall8BitData fromBitmapImageRep:iconBitmap1 6x16];
409 [self setIconFamilyElement:kSmall8BitMask fromBitmapImageRep:iconBitmap1 6x16];
410 [self setIconFamilyElement:kSmall1BitMask fromBitmapImageRep:iconBitmap1 6x16];
411 [iconBitmap16x16 release];
412 }
413 }
414
415 // Release the icon.
416 [bitmappedIconImage512x512 release];
417
418 // Return the new icon family!
419 return self;
420 }
421
422 - (void) dealloc
423 {
424 DisposeHandle( (Handle)hIconFamily );
425 [super dealloc];
426 }
427
428 - (void) finalize
429 {
430 /* "Starting with Mac OS X v10.3, Memory Manager is thread safe"
431 -- Memory Manager Reference
432 */
433 DisposeHandle( (Handle)hIconFamily );
434 hIconFamily = NULL;
435
436 [super finalize];
437 }
438
439 - (NSBitmapImageRep*) bitmapImageRepWithAlphaForIconFamilyElement:(OSType)elemen tType
440 {
441 NSBitmapImageRep* bitmapImageRep;
442 int pixelsWide;
443 Handle hRawBitmapData;
444 Handle hRawMaskData = NULL;
445 OSType maskElementType;
446 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
447 NSBitmapFormat bitmapFormat = NSAlphaFirstBitmapFormat;
448 #endif
449 OSErr result;
450 UInt32* pRawBitmapData;
451 UInt32* pRawBitmapDataEnd;
452 unsigned char* pRawMaskData;
453 unsigned char* pBitmapImageRepBitmapData;
454
455 // Make sure elementType is a valid type that we know how to handle, and
456 // figure out the dimensions and bit depth of the bitmap for that type.
457 switch (elementType) {
458 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
459 // 'ic09' 512x512 32-bit RGB image
460 case kIconServices512PixelDataARGB:
461 maskElementType = 0;
462 pixelsWide = 512;
463 break;
464 #endif
465
466 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
467 // 'ic08' 256x256 32-bit ARGB image
468 case kIconServices256PixelDataARGB:
469 maskElementType = 0;
470 pixelsWide = 256;
471 break;
472 #endif
473
474 // 'it32' 128x128 32-bit RGB image
475 case kThumbnail32BitData:
476 maskElementType = kThumbnail8BitMask;
477 pixelsWide = 128;
478 break;
479
480 // 'ih32' 48x48 32-bit RGB image
481 case kHuge32BitData:
482 maskElementType = kHuge8BitMask;
483 pixelsWide = 48;
484 break;
485
486 // 'il32' 32x32 32-bit RGB image
487 case kLarge32BitData:
488 maskElementType = kLarge8BitMask;
489 pixelsWide = 32;
490 break;
491
492 // 'is32' 16x16 32-bit RGB image
493 case kSmall32BitData:
494 maskElementType = kSmall8BitMask;
495 pixelsWide = 16;
496 break;
497
498 default:
499 return nil;
500 }
501
502 // Get the raw, uncompressed bitmap data for the requested element.
503 hRawBitmapData = NewHandle( pixelsWide * pixelsWide * 4 );
504 result = GetIconFamilyData( hIconFamily, elementType, hRawBitmapData );
505 if (result != noErr) {
506 DisposeHandle( hRawBitmapData );
507 return nil;
508 }
509
510 if (maskElementType) {
511 // Get the corresponding raw, uncompressed 8-bit mask data.
512 hRawMaskData = NewHandle( pixelsWide * pixelsWide );
513 result = GetIconFamilyData( hIconFamily, maskElementType, hRawMaskData ) ;
514 if (result != noErr) {
515 DisposeHandle( hRawMaskData );
516 hRawMaskData = NULL;
517 }
518 }
519
520 // The retrieved raw bitmap data is stored in memory as 32 bit per pixel, 8 bit per sample xRGB data. (The sample order provided by IconServices is the sam e, regardless of whether we're running on a big-endian (PPC) or little-endian (I ntel) architecture.)
521 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
522 // With proper attention to byte order, we can fold the mask data into the c olor data in-place, producing ARGB data suitable for handing off to NSBitmapImag eRep.
523 #else
524 // With proper attention to byte order, we can fold the mask data into the c olor data in-place, producing RGBA data suitable for handing off to NSBitmapImag eRep.
525 #endif
526 // HLock( hRawBitmapData ); // Handle-based memory isn't compacted anymore, s o calling HLock()/HUnlock() is unnecessary.
527 pRawBitmapData = (UInt32*) *hRawBitmapData;
528 pRawBitmapDataEnd = pRawBitmapData + pixelsWide * pixelsWide;
529 if (hRawMaskData) {
530 // HLock( hRawMaskData ); // Handle-based memory isn't compacted anymore, so calling HLock()/HUnlock() is unnecessary.
531 pRawMaskData = (UInt8*) *hRawMaskData;
532 while (pRawBitmapData < pRawBitmapDataEnd) {
533 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
534 // Convert the xRGB pixel data to ARGB.
535 // PowerPC Intel
536 // ------- -----
537 // Bytes in memory are x R G B x R G B
538 // *pRawBitmapData loads as 32-bit word into register xRGB BGRx
539 // CFSwapInt32HostToBig() swaps this to xRGB xRGB
540 // Loading *pRawMaskData and shifting left 24 bits yields A000 A000
541 // Bitwise ORing these two words together yields ARGB ARGB
542 // CFSwapInt32BigToHost() swaps this to ARGB BGRA
543 // Bytes in memory after they're stored as a 32-bit word A R G B A R G B
544 *pRawBitmapData = CFSwapInt32BigToHost((*pRawMaskData++ << 24) | CFS wapInt32HostToBig(*pRawBitmapData));
545 #else
546 // Convert the xRGB pixel data to RGBA.
547 // PowerPC Intel
548 // ------- -----
549 // Bytes in memory are x R G B x R G B
550 // *pRawBitmapData loads as 32-bit word into register xRGB BGRx
551 // CFSwapInt32HostToBig() swaps this to xRGB xRGB
552 // Shifting left 8 bits yields ('0' denotes all zero bits) RGB0 RGB0
553 // Bitwise ORing with *pRawMaskData byte yields RGBA RGBA
554 // CFSwapInt32BigToHost() swaps this to RGBA ABGR
555 // Bytes in memory after they're stored as a 32-bit word R G B A R G B A
556 *pRawBitmapData = CFSwapInt32BigToHost((CFSwapInt32HostToBig(*pRawBi tmapData) << 8) | *pRawMaskData++);
557 #endif
558 ++pRawBitmapData;
559 }
560 // HUnlock( hRawMaskData ); // Handle-based memory isn't compacted anymor e, so calling HLock()/HUnlock() is unnecessary.
561 } else {
562 if(maskElementType) {
563 // We SHOULD have a mask, but apparently not. Fake it with alpha=1.
564 while (pRawBitmapData < pRawBitmapDataEnd) {
565 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
566 // Set alpha byte to 0xff.
567 // PowerPC Intel
568 // ------- -----
569 // Bytes in memory are x R G B x R G B
570 // Writing a single 0xff byte ('1') at pRawBitmapData yields 1 R G B 1 R G B
571 *(unsigned char *)pRawBitmapData = 0xff;
572 #else
573 // Set alpha byte to 0xff.
574 // PowerPC Intel
575 // ------- -----
576 // Bytes in memory are R G B x R G B x
577 // Writing a single 0xff byte, 3 bytes past pRawBitmapData yield s R G B 1 R G B 1
578 *((unsigned char *)pRawBitmapData + 3) = 0xff;
579 #endif
580 ++pRawBitmapData;
581 }
582 }
583 }
584
585 // Create a new NSBitmapImageRep with the given bitmap data. Note that
586 // when creating the NSBitmapImageRep we pass in NULL for the "planes"
587 // parameter. This causes the new NSBitmapImageRep to allocate its own
588 // buffer for the bitmap data (which it will own and release when the
589 // NSBitmapImageRep is released), rather than referencing the bitmap
590 // data we pass in (which will soon disappear when we call
591 // DisposeHandle() below!). (See the NSBitmapImageRep documentation for
592 // the -initWithBitmapDataPlanes:... method, where this is explained.)
593 //
594 // Once we have the new NSBitmapImageRep, we get a pointer to its
595 // bitmapData and copy our bitmap data in.
596 bitmapImageRep = [[[NSBitmapImageRep alloc]
597 initWithBitmapDataPlanes:NULL
598 pixelsWide:pixelsWide
599 pixelsHigh:pixelsWide
600 bitsPerSample:8
601 samplesPerPixel:4
602 hasAlpha:YES
603 isPlanar:NO
604 colorSpaceName:NSDeviceRGBColorSpace // NOTE: is this right?
605 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
606 bitmapFormat:bitmapFormat
607 #endif
608 bytesPerRow:0
609 bitsPerPixel:0] autorelease];
610 pBitmapImageRepBitmapData = [bitmapImageRep bitmapData];
611 if (pBitmapImageRepBitmapData) {
612 memcpy( pBitmapImageRepBitmapData, *hRawBitmapData,
613 pixelsWide * pixelsWide * 4 );
614 }
615 // HUnlock( hRawBitmapData ); // Handle-based memory isn't compacted anymore, so calling HLock()/HUnlock() is unnecessary.
616
617 // Free the retrieved raw data.
618 DisposeHandle( hRawBitmapData );
619 if (hRawMaskData)
620 DisposeHandle( hRawMaskData );
621
622 // Return nil if the NSBitmapImageRep didn't give us a buffer to copy into.
623 if (pBitmapImageRepBitmapData == NULL)
624 return nil;
625
626 // Return the new NSBitmapImageRep.
627 return bitmapImageRep;
628 }
629
630 - (NSImage*) imageWithAllReps
631 {
632 NSImage* image = NULL;
633 image = [[[NSImage alloc] initWithData:[NSData dataWithBytes:*hIconFamily le ngth:GetHandleSize((Handle)hIconFamily)]] autorelease];
634 return image;
635 }
636
637 - (BOOL) setIconFamilyElement:(OSType)elementType fromBitmapImageRep:(NSBitmapIm ageRep*)bitmapImageRep
638 {
639 Handle hRawData = NULL;
640 OSErr result;
641
642 switch (elementType) {
643 // 'ic08' 512x512 32-bit ARGB image
644 case kIconServices512PixelDataARGB:
645 hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep req uiredPixelSize:512];
646 break;
647
648 // 'ic08' 256x256 32-bit ARGB image
649 case kIconServices256PixelDataARGB:
650 hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep req uiredPixelSize:256];
651 break;
652
653 // 'it32' 128x128 32-bit RGB image
654 case kThumbnail32BitData:
655 hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:128];
656 break;
657
658 // 't8mk' 128x128 8-bit alpha mask
659 case kThumbnail8BitMask:
660 hRawData = [IconFamily get8BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:128];
661 break;
662
663 // 'il32' 32x32 32-bit RGB image
664 case kLarge32BitData:
665 hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:32];
666 break;
667
668 // 'l8mk' 32x32 8-bit alpha mask
669 case kLarge8BitMask:
670 hRawData = [IconFamily get8BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:32];
671 break;
672
673 // 'ICN#' 32x32 1-bit alpha mask
674 case kLarge1BitMask:
675 hRawData = [IconFamily get1BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:32];
676 break;
677
678 // 'icl8' 32x32 8-bit indexed image data
679 case kLarge8BitData:
680 hRawData = [IconFamily get8BitDataFromBitmapImageRep:bitmapImage Rep requiredPixelSize:32];
681 break;
682
683 // 'is32' 16x16 32-bit RGB image
684 case kSmall32BitData:
685 hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImag eRep requiredPixelSize:16];
686 break;
687
688 // 's8mk' 16x16 8-bit alpha mask
689 case kSmall8BitMask:
690 hRawData = [IconFamily get8BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:16];
691 break;
692
693 // 'ics#' 16x16 1-bit alpha mask
694 case kSmall1BitMask:
695 hRawData = [IconFamily get1BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:16];
696 break;
697
698 // 'ics8' 16x16 8-bit indexed image data
699 case kSmall8BitData:
700 hRawData = [IconFamily get8BitDataFromBitmapImageRep:bitmapImage Rep requiredPixelSize:16];
701 break;
702
703 default:
704 return NO;
705 }
706
707 // NSLog(@"setIconFamilyElement:%@ fromBitmapImageRep:%@ generated handl e %p of size %d", NSFileTypeForHFSTypeCode(elementType), bitmapImageRep, hRawDat a, GetHandleSize(hRawData));
708
709 if (hRawData == NULL)
710 {
711 NSLog(@"Null data returned to setIconFamilyElement:fromBitmapIma geRep:");
712 return NO;
713 }
714
715 result = SetIconFamilyData( hIconFamily, elementType, hRawData );
716 DisposeHandle( hRawData );
717
718 if (result != noErr)
719 {
720 NSLog(@"SetIconFamilyData() returned error %d", result);
721 return NO;
722 }
723
724 return YES;
725 }
726
727 - (BOOL) setAsCustomIconForFile:(NSString*)path
728 {
729 return( [self setAsCustomIconForFile:path withCompatibility:NO] );
730 }
731
732 - (BOOL) setAsCustomIconForFile:(NSString*)path withCompatibility:(BOOL)compat
733 {
734 FSRef targetFileFSRef;
735 FSRef parentDirectoryFSRef;
736 SInt16 file;
737 OSStatus result;
738 struct FSCatalogInfo catInfo;
739 struct FileInfo *finderInfo = (struct FileInfo *)&catInfo.finderInfo;
740 Handle hExistingCustomIcon;
741 Handle hIconFamilyCopy;
742 NSString *parentDirectory;
743
744 // Before we do anything, get the original modification time for the target file.
745 NSDate* modificationDate = [[[NSFileManager defaultManager] iconfamily_attri butesAtPath:path] objectForKey:NSFileModificationDate];
746
747 if ([path isAbsolutePath])
748 parentDirectory = [path stringByDeletingLastPathComponent];
749 else
750 parentDirectory = [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:[path stringByDeletingLastPathComponent]];
751
752 // Get an FSRef for the target file's parent directory that we can use in
753 // the FSCreateResFile() and FNNotify() calls below.
754 if (![parentDirectory getFSRef:&parentDirectoryFSRef createFileIfNecessary:N O])
755 return NO;
756
757 // Get the name of the file, for FSCreateResFile.
758 struct HFSUniStr255 filename;
759 NSString *filenameString = [path lastPathComponent];
760 filename.length = [filenameString length];
761 [filenameString getCharacters:filename.unicode];
762
763 // Make sure the file has a resource fork that we can open. (Although
764 // this sounds like it would clobber an existing resource fork, the Carbon
765 // Resource Manager docs for this function say that's not the case. If
766 // the file already has a resource fork, we receive a result code of
767 // dupFNErr, which is not really an error per se, but just a notification
768 // to us that creating a new resource fork for the file was not necessary.)
769 FSCreateResFile(
770 &parentDirectoryFSRef,
771 filename.length,
772 filename.unicode,
773 kFSCatInfoNone,
774 /*catalogInfo/*/ NULL,
775 &targetFileFSRef,
776 /*newSpec*/ NULL);
777 result = ResError();
778 if (result == dupFNErr) {
779 // If the call to FSCreateResFile() returned dupFNErr, targetFileFSRef w ill not have been set, so create it from the path.
780 if (![path getFSRef:&targetFileFSRef createFileIfNecessary:NO])
781 return NO;
782 } else if (result != noErr) {
783 return NO;
784 }
785
786 // Open the file's resource fork.
787 file = FSOpenResFile( &targetFileFSRef, fsRdWrPerm );
788 if (file == -1)
789 return NO;
790
791 // Make a copy of the icon family data to pass to AddResource().
792 // (AddResource() takes ownership of the handle we pass in; after the
793 // CloseResFile() call its master pointer will be set to 0xffffffff.
794 // We want to keep the icon family data, so we make a copy.)
795 // HandToHand() returns the handle of the copy in hIconFamily.
796 hIconFamilyCopy = (Handle) hIconFamily;
797 result = HandToHand( &hIconFamilyCopy );
798 if (result != noErr) {
799 CloseResFile( file );
800 return NO;
801 }
802
803 // Remove the file's existing kCustomIconResource of type kIconFamilyType
804 // (if any).
805 hExistingCustomIcon = GetResource( kIconFamilyType, kCustomIconResource );
806 if( hExistingCustomIcon )
807 RemoveResource( hExistingCustomIcon );
808
809 // Now add our icon family as the file's new custom icon.
810 AddResource( (Handle)hIconFamilyCopy, kIconFamilyType,
811 kCustomIconResource, "\p");
812 if (ResError() != noErr) {
813 CloseResFile( file );
814 return NO;
815 }
816
817 if( compat )
818 {
819 [self addResourceType:kLarge8BitData asResID:kCustomIconResource];
820 [self addResourceType:kLarge1BitMask asResID:kCustomIconResource];
821 [self addResourceType:kSmall8BitData asResID:kCustomIconResource];
822 [self addResourceType:kSmall1BitMask asResID:kCustomIconResource];
823 }
824
825 // Close the file's resource fork, flushing the resource map and new icon
826 // data out to disk.
827 CloseResFile( file );
828 if (ResError() != noErr)
829 return NO;
830
831 // Prepare to get the Finder info.
832
833 // Now we need to set the file's Finder info so the Finder will know that
834 // it has a custom icon. Start by getting the file's current finder info:
835 result = FSGetCatalogInfo(
836 &targetFileFSRef,
837 kFSCatInfoFinderInfo,
838 &catInfo,
839 /*outName*/ NULL,
840 /*fsSpec*/ NULL,
841 /*parentRef*/ NULL);
842 if (result != noErr)
843 return NO;
844
845 // Set the kHasCustomIcon flag, and clear the kHasBeenInited flag.
846 //
847 // From Apple's "CustomIcon" code sample:
848 // "set bit 10 (has custom icon) and unset the inited flag
849 // kHasBeenInited is 0x0100 so the mask will be 0xFEFF:"
850 // finderInfo.fdFlags = 0xFEFF & (finderInfo.fdFlags | kHasCustomIcon ) ;
851 finderInfo->finderFlags = (finderInfo->finderFlags | kHasCustomIcon ) & ~kHa sBeenInited;
852
853 // Now write the Finder info back.
854 result = FSSetCatalogInfo( &targetFileFSRef, kFSCatInfoFinderInfo, &catInfo );
855 if (result != noErr)
856 return NO;
857
858 // Now set the modification time back to when the file was actually last mod ified.
859 NSDictionary* attributes = [NSDictionary dictionaryWithObjectsAndKeys:modifi cationDate, NSFileModificationDate, nil];
860 [[NSFileManager defaultManager] iconfamily_setAttributes:attributes atPath:p ath];
861
862 // Notify the system that the directory containing the file has changed, to
863 // give Finder the chance to find out about the file's new custom icon.
864 result = FNNotify( &parentDirectoryFSRef, kFNDirectoryModifiedMessage, kNilO ptions );
865 if (result != noErr)
866 return NO;
867
868 return YES;
869 }
870
871 + (BOOL) removeCustomIconFromFile:(NSString*)path
872 {
873 FSRef targetFileFSRef;
874 FSRef parentDirectoryFSRef;
875 SInt16 file;
876 OSStatus result;
877 struct FSCatalogInfo catInfo;
878 struct FileInfo *finderInfo = (struct FileInfo *)&catInfo.finderInfo;
879 Handle hExistingCustomIcon;
880
881 // Get an FSRef for the target file.
882 if (![path getFSRef:&targetFileFSRef createFileIfNecessary:NO])
883 return NO;
884
885 // Open the file's resource fork, if it has one.
886 file = FSOpenResFile( &targetFileFSRef, fsRdWrPerm );
887 if (file == -1)
888 return NO;
889
890 // Remove the file's existing kCustomIconResource of type kIconFamilyType
891 // (if any).
892 hExistingCustomIcon = GetResource( kIconFamilyType, kCustomIconResource );
893 if( hExistingCustomIcon )
894 RemoveResource( hExistingCustomIcon );
895
896 // Close the file's resource fork, flushing the resource map out to disk.
897 CloseResFile( file );
898 if (ResError() != noErr)
899 return NO;
900
901 // Now we need to set the file's Finder info so the Finder will know that
902 // it has no custom icon. Start by getting the file's current Finder info.
903 // Also get an FSRef for its parent directory, that we can use in the
904 // FNNotify() call below.
905 result = FSGetCatalogInfo(
906 &targetFileFSRef,
907 kFSCatInfoFinderInfo,
908 &catInfo,
909 /*outName*/ NULL,
910 /*fsSpec*/ NULL,
911 &parentDirectoryFSRef );
912 if (result != noErr)
913 return NO;
914
915 // Clear the kHasCustomIcon flag and the kHasBeenInited flag.
916 finderInfo->finderFlags = finderInfo->finderFlags & ~(kHasCustomIcon | kHasB eenInited);
917
918 // Now write the Finder info back.
919 result = FSSetCatalogInfo( &targetFileFSRef, kFSCatInfoFinderInfo, &catInfo );
920 if (result != noErr)
921 return NO;
922
923 // Notify the system that the directory containing the file has changed, to give Finder the chance to find out about the file's new custom icon.
924 result = FNNotify( &parentDirectoryFSRef, kFNDirectoryModifiedMessage, kNilO ptions );
925 if (result != noErr)
926 return NO;
927
928 return YES;
929 }
930
931 - (BOOL) setAsCustomIconForDirectory:(NSString*)path
932 {
933 return [self setAsCustomIconForDirectory:path withCompatibility:NO];
934 }
935
936 - (BOOL) setAsCustomIconForDirectory:(NSString*)path withCompatibility:(BOOL)com pat
937 {
938 NSFileManager *fm = [NSFileManager defaultManager];
939 BOOL isDir;
940 BOOL exists;
941 NSString *iconrPath;
942 FSRef targetFolderFSRef, iconrFSRef;
943 SInt16 file;
944 OSErr result;
945 struct HFSUniStr255 filename;
946 struct FSCatalogInfo catInfo;
947 Handle hExistingCustomIcon;
948 Handle hIconFamilyCopy;
949
950 // Confirm that "path" exists and specifies a directory.
951 exists = [fm fileExistsAtPath:path isDirectory:&isDir];
952 if( !isDir || !exists )
953 return NO;
954
955 // Get an FSRef for the folder.
956 if( ![path getFSRef:&targetFolderFSRef createFileIfNecessary:NO] )
957 return NO;
958
959 // Remove and re-create any existing "Icon\r" file in the directory, and get an FSRef for it.
960 iconrPath = [path stringByAppendingPathComponent:@"Icon\r"];
961 if( [fm fileExistsAtPath:iconrPath] )
962 {
963 if( ![fm iconfamily_removeItemAtPath:iconrPath] )
964 return NO;
965 }
966 if( ![iconrPath getFSRef:&iconrFSRef createFileIfNecessary:YES] )
967 return NO;
968
969 // Get type and creator information for the Icon file.
970 result = FSGetCatalogInfo(
971 &iconrFSRef,
972 kFSCatInfoFinderInfo,
973 &catInfo,
974 /*outName*/ NULL,
975 /*fsSpec*/ NULL,
976 /*parentRef*/ NULL );
977 // This shouldn't fail because we just created the file above.
978 if( result != noErr )
979 return NO;
980 else {
981 // The file doesn't exist. Prepare to create it.
982 struct FileInfo *finderInfo = (struct FileInfo *)catInfo.finderInfo;
983
984 // These are the file type and creator given to Icon files created by
985 // the Finder.
986 finderInfo->fileType = 'icon';
987 finderInfo->fileCreator = 'MACS';
988
989 // Icon files should be invisible.
990 finderInfo->finderFlags = kIsInvisible;
991
992 // Because the inited flag is not set in finderFlags above, the Finder
993 // will ignore the location, unless it's in the 'magic rectangle' of
994 // { -24,000, -24,000, -16,000, -16,000 } (technote TB42).
995 // So we need to make sure to set this to zero anyway, so that the
996 // Finder will position it automatically. If the user makes the Icon
997 // file visible for any reason, we don't want it to be positioned in an
998 // exotic corner of the window.
999 finderInfo->location.h = finderInfo->location.v = 0;
1000
1001 // Standard reserved-field practice.
1002 finderInfo->reservedField = 0;
1003
1004 // Update the catalog info:
1005 result = FSSetCatalogInfo(&iconrFSRef, kFSCatInfoFinderInfo, &catInfo);
1006
1007 if (result != noErr)
1008 return NO;
1009 }
1010
1011 // Get the filename, to be applied to the Icon file.
1012 filename.length = [@"Icon\r" length];
1013 [@"Icon\r" getCharacters:filename.unicode];
1014
1015 // Make sure the file has a resource fork that we can open. (Although
1016 // this sounds like it would clobber an existing resource fork, the Carbon
1017 // Resource Manager docs for this function say that's not the case.)
1018 FSCreateResFile(
1019 &targetFolderFSRef,
1020 filename.length,
1021 filename.unicode,
1022 kFSCatInfoFinderInfo,
1023 &catInfo,
1024 &iconrFSRef,
1025 /*newSpec*/ NULL);
1026 result = ResError();
1027 if (!(result == noErr || result == dupFNErr))
1028 return NO;
1029
1030 // Open the file's resource fork.
1031 file = FSOpenResFile( &iconrFSRef, fsRdWrPerm );
1032 if (file == -1)
1033 return NO;
1034
1035 // Make a copy of the icon family data to pass to AddResource().
1036 // (AddResource() takes ownership of the handle we pass in; after the
1037 // CloseResFile() call its master pointer will be set to 0xffffffff.
1038 // We want to keep the icon family data, so we make a copy.)
1039 // HandToHand() returns the handle of the copy in hIconFamily.
1040 hIconFamilyCopy = (Handle) hIconFamily;
1041 result = HandToHand( &hIconFamilyCopy );
1042 if (result != noErr) {
1043 CloseResFile( file );
1044 return NO;
1045 }
1046
1047 // Remove the file's existing kCustomIconResource of type kIconFamilyType
1048 // (if any).
1049 hExistingCustomIcon = GetResource( kIconFamilyType, kCustomIconResource );
1050 if( hExistingCustomIcon )
1051 RemoveResource( hExistingCustomIcon );
1052
1053 // Now add our icon family as the file's new custom icon.
1054 AddResource( (Handle)hIconFamilyCopy, kIconFamilyType,
1055 kCustomIconResource, "\p");
1056
1057 if (ResError() != noErr) {
1058 CloseResFile( file );
1059 return NO;
1060 }
1061
1062 if( compat )
1063 {
1064 [self addResourceType:kLarge8BitData asResID:kCustomIconResource];
1065 [self addResourceType:kLarge1BitMask asResID:kCustomIconResource];
1066 [self addResourceType:kSmall8BitData asResID:kCustomIconResource];
1067 [self addResourceType:kSmall1BitMask asResID:kCustomIconResource];
1068 }
1069
1070 // Close the file's resource fork, flushing the resource map and new icon
1071 // data out to disk.
1072 CloseResFile( file );
1073 if (ResError() != noErr)
1074 return NO;
1075
1076 result = FSGetCatalogInfo( &targetFolderFSRef,
1077 kFSCatInfoFinderInfo,
1078 &catInfo,
1079 /*outName*/ NULL,
1080 /*fsSpec*/ NULL,
1081 /*parentRef*/ NULL);
1082 if( result != noErr )
1083 return NO;
1084
1085 // Tell the Finder that the folder now has a custom icon.
1086 ((struct FolderInfo *)catInfo.finderInfo)->finderFlags = ( ((struct FolderIn fo *)catInfo.finderInfo)->finderFlags | kHasCustomIcon ) & ~kHasBeenInited;
1087
1088 result = FSSetCatalogInfo( &targetFolderFSRef,
1089 kFSCatInfoFinderInfo,
1090 &catInfo);
1091 if( result != noErr )
1092 return NO;
1093
1094 // Notify the system that the target directory has changed, to give Finder
1095 // the chance to find out about its new custom icon.
1096 result = FNNotify( &targetFolderFSRef, kFNDirectoryModifiedMessage, kNilOpti ons );
1097 if (result != noErr)
1098 return NO;
1099
1100 return YES;
1101 }
1102
1103 + (BOOL) removeCustomIconFromDirectory:(NSString*)path
1104 {
1105 FSRef targetFolderFSRef;
1106 if( [path getFSRef:&targetFolderFSRef createFileIfNecessary:NO] ) {
1107 OSStatus result;
1108 struct FSCatalogInfo catInfo;
1109 struct FileInfo *finderInfo = (struct FileInfo *)catInfo.finderInfo;
1110
1111 result = FSGetCatalogInfo( &targetFolderFSRef,
1112 kFSCatInfoFinderInfo,
1113 &catInfo,
1114 /*outName*/ NULL,
1115 /*fsSpec*/ NULL,
1116 /*parentRef*/ NULL);
1117 if( result != noErr )
1118 return NO;
1119
1120 // Tell the Finder that the folder no longer has a custom icon.
1121 finderInfo->finderFlags &= ~( kHasCustomIcon | kHasBeenInited );
1122
1123 result = FSSetCatalogInfo( &targetFolderFSRef,
1124 kFSCatInfoFinderInfo,
1125 &catInfo);
1126 if( result != noErr )
1127 return NO;
1128
1129 // Notify the system that the target directory has changed, to give Find er
1130 // the chance to find out about its new custom icon.
1131 result = FNNotify( &targetFolderFSRef, kFNDirectoryModifiedMessage, kNil Options );
1132 if (result != noErr)
1133 return NO;
1134 }
1135
1136 if( ! [[NSFileManager defaultManager] iconfamily_removeItemAtPath:[path stri ngByAppendingPathComponent:@"Icon\r"]] )
1137 return NO;
1138
1139 return YES;
1140 }
1141
1142 - (NSData *) data
1143 {
1144 return [NSData dataWithBytes:*hIconFamily length:GetHandleSize((Handle)hIcon Family)];
1145 }
1146
1147 - (BOOL) writeToFile:(NSString*)path
1148 {
1149 return [[self data] writeToFile:path atomically:NO];
1150 }
1151
1152 @end
1153
1154 @implementation IconFamily (Internals)
1155
1156 + (NSImage*) resampleImage:(NSImage*)image toIconWidth:(int)iconWidth usingImage Interpolation:(NSImageInterpolation)imageInterpolation
1157 {
1158 NSGraphicsContext* graphicsContext;
1159 BOOL wasAntialiasing;
1160 NSImageInterpolation previousImageInterpolation;
1161 NSImage* newImage;
1162 NSImage* workingImage;
1163 NSImageRep* workingImageRep;
1164 NSSize size, pixelSize, newSize;
1165 NSRect iconRect;
1166 NSRect targetRect;
1167
1168 // Create a working copy of the image and scale its size down to fit in
1169 // the square area of the icon.
1170 //
1171 // It seems like there should be a more memory-efficient alternative to
1172 // first duplicating the entire original image, but I don't know what it
1173 // is. We need to change some properties ("size" and "scalesWhenResized")
1174 // of the original image, but we shouldn't change the original, so a copy
1175 // is necessary.
1176 workingImage = [image copyWithZone:[image zone]];
1177 [workingImage setScalesWhenResized:YES];
1178 size = [workingImage size];
1179 workingImageRep = [workingImage iconfamily_bestRepresentation];
1180 if ([workingImageRep isKindOfClass:[NSBitmapImageRep class]]) {
1181 pixelSize.width = [workingImageRep pixelsWide];
1182 pixelSize.height = [workingImageRep pixelsHigh];
1183 if (!NSEqualSizes( size, pixelSize )) {
1184 [workingImage setSize:pixelSize];
1185 [workingImageRep setSize:pixelSize];
1186 size = pixelSize;
1187 }
1188 }
1189 if (size.width >= size.height) {
1190 newSize.width = iconWidth;
1191 newSize.height = (float)floor( iconWidth * size.height / size.width + 0. 5 );
1192 } else {
1193 newSize.height = iconWidth;
1194 newSize.width = (float)floor( iconWidth * size.width / size.height + 0. 5 );
1195 }
1196 [workingImage setSize:newSize];
1197
1198 // Create a new image the size of the icon, and clear it to transparent.
1199 newImage = [[NSImage alloc] initWithSize:NSMakeSize(iconWidth,iconWidth)];
1200 [newImage lockFocus];
1201 iconRect.origin.x = iconRect.origin.y = 0;
1202 iconRect.size.width = iconRect.size.height = iconWidth;
1203 [[NSColor clearColor] set];
1204 NSRectFill( iconRect );
1205
1206 // Set current graphics context to use antialiasing and high-quality
1207 // image scaling.
1208 graphicsContext = [NSGraphicsContext currentContext];
1209 wasAntialiasing = [graphicsContext shouldAntialias];
1210 previousImageInterpolation = [graphicsContext imageInterpolation];
1211 [graphicsContext setShouldAntialias:YES];
1212 [graphicsContext setImageInterpolation:imageInterpolation];
1213
1214 // Composite the working image into the icon bitmap, centered.
1215 targetRect.origin.x = ((float)iconWidth - newSize.width ) / 2.0f;
1216 targetRect.origin.y = ((float)iconWidth - newSize.height) / 2.0f;
1217 targetRect.size.width = newSize.width;
1218 targetRect.size.height = newSize.height;
1219 [workingImageRep drawInRect:targetRect];
1220
1221 // Restore previous graphics context settings.
1222 [graphicsContext setShouldAntialias:wasAntialiasing];
1223 [graphicsContext setImageInterpolation:previousImageInterpolation];
1224
1225 [newImage unlockFocus];
1226
1227 [workingImage release];
1228
1229 // Return the new image!
1230 return [newImage autorelease];
1231 }
1232
1233 + (Handle) get32BitDataFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requ iredPixelSize:(int)requiredPixelSize
1234 {
1235 Handle hRawData;
1236 unsigned char* pRawData;
1237 Size rawDataSize;
1238 unsigned char* pSrc;
1239 unsigned char* pDest;
1240 int x, y;
1241 unsigned char alphaByte;
1242 float oneOverAlpha;
1243
1244 // Get information about the bitmapImageRep.
1245 long pixelsWide = [bitmapImageRep pixelsWide];
1246 long pixelsHigh = [bitmapImageRep pixelsHigh];
1247 long bitsPerSample = [bitmapImageRep bitsPerSample];
1248 long samplesPerPixel = [bitmapImageRep samplesPerPixel];
1249 long bitsPerPixel = [bitmapImageRep bitsPerPixel];
1250 BOOL isPlanar = [bitmapImageRep isPlanar];
1251 long bytesPerRow = [bitmapImageRep bytesPerRow];
1252 unsigned char* bitmapData = [bitmapImageRep bitmapData];
1253
1254 // Make sure bitmap has the required dimensions.
1255 if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize)
1256 return NULL;
1257
1258 // So far, this code only handles non-planar 32-bit RGBA and 24-bit RGB sour ce bitmaps.
1259 // This could be made more flexible with some additional programming to acco mmodate other possible
1260 // formats...
1261 if (isPlanar)
1262 {
1263 NSLog(@"get32BitDataFromBitmapImageRep:requiredPixelSize: return ing NULL due to isPlanar == YES");
1264 return NULL;
1265 }
1266 if (bitsPerSample != 8)
1267 {
1268 NSLog(@"get32BitDataFromBitmapImageRep:requiredPixelSize: return ing NULL due to bitsPerSample == %ld", bitsPerSample);
1269 return NULL;
1270 }
1271
1272 if (((samplesPerPixel == 3) && (bitsPerPixel == 24)) || ((samplesPerPixe l == 4) && (bitsPerPixel == 32)))
1273 {
1274 rawDataSize = pixelsWide * pixelsHigh * 4;
1275 hRawData = NewHandle( rawDataSize );
1276 if (hRawData == NULL)
1277 return NULL;
1278 pRawData = (unsigned char*) *hRawData;
1279
1280 pDest = pRawData;
1281
1282 if (bitsPerPixel == 32) {
1283 for (y = 0; y < pixelsHigh; y++) {
1284 pSrc = bitmapData + y * bytesPerRow;
1285 for (x = 0; x < pixelsWide; x++) {
1286 // Each pixel is 3 bytes of RGB data, followed by 1 byte of
1287 // alpha. The RGB values are pr emultiplied by the alpha (so
1288 // that Quartz can save time whe n compositing the bitmap to a
1289 // destination), and we undo thi s premultiplication (with some
1290 // lossiness unfortunately) when retrieving the bitmap data.
1291 *pDest++ = alphaByte = *(pSrc+3) ;
1292 if (alphaByte) {
1293 oneOverAlpha = 255.0f / (float)alphaByte;
1294 *pDest++ = *(pSrc+0) * o neOverAlpha;
1295 *pDest++ = *(pSrc+1) * o neOverAlpha;
1296 *pDest++ = *(pSrc+2) * o neOverAlpha;
1297 } else {
1298 *pDest++ = 0;
1299 *pDest++ = 0;
1300 *pDest++ = 0;
1301 }
1302 pSrc+=4;
1303 }
1304 }
1305 } else if (bitsPerPixel == 24) {
1306 for (y = 0; y < pixelsHigh; y++) {
1307 pSrc = bitmapData + y * bytesPerRow;
1308 for (x = 0; x < pixelsWide; x++) {
1309 *pDest++ = 0xFF;
1310 *pDest++ = *pSrc++;
1311 *pDest++ = *pSrc++;
1312 *pDest++ = *pSrc++;
1313 }
1314 }
1315 }
1316 }
1317 else
1318 {
1319 NSLog(@"get32BitDataFromBitmapImageRep:requiredPixelSize: return ing NULL due to samplesPerPixel == %ld, bitsPerPixel == %ld", samplesPerPixel, b itsPerPixel);
1320 return NULL;
1321 }
1322
1323 return hRawData;
1324 }
1325
1326 + (Handle) get8BitDataFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requi redPixelSize:(int)requiredPixelSize
1327 {
1328 Handle hRawData;
1329 unsigned char* pRawData;
1330 Size rawDataSize;
1331 unsigned char* pSrc;
1332 unsigned char* pDest;
1333 int x, y;
1334
1335 // Get information about the bitmapImageRep.
1336 long pixelsWide = [bitmapImageRep pixelsWide];
1337 long pixelsHigh = [bitmapImageRep pixelsHigh];
1338 long bitsPerSample = [bitmapImageRep bitsPerSample];
1339 long samplesPerPixel = [bitmapImageRep samplesPerPixel];
1340 long bitsPerPixel = [bitmapImageRep bitsPerPixel];
1341 BOOL isPlanar = [bitmapImageRep isPlanar];
1342 long bytesPerRow = [bitmapImageRep bytesPerRow];
1343 unsigned char* bitmapData = [bitmapImageRep bitmapData];
1344
1345 // Make sure bitmap has the required dimensions.
1346 if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize)
1347 return NULL;
1348
1349 // So far, this code only handles non-planar 32-bit RGBA and 24-bit RGB sour ce bitmaps.
1350 // This could be made more flexible with some additional programming...
1351 if (isPlanar)
1352 {
1353 NSLog(@"get8BitDataFromBitmapImageRep:requiredPixelSize: returni ng NULL due to isPlanar == YES");
1354 return NULL;
1355 }
1356 if (bitsPerSample != 8)
1357 {
1358 NSLog(@"get8BitDataFromBitmapImageRep:requiredPixelSize: returni ng NULL due to bitsPerSample == %ld", bitsPerSample);
1359 return NULL;
1360 }
1361
1362 if (((samplesPerPixel == 3) && (bitsPerPixel == 24)) || ((samplesPerPixe l == 4) && (bitsPerPixel == 32)))
1363 {
1364 CGDirectPaletteRef cgPal;
1365 CGDeviceColor cgCol;
1366
1367 rawDataSize = pixelsWide * pixelsHigh;
1368 hRawData = NewHandle( rawDataSize );
1369 if (hRawData == NULL)
1370 return NULL;
1371 pRawData = (unsigned char*) *hRawData;
1372
1373 cgPal = CGPaletteCreateDefaultColorPalette();
1374
1375 pDest = pRawData;
1376 if (bitsPerPixel == 32) {
1377 for (y = 0; y < pixelsHigh; y++) {
1378 pSrc = bitmapData + y * bytesPerRow;
1379 for (x = 0; x < pixelsWide; x++) {
1380 cgCol.red = ((float)*(pSrc)) / 255;
1381 cgCol.green = ((float)*(pSrc+1)) / 255;
1382 cgCol.blue = ((float)*(pSrc+2)) / 255;
1383
1384 *pDest++ = CGPaletteGetIndexForColor(cgP al, cgCol);
1385
1386 pSrc+=4;
1387 }
1388 }
1389 } else if (bitsPerPixel == 24) {
1390 for (y = 0; y < pixelsHigh; y++) {
1391 pSrc = bitmapData + y * bytesPerRow;
1392 for (x = 0; x < pixelsWide; x++) {
1393 cgCol.red = ((float)*(pSrc)) / 255;
1394 cgCol.green = ((float)*(pSrc+1)) / 255;
1395 cgCol.blue = ((float)*(pSrc+2)) / 255;
1396
1397 *pDest++ = CGPaletteGetIndexForColor(cgP al, cgCol);
1398
1399 pSrc+=3;
1400 }
1401 }
1402 }
1403
1404 CGPaletteRelease(cgPal);
1405 }
1406 else
1407 {
1408 NSLog(@"get8BitDataFromBitmapImageRep:requiredPixelSize: returni ng NULL due to samplesPerPixel == %ld, bitsPerPixel == %ld", samplesPerPixel, bi tsPerPixel);
1409 return NULL;
1410 }
1411
1412 return hRawData;
1413 }
1414
1415 + (Handle) get8BitMaskFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requi redPixelSize:(int)requiredPixelSize
1416 {
1417 Handle hRawData;
1418 unsigned char* pRawData;
1419 Size rawDataSize;
1420 unsigned char* pSrc;
1421 unsigned char* pDest;
1422 int x, y;
1423
1424 // Get information about the bitmapImageRep.
1425 long pixelsWide = [bitmapImageRep pixelsWide];
1426 long pixelsHigh = [bitmapImageRep pixelsHigh];
1427 long bitsPerSample = [bitmapImageRep bitsPerSample];
1428 long samplesPerPixel = [bitmapImageRep samplesPerPixel];
1429 long bitsPerPixel = [bitmapImageRep bitsPerPixel];
1430 BOOL isPlanar = [bitmapImageRep isPlanar];
1431 long bytesPerRow = [bitmapImageRep bytesPerRow];
1432 unsigned char* bitmapData = [bitmapImageRep bitmapData];
1433
1434 // Make sure bitmap has the required dimensions.
1435 if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize)
1436 return NULL;
1437
1438 // So far, this code only handles non-planar 32-bit RGBA, 24-bit RGB and 8-b it grayscale source bitmaps.
1439 // This could be made more flexible with some additional programming...
1440 if (isPlanar)
1441 {
1442 NSLog(@"get8BitMaskFromBitmapImageRep:requiredPixelSize: returni ng NULL due to isPlanar == YES");
1443 return NULL;
1444 }
1445 if (bitsPerSample != 8)
1446 {
1447 NSLog(@"get8BitMaskFromBitmapImageRep:requiredPixelSize: returni ng NULL due to bitsPerSample == %ld", bitsPerSample);
1448 return NULL;
1449 }
1450
1451 if (((samplesPerPixel == 1) && (bitsPerPixel == 8)) || ((samplesPerPixel == 3) && (bitsPerPixel == 24)) || ((samplesPerPixel == 4) && (bitsPerPixel == 3 2)))
1452 {
1453 rawDataSize = pixelsWide * pixelsHigh;
1454 hRawData = NewHandle( rawDataSize );
1455 if (hRawData == NULL)
1456 return NULL;
1457 pRawData = (unsigned char*) *hRawData;
1458
1459 pSrc = bitmapData;
1460 pDest = pRawData;
1461
1462 if (bitsPerPixel == 32) {
1463 for (y = 0; y < pixelsHigh; y++) {
1464 pSrc = bitmapData + y * bytesPerRow;
1465 for (x = 0; x < pixelsWide; x++) {
1466 pSrc += 3;
1467 *pDest++ = *pSrc++;
1468 }
1469 }
1470 }
1471 else if (bitsPerPixel == 24) {
1472 memset( pDest, 255, rawDataSize );
1473 }
1474 else if (bitsPerPixel == 8) {
1475 for (y = 0; y < pixelsHigh; y++) {
1476 memcpy( pDest, pSrc, pixelsWide );
1477 pSrc += bytesPerRow;
1478 pDest += pixelsWide;
1479 }
1480 }
1481 }
1482 else
1483 {
1484 NSLog(@"get8BitMaskFromBitmapImageRep:requiredPixelSize: returni ng NULL due to samplesPerPixel == %ld, bitsPerPixel == %ld", samplesPerPixel, bi tsPerPixel);
1485 return NULL;
1486 }
1487
1488 return hRawData;
1489 }
1490
1491 // NOTE: This method hasn't been fully tested yet.
1492 + (Handle) get1BitMaskFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requi redPixelSize:(int)requiredPixelSize
1493 {
1494 Handle hRawData;
1495 unsigned char* pRawData;
1496 Size rawDataSize;
1497 unsigned char* pSrc;
1498 unsigned char* pDest;
1499 int x, y;
1500 unsigned char maskByte;
1501
1502 // Get information about the bitmapImageRep.
1503 long pixelsWide = [bitmapImageRep pixelsWide];
1504 long pixelsHigh = [bitmapImageRep pixelsHigh];
1505 long bitsPerSample = [bitmapImageRep bitsPerSample];
1506 long samplesPerPixel = [bitmapImageRep samplesPerPixel];
1507 long bitsPerPixel = [bitmapImageRep bitsPerPixel];
1508 BOOL isPlanar = [bitmapImageRep isPlanar];
1509 long bytesPerRow = [bitmapImageRep bytesPerRow];
1510 unsigned char* bitmapData = [bitmapImageRep bitmapData];
1511
1512 // Make sure bitmap has the required dimensions.
1513 if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize)
1514 return NULL;
1515
1516 // So far, this code only handles non-planar 32-bit RGBA, 24-bit RGB, 8-bit grayscale, and 1-bit source bitmaps.
1517 // This could be made more flexible with some additional programming...
1518 if (isPlanar)
1519 {
1520 NSLog(@"get1BitMaskFromBitmapImageRep:requiredPixelSize: returni ng NULL due to isPlanar == YES");
1521 return NULL;
1522 }
1523
1524 if (((bitsPerPixel == 1) && (samplesPerPixel == 1) && (bitsPerSample == 1)) || ((bitsPerPixel == 8) && (samplesPerPixel == 1) && (bitsPerSample == 8)) | |
1525 ((bitsPerPixel == 24) && (samplesPerPixel == 3) && (bitsPerSampl e == 8)) || ((bitsPerPixel == 32) && (samplesPerPixel == 4) && (bitsPerSample == 8)))
1526 {
1527 rawDataSize = (pixelsWide * pixelsHigh)/4;
1528 hRawData = NewHandle( rawDataSize );
1529 if (hRawData == NULL)
1530 return NULL;
1531 pRawData = (unsigned char*) *hRawData;
1532
1533 pSrc = bitmapData;
1534 pDest = pRawData;
1535
1536 if (bitsPerPixel == 32) {
1537 for (y = 0; y < pixelsHigh; y++) {
1538 pSrc = bitmapData + y * bytesPerRow;
1539 for (x = 0; x < pixelsWide; x += 8) {
1540 maskByte = 0;
1541 maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x80 : 0; pSrc += 4;
1542 maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x40 : 0; pSrc += 4;
1543 maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x20 : 0; pSrc += 4;
1544 maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x10 : 0; pSrc += 4;
1545 maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x08 : 0; pSrc += 4;
1546 maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x04 : 0; pSrc += 4;
1547 maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x02 : 0; pSrc += 4;
1548 maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x01 : 0; pSrc += 4;
1549 *pDest++ = maskByte;
1550 }
1551 }
1552 }
1553 else if (bitsPerPixel == 24) {
1554 memset( pDest, 255, rawDataSize );
1555 }
1556 else if (bitsPerPixel == 8) {
1557 for (y = 0; y < pixelsHigh; y++) {
1558 pSrc = bitmapData + y * bytesPerRow;
1559 for (x = 0; x < pixelsWide; x += 8) {
1560 maskByte = 0;
1561 maskByte |= *pSrc++ ? 0x80 : 0;
1562 maskByte |= *pSrc++ ? 0x40 : 0;
1563 maskByte |= *pSrc++ ? 0x20 : 0;
1564 maskByte |= *pSrc++ ? 0x10 : 0;
1565 maskByte |= *pSrc++ ? 0x08 : 0;
1566 maskByte |= *pSrc++ ? 0x04 : 0;
1567 maskByte |= *pSrc++ ? 0x02 : 0;
1568 maskByte |= *pSrc++ ? 0x01 : 0;
1569 *pDest++ = maskByte;
1570 }
1571 }
1572 }
1573 else if (bitsPerPixel == 1) {
1574 for (y = 0; y < pixelsHigh; y++) {
1575 memcpy( pDest, pSrc, pixelsWide / 8 );
1576 pDest += pixelsWide / 8;
1577 pSrc += bytesPerRow;
1578 }
1579 }
1580
1581 memcpy( pRawData+(pixelsWide*pixelsHigh)/8, pRawData, (pixelsWid e*pixelsHigh)/8 );
1582 }
1583 else
1584 {
1585 NSLog(@"get1BitMaskFromBitmapImageRep:requiredPixelSize: returni ng NULL due to bitsPerPixel == %ld, samplesPerPixel== %ld, bitsPerSample == %ld" , bitsPerPixel, samplesPerPixel, bitsPerSample);
1586 return NULL;
1587 }
1588
1589 return hRawData;
1590 }
1591
1592 - (BOOL) addResourceType:(OSType)type asResID:(int)resID
1593 {
1594 Handle hIconRes = NewHandle(0);
1595 OSErr err;
1596
1597 err = GetIconFamilyData( hIconFamily, type, hIconRes );
1598
1599 if( !GetHandleSize(hIconRes) || err != noErr )
1600 return NO;
1601
1602 AddResource( hIconRes, type, resID, "\p" );
1603
1604 return YES;
1605 }
1606
1607 @end
1608
1609 // Methods for interfacing with the Cocoa Pasteboard.
1610
1611 @implementation IconFamily (ScrapAdditions)
1612
1613 + (BOOL) canInitWithScrap
1614 {
1615 NSArray *types = [[NSPasteboard generalPasteboard] types];
1616 return [types containsObject:ICONFAMILY_UTI] || [types containsObject:ICONFA MILY_PBOARD_TYPE];
1617 }
1618
1619 + (IconFamily*) iconFamilyWithScrap
1620 {
1621 return [[[IconFamily alloc] initWithScrap] autorelease];
1622 }
1623
1624 - initWithScrap
1625 {
1626 NSPasteboard *pboard = [NSPasteboard generalPasteboard];
1627
1628 NSData *data = [pboard dataForType:ICONFAMILY_UTI];
1629 if( !data )
1630 data = [pboard dataForType:ICONFAMILY_PBOARD_TYPE];
1631 if( !data )
1632 {
1633 [self release];
1634 return nil;
1635 }
1636
1637 self = [self initWithData:data];
1638
1639 return self;
1640 }
1641
1642 - (BOOL) putOnScrap
1643 {
1644 NSPasteboard *pboard = [NSPasteboard generalPasteboard];
1645
1646 [pboard declareTypes:[NSArray arrayWithObjects:ICONFAMILY_UTI, ICONFAMILY_PB OARD_TYPE, nil] owner:self];
1647 NSData *data = [self data];
1648 [pboard setData:data forType:ICONFAMILY_UTI];
1649 [pboard setData:data forType:ICONFAMILY_PBOARD_TYPE];
1650
1651 return YES;
1652 }
1653
1654 @end
1655
1656
1657 @implementation NSFileManager (IconFamilyCompatibility)
1658
1659 - (NSDictionary *) iconfamily_attributesAtPath:(NSString *)path
1660 {
1661 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
1662 if ([!self respondsToSelector:@selector(attributesOfItemAtPath:error:)])
1663 {
1664 return [self fileAttributesAtPath:path traverseLink:NO];
1665 }
1666 #endif
1667
1668 return [self attributesOfItemAtPath:path error:NULL];
1669 }
1670
1671
1672 - (BOOL) iconfamily_setAttributes:(NSDictionary *)attributes atPath:(NSString *) path
1673 {
1674 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
1675 if ([!self respondsToSelector:@selector(setAttributes:ofItemAtPath:error :)])
1676 {
1677 return [self changeFileAttributes:attributes atPath:path];
1678 }
1679 #endif
1680
1681 return [self setAttributes:attributes ofItemAtPath:path error:NULL];
1682 }
1683
1684
1685 - (BOOL) iconfamily_removeItemAtPath:(NSString *)path
1686 {
1687 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
1688 if ([!self respondsToSelector:@selector(removeItemAtPath:error:)])
1689 {
1690 return [self removeFileAtPath:path handler:nil];
1691 }
1692 #endif
1693
1694 return [self removeItemAtPath:path error:NULL];
1695 }
1696
1697 @end
1698
1699
1700 @implementation NSImage (IconFamilyCompatibility)
1701
1702 - (NSImageRep *) iconfamily_bestRepresentation
1703 {
1704 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
1705 if ([!self respondsToSelector:@selector(bestRepresentationForRect:contex t:hints:)])
1706 {
1707 return [self bestRepresentationForDevice:nil];
1708 }
1709 #endif
1710
1711 return [self bestRepresentationForRect:(NSRect){NSZeroPoint, [self size] } context:nil hints:nil];
1712 }
1713
1714 @end
OLDNEW
« no previous file with comments | « third_party/icon_family/IconFamily.h ('k') | third_party/icon_family/LICENSE » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698