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

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

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