├── README.markdown └── source ├── Classes ├── AppDelegate.h ├── AppDelegate.m ├── IconFamily.h ├── IconFamily.m ├── NSString+CarbonFSRefCreation.h ├── NSString+CarbonFSRefCreation.m └── main.m ├── Info.plist ├── Interface ├── MacOSXPublicBeta.icns ├── MainMenu.xib └── appStore.icns ├── MakeThumbnail.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── Alex.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── Alex.xcuserdatad │ └── xcschemes │ ├── MakeThumbnail.xcscheme │ └── xcschememanagement.plist └── MakeThumbnail_Prefix.pch /README.markdown: -------------------------------------------------------------------------------- 1 | #IconFamily class 2 | 3 | by Troy Stephens, Thomas Schnitzer, David Remahl, Nathan Day, Ben Haller, Sven Janssen, Peter Hosey, Conor Dearden, Elliot Glaysher, and Dave MacLachlan 4 | 5 | ##Modifications 6 | 7 | This fork of IconFamily by **Alex Zielenski** adds the following: 8 | 9 | * Usage of ```kIconServices[size]PixelDataARGB``` types 10 | * Correct encoding of image data under Lion 11 | * Removal of deprecated APIs and replacement of equivalent up to date ones 12 | * Lossless encoding using the Accelerate APIs for 32 bit and 24 bit types 13 | * Implementation of ```NSPasteboardReading``` and ```NSPasteboardWriting``` 14 | 15 | ##Purpose 16 | 17 | "IconFamily" is a Cocoa/Objective-C wrapper for Mac OS X Icon Services' "IconFamily" data type. Its main purpose is to enable Cocoa applications to easily assign custom file icons from NSImage instances. Using the IconFamily class you can: 18 | 19 | * create a multi-representation icon family from any arbitrary NSImage 20 | * assign an icon family as a file's custom icon resource, so it will appear in Finder views 21 | * read and write .icns files 22 | * copy icon data to and from the scrap (pasteboard) 23 | * get and set the elements of an icon family in convenient, Cocoa-compatible NSBitmapImageRep form 24 | 25 | The IconFamily code started out as a small experiment that yielded a modest bit of code that has since found its way into a gratifying number of applications. It's extensively commented, so extending it further and fixing problems should be pretty easy. I welcome contributions, suggestions, and feedback that will help to improve it further. 26 | 27 | ##License 28 | 29 | The IconFamily source code is released under The MIT License, which permits commercial as well as non-commercial use. 30 | 31 | ##Download 32 | 33 | Get the latest complete source code at sourceforge. 34 | 35 | There is reference documentation for the IconFamily class on the sourceforge project page. 36 | 37 | ##Credits/Contributors 38 | 39 | I'm grateful to a number of talented and generous people for enhancements, bug fixes, and feedback that have helped improve the IconFamily code over the years. Thanks, guys! 40 | 41 | Thomas Schnitzer provided contributions to the icon family element extraction code, and valuable help in understanding the related Carbon APIs, that made the initial releases possible. 42 | 43 | David Remahl, author of Can Combine Icons, generously donated his own extensions to the IconFamily class for the 0.3 and 0.4.x releases. Nathan Day has likewise helped fix bugs and has contributed useful extensions, in the course of using the IconFamily code to build Popup Dock. Ben Haller, proprietor of Stick Software, pitched in his own contributions and dedication to get the 0.4 release of IconFamily out the door. 44 | 45 | Sven Janssen, Peter Hosey, Conor Dearden, and Elliot Glaysher reported bugs and contributed patches to modernize the IconFamily code and keep the project going in the 0.9.x releases. 46 | 47 | Dave MacLachlan of Google has contributed support for 256x256 and 512x512 icon family elements that I've rolled into a 0.9.3 release. 48 | 49 | Mike Margolis, author of Sugar Cube Software's Pic2Icon tool, has contributed support for creating shadowed, dog-eared document-like thumbnail icons that I've been meaning for a good long while now to fold into a future release. (Sorry, Mike!) 50 | 51 | 52 | -------------------------------------------------------------------------------- /source/Classes/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MakeThumbnail 4 | // 5 | // Created by Alex Zielenski on 4/7/12. 6 | // Copyright (c) 2012 Alex Zielenski. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /source/Classes/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // MakeThumbnail 4 | // 5 | // Created by Alex Zielenski on 4/7/12. 6 | // Copyright (c) 2012 Alex Zielenski. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "IconFamily.h" 11 | 12 | @implementation AppDelegate 13 | 14 | - (void)applicationDidFinishLaunching:(NSNotification *)notification { 15 | IconFamily *family = [IconFamily iconFamilyWithContentsOfFile:[[NSBundle mainBundle] pathForImageResource:@"appStore"]]; 16 | // [family writeToFile:@"/Users/Alex/Desktop/appStore.icns"]; 17 | 18 | IconFamily *cpy = [IconFamily iconFamily]; 19 | 20 | [cpy setIconFamilyElement:kIconServices1024PixelDataARGB fromBitmapImageRep:[family bitmapImageRepWithAlphaForIconFamilyElement:kIconServices1024PixelDataARGB]]; 21 | [cpy setIconFamilyElement:kIconServices512PixelDataARGB fromBitmapImageRep:[family bitmapImageRepWithAlphaForIconFamilyElement:kIconServices512PixelDataARGB]]; 22 | [cpy setIconFamilyElement:kIconServices256PixelDataARGB fromBitmapImageRep:[family bitmapImageRepWithAlphaForIconFamilyElement:kIconServices256PixelDataARGB]]; 23 | [cpy setIconFamilyElement:kIconServices128PixelDataARGB fromBitmapImageRep:[family bitmapImageRepWithAlphaForIconFamilyElement:kIconServices128PixelDataARGB]]; 24 | [cpy setIconFamilyElement:kIconServices48PixelDataARGB fromBitmapImageRep:[family bitmapImageRepWithAlphaForIconFamilyElement:kIconServices48PixelDataARGB]]; 25 | [cpy setIconFamilyElement:kIconServices32PixelDataARGB fromBitmapImageRep:[family bitmapImageRepWithAlphaForIconFamilyElement:kIconServices32PixelDataARGB]]; 26 | [cpy setIconFamilyElement:kIconServices16PixelDataARGB fromBitmapImageRep:[family bitmapImageRepWithAlphaForIconFamilyElement:kIconServices16PixelDataARGB]]; 27 | 28 | 29 | // [cpy writeToFile:@"/Users/Alex/Desktop/appStore2.icns"]; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /source/Classes/IconFamily.h: -------------------------------------------------------------------------------- 1 | // IconFamily.h 2 | // IconFamily class interface 3 | // by Troy Stephens, Thomas Schnitzer, David Remahl, Nathan Day, Ben Haller, Sven 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 project 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, whose 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 in the Software without restriction, including without limitation the rights to use, 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 all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 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 25 | #import 26 | 27 | // This class is a Cocoa/Objective-C wrapper for the Mac OS X Carbon API's 28 | // "icon family" data type. Its main purpose is to enable Cocoa applications 29 | // to easily create custom file icons from NSImage instances, and thus take 30 | // advantage of Mac OS X's new larger RGBA "thumbnail" icon format to provide 31 | // richly detailed thumbnail previews of the files' contents. 32 | // 33 | // Using IconFamily, this becomes as simple as: 34 | // 35 | // id iconFamily = [IconFamily iconFamilyWithThumbnailsOfImage:anImage]; 36 | // [iconFamily setAsCustomIconForFile:anExistingFile]; 37 | // 38 | // You can also write an icon family to an .icns file using the -writeToFile: 39 | // method. 40 | 41 | enum { 42 | kIconServices512RetinaPixelDataARGB = 'ic10', /* non-premultiplied 1024x1024 ARGB bitmap*/ 43 | kIconServices256RetinaPixelDataARGB = 'ic14', /* non-premultiplied 512x512 ARGB bitmap*/ 44 | kIconServices128RetinaPixelDataARGB = 'ic13', /* non-premultiplied 256x256 ARGB bitmap*/ 45 | kIconServices32RetinaPixelDataARGB = 'ic12', /* non-premultiplied 64x64 ARGB bitmap*/ 46 | kIconServices16RetinaPixelDataARGB = 'ic11' /* non-premultiplied 32x32 ARGB bitmap*/ 47 | }; 48 | 49 | @interface IconFamily : NSObject 50 | { 51 | IconFamilyHandle hIconFamily; 52 | } 53 | 54 | // Convenience methods. These use the corresponding -init... methods to return 55 | // an autoreleased IconFamily instance. 56 | 57 | + (IconFamily*) iconFamily; 58 | + (IconFamily*) iconFamilyWithContentsOfFile:(NSString*)path; 59 | + (IconFamily*) iconFamilyWithIconOfFile:(NSString*)path; 60 | + (IconFamily*) iconFamilyWithIconFamilyHandle:(IconFamilyHandle)hNewIconFamily; 61 | + (IconFamily*) iconFamilyWithSystemIcon:(int)fourByteCode; 62 | + (IconFamily*) iconFamilyWithThumbnailsOfImage:(NSImage*)image; 63 | + (IconFamily*) iconFamilyWithThumbnailsOfImage:(NSImage*)image usingImageInterpolation:(NSImageInterpolation)imageInterpolation; 64 | 65 | // Initializes as a new, empty IconFamily. This is IconFamily's designated 66 | // initializer method. 67 | 68 | - init; 69 | 70 | // Initializes an IconFamily by loading the contents of an .icns file. 71 | 72 | - initWithContentsOfFile:(NSString*)path; 73 | 74 | // Initializes an IconFamily from an existing Carbon IconFamilyHandle. 75 | 76 | - initWithIconFamilyHandle:(IconFamilyHandle)hNewIconFamily; 77 | 78 | // Initializes an IconFamily by loading the Finder icon that's assigned to a 79 | // file. 80 | 81 | - initWithIconOfFile:(NSString*)path; 82 | 83 | // Initializes an IconFamily by referencing a standard system icon. 84 | 85 | - initWithSystemIcon:(int)fourByteCode; 86 | 87 | // Initializes an IconFamily by creating its elements from a resampled 88 | // NSImage. The second form of this method allows you to specify the degree 89 | // of antialiasing to be used in resampling the image, by passing in one of 90 | // the NSImageInterpolation... constants that are defined in 91 | // NSGraphicsContext.h. The first form of this initializer simply calls the 92 | // second form with imageInterpolation set to NSImageInterpolationHigh, which 93 | // produces highly smoothed thumbnails. 94 | 95 | - initWithThumbnailsOfImage:(NSImage*)image; 96 | - initWithThumbnailsOfImage:(NSImage*)image usingImageInterpolation:(NSImageInterpolation)imageInterpolation; 97 | 98 | // Writes the icon family to an .icns file. 99 | 100 | - (BOOL) writeToFile:(NSString*)path; 101 | 102 | // Sets the image data for one of the icon family's elements from an 103 | // NSBitmapImageRep. The "elementType" parameter must be one of the icon 104 | // family element types listed below, and the format of the "bitmapImageRep" 105 | // must match the corresponding requirements specified below. Regardless of 106 | // the elementType, the bitmapImageRep must also be non-planar and have 8 bits 107 | // per sample. 108 | // 109 | // elementType dimensions format 110 | // ------------------- ---------- --------------------------------------- 111 | // kIconServices512PixelDataARGB 512 x 512 32-bit RGBA, 32-bit RGB, or 24-bit RGB 112 | // kIconServices256PixelDataARGB 256 x 256 32-bit RGBA, 32-bit RGB, or 24-bit RGB 113 | // kThumbnail32BitData 128 x 128 32-bit RGBA, 32-bit RGB, or 24-bit RGB 114 | // kThumbnail8BitMask 128 x 128 32-bit RGBA or 8-bit intensity 115 | // kLarge32BitData 32 x 32 32-bit RGBA, 32-bit RGB, or 24-bit RGB 116 | // kLarge8BitMask 32 x 32 32-bit RGBA or 8-bit intensity 117 | // kLarge1BitMask 32 x 32 32-bit RGBA, 8-bit intensity, or 1-bit 118 | // kSmall32BitData 16 x 16 32-bit RGBA, 32-bit RGB, or 24-bit RGB 119 | // kSmall8BitMask 16 x 16 32-bit RGBA or 8-bit intensity 120 | // kSmall1BitMask 16 x 16 32-bit RGBA, 8-bit intensity, or 1-bit 121 | // 122 | // When an RGBA image is supplied to set a "Mask" element, the mask data is 123 | // taken from the image's alpha channel. 124 | // 125 | // NOTE: Setting an IconFamily's kLarge1BitMask seems to damage the IconFamily 126 | // for some as yet unknown reason. (If you then assign the icon family 127 | // as a file's custom icon using -setAsCustomIconForFile:, the custom 128 | // icon doesn't appear for the file in the Finder.) However, both 129 | // custom icon display and mouse-click hit-testing in the Finder seem to 130 | // work fine when we only set the other four elements (thus keeping the 131 | // existing kLarge1BitMask from the valid icon family from which we 132 | // initialized the IconFamily via -initWithContentsOfFile:, since 133 | // IconFamily's -init method is currently broken...), so it seems safe 134 | // to just leave the kLarge1BitMask alone. 135 | 136 | - (BOOL) setIconFamilyElement:(OSType)elementType 137 | fromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep; 138 | 139 | // Gets the image data for one of the icon family's elements as a new, 32-bit 140 | // RGBA NSBitmapImageRep. The specified elementType should be one of 141 | // kIconServices512PixelDataARGB, kIconServices256PixelDataARGB, 142 | // kThumbnail32BitData, kLarge32BitData, or kSmall32BitData. 143 | // 144 | // The returned NSBitmapImageRep will have the corresponding 8-bit mask data 145 | // in its alpha channel, or a fully opaque alpha channel if the icon family 146 | // has no 8-bit mask data for the specified alpha channel. 147 | // 148 | // Returns nil if the requested element cannot be retrieved (e.g. if the 149 | // icon family has no such 32BitData element). 150 | 151 | - (NSBitmapImageRep*) bitmapImageRepWithAlphaForIconFamilyElement:(OSType)elementType; 152 | 153 | // Creates and returns an NSImage that contains the icon family's various 154 | // elements as its NSImageReps. 155 | 156 | - (NSImage*) imageWithAllReps; 157 | 158 | // NOTE: Planned method -- not yet implemented. 159 | // 160 | // Gets the image data for one of the icon family's elements as a new 161 | // NSBitmapImageRep. The specified elementType should be one of 162 | // kThumbnail32BitData, kThumbnail32BitMask, kLarge32BitData, kLarge8BitMask, 163 | // kLarge1BitMask, kSmall32BitData, kSmall8BitMask, or kSmall1BitMask. 164 | 165 | // - (NSBitmapImageRep*) bitmapImageRepForIconFamilyElement:(OSType)elementType; 166 | 167 | // Writes the icon family to the resource fork of the specified file as its 168 | // kCustomIconResource, and sets the necessary Finder bits so the icon will 169 | // be displayed for the file in Finder views. 170 | 171 | - (BOOL) setAsCustomIconForFile:(NSString*)path; 172 | - (BOOL) setAsCustomIconForFile:(NSString*)path withCompatibility:(BOOL)compat; 173 | - (BOOL) setAsCustomIconForFile:(NSString*)path withCompatibility:(BOOL)compat error:(NSError **)error; 174 | 175 | // Same as the -setAsCustomIconForFile:... methods, but for folders (directories). 176 | 177 | - (BOOL) setAsCustomIconForDirectory:(NSString*)path; 178 | - (BOOL) setAsCustomIconForDirectory:(NSString*)path withCompatibility:(BOOL)compat; 179 | - (BOOL) setAsCustomIconForDirectory:(NSString*)path withCompatibility:(BOOL)compat error:(NSError **)error; 180 | 181 | // Removes the custom icon (if any) from the specified file's resource fork, 182 | // and clears the necessary Finder bits for the file. (Note that this is a 183 | // class method, so you don't need an instance of IconFamily to invoke it.) 184 | 185 | + (BOOL) removeCustomIconFromFile:(NSString*)path; 186 | 187 | //Same as the -removeCustomIconFromFile: method, but for folders (directories). 188 | 189 | + (BOOL) removeCustomIconFromDirectory:(NSString*)path; 190 | + (BOOL) removeCustomIconFromDirectory:(NSString*)path error:(NSError **)error; 191 | 192 | - (NSData *)data; 193 | + (BOOL)canInitWithPasteboard:(NSPasteboard *)pasteboard; 194 | 195 | @end 196 | -------------------------------------------------------------------------------- /source/Classes/IconFamily.m: -------------------------------------------------------------------------------- 1 | // IconFamily.m 2 | // IconFamily class implementation 3 | // by Troy Stephens, Thomas Schnitzer, David Remahl, Nathan Day, Ben Haller, Sven 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 project 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, whose 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 in the Software without restriction, including without limitation the rights to use, 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 all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 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 | #import 27 | 28 | // Necessary on 10.5 for Preview's "New with Clipboard" menu item to see the IconFamily data. 29 | #define ICONFAMILY_UTI @"com.apple.icns" 30 | 31 | // Determined by using Pasteboard Manager to put com.apple.icns data on the clipboard. Alternatively, you can determine this by copying an application to the clipboard using the Finder (select an application and press cmd-C). 32 | #define ICONFAMILY_PBOARD_TYPE @"'icns' (CorePasteboardFlavorType 0x69636E73)" 33 | 34 | @interface IconFamily (Internals) 35 | 36 | + (NSImage*) resampleImage:(NSImage*)image toIconWidth:(int)width usingImageInterpolation:(NSImageInterpolation)imageInterpolation; 37 | 38 | + (Handle) get32BitDataFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize; 39 | 40 | + (Handle) get8BitDataFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize; 41 | 42 | + (Handle) get8BitMaskFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize; 43 | 44 | + (Handle) get1BitMaskFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize; 45 | 46 | - (BOOL) addResourceType:(OSType)type asResID:(int)resID; 47 | 48 | @end 49 | 50 | @implementation IconFamily 51 | 52 | + (IconFamily*) iconFamily 53 | { 54 | return [[[IconFamily alloc] init] autorelease]; 55 | } 56 | 57 | + (IconFamily*) iconFamilyWithContentsOfFile:(NSString*)path 58 | { 59 | return [[[IconFamily alloc] initWithContentsOfFile:path] autorelease]; 60 | } 61 | 62 | + (IconFamily*) iconFamilyWithIconOfFile:(NSString*)path 63 | { 64 | return [[[IconFamily alloc] initWithIconOfFile:path] autorelease]; 65 | } 66 | 67 | + (IconFamily*) iconFamilyWithIconFamilyHandle:(IconFamilyHandle)hNewIconFamily 68 | { 69 | return [[[IconFamily alloc] initWithIconFamilyHandle:hNewIconFamily] autorelease]; 70 | } 71 | 72 | + (IconFamily*) iconFamilyWithSystemIcon:(int)fourByteCode 73 | { 74 | return [[[IconFamily alloc] initWithSystemIcon:fourByteCode] autorelease]; 75 | } 76 | 77 | + (IconFamily*) iconFamilyWithThumbnailsOfImage:(NSImage*)image 78 | { 79 | return [[[IconFamily alloc] initWithThumbnailsOfImage:image] autorelease]; 80 | } 81 | 82 | + (IconFamily*) iconFamilyWithThumbnailsOfImage:(NSImage*)image usingImageInterpolation:(NSImageInterpolation)imageInterpolation 83 | { 84 | return [[[IconFamily alloc] initWithThumbnailsOfImage:image usingImageInterpolation:imageInterpolation] autorelease]; 85 | } 86 | 87 | // This is IconFamily's designated initializer. It creates a new IconFamily that initially has no elements. 88 | // 89 | // The proper way to do this is to simply allocate a zero-sized handle (not to be confused with an empty handle) and assign it to hIconFamily. This technique works on Mac OS X 10.2 as well as on 10.0.x and 10.1.x. Our previous technique of allocating an IconFamily struct with a resourceSize of 0 no longer works as of Mac OS X 10.2. 90 | - init 91 | { 92 | self = [super init]; 93 | if (self) { 94 | hIconFamily = (IconFamilyHandle) NewHandle( 0 ); 95 | if (hIconFamily == NULL) { 96 | [self autorelease]; 97 | return nil; 98 | } 99 | } 100 | return self; 101 | } 102 | 103 | - initWithData:(NSData *)data 104 | { 105 | self = [self init]; 106 | if (self) { 107 | Handle storageMem = NULL; 108 | 109 | OSStatus err = PtrToHand([data bytes], &storageMem, (long)[data length]); 110 | if( err != noErr ) 111 | { 112 | [self release]; 113 | return nil; 114 | } 115 | 116 | hIconFamily = (IconFamilyHandle)storageMem; 117 | } 118 | return self; 119 | } 120 | 121 | - initWithContentsOfFile:(NSString*)path 122 | { 123 | FSRef ref; 124 | OSStatus result; 125 | 126 | self = [self init]; 127 | if (self) { 128 | if (hIconFamily) { 129 | DisposeHandle( (Handle)hIconFamily ); 130 | hIconFamily = NULL; 131 | } 132 | if (![path getFSRef:&ref createFileIfNecessary:NO]) { 133 | [self autorelease]; 134 | return nil; 135 | } 136 | result = ReadIconFromFSRef( &ref, &hIconFamily ); 137 | if (result != noErr) { 138 | [self autorelease]; 139 | return nil; 140 | } 141 | } 142 | return self; 143 | } 144 | 145 | - initWithIconFamilyHandle:(IconFamilyHandle)hNewIconFamily 146 | { 147 | self = [self init]; 148 | if (self) { 149 | if (hIconFamily) { 150 | DisposeHandle( (Handle)hIconFamily ); 151 | hIconFamily = NULL; 152 | } 153 | hIconFamily = hNewIconFamily; 154 | } 155 | return self; 156 | } 157 | 158 | - initWithIconOfFile:(NSString*)path 159 | { 160 | IconRef iconRef; 161 | OSStatus result; 162 | SInt16 label; 163 | FSRef ref; 164 | 165 | self = [self init]; 166 | if (self) 167 | { 168 | if (hIconFamily) 169 | { 170 | DisposeHandle( (Handle)hIconFamily ); 171 | hIconFamily = NULL; 172 | } 173 | 174 | if( ![path getFSRef:&ref createFileIfNecessary:NO] ) 175 | { 176 | [self autorelease]; 177 | return nil; 178 | } 179 | 180 | result = GetIconRefFromFileInfo( 181 | &ref, 182 | /*inFileNameLength*/ 0, 183 | /*inFileName*/ NULL, 184 | kFSCatInfoNone, 185 | /*inCatalogInfo*/ NULL, 186 | kIconServicesNormalUsageFlag, 187 | &iconRef, 188 | &label ); 189 | 190 | if (result != noErr) 191 | { 192 | [self autorelease]; 193 | return nil; 194 | } 195 | 196 | result = IconRefToIconFamily( 197 | iconRef, 198 | kSelectorAllAvailableData, 199 | &hIconFamily ); 200 | 201 | ReleaseIconRef( iconRef ); 202 | 203 | if (result != noErr || !hIconFamily) 204 | { 205 | [self autorelease]; 206 | return nil; 207 | } 208 | } 209 | return self; 210 | } 211 | 212 | - initWithSystemIcon:(int)fourByteCode 213 | { 214 | IconRef iconRef; 215 | OSErr result; 216 | 217 | self = [self init]; 218 | if (self) 219 | { 220 | if (hIconFamily) 221 | { 222 | DisposeHandle( (Handle)hIconFamily ); 223 | hIconFamily = NULL; 224 | } 225 | 226 | result = GetIconRef(kOnSystemDisk, kSystemIconsCreator, fourByteCode, &iconRef); 227 | 228 | if (result != noErr) 229 | { 230 | [self autorelease]; 231 | return nil; 232 | } 233 | 234 | result = IconRefToIconFamily( 235 | iconRef, 236 | kSelectorAllAvailableData, 237 | &hIconFamily ); 238 | 239 | if (result != noErr || !hIconFamily) 240 | { 241 | [self autorelease]; 242 | return nil; 243 | } 244 | 245 | ReleaseIconRef( iconRef ); 246 | } 247 | return self; 248 | } 249 | 250 | - initWithThumbnailsOfImage:(NSImage*)image 251 | { 252 | // The default is to use a high degree of antialiasing, producing a smooth image. 253 | return [self initWithThumbnailsOfImage:image usingImageInterpolation:NSImageInterpolationHigh]; 254 | } 255 | 256 | - initWithThumbnailsOfImage:(NSImage*)image usingImageInterpolation:(NSImageInterpolation)imageInterpolation 257 | { 258 | NSImage* iconImage1024x1024; 259 | NSImage* iconImage512x512; 260 | NSImage* iconImage256x256; 261 | NSImage* iconImage128x128; 262 | NSImage* iconImage48x48; 263 | NSImage* iconImage32x32; 264 | NSImage* iconImage16x16; 265 | NSImage* bitmappedIconImage1024x1024; 266 | NSBitmapImageRep* iconBitmap1024x1024; 267 | NSBitmapImageRep* iconBitmap512x512; 268 | NSBitmapImageRep* iconBitmap256x256; 269 | NSBitmapImageRep* iconBitmap128x128; 270 | NSBitmapImageRep* iconBitmap48x48; 271 | NSBitmapImageRep* iconBitmap32x32; 272 | NSBitmapImageRep* iconBitmap16x16; 273 | 274 | // Start with a new, empty IconFamily. 275 | self = [self init]; 276 | if (self == nil) 277 | return nil; 278 | 279 | // Resample the given image to create a 1024x1024 pixel, 32-bit RGBA 280 | // version, and use that as our "thumbnail" (1024x1024) icon and mask. 281 | // 282 | // Our +resampleImage:toIconWidth:... method, in its present form, 283 | // returns an NSImage that contains an NSCacheImageRep, rather than 284 | // an NSBitmapImageRep. We convert to an NSBitmapImageRep, so that 285 | // our methods can scan the image data, using initWithFocusedViewRect:. 286 | 287 | iconImage1024x1024 = [IconFamily resampleImage:image toIconWidth:1024 usingImageInterpolation:imageInterpolation]; 288 | if (!iconImage1024x1024) { 289 | [self autorelease]; 290 | return nil; 291 | } 292 | 293 | [iconImage1024x1024 lockFocus]; 294 | iconBitmap1024x1024 = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, 1024, 1024)] autorelease]; 295 | [iconImage1024x1024 unlockFocus]; 296 | if (!iconBitmap1024x1024) { 297 | [self release]; 298 | return nil; 299 | } 300 | // Create an NSImage with the iconBitmap1024x1024 NSBitmapImageRep, that we 301 | // can resample to create the smaller icon family elements. (This is 302 | // most likely more efficient than resampling from the original image again, 303 | // particularly if it is large. It produces a slightly different result, but 304 | // the difference is minor and should not be objectionable...) 305 | 306 | bitmappedIconImage1024x1024 = [[NSImage alloc] initWithSize:NSMakeSize(1024, 1024)]; 307 | [bitmappedIconImage1024x1024 addRepresentation:iconBitmap1024x1024]; 308 | 309 | if (!bitmappedIconImage1024x1024) { 310 | [self autorelease]; 311 | return nil; 312 | } 313 | 314 | [self setIconFamilyElement:kIconServices1024PixelDataARGB fromBitmapImageRep:iconBitmap1024x1024]; 315 | 316 | iconImage512x512 = [IconFamily resampleImage:bitmappedIconImage1024x1024 toIconWidth:512 usingImageInterpolation:imageInterpolation]; 317 | if (iconImage512x512) { 318 | [iconImage512x512 lockFocus]; 319 | iconBitmap512x512 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, 512, 512)]; 320 | [iconImage512x512 unlockFocus]; 321 | if (iconImage512x512) { 322 | [self setIconFamilyElement:kIconServices512PixelDataARGB fromBitmapImageRep:iconBitmap512x512]; 323 | [iconBitmap512x512 release]; 324 | } 325 | } 326 | 327 | iconImage256x256 = [IconFamily resampleImage:bitmappedIconImage1024x1024 toIconWidth:256 usingImageInterpolation:imageInterpolation]; 328 | if (iconImage256x256) { 329 | [iconImage256x256 lockFocus]; 330 | iconBitmap256x256 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, 256, 256)]; 331 | [iconImage256x256 unlockFocus]; 332 | if (iconBitmap256x256) { 333 | [self setIconFamilyElement:kIconServices256PixelDataARGB fromBitmapImageRep:iconBitmap256x256]; 334 | [iconBitmap256x256 release]; 335 | } 336 | } 337 | 338 | iconImage128x128 = [IconFamily resampleImage:bitmappedIconImage1024x1024 toIconWidth:128 usingImageInterpolation:imageInterpolation]; 339 | if (iconImage128x128) { 340 | [iconImage128x128 lockFocus]; 341 | iconBitmap128x128 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, 128, 128)]; 342 | [iconImage128x128 unlockFocus]; 343 | 344 | if (iconBitmap128x128) { 345 | [self setIconFamilyElement:kIconServices128PixelDataARGB fromBitmapImageRep:iconBitmap128x128]; 346 | [iconBitmap128x128 release]; 347 | } 348 | } 349 | 350 | // Resample the 1024x1024 image to create a 48x48 pixel, 32-bit RGBA version, 351 | // and use that as our "huge" (48x48) icon and 8-bit mask. 352 | iconImage48x48 = [IconFamily resampleImage:bitmappedIconImage1024x1024 toIconWidth:48 usingImageInterpolation:imageInterpolation]; 353 | if (iconImage48x48) { 354 | [iconImage48x48 lockFocus]; 355 | iconBitmap48x48 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, 48, 48)]; 356 | [iconImage48x48 unlockFocus]; 357 | if (iconBitmap48x48) { 358 | [self setIconFamilyElement:kIconServices48PixelDataARGB fromBitmapImageRep:iconBitmap48x48]; 359 | [iconBitmap48x48 release]; 360 | } 361 | } 362 | 363 | // Resample the 1024x1024 image to create a 32x32 pixel, 32-bit RGBA version, 364 | // and use that as our "large" (32x32) icon and 8-bit mask. 365 | iconImage32x32 = [IconFamily resampleImage:bitmappedIconImage1024x1024 toIconWidth:32 usingImageInterpolation:imageInterpolation]; 366 | if (iconImage32x32) { 367 | [iconImage32x32 lockFocus]; 368 | iconBitmap32x32 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, 32, 32)]; 369 | [iconImage32x32 unlockFocus]; 370 | if (iconBitmap32x32) { 371 | [self setIconFamilyElement:kIconServices32PixelDataARGB fromBitmapImageRep:iconBitmap32x32]; 372 | [iconBitmap32x32 release]; 373 | } 374 | } 375 | 376 | // Resample the 1024x1024 image to create a 16x16 pixel, 32-bit RGBA version, 377 | // and use that as our "small" (16x16) icon and 8-bit mask. 378 | iconImage16x16 = [IconFamily resampleImage:bitmappedIconImage1024x1024 toIconWidth:16 usingImageInterpolation:imageInterpolation]; 379 | if (iconImage16x16) { 380 | [iconImage16x16 lockFocus]; 381 | iconBitmap16x16 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, 16, 16)]; 382 | [iconImage16x16 unlockFocus]; 383 | if (iconBitmap16x16) { 384 | [self setIconFamilyElement:kIconServices16PixelDataARGB fromBitmapImageRep:iconBitmap16x16]; 385 | [iconBitmap16x16 release]; 386 | } 387 | } 388 | 389 | // Release the icon. 390 | [bitmappedIconImage1024x1024 release]; 391 | 392 | // Return the new icon family! 393 | return self; 394 | } 395 | 396 | - (void) dealloc 397 | { 398 | DisposeHandle( (Handle)hIconFamily ); 399 | [super dealloc]; 400 | } 401 | 402 | - (void) finalize 403 | { 404 | /* "Starting with Mac OS X v10.3, Memory Manager is thread safe" 405 | -- Memory Manager Reference 406 | */ 407 | DisposeHandle( (Handle)hIconFamily ); 408 | hIconFamily = NULL; 409 | 410 | [super finalize]; 411 | } 412 | 413 | - (NSBitmapImageRep*) bitmapImageRepWithAlphaForIconFamilyElement:(OSType)elementType; 414 | { 415 | NSBitmapImageRep* bitmapImageRep; 416 | NSInteger pixelsWide; 417 | Handle hRawBitmapData; 418 | Handle hRawMaskData = NULL; 419 | OSType maskElementType; 420 | NSBitmapFormat bitmapFormat = NSAlphaFirstBitmapFormat; 421 | OSErr result; 422 | UInt32* pRawBitmapData; 423 | UInt32* pRawBitmapDataEnd; 424 | unsigned char* pRawMaskData; 425 | unsigned char* pBitmapImageRepBitmapData; 426 | 427 | // Make sure elementType is a valid type that we know how to handle, and 428 | // figure out the dimensions and bit depth of the bitmap for that type. 429 | switch (elementType) 430 | { 431 | // 'ic10' 1024x1024 32-bit RGB image 432 | case kIconServices512RetinaPixelDataARGB: 433 | maskElementType = 0; 434 | pixelsWide = 1024; 435 | break; 436 | // 'ic14' 512x512 32-bit RGB image 437 | case kIconServices256RetinaPixelDataARGB: 438 | maskElementType = 0; 439 | pixelsWide = 512; 440 | break; 441 | // 'ic13' 256x256 32-bit RGB image 442 | case kIconServices128RetinaPixelDataARGB: 443 | maskElementType = 0; 444 | pixelsWide = 256; 445 | break; 446 | // 'ic12' 64x64 32-bit RGB image 447 | case kIconServices32RetinaPixelDataARGB: 448 | maskElementType = 0; 449 | pixelsWide = 64; 450 | break; 451 | // 'ic11' 32x32 32-bit RGB image 452 | case kIconServices16RetinaPixelDataARGB: 453 | maskElementType = 0; 454 | pixelsWide = 32; 455 | break; 456 | 457 | #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 458 | // 'ic09' 512x512 32-bit RGB image 459 | case kIconServices512PixelDataARGB: 460 | maskElementType = 0; 461 | pixelsWide = 512; 462 | break; 463 | #endif 464 | 465 | // 'ic08' 256x256 32-bit ARGB image 466 | case kIconServices256PixelDataARGB: 467 | maskElementType = 0; 468 | pixelsWide = 256; 469 | break; 470 | 471 | case kIconServices128PixelDataARGB: 472 | maskElementType = 0; 473 | pixelsWide = 128; 474 | break; 475 | 476 | case kIconServices48PixelDataARGB: 477 | maskElementType = 0; 478 | pixelsWide = 48; 479 | break; 480 | 481 | case kIconServices32PixelDataARGB: 482 | maskElementType = 0; 483 | pixelsWide = 32; 484 | break; 485 | 486 | case kIconServices16PixelDataARGB: 487 | maskElementType = 0; 488 | pixelsWide = 16; 489 | break; 490 | 491 | // 'it32' 128x128 32-bit RGB image 492 | case kThumbnail32BitData: 493 | maskElementType = kThumbnail8BitMask; 494 | pixelsWide = 128; 495 | break; 496 | 497 | // 'ih32' 48x48 32-bit RGB image 498 | case kHuge32BitData: 499 | maskElementType = kHuge8BitMask; 500 | pixelsWide = 48; 501 | break; 502 | 503 | // 'il32' 32x32 32-bit RGB image 504 | case kLarge32BitData: 505 | maskElementType = kLarge8BitMask; 506 | pixelsWide = 32; 507 | break; 508 | 509 | // 'is32' 16x16 32-bit RGB image 510 | case kSmall32BitData: 511 | maskElementType = kSmall8BitMask; 512 | pixelsWide = 16; 513 | break; 514 | 515 | default: 516 | return nil; 517 | } 518 | 519 | // Get the raw, uncompressed bitmap data for the requested element. 520 | hRawBitmapData = NewHandle( pixelsWide * pixelsWide * 4 ); 521 | result = GetIconFamilyData( hIconFamily, elementType, hRawBitmapData ); 522 | if (result != noErr) { 523 | DisposeHandle( hRawBitmapData ); 524 | return nil; 525 | } 526 | 527 | if (maskElementType) { 528 | // Get the corresponding raw, uncompressed 8-bit mask data. 529 | hRawMaskData = NewHandle( pixelsWide * pixelsWide ); 530 | result = GetIconFamilyData( hIconFamily, maskElementType, hRawMaskData ); 531 | if (result != noErr) { 532 | DisposeHandle( hRawMaskData ); 533 | hRawMaskData = NULL; 534 | } 535 | } 536 | 537 | // 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 same, regardless of whether we're running on a big-endian (PPC) or little-endian (Intel) architecture.) 538 | 539 | pRawBitmapData = (UInt32*) *hRawBitmapData; 540 | pRawBitmapDataEnd = pRawBitmapData + pixelsWide * pixelsWide; 541 | if (hRawMaskData) { 542 | 543 | pRawMaskData = (UInt8*) *hRawMaskData; 544 | while (pRawBitmapData < pRawBitmapDataEnd) { 545 | 546 | *pRawBitmapData = CFSwapInt32BigToHost((*pRawMaskData++ << 24) | CFSwapInt32HostToBig(*pRawBitmapData)); 547 | ++pRawBitmapData; 548 | 549 | } 550 | 551 | } else { 552 | if(maskElementType) { 553 | // We SHOULD have a mask, but apparently not. Fake it with alpha=1. 554 | while (pRawBitmapData < pRawBitmapDataEnd) { 555 | *(unsigned char *)pRawBitmapData = 0xff; 556 | ++pRawBitmapData; 557 | } 558 | } 559 | } 560 | 561 | // Create a new NSBitmapImageRep with the given bitmap data. Note that 562 | // when creating the NSBitmapImageRep we pass in NULL for the "planes" 563 | // parameter. This causes the new NSBitmapImageRep to allocate its own 564 | // buffer for the bitmap data (which it will own and release when the 565 | // NSBitmapImageRep is released), rather than referencing the bitmap 566 | // data we pass in (which will soon disappear when we call 567 | // DisposeHandle() below!). (See the NSBitmapImageRep documentation for 568 | // the -initWithBitmapDataPlanes:... method, where this is explained.) 569 | // 570 | // Once we have the new NSBitmapImageRep, we get a pointer to its 571 | // bitmapData and copy our bitmap data in. 572 | bitmapImageRep = [[[NSBitmapImageRep alloc] 573 | initWithBitmapDataPlanes:NULL 574 | pixelsWide:pixelsWide 575 | pixelsHigh:pixelsWide 576 | bitsPerSample:8 577 | samplesPerPixel:4 578 | hasAlpha:YES 579 | isPlanar:NO 580 | colorSpaceName:NSDeviceRGBColorSpace // NOTE: is this right? 581 | bitmapFormat:bitmapFormat 582 | bytesPerRow:0 583 | bitsPerPixel:0] autorelease]; 584 | pBitmapImageRepBitmapData = [bitmapImageRep bitmapData]; 585 | if (pBitmapImageRepBitmapData) { 586 | memcpy( pBitmapImageRepBitmapData, *hRawBitmapData, 587 | pixelsWide * pixelsWide * 4 ); 588 | } 589 | // HUnlock( hRawBitmapData ); // Handle-based memory isn't compacted anymore, so calling HLock()/HUnlock() is unnecessary. 590 | 591 | // Free the retrieved raw data. 592 | DisposeHandle( hRawBitmapData ); 593 | if (hRawMaskData) 594 | DisposeHandle( hRawMaskData ); 595 | 596 | // Return nil if the NSBitmapImageRep didn't give us a buffer to copy into. 597 | if (pBitmapImageRepBitmapData == NULL) 598 | return nil; 599 | 600 | // Return the new NSBitmapImageRep. 601 | return bitmapImageRep; 602 | } 603 | 604 | - (NSImage*) imageWithAllReps 605 | { 606 | NSImage* image = NULL; 607 | image = [[[NSImage alloc] initWithData:[NSData dataWithBytes:*hIconFamily length:GetHandleSize((Handle)hIconFamily)]] autorelease]; 608 | return image; 609 | } 610 | 611 | - (BOOL) setIconFamilyElement:(OSType)elementType fromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep 612 | { 613 | if (!bitmapImageRep) 614 | return NO; 615 | 616 | Handle hRawData = NULL; 617 | OSErr result; 618 | 619 | switch (elementType) 620 | { 621 | // 'ic10' 1024x1024 32-bit ARGB image 622 | case kIconServices512RetinaPixelDataARGB: 623 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:1024]; 624 | break; 625 | 626 | // 'ic14' 512x512 32-bit ARGB image 627 | case kIconServices256RetinaPixelDataARGB: 628 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:512]; 629 | break; 630 | 631 | // 'ic13' 256x256 32-bit ARGB image 632 | case kIconServices128RetinaPixelDataARGB: 633 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:256]; 634 | break; 635 | 636 | // 'ic12' 64x64 32-bit ARGB image 637 | case kIconServices32RetinaPixelDataARGB: 638 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:64]; 639 | break; 640 | 641 | // 'ic11' 32x32 32-bit ARGB image 642 | case kIconServices16RetinaPixelDataARGB: 643 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:32]; 644 | break; 645 | 646 | // 'ic09' 512x512 32-bit ARGB image 647 | case kIconServices512PixelDataARGB: 648 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:512]; 649 | break; 650 | 651 | // 'ic08' 256x256 32-bit ARGB image 652 | case kIconServices256PixelDataARGB: 653 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:256]; 654 | break; 655 | 656 | // 'ic07' 128x128 32-bit ARGB image 657 | case kIconServices128PixelDataARGB: 658 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:128]; 659 | break; 660 | 661 | // 'ic06' 256x256 32-bit ARGB image 662 | case kIconServices48PixelDataARGB: 663 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:48]; 664 | break; 665 | 666 | // 'ic05' 256x256 32-bit ARGB image 667 | case kIconServices32PixelDataARGB: 668 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:32]; 669 | break; 670 | 671 | // 'ic04' 256x256 32-bit ARGB image 672 | case kIconServices16PixelDataARGB: 673 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:16]; 674 | break; 675 | 676 | // 'it32' 128x128 32-bit RGB image 677 | case kThumbnail32BitData: 678 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:128]; 679 | break; 680 | 681 | // 't8mk' 128x128 8-bit alpha mask 682 | case kThumbnail8BitMask: 683 | hRawData = [IconFamily get8BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:128]; 684 | break; 685 | 686 | // 'ih48' 48x48 32-bit RGB image 687 | case kHuge32BitData: 688 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:48]; 689 | break; 690 | 691 | // 'h8mk' 48x49 8-bit alpha mask 692 | case kHuge8BitMask: 693 | hRawData = [IconFamily get8BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:48]; 694 | break; 695 | 696 | // 'ich#' 48x48 1-bit alpha mask 697 | case kHuge1BitMask: 698 | hRawData = [IconFamily get1BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:48]; 699 | break; 700 | 701 | // 'ich8' 48x48 8-bit indexed image data 702 | case kHuge8BitData: 703 | hRawData = [IconFamily get8BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:48]; 704 | break; 705 | 706 | // 'il32' 32x32 32-bit RGB image 707 | case kLarge32BitData: 708 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:32]; 709 | break; 710 | 711 | // 'l8mk' 32x32 8-bit alpha mask 712 | case kLarge8BitMask: 713 | hRawData = [IconFamily get8BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:32]; 714 | break; 715 | 716 | // 'ICN#' 32x32 1-bit alpha mask 717 | case kLarge1BitMask: 718 | hRawData = [IconFamily get1BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:32]; 719 | break; 720 | 721 | // 'icl8' 32x32 8-bit indexed image data 722 | case kLarge8BitData: 723 | hRawData = [IconFamily get8BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:32]; 724 | break; 725 | 726 | // 'is32' 16x16 32-bit RGB image 727 | case kSmall32BitData: 728 | hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:16]; 729 | break; 730 | 731 | // 's8mk' 16x16 8-bit alpha mask 732 | case kSmall8BitMask: 733 | hRawData = [IconFamily get8BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:16]; 734 | break; 735 | 736 | // 'ics#' 16x16 1-bit alpha mask 737 | case kSmall1BitMask: 738 | hRawData = [IconFamily get1BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:16]; 739 | break; 740 | 741 | // 'ics8' 16x16 8-bit indexed image data 742 | case kSmall8BitData: 743 | hRawData = [IconFamily get8BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:16]; 744 | break; 745 | 746 | default: 747 | return NO; 748 | } 749 | 750 | // NSLog(@"setIconFamilyElement:%@ fromBitmapImageRep:%@ generated handle %p of size %d", NSFileTypeForHFSTypeCode(elementType), bitmapImageRep, hRawData, GetHandleSize(hRawData)); 751 | 752 | if (hRawData == NULL) 753 | { 754 | NSLog(@"Null data returned to setIconFamilyElement:fromBitmapImageRep:"); 755 | return NO; 756 | } 757 | 758 | result = SetIconFamilyData( hIconFamily, elementType, hRawData ); 759 | DisposeHandle( hRawData ); 760 | 761 | if (result != noErr) 762 | { 763 | NSLog(@"SetIconFamilyData() returned error %d", result); 764 | return NO; 765 | } 766 | 767 | return YES; 768 | } 769 | 770 | - (BOOL) setAsCustomIconForFile:(NSString*)path 771 | { 772 | return( [self setAsCustomIconForFile:path withCompatibility:NO error:NULL] ); 773 | } 774 | 775 | - (BOOL) setAsCustomIconForFile:(NSString*)path withCompatibility:(BOOL)compat 776 | { 777 | return( [self setAsCustomIconForFile:path withCompatibility:NO error:NULL] ); 778 | } 779 | 780 | - (BOOL) setAsCustomIconForFile:(NSString*)path withCompatibility:(BOOL)compat error:(NSError **)error 781 | { 782 | FSRef targetFileFSRef; 783 | FSRef parentDirectoryFSRef; 784 | SInt16 file; 785 | OSStatus result; 786 | struct FSCatalogInfo catInfo; 787 | struct FileInfo *finderInfo = (struct FileInfo *)&catInfo.finderInfo; 788 | Handle hExistingCustomIcon; 789 | Handle hIconFamilyCopy; 790 | NSString *parentDirectory; 791 | 792 | // Before we do anything, get the original modification time for the target file. 793 | NSDate* modificationDate = [[[NSFileManager defaultManager] attributesOfItemAtPath:path error:error] objectForKey:NSFileModificationDate]; 794 | 795 | if ([path isAbsolutePath]) 796 | parentDirectory = [path stringByDeletingLastPathComponent]; 797 | else 798 | parentDirectory = [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:[path stringByDeletingLastPathComponent]]; 799 | 800 | // Get an FSRef for the target file's parent directory that we can use in 801 | // the FSCreateResFile() and FNNotify() calls below. 802 | if (![parentDirectory getFSRef:&parentDirectoryFSRef createFileIfNecessary:NO]) 803 | return NO; 804 | 805 | // Get the name of the file, for FSCreateResFile. 806 | struct HFSUniStr255 filename; 807 | NSString *filenameString = [path lastPathComponent]; 808 | filename.length = [filenameString length]; 809 | [filenameString getCharacters:filename.unicode]; 810 | 811 | // Make sure the file has a resource fork that we can open. (Although 812 | // this sounds like it would clobber an existing resource fork, the Carbon 813 | // Resource Manager docs for this function say that's not the case. If 814 | // the file already has a resource fork, we receive a result code of 815 | // dupFNErr, which is not really an error per se, but just a notification 816 | // to us that creating a new resource fork for the file was not necessary.) 817 | FSCreateResFile( 818 | &parentDirectoryFSRef, 819 | filename.length, 820 | filename.unicode, 821 | kFSCatInfoNone, 822 | /*catalogInfo/*/ NULL, 823 | &targetFileFSRef, 824 | /*newSpec*/ NULL); 825 | result = ResError(); 826 | if (result == dupFNErr) { 827 | // If the call to FSCreateResFile() returned dupFNErr, targetFileFSRef will not have been set, so create it from the path. 828 | if (![path getFSRef:&targetFileFSRef createFileIfNecessary:NO]) 829 | return NO; 830 | } else if (result != noErr) { 831 | return NO; 832 | } 833 | 834 | // Open the file's resource fork. 835 | file = FSOpenResFile( &targetFileFSRef, fsRdWrPerm ); 836 | if (file == -1) 837 | return NO; 838 | 839 | // Make a copy of the icon family data to pass to AddResource(). 840 | // (AddResource() takes ownership of the handle we pass in; after the 841 | // CloseResFile() call its master pointer will be set to 0xffffffff. 842 | // We want to keep the icon family data, so we make a copy.) 843 | // HandToHand() returns the handle of the copy in hIconFamily. 844 | hIconFamilyCopy = (Handle) hIconFamily; 845 | result = HandToHand( &hIconFamilyCopy ); 846 | if (result != noErr) { 847 | CloseResFile( file ); 848 | return NO; 849 | } 850 | 851 | // Remove the file's existing kCustomIconResource of type kIconFamilyType 852 | // (if any). 853 | hExistingCustomIcon = GetResource( kIconFamilyType, kCustomIconResource ); 854 | if( hExistingCustomIcon ) 855 | RemoveResource( hExistingCustomIcon ); 856 | 857 | // Now add our icon family as the file's new custom icon. 858 | AddResource( (Handle)hIconFamilyCopy, kIconFamilyType, 859 | kCustomIconResource, "\p"); 860 | if (ResError() != noErr) { 861 | CloseResFile( file ); 862 | return NO; 863 | } 864 | 865 | if( compat ) 866 | { 867 | [self addResourceType:kLarge8BitData asResID:kCustomIconResource]; 868 | [self addResourceType:kLarge1BitMask asResID:kCustomIconResource]; 869 | [self addResourceType:kSmall8BitData asResID:kCustomIconResource]; 870 | [self addResourceType:kSmall1BitMask asResID:kCustomIconResource]; 871 | } 872 | 873 | // Close the file's resource fork, flushing the resource map and new icon 874 | // data out to disk. 875 | CloseResFile( file ); 876 | if (ResError() != noErr) 877 | return NO; 878 | 879 | // Prepare to get the Finder info. 880 | 881 | // Now we need to set the file's Finder info so the Finder will know that 882 | // it has a custom icon. Start by getting the file's current finder info: 883 | result = FSGetCatalogInfo( 884 | &targetFileFSRef, 885 | kFSCatInfoFinderInfo, 886 | &catInfo, 887 | /*outName*/ NULL, 888 | /*fsSpec*/ NULL, 889 | /*parentRef*/ NULL); 890 | if (result != noErr) 891 | return NO; 892 | 893 | // Set the kHasCustomIcon flag, and clear the kHasBeenInited flag. 894 | // 895 | // From Apple's "CustomIcon" code sample: 896 | // "set bit 10 (has custom icon) and unset the inited flag 897 | // kHasBeenInited is 0x0100 so the mask will be 0xFEFF:" 898 | // finderInfo.fdFlags = 0xFEFF & (finderInfo.fdFlags | kHasCustomIcon ) ; 899 | finderInfo->finderFlags = (finderInfo->finderFlags | kHasCustomIcon ) & ~kHasBeenInited; 900 | 901 | // Now write the Finder info back. 902 | result = FSSetCatalogInfo( &targetFileFSRef, kFSCatInfoFinderInfo, &catInfo ); 903 | if (result != noErr) 904 | return NO; 905 | 906 | // Now set the modification time back to when the file was actually last modified. 907 | NSDictionary* attributes = [NSDictionary dictionaryWithObjectsAndKeys:modificationDate, NSFileModificationDate, nil]; 908 | [[NSFileManager defaultManager] setAttributes:attributes ofItemAtPath:path error:nil]; 909 | 910 | // Notify the system that the directory containing the file has changed, to 911 | // give Finder the chance to find out about the file's new custom icon. 912 | result = FNNotify( &parentDirectoryFSRef, kFNDirectoryModifiedMessage, kNilOptions ); 913 | if (result != noErr) 914 | return NO; 915 | 916 | return YES; 917 | } 918 | 919 | + (BOOL) removeCustomIconFromFile:(NSString*)path 920 | { 921 | FSRef targetFileFSRef; 922 | FSRef parentDirectoryFSRef; 923 | SInt16 file; 924 | OSStatus result; 925 | struct FSCatalogInfo catInfo; 926 | struct FileInfo *finderInfo = (struct FileInfo *)&catInfo.finderInfo; 927 | Handle hExistingCustomIcon; 928 | 929 | // Get an FSRef for the target file. 930 | if (![path getFSRef:&targetFileFSRef createFileIfNecessary:NO]) 931 | return NO; 932 | 933 | // Open the file's resource fork, if it has one. 934 | file = FSOpenResFile( &targetFileFSRef, fsRdWrPerm ); 935 | if (file == -1) 936 | return NO; 937 | 938 | // Remove the file's existing kCustomIconResource of type kIconFamilyType 939 | // (if any). 940 | hExistingCustomIcon = GetResource( kIconFamilyType, kCustomIconResource ); 941 | if( hExistingCustomIcon ) 942 | RemoveResource( hExistingCustomIcon ); 943 | 944 | // Close the file's resource fork, flushing the resource map out to disk. 945 | CloseResFile( file ); 946 | if (ResError() != noErr) 947 | return NO; 948 | 949 | // Now we need to set the file's Finder info so the Finder will know that 950 | // it has no custom icon. Start by getting the file's current Finder info. 951 | // Also get an FSRef for its parent directory, that we can use in the 952 | // FNNotify() call below. 953 | result = FSGetCatalogInfo( 954 | &targetFileFSRef, 955 | kFSCatInfoFinderInfo, 956 | &catInfo, 957 | /*outName*/ NULL, 958 | /*fsSpec*/ NULL, 959 | &parentDirectoryFSRef ); 960 | if (result != noErr) 961 | return NO; 962 | 963 | // Clear the kHasCustomIcon flag and the kHasBeenInited flag. 964 | finderInfo->finderFlags = finderInfo->finderFlags & ~(kHasCustomIcon | kHasBeenInited); 965 | 966 | // Now write the Finder info back. 967 | result = FSSetCatalogInfo( &targetFileFSRef, kFSCatInfoFinderInfo, &catInfo ); 968 | if (result != noErr) 969 | return NO; 970 | 971 | // 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. 972 | result = FNNotify( &parentDirectoryFSRef, kFNDirectoryModifiedMessage, kNilOptions ); 973 | if (result != noErr) 974 | return NO; 975 | 976 | return YES; 977 | } 978 | 979 | - (BOOL) setAsCustomIconForDirectory:(NSString*)path 980 | { 981 | return [self setAsCustomIconForDirectory:path withCompatibility:NO error:NULL]; 982 | } 983 | 984 | - (BOOL) setAsCustomIconForDirectory:(NSString*)path withCompatibility:(BOOL)compat 985 | { 986 | return [self setAsCustomIconForDirectory:path withCompatibility:NO error:NULL]; 987 | } 988 | 989 | - (BOOL) setAsCustomIconForDirectory:(NSString*)path withCompatibility:(BOOL)compat error:(NSError **)error 990 | { 991 | NSFileManager *fm = [NSFileManager defaultManager]; 992 | BOOL isDir; 993 | BOOL exists; 994 | NSString *iconrPath; 995 | FSRef targetFolderFSRef, iconrFSRef; 996 | SInt16 file; 997 | OSErr result; 998 | struct HFSUniStr255 filename; 999 | struct FSCatalogInfo catInfo; 1000 | Handle hExistingCustomIcon; 1001 | Handle hIconFamilyCopy; 1002 | 1003 | // Confirm that "path" exists and specifies a directory. 1004 | exists = [fm fileExistsAtPath:path isDirectory:&isDir]; 1005 | if( !isDir || !exists ) 1006 | return NO; 1007 | 1008 | // Get an FSRef for the folder. 1009 | if( ![path getFSRef:&targetFolderFSRef createFileIfNecessary:NO] ) 1010 | return NO; 1011 | 1012 | // Remove and re-create any existing "Icon\r" file in the directory, and get an FSRef for it. 1013 | iconrPath = [path stringByAppendingPathComponent:@"Icon\r"]; 1014 | if( [fm fileExistsAtPath:iconrPath] ) 1015 | { 1016 | if( ![fm removeItemAtPath:iconrPath error:error] ) 1017 | return NO; 1018 | } 1019 | if( ![iconrPath getFSRef:&iconrFSRef createFileIfNecessary:YES] ) 1020 | return NO; 1021 | 1022 | // Get type and creator information for the Icon file. 1023 | result = FSGetCatalogInfo( 1024 | &iconrFSRef, 1025 | kFSCatInfoFinderInfo, 1026 | &catInfo, 1027 | /*outName*/ NULL, 1028 | /*fsSpec*/ NULL, 1029 | /*parentRef*/ NULL ); 1030 | // This shouldn't fail because we just created the file above. 1031 | if( result != noErr ) 1032 | return NO; 1033 | else { 1034 | // The file doesn't exist. Prepare to create it. 1035 | struct FileInfo *finderInfo = (struct FileInfo *)catInfo.finderInfo; 1036 | 1037 | // These are the file type and creator given to Icon files created by 1038 | // the Finder. 1039 | finderInfo->fileType = 'icon'; 1040 | finderInfo->fileCreator = 'MACS'; 1041 | 1042 | // Icon files should be invisible. 1043 | finderInfo->finderFlags = kIsInvisible; 1044 | 1045 | // Because the inited flag is not set in finderFlags above, the Finder 1046 | // will ignore the location, unless it's in the 'magic rectangle' of 1047 | // { -24,000, -24,000, -16,000, -16,000 } (technote TB42). 1048 | // So we need to make sure to set this to zero anyway, so that the 1049 | // Finder will position it automatically. If the user makes the Icon 1050 | // file visible for any reason, we don't want it to be positioned in an 1051 | // exotic corner of the window. 1052 | finderInfo->location.h = finderInfo->location.v = 0; 1053 | 1054 | // Standard reserved-field practice. 1055 | finderInfo->reservedField = 0; 1056 | 1057 | // Update the catalog info: 1058 | result = FSSetCatalogInfo(&iconrFSRef, kFSCatInfoFinderInfo, &catInfo); 1059 | 1060 | if (result != noErr) 1061 | return NO; 1062 | } 1063 | 1064 | // Get the filename, to be applied to the Icon file. 1065 | filename.length = [@"Icon\r" length]; 1066 | [@"Icon\r" getCharacters:filename.unicode]; 1067 | 1068 | // Make sure the file has a resource fork that we can open. (Although 1069 | // this sounds like it would clobber an existing resource fork, the Carbon 1070 | // Resource Manager docs for this function say that's not the case.) 1071 | FSCreateResFile( 1072 | &targetFolderFSRef, 1073 | filename.length, 1074 | filename.unicode, 1075 | kFSCatInfoFinderInfo, 1076 | &catInfo, 1077 | &iconrFSRef, 1078 | /*newSpec*/ NULL); 1079 | result = ResError(); 1080 | if (!(result == noErr || result == dupFNErr)) 1081 | return NO; 1082 | 1083 | // Open the file's resource fork. 1084 | file = FSOpenResFile( &iconrFSRef, fsRdWrPerm ); 1085 | if (file == -1) 1086 | return NO; 1087 | 1088 | // Make a copy of the icon family data to pass to AddResource(). 1089 | // (AddResource() takes ownership of the handle we pass in; after the 1090 | // CloseResFile() call its master pointer will be set to 0xffffffff. 1091 | // We want to keep the icon family data, so we make a copy.) 1092 | // HandToHand() returns the handle of the copy in hIconFamily. 1093 | hIconFamilyCopy = (Handle) hIconFamily; 1094 | result = HandToHand( &hIconFamilyCopy ); 1095 | if (result != noErr) { 1096 | CloseResFile( file ); 1097 | return NO; 1098 | } 1099 | 1100 | // Remove the file's existing kCustomIconResource of type kIconFamilyType 1101 | // (if any). 1102 | hExistingCustomIcon = GetResource( kIconFamilyType, kCustomIconResource ); 1103 | if( hExistingCustomIcon ) 1104 | RemoveResource( hExistingCustomIcon ); 1105 | 1106 | // Now add our icon family as the file's new custom icon. 1107 | AddResource( (Handle)hIconFamilyCopy, kIconFamilyType, 1108 | kCustomIconResource, "\p"); 1109 | 1110 | if (ResError() != noErr) { 1111 | CloseResFile( file ); 1112 | return NO; 1113 | } 1114 | 1115 | if( compat ) 1116 | { 1117 | [self addResourceType:kLarge8BitData asResID:kCustomIconResource]; 1118 | [self addResourceType:kLarge1BitMask asResID:kCustomIconResource]; 1119 | [self addResourceType:kSmall8BitData asResID:kCustomIconResource]; 1120 | [self addResourceType:kSmall1BitMask asResID:kCustomIconResource]; 1121 | } 1122 | 1123 | // Close the file's resource fork, flushing the resource map and new icon 1124 | // data out to disk. 1125 | CloseResFile( file ); 1126 | if (ResError() != noErr) 1127 | return NO; 1128 | 1129 | result = FSGetCatalogInfo( &targetFolderFSRef, 1130 | kFSCatInfoFinderInfo, 1131 | &catInfo, 1132 | /*outName*/ NULL, 1133 | /*fsSpec*/ NULL, 1134 | /*parentRef*/ NULL); 1135 | if( result != noErr ) 1136 | return NO; 1137 | 1138 | // Tell the Finder that the folder now has a custom icon. 1139 | ((struct FolderInfo *)catInfo.finderInfo)->finderFlags = ( ((struct FolderInfo *)catInfo.finderInfo)->finderFlags | kHasCustomIcon ) & ~kHasBeenInited; 1140 | 1141 | result = FSSetCatalogInfo( &targetFolderFSRef, 1142 | kFSCatInfoFinderInfo, 1143 | &catInfo); 1144 | if( result != noErr ) 1145 | return NO; 1146 | 1147 | // Notify the system that the target directory has changed, to give Finder 1148 | // the chance to find out about its new custom icon. 1149 | result = FNNotify( &targetFolderFSRef, kFNDirectoryModifiedMessage, kNilOptions ); 1150 | if (result != noErr) 1151 | return NO; 1152 | 1153 | return YES; 1154 | } 1155 | 1156 | + (BOOL) removeCustomIconFromDirectory:(NSString*)path 1157 | { 1158 | return( [self removeCustomIconFromDirectory:path error:NULL] ); 1159 | } 1160 | 1161 | + (BOOL) removeCustomIconFromDirectory:(NSString*)path error:(NSError **)error 1162 | { 1163 | FSRef targetFolderFSRef; 1164 | if( [path getFSRef:&targetFolderFSRef createFileIfNecessary:NO] ) { 1165 | OSStatus result; 1166 | struct FSCatalogInfo catInfo; 1167 | struct FileInfo *finderInfo = (struct FileInfo *)catInfo.finderInfo; 1168 | 1169 | result = FSGetCatalogInfo( &targetFolderFSRef, 1170 | kFSCatInfoFinderInfo, 1171 | &catInfo, 1172 | /*outName*/ NULL, 1173 | /*fsSpec*/ NULL, 1174 | /*parentRef*/ NULL); 1175 | if( result != noErr ) 1176 | return NO; 1177 | 1178 | // Tell the Finder that the folder no longer has a custom icon. 1179 | finderInfo->finderFlags &= ~( kHasCustomIcon | kHasBeenInited ); 1180 | 1181 | result = FSSetCatalogInfo( &targetFolderFSRef, 1182 | kFSCatInfoFinderInfo, 1183 | &catInfo); 1184 | if( result != noErr ) 1185 | return NO; 1186 | 1187 | // Notify the system that the target directory has changed, to give Finder 1188 | // the chance to find out about its new custom icon. 1189 | result = FNNotify( &targetFolderFSRef, kFNDirectoryModifiedMessage, kNilOptions ); 1190 | if (result != noErr) 1191 | return NO; 1192 | } 1193 | 1194 | if( ! [[NSFileManager defaultManager] removeItemAtPath:[path stringByAppendingPathComponent:@"Icon\r"] error:error] ) 1195 | return NO; 1196 | 1197 | return YES; 1198 | } 1199 | 1200 | - (NSData *) data 1201 | { 1202 | return [NSData dataWithBytes:*hIconFamily length:GetHandleSize((Handle)hIconFamily)]; 1203 | } 1204 | 1205 | - (BOOL) writeToFile:(NSString*)path 1206 | { 1207 | return [[self data] writeToFile:path atomically:NO]; 1208 | } 1209 | 1210 | 1211 | #pragma mark - NSPasteboardReading 1212 | 1213 | - (id)initWithPasteboardPropertyList:(id)data ofType:(NSString *)type { 1214 | return [self initWithData:data]; 1215 | } 1216 | 1217 | + (NSArray *)readableTypesForPasteboard:(NSPasteboard *)pasteboard { 1218 | return [NSArray arrayWithObjects:ICONFAMILY_UTI, ICONFAMILY_PBOARD_TYPE, nil]; 1219 | } 1220 | 1221 | + (NSPasteboardReadingOptions)readingOptionsForType:(NSString *)type pasteboard:(NSPasteboard *)pasteboard { 1222 | return NSPasteboardReadingAsData; 1223 | } 1224 | 1225 | + (BOOL)canInitWithPasteboard:(NSPasteboard *)pasteboard { 1226 | return [pasteboard canReadItemWithDataConformingToTypes:[self.class readableTypesForPasteboard:pasteboard]]; 1227 | } 1228 | 1229 | #pragma mark - NSPasteboardWriting 1230 | 1231 | - (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard { 1232 | return [self.class readableTypesForPasteboard:pasteboard]; 1233 | } 1234 | 1235 | - (id)pasteboardPropertyListForType:(NSString *)type { 1236 | return self.data; 1237 | } 1238 | 1239 | @end 1240 | 1241 | #pragma mark - Internals 1242 | @implementation IconFamily (Internals) 1243 | 1244 | + (NSImage*) resampleImage:(NSImage*)image toIconWidth:(int)iconWidth usingImageInterpolation:(NSImageInterpolation)imageInterpolation 1245 | { 1246 | NSGraphicsContext* graphicsContext; 1247 | BOOL wasAntialiasing; 1248 | NSImageInterpolation previousImageInterpolation; 1249 | NSImage* newImage; 1250 | NSImage* workingImage; 1251 | NSImageRep* workingImageRep; 1252 | NSSize size, pixelSize, newSize; 1253 | NSRect iconRect; 1254 | NSRect targetRect; 1255 | 1256 | // Create a working copy of the image and scale its size down to fit in 1257 | // the square area of the icon. 1258 | // 1259 | // It seems like there should be a more memory-efficient alternative to 1260 | // first duplicating the entire original image, but I don't know what it 1261 | // is. We need to change some properties ("size" and "scalesWhenResized") 1262 | // of the original image, but we shouldn't change the original, so a copy 1263 | // is necessary. 1264 | workingImage = [image copyWithZone:[image zone]]; 1265 | [workingImage setScalesWhenResized:YES]; 1266 | size = [workingImage size]; 1267 | workingImageRep = [workingImage bestRepresentationForRect:NSZeroRect context:nil hints:nil]; 1268 | if ([workingImageRep isKindOfClass:[NSBitmapImageRep class]]) { 1269 | pixelSize.width = [workingImageRep pixelsWide]; 1270 | pixelSize.height = [workingImageRep pixelsHigh]; 1271 | if (!NSEqualSizes( size, pixelSize )) { 1272 | [workingImage setSize:pixelSize]; 1273 | [workingImageRep setSize:pixelSize]; 1274 | size = pixelSize; 1275 | } 1276 | } 1277 | if (size.width >= size.height) { 1278 | newSize.width = iconWidth; 1279 | newSize.height = (float)floor( iconWidth * size.height / size.width + 0.5 ); 1280 | } else { 1281 | newSize.height = iconWidth; 1282 | newSize.width = (float)floor( iconWidth * size.width / size.height + 0.5 ); 1283 | } 1284 | [workingImage setSize:newSize]; 1285 | 1286 | // Create a new image the size of the icon, and clear it to transparent. 1287 | newImage = [[NSImage alloc] initWithSize:NSMakeSize(iconWidth,iconWidth)]; 1288 | [newImage lockFocus]; 1289 | iconRect.origin.x = iconRect.origin.y = 0; 1290 | iconRect.size.width = iconRect.size.height = iconWidth; 1291 | [[NSColor clearColor] set]; 1292 | NSRectFill( iconRect ); 1293 | 1294 | // Set current graphics context to use antialiasing and high-quality 1295 | // image scaling. 1296 | graphicsContext = [NSGraphicsContext currentContext]; 1297 | wasAntialiasing = [graphicsContext shouldAntialias]; 1298 | previousImageInterpolation = [graphicsContext imageInterpolation]; 1299 | [graphicsContext setShouldAntialias:YES]; 1300 | [graphicsContext setImageInterpolation:imageInterpolation]; 1301 | 1302 | // Composite the working image into the icon bitmap, centered. 1303 | targetRect.origin.x = ((float)iconWidth - newSize.width ) / 2.0f; 1304 | targetRect.origin.y = ((float)iconWidth - newSize.height) / 2.0f; 1305 | targetRect.size.width = newSize.width; 1306 | targetRect.size.height = newSize.height; 1307 | [workingImageRep drawInRect:targetRect]; 1308 | 1309 | // Restore previous graphics context settings. 1310 | [graphicsContext setShouldAntialias:wasAntialiasing]; 1311 | [graphicsContext setImageInterpolation:previousImageInterpolation]; 1312 | 1313 | [newImage unlockFocus]; 1314 | 1315 | [workingImage release]; 1316 | 1317 | // Return the new image! 1318 | return [newImage autorelease]; 1319 | } 1320 | 1321 | + (Handle) get32BitDataFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize 1322 | { 1323 | Handle hRawData; 1324 | unsigned char* pRawData; 1325 | Size rawDataSize; 1326 | 1327 | // Get information about the bitmapImageRep. 1328 | NSInteger pixelsWide = [bitmapImageRep pixelsWide]; 1329 | NSInteger pixelsHigh = [bitmapImageRep pixelsHigh]; 1330 | NSInteger bitsPerSample = [bitmapImageRep bitsPerSample]; 1331 | NSInteger samplesPerPixel = [bitmapImageRep samplesPerPixel]; 1332 | NSInteger bitsPerPixel = [bitmapImageRep bitsPerPixel]; 1333 | BOOL isPlanar = [bitmapImageRep isPlanar]; 1334 | 1335 | // Make sure bitmap has the required dimensions. 1336 | if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize) 1337 | return NULL; 1338 | 1339 | if (isPlanar) 1340 | { 1341 | NSLog(@"get32BitDataFromBitmapImageRep:requiredPixelSize: returning NULL due to isPlanar == YES"); 1342 | return NULL; 1343 | } 1344 | if (bitsPerSample != 8) 1345 | { 1346 | NSLog(@"get32BitDataFromBitmapImageRep:requiredPixelSize: returning NULL due to bitsPerSample == %ld", (long)bitsPerSample); 1347 | return NULL; 1348 | } 1349 | 1350 | if (((samplesPerPixel == 3) && (bitsPerPixel == 24)) || ((samplesPerPixel == 4) && (bitsPerPixel == 32))) { 1351 | rawDataSize = pixelsWide * pixelsHigh * 4; 1352 | hRawData = NewHandle( rawDataSize ); 1353 | if (hRawData == NULL) 1354 | return NULL; 1355 | pRawData = (unsigned char*) *hRawData; 1356 | 1357 | CGImageRef image = bitmapImageRep.CGImage; 1358 | 1359 | CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(image); 1360 | 1361 | NSInteger width = CGImageGetWidth(image); 1362 | NSInteger height = CGImageGetHeight(image); 1363 | 1364 | 1365 | CGDataProviderRef provider = CGImageGetDataProvider(image); 1366 | CFDataRef data = CGDataProviderCopyData(provider); 1367 | 1368 | UInt8* bytes = malloc(width * height * 4); 1369 | CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), bytes); 1370 | CFRelease(data); 1371 | 1372 | BOOL alphaFirst = (alphaInfo == kCGImageAlphaFirst || alphaInfo == kCGImageAlphaPremultipliedFirst); 1373 | BOOL premultiplied = (alphaInfo == kCGImageAlphaPremultipliedFirst || alphaInfo == kCGImageAlphaPremultipliedLast); 1374 | BOOL little = (CGImageGetBitmapInfo(image) == kCGBitmapByteOrder32Little); 1375 | 1376 | if (bitsPerPixel == 32) { 1377 | 1378 | vImage_Buffer src; 1379 | src.data = (void*)bytes; 1380 | src.rowBytes = 4 * width; 1381 | src.width = width; 1382 | src.height = height; 1383 | 1384 | vImage_Buffer dest; 1385 | dest.data = pRawData; 1386 | dest.rowBytes = 4 * width; 1387 | dest.width = width; 1388 | dest.height = height; 1389 | 1390 | uint8_t permuteMap[4]; 1391 | if (alphaFirst) { 1392 | if (little) { 1393 | // BGRA to ARGB 1394 | permuteMap[0] = 3; 1395 | permuteMap[1] = 2; 1396 | permuteMap[2] = 1; 1397 | permuteMap[3] = 0; 1398 | } else { 1399 | // ARGB to ARGB 1400 | permuteMap[0] = 0; 1401 | permuteMap[1] = 1; 1402 | permuteMap[2] = 2; 1403 | permuteMap[3] = 3; 1404 | } 1405 | } else { 1406 | if (little) { 1407 | // ABGR to ARGB 1408 | permuteMap[0] = 0; 1409 | permuteMap[1] = 3; 1410 | permuteMap[2] = 2; 1411 | permuteMap[3] = 1; 1412 | } else { 1413 | // RGBA to ARGB 1414 | permuteMap[0] = 3; 1415 | permuteMap[1] = 0; 1416 | permuteMap[2] = 1; 1417 | permuteMap[3] = 2; 1418 | } 1419 | } 1420 | 1421 | vImagePermuteChannels_ARGB8888(&src, &dest, permuteMap, 0); 1422 | 1423 | if (premultiplied) { 1424 | vImageUnpremultiplyData_ARGB8888(&dest, &dest, 0); 1425 | } 1426 | 1427 | 1428 | } else if (bitsPerPixel == 24) { 1429 | 1430 | vImage_Buffer src; 1431 | src.data = (void*)bytes; 1432 | src.rowBytes = 3 * width; 1433 | src.width = width; 1434 | src.height = height; 1435 | 1436 | vImage_Buffer dest; 1437 | dest.data = pRawData; 1438 | dest.rowBytes = 4 * width; 1439 | dest.width = width; 1440 | dest.height = height; 1441 | 1442 | vImageConvert_RGB888toARGB8888(&src, NULL, (Pixel_8)0xFFFF, &dest, false, 0); 1443 | 1444 | uint8_t permuteMap[4]; 1445 | if (little) { // BGR to RGB 1446 | permuteMap[0] = 2; 1447 | permuteMap[1] = 1; 1448 | permuteMap[2] = 0; 1449 | } else { 1450 | permuteMap[0] = 0; 1451 | permuteMap[1] = 1; 1452 | permuteMap[2] = 2; 1453 | } 1454 | 1455 | vImagePermuteChannels_ARGB8888(&dest, &dest, permuteMap, 0); 1456 | 1457 | } 1458 | 1459 | free(bytes); 1460 | } 1461 | else 1462 | { 1463 | NSLog(@"get32BitDataFromBitmapImageRep:requiredPixelSize: returning NULL due to samplesPerPixel == %ld, bitsPerPixel == %ld", 1464 | (long)samplesPerPixel, (long)bitsPerPixel); 1465 | return NULL; 1466 | } 1467 | 1468 | return hRawData; 1469 | } 1470 | 1471 | + (Handle) get8BitDataFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize 1472 | { 1473 | Handle hRawData; 1474 | unsigned char* pRawData; 1475 | Size rawDataSize; 1476 | unsigned char* pSrc; 1477 | unsigned char* pDest; 1478 | int x, y; 1479 | 1480 | // Get information about the bitmapImageRep. 1481 | NSInteger pixelsWide = [bitmapImageRep pixelsWide]; 1482 | NSInteger pixelsHigh = [bitmapImageRep pixelsHigh]; 1483 | NSInteger bitsPerSample = [bitmapImageRep bitsPerSample]; 1484 | NSInteger samplesPerPixel = [bitmapImageRep samplesPerPixel]; 1485 | NSInteger bitsPerPixel = [bitmapImageRep bitsPerPixel]; 1486 | BOOL isPlanar = [bitmapImageRep isPlanar]; 1487 | NSInteger bytesPerRow = [bitmapImageRep bytesPerRow]; 1488 | unsigned char* bitmapData = [bitmapImageRep bitmapData]; 1489 | 1490 | // Make sure bitmap has the required dimensions. 1491 | if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize) 1492 | return NULL; 1493 | 1494 | // So far, this code only handles non-planar 32-bit RGBA and 24-bit RGB source bitmaps. 1495 | // This could be made more flexible with some additional programming... 1496 | if (isPlanar) 1497 | { 1498 | NSLog(@"get8BitDataFromBitmapImageRep:requiredPixelSize: returning NULL due to isPlanar == YES"); 1499 | return NULL; 1500 | } 1501 | if (bitsPerSample != 8) 1502 | { 1503 | NSLog(@"get8BitDataFromBitmapImageRep:requiredPixelSize: returning NULL due to bitsPerSample == %ld", 1504 | (long)bitsPerSample); 1505 | return NULL; 1506 | } 1507 | 1508 | if (((samplesPerPixel == 3) && (bitsPerPixel == 24)) || ((samplesPerPixel == 4) && (bitsPerPixel == 32))) 1509 | { 1510 | rawDataSize = pixelsWide * pixelsHigh; 1511 | hRawData = NewHandle( rawDataSize ); 1512 | if (hRawData == NULL) 1513 | return NULL; 1514 | pRawData = (unsigned char*) *hRawData; 1515 | 1516 | pDest = pRawData; 1517 | if (bitsPerPixel == 32) { 1518 | for (y = 0; y < pixelsHigh; y++) { 1519 | pSrc = bitmapData + y * bytesPerRow; 1520 | for (x = 0; x < pixelsWide; x++) { 1521 | unsigned char r = *(pSrc + 1); 1522 | unsigned char g = *(pSrc + 2); 1523 | unsigned char b = *(pSrc + 3); 1524 | 1525 | *pDest++ = (0 << 24) | (r << 16) | (g << 8) | b; 1526 | 1527 | pSrc+=4; 1528 | } 1529 | } 1530 | } else if (bitsPerPixel == 24) { 1531 | for (y = 0; y < pixelsHigh; y++) { 1532 | pSrc = bitmapData + y * bytesPerRow; 1533 | for (x = 0; x < pixelsWide; x++) { 1534 | unsigned char r = *(pSrc); 1535 | unsigned char g = *(pSrc + 1); 1536 | unsigned char b = *(pSrc + 2); 1537 | 1538 | *pDest++ = (0 << 24) | (r << 16) | (g << 8) | b; 1539 | 1540 | pSrc+=3; 1541 | } 1542 | } 1543 | } 1544 | 1545 | } 1546 | else 1547 | { 1548 | NSLog(@"get8BitDataFromBitmapImageRep:requiredPixelSize: returning NULL due to samplesPerPixel == %ld, bitsPerPixel == %ld", 1549 | (long)samplesPerPixel, (long)bitsPerPixel); 1550 | return NULL; 1551 | } 1552 | 1553 | return hRawData; 1554 | } 1555 | 1556 | + (Handle) get8BitMaskFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize 1557 | { 1558 | Handle hRawData; 1559 | unsigned char* pRawData; 1560 | Size rawDataSize; 1561 | unsigned char* pSrc; 1562 | unsigned char* pDest; 1563 | int x, y; 1564 | 1565 | // Get information about the bitmapImageRep. 1566 | long pixelsWide = [bitmapImageRep pixelsWide]; 1567 | long pixelsHigh = [bitmapImageRep pixelsHigh]; 1568 | long bitsPerSample = [bitmapImageRep bitsPerSample]; 1569 | long samplesPerPixel = [bitmapImageRep samplesPerPixel]; 1570 | long bitsPerPixel = [bitmapImageRep bitsPerPixel]; 1571 | BOOL isPlanar = [bitmapImageRep isPlanar]; 1572 | long bytesPerRow = [bitmapImageRep bytesPerRow]; 1573 | unsigned char* bitmapData = [bitmapImageRep bitmapData]; 1574 | 1575 | // Make sure bitmap has the required dimensions. 1576 | if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize) 1577 | return NULL; 1578 | 1579 | // So far, this code only handles non-planar 32-bit RGBA, 24-bit RGB and 8-bit grayscale source bitmaps. 1580 | // This could be made more flexible with some additional programming... 1581 | if (isPlanar) 1582 | { 1583 | NSLog(@"get8BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to isPlanar == YES"); 1584 | return NULL; 1585 | } 1586 | if (bitsPerSample != 8) 1587 | { 1588 | NSLog(@"get8BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to bitsPerSample == %ld", bitsPerSample); 1589 | return NULL; 1590 | } 1591 | 1592 | if (((samplesPerPixel == 1) && (bitsPerPixel == 8)) || ((samplesPerPixel == 3) && (bitsPerPixel == 24)) || ((samplesPerPixel == 4) && (bitsPerPixel == 32))) 1593 | { 1594 | rawDataSize = pixelsWide * pixelsHigh; 1595 | hRawData = NewHandle( rawDataSize ); 1596 | if (hRawData == NULL) 1597 | return NULL; 1598 | pRawData = (unsigned char*) *hRawData; 1599 | 1600 | pSrc = bitmapData; 1601 | pDest = pRawData; 1602 | 1603 | if (bitsPerPixel == 32) { 1604 | for (y = 0; y < pixelsHigh; y++) { 1605 | pSrc = bitmapData + y * bytesPerRow; 1606 | for (x = 0; x < pixelsWide; x++) { 1607 | pSrc += 3; 1608 | *pDest++ = *pSrc++; 1609 | } 1610 | } 1611 | } 1612 | else if (bitsPerPixel == 24) { 1613 | memset( pDest, 255, rawDataSize ); 1614 | } 1615 | else if (bitsPerPixel == 8) { 1616 | for (y = 0; y < pixelsHigh; y++) { 1617 | memcpy( pDest, pSrc, pixelsWide ); 1618 | pSrc += bytesPerRow; 1619 | pDest += pixelsWide; 1620 | } 1621 | } 1622 | } 1623 | else 1624 | { 1625 | NSLog(@"get8BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to samplesPerPixel == %ld, bitsPerPixel == %ld", samplesPerPixel, bitsPerPixel); 1626 | return NULL; 1627 | } 1628 | 1629 | return hRawData; 1630 | } 1631 | 1632 | // NOTE: This method hasn't been fully tested yet. 1633 | + (Handle) get1BitMaskFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize 1634 | { 1635 | Handle hRawData; 1636 | unsigned char* pRawData; 1637 | Size rawDataSize; 1638 | unsigned char* pSrc; 1639 | unsigned char* pDest; 1640 | int x, y; 1641 | unsigned char maskByte; 1642 | 1643 | // Get information about the bitmapImageRep. 1644 | long pixelsWide = [bitmapImageRep pixelsWide]; 1645 | long pixelsHigh = [bitmapImageRep pixelsHigh]; 1646 | long bitsPerSample = [bitmapImageRep bitsPerSample]; 1647 | long samplesPerPixel = [bitmapImageRep samplesPerPixel]; 1648 | long bitsPerPixel = [bitmapImageRep bitsPerPixel]; 1649 | BOOL isPlanar = [bitmapImageRep isPlanar]; 1650 | long bytesPerRow = [bitmapImageRep bytesPerRow]; 1651 | unsigned char* bitmapData = [bitmapImageRep bitmapData]; 1652 | 1653 | // Make sure bitmap has the required dimensions. 1654 | if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize) 1655 | return NULL; 1656 | 1657 | // So far, this code only handles non-planar 32-bit RGBA, 24-bit RGB, 8-bit grayscale, and 1-bit source bitmaps. 1658 | // This could be made more flexible with some additional programming... 1659 | if (isPlanar) 1660 | { 1661 | NSLog(@"get1BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to isPlanar == YES"); 1662 | return NULL; 1663 | } 1664 | 1665 | if (((bitsPerPixel == 1) && (samplesPerPixel == 1) && (bitsPerSample == 1)) || ((bitsPerPixel == 8) && (samplesPerPixel == 1) && (bitsPerSample == 8)) || 1666 | ((bitsPerPixel == 24) && (samplesPerPixel == 3) && (bitsPerSample == 8)) || ((bitsPerPixel == 32) && (samplesPerPixel == 4) && (bitsPerSample == 8))) 1667 | { 1668 | rawDataSize = (pixelsWide * pixelsHigh)/4; 1669 | hRawData = NewHandle( rawDataSize ); 1670 | if (hRawData == NULL) 1671 | return NULL; 1672 | pRawData = (unsigned char*) *hRawData; 1673 | 1674 | pSrc = bitmapData; 1675 | pDest = pRawData; 1676 | 1677 | if (bitsPerPixel == 32) { 1678 | for (y = 0; y < pixelsHigh; y++) { 1679 | pSrc = bitmapData + y * bytesPerRow; 1680 | for (x = 0; x < pixelsWide; x += 8) { 1681 | maskByte = 0; 1682 | maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x80 : 0; pSrc += 4; 1683 | maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x40 : 0; pSrc += 4; 1684 | maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x20 : 0; pSrc += 4; 1685 | maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x10 : 0; pSrc += 4; 1686 | maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x08 : 0; pSrc += 4; 1687 | maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x04 : 0; pSrc += 4; 1688 | maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x02 : 0; pSrc += 4; 1689 | maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x01 : 0; pSrc += 4; 1690 | *pDest++ = maskByte; 1691 | } 1692 | } 1693 | } 1694 | else if (bitsPerPixel == 24) { 1695 | memset( pDest, 255, rawDataSize ); 1696 | } 1697 | else if (bitsPerPixel == 8) { 1698 | for (y = 0; y < pixelsHigh; y++) { 1699 | pSrc = bitmapData + y * bytesPerRow; 1700 | for (x = 0; x < pixelsWide; x += 8) { 1701 | maskByte = 0; 1702 | maskByte |= *pSrc++ ? 0x80 : 0; 1703 | maskByte |= *pSrc++ ? 0x40 : 0; 1704 | maskByte |= *pSrc++ ? 0x20 : 0; 1705 | maskByte |= *pSrc++ ? 0x10 : 0; 1706 | maskByte |= *pSrc++ ? 0x08 : 0; 1707 | maskByte |= *pSrc++ ? 0x04 : 0; 1708 | maskByte |= *pSrc++ ? 0x02 : 0; 1709 | maskByte |= *pSrc++ ? 0x01 : 0; 1710 | *pDest++ = maskByte; 1711 | } 1712 | } 1713 | } 1714 | else if (bitsPerPixel == 1) { 1715 | for (y = 0; y < pixelsHigh; y++) { 1716 | memcpy( pDest, pSrc, pixelsWide / 8 ); 1717 | pDest += pixelsWide / 8; 1718 | pSrc += bytesPerRow; 1719 | } 1720 | } 1721 | 1722 | memcpy( pRawData+(pixelsWide*pixelsHigh)/8, pRawData, (pixelsWide*pixelsHigh)/8 ); 1723 | } 1724 | else 1725 | { 1726 | NSLog(@"get1BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to bitsPerPixel == %ld, samplesPerPixel== %ld, bitsPerSample == %ld", bitsPerPixel, samplesPerPixel, bitsPerSample); 1727 | return NULL; 1728 | } 1729 | 1730 | return hRawData; 1731 | } 1732 | 1733 | - (BOOL) addResourceType:(OSType)type asResID:(int)resID 1734 | { 1735 | Handle hIconRes = NewHandle(0); 1736 | OSErr err; 1737 | 1738 | err = GetIconFamilyData( hIconFamily, type, hIconRes ); 1739 | 1740 | if( !GetHandleSize(hIconRes) || err != noErr ) 1741 | return NO; 1742 | 1743 | AddResource( hIconRes, type, resID, "\p" ); 1744 | 1745 | return YES; 1746 | } 1747 | @end 1748 | 1749 | -------------------------------------------------------------------------------- /source/Classes/NSString+CarbonFSRefCreation.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2001-2010 Troy N. Stephens 3 | 4 | Use and distribution of this source code is governed by the MIT License, whose terms are as follows. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, 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: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 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. 11 | */ 12 | 13 | #import 14 | #import 15 | 16 | @interface NSString (CarbonFSRefCreation) 17 | 18 | // Fills in the given FSRef struct so it specifies the file whose path is in this string. 19 | // If the file doesn't exist, and "createFile" is YES, this method will attempt to create 20 | // an empty file with the specified path. (The caller should insure that the directory 21 | // the file is to be placed in already exists.) 22 | 23 | - (BOOL) getFSRef:(FSRef*)fsRef createFileIfNecessary:(BOOL)createFile; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /source/Classes/NSString+CarbonFSRefCreation.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2001-2010 Troy N. Stephens 3 | 4 | Use and distribution of this source code is governed by the MIT License, whose terms are as follows. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, 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: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 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. 11 | */ 12 | 13 | #import "NSString+CarbonFSRefCreation.h" 14 | 15 | @implementation NSString (CarbonFSRefCreation) 16 | 17 | - (BOOL) getFSRef:(FSRef*)fsRef createFileIfNecessary:(BOOL)createFile 18 | { 19 | NSFileManager* fileManager = [NSFileManager defaultManager]; 20 | CFURLRef urlRef; 21 | Boolean gotFSRef; 22 | 23 | // Check whether the file exists already. If not, create an empty file if requested. 24 | if (![fileManager fileExistsAtPath:self]) { 25 | if (createFile) { 26 | NSString *emptyString = @""; 27 | if (![emptyString writeToFile:self atomically:YES encoding:NSUTF8StringEncoding error:NULL]) { 28 | return NO; 29 | } 30 | } else { 31 | return NO; 32 | } 33 | } 34 | 35 | // Create a CFURL with the specified POSIX path. 36 | urlRef = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, 37 | (CFStringRef) self, 38 | kCFURLPOSIXPathStyle, 39 | FALSE /* isDirectory */ ); 40 | if (urlRef == NULL) { 41 | // printf( "** Couldn't make a CFURLRef for the file.\n" ); 42 | return NO; 43 | } 44 | 45 | // Try to create an FSRef from the URL. (If the specified file doesn't exist, this 46 | // function will return false, but if we've reached this code we've already insured 47 | // that the file exists.) 48 | gotFSRef = CFURLGetFSRef( urlRef, fsRef ); 49 | CFRelease( urlRef ); 50 | 51 | if (!gotFSRef) { 52 | // printf( "** Couldn't get an FSRef for the file.\n" ); 53 | return NO; 54 | } 55 | 56 | return YES; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /source/Classes/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | return NSApplicationMain(argc, (const char **) argv); 6 | } 7 | -------------------------------------------------------------------------------- /source/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | MacOSXPublicBeta 11 | CFBundleIdentifier 12 | com.yourcompany.MakeThumbnail 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 0.9.4 23 | NSMainNibFile 24 | MainMenu 25 | NSPrincipalClass 26 | NSApplication 27 | 28 | 29 | -------------------------------------------------------------------------------- /source/Interface/MacOSXPublicBeta.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uliwitness/IconFamily/ca922f7fb7cd3d15a4d7e0a4b672b77b999db088/source/Interface/MacOSXPublicBeta.icns -------------------------------------------------------------------------------- /source/Interface/appStore.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uliwitness/IconFamily/ca922f7fb7cd3d15a4d7e0a4b672b77b999db088/source/Interface/appStore.icns -------------------------------------------------------------------------------- /source/MakeThumbnail.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 44; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; 11 | FAD5D2F11530E8B400722EB8 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAD5D2F01530E8B400722EB8 /* Carbon.framework */; }; 12 | FAD5D2FD1530F0DA00722EB8 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAD5D2FC1530F0DA00722EB8 /* Accelerate.framework */; }; 13 | FAD5D3051531046100722EB8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FAD5D3041531046100722EB8 /* main.m */; }; 14 | FAD5D3091531046700722EB8 /* appStore.icns in Resources */ = {isa = PBXBuildFile; fileRef = FAD5D3061531046700722EB8 /* appStore.icns */; }; 15 | FAD5D30A1531046700722EB8 /* MacOSXPublicBeta.icns in Resources */ = {isa = PBXBuildFile; fileRef = FAD5D3071531046700722EB8 /* MacOSXPublicBeta.icns */; }; 16 | FAD5D30B1531046700722EB8 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = FAD5D3081531046700722EB8 /* MainMenu.xib */; }; 17 | FAD5D30C1531047000722EB8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FAD5D2FF1531045A00722EB8 /* AppDelegate.m */; }; 18 | FAD5D30D1531047300722EB8 /* IconFamily.m in Sources */ = {isa = PBXBuildFile; fileRef = FAD5D3011531045A00722EB8 /* IconFamily.m */; }; 19 | FAD5D30E1531047300722EB8 /* NSString+CarbonFSRefCreation.m in Sources */ = {isa = PBXBuildFile; fileRef = FAD5D3031531045A00722EB8 /* NSString+CarbonFSRefCreation.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 24 | 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; 25 | 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 26 | 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 27 | 32CA4F630368D1EE00C91783 /* MakeThumbnail_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MakeThumbnail_Prefix.pch; sourceTree = ""; }; 28 | 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 29 | 8D1107320486CEB800E47090 /* MakeThumbnail.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MakeThumbnail.app; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | FAD5D2F01530E8B400722EB8 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; 31 | FAD5D2FC1530F0DA00722EB8 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; 32 | FAD5D2FE1531045A00722EB8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Classes/AppDelegate.h; sourceTree = ""; }; 33 | FAD5D2FF1531045A00722EB8 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Classes/AppDelegate.m; sourceTree = ""; }; 34 | FAD5D3001531045A00722EB8 /* IconFamily.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IconFamily.h; path = Classes/IconFamily.h; sourceTree = ""; }; 35 | FAD5D3011531045A00722EB8 /* IconFamily.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = IconFamily.m; path = Classes/IconFamily.m; sourceTree = ""; }; 36 | FAD5D3021531045A00722EB8 /* NSString+CarbonFSRefCreation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "NSString+CarbonFSRefCreation.h"; path = "Classes/NSString+CarbonFSRefCreation.h"; sourceTree = ""; }; 37 | FAD5D3031531045A00722EB8 /* NSString+CarbonFSRefCreation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "NSString+CarbonFSRefCreation.m"; path = "Classes/NSString+CarbonFSRefCreation.m"; sourceTree = ""; }; 38 | FAD5D3041531046100722EB8 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Classes/main.m; sourceTree = ""; }; 39 | FAD5D3061531046700722EB8 /* appStore.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = appStore.icns; path = Interface/appStore.icns; sourceTree = ""; }; 40 | FAD5D3071531046700722EB8 /* MacOSXPublicBeta.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = MacOSXPublicBeta.icns; path = Interface/MacOSXPublicBeta.icns; sourceTree = ""; }; 41 | FAD5D3081531046700722EB8 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MainMenu.xib; path = Interface/MainMenu.xib; sourceTree = ""; }; 42 | /* End PBXFileReference section */ 43 | 44 | /* Begin PBXFrameworksBuildPhase section */ 45 | 8D11072E0486CEB800E47090 /* Frameworks */ = { 46 | isa = PBXFrameworksBuildPhase; 47 | buildActionMask = 2147483647; 48 | files = ( 49 | FAD5D2FD1530F0DA00722EB8 /* Accelerate.framework in Frameworks */, 50 | FAD5D2F11530E8B400722EB8 /* Carbon.framework in Frameworks */, 51 | 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 080E96DDFE201D6D7F000001 /* Classes */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | FAD5D2FE1531045A00722EB8 /* AppDelegate.h */, 62 | FAD5D2FF1531045A00722EB8 /* AppDelegate.m */, 63 | FAD5D3001531045A00722EB8 /* IconFamily.h */, 64 | FAD5D3011531045A00722EB8 /* IconFamily.m */, 65 | FAD5D3021531045A00722EB8 /* NSString+CarbonFSRefCreation.h */, 66 | FAD5D3031531045A00722EB8 /* NSString+CarbonFSRefCreation.m */, 67 | ); 68 | name = Classes; 69 | sourceTree = ""; 70 | }; 71 | 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | FAD5D2FC1530F0DA00722EB8 /* Accelerate.framework */, 75 | FAD5D2F01530E8B400722EB8 /* Carbon.framework */, 76 | 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, 77 | ); 78 | name = "Linked Frameworks"; 79 | sourceTree = ""; 80 | }; 81 | 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 29B97324FDCFA39411CA2CEA /* AppKit.framework */, 85 | 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, 86 | 29B97325FDCFA39411CA2CEA /* Foundation.framework */, 87 | ); 88 | name = "Other Frameworks"; 89 | sourceTree = ""; 90 | }; 91 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 8D1107320486CEB800E47090 /* MakeThumbnail.app */, 95 | ); 96 | name = Products; 97 | sourceTree = ""; 98 | }; 99 | 29B97314FDCFA39411CA2CEA /* MakeThumbnail */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 080E96DDFE201D6D7F000001 /* Classes */, 103 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 104 | 29B97317FDCFA39411CA2CEA /* Resources */, 105 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 106 | 19C28FACFE9D520D11CA2CBB /* Products */, 107 | ); 108 | name = MakeThumbnail; 109 | sourceTree = ""; 110 | }; 111 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | FAD5D3041531046100722EB8 /* main.m */, 115 | 32CA4F630368D1EE00C91783 /* MakeThumbnail_Prefix.pch */, 116 | ); 117 | name = "Other Sources"; 118 | sourceTree = ""; 119 | }; 120 | 29B97317FDCFA39411CA2CEA /* Resources */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | FAD5D3061531046700722EB8 /* appStore.icns */, 124 | FAD5D3071531046700722EB8 /* MacOSXPublicBeta.icns */, 125 | FAD5D3081531046700722EB8 /* MainMenu.xib */, 126 | 8D1107310486CEB800E47090 /* Info.plist */, 127 | ); 128 | name = Resources; 129 | sourceTree = ""; 130 | }; 131 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, 135 | 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, 136 | ); 137 | name = Frameworks; 138 | sourceTree = ""; 139 | }; 140 | /* End PBXGroup section */ 141 | 142 | /* Begin PBXNativeTarget section */ 143 | 8D1107260486CEB800E47090 /* MakeThumbnail */ = { 144 | isa = PBXNativeTarget; 145 | buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "MakeThumbnail" */; 146 | buildPhases = ( 147 | 8D1107290486CEB800E47090 /* Resources */, 148 | 8D11072C0486CEB800E47090 /* Sources */, 149 | 8D11072E0486CEB800E47090 /* Frameworks */, 150 | ); 151 | buildRules = ( 152 | ); 153 | dependencies = ( 154 | ); 155 | name = MakeThumbnail; 156 | productInstallPath = "$(HOME)/Applications"; 157 | productName = MakeThumbnail; 158 | productReference = 8D1107320486CEB800E47090 /* MakeThumbnail.app */; 159 | productType = "com.apple.product-type.application"; 160 | }; 161 | /* End PBXNativeTarget section */ 162 | 163 | /* Begin PBXProject section */ 164 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 165 | isa = PBXProject; 166 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MakeThumbnail" */; 167 | compatibilityVersion = "Xcode 2.4"; 168 | developmentRegion = English; 169 | hasScannedForEncodings = 1; 170 | knownRegions = ( 171 | en, 172 | ); 173 | mainGroup = 29B97314FDCFA39411CA2CEA /* MakeThumbnail */; 174 | projectDirPath = ""; 175 | projectRoot = ""; 176 | targets = ( 177 | 8D1107260486CEB800E47090 /* MakeThumbnail */, 178 | ); 179 | }; 180 | /* End PBXProject section */ 181 | 182 | /* Begin PBXResourcesBuildPhase section */ 183 | 8D1107290486CEB800E47090 /* Resources */ = { 184 | isa = PBXResourcesBuildPhase; 185 | buildActionMask = 2147483647; 186 | files = ( 187 | FAD5D3091531046700722EB8 /* appStore.icns in Resources */, 188 | FAD5D30A1531046700722EB8 /* MacOSXPublicBeta.icns in Resources */, 189 | FAD5D30B1531046700722EB8 /* MainMenu.xib in Resources */, 190 | ); 191 | runOnlyForDeploymentPostprocessing = 0; 192 | }; 193 | /* End PBXResourcesBuildPhase section */ 194 | 195 | /* Begin PBXSourcesBuildPhase section */ 196 | 8D11072C0486CEB800E47090 /* Sources */ = { 197 | isa = PBXSourcesBuildPhase; 198 | buildActionMask = 2147483647; 199 | files = ( 200 | FAD5D3051531046100722EB8 /* main.m in Sources */, 201 | FAD5D30C1531047000722EB8 /* AppDelegate.m in Sources */, 202 | FAD5D30D1531047300722EB8 /* IconFamily.m in Sources */, 203 | FAD5D30E1531047300722EB8 /* NSString+CarbonFSRefCreation.m in Sources */, 204 | ); 205 | runOnlyForDeploymentPostprocessing = 0; 206 | }; 207 | /* End PBXSourcesBuildPhase section */ 208 | 209 | /* Begin XCBuildConfiguration section */ 210 | C01FCF4B08A954540054247B /* Debug */ = { 211 | isa = XCBuildConfiguration; 212 | buildSettings = { 213 | COPY_PHASE_STRIP = NO; 214 | GCC_DYNAMIC_NO_PIC = NO; 215 | GCC_ENABLE_FIX_AND_CONTINUE = YES; 216 | GCC_MODEL_TUNING = G5; 217 | GCC_OPTIMIZATION_LEVEL = 0; 218 | INFOPLIST_FILE = Info.plist; 219 | INSTALL_PATH = "$(HOME)/Applications"; 220 | PRODUCT_NAME = MakeThumbnail; 221 | WRAPPER_EXTENSION = app; 222 | ZERO_LINK = YES; 223 | }; 224 | name = Debug; 225 | }; 226 | C01FCF4C08A954540054247B /* Release */ = { 227 | isa = XCBuildConfiguration; 228 | buildSettings = { 229 | GCC_GENERATE_DEBUGGING_SYMBOLS = NO; 230 | GCC_MODEL_TUNING = G5; 231 | INFOPLIST_FILE = Info.plist; 232 | INSTALL_PATH = "$(HOME)/Applications"; 233 | PRODUCT_NAME = MakeThumbnail; 234 | WRAPPER_EXTENSION = app; 235 | }; 236 | name = Release; 237 | }; 238 | C01FCF4F08A954540054247B /* Debug */ = { 239 | isa = XCBuildConfiguration; 240 | buildSettings = { 241 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; 242 | ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; 243 | GCC_TREAT_WARNINGS_AS_ERRORS = YES; 244 | GCC_VERSION = ""; 245 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 246 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; 247 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 248 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 249 | GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; 250 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 251 | GCC_WARN_MISSING_PARENTHESES = YES; 252 | GCC_WARN_SHADOW = YES; 253 | GCC_WARN_SIGN_COMPARE = YES; 254 | GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; 255 | GCC_WARN_UNDECLARED_SELECTOR = YES; 256 | GCC_WARN_UNUSED_FUNCTION = YES; 257 | GCC_WARN_UNUSED_LABEL = YES; 258 | GCC_WARN_UNUSED_VALUE = YES; 259 | GCC_WARN_UNUSED_VARIABLE = YES; 260 | PREBINDING = NO; 261 | RUN_CLANG_STATIC_ANALYZER = YES; 262 | SDKROOT = macosx; 263 | "SDKROOT[arch=x86_64]" = macosx; 264 | }; 265 | name = Debug; 266 | }; 267 | C01FCF5008A954540054247B /* Release */ = { 268 | isa = XCBuildConfiguration; 269 | buildSettings = { 270 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; 271 | ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; 272 | GCC_TREAT_WARNINGS_AS_ERRORS = YES; 273 | GCC_VERSION = ""; 274 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 275 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; 276 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 277 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 278 | GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; 279 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 280 | GCC_WARN_MISSING_PARENTHESES = YES; 281 | GCC_WARN_SHADOW = YES; 282 | GCC_WARN_SIGN_COMPARE = YES; 283 | GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; 284 | GCC_WARN_UNDECLARED_SELECTOR = YES; 285 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 286 | GCC_WARN_UNUSED_FUNCTION = YES; 287 | GCC_WARN_UNUSED_LABEL = YES; 288 | GCC_WARN_UNUSED_VALUE = YES; 289 | GCC_WARN_UNUSED_VARIABLE = YES; 290 | PREBINDING = NO; 291 | RUN_CLANG_STATIC_ANALYZER = YES; 292 | SDKROOT = macosx; 293 | "SDKROOT[arch=x86_64]" = macosx; 294 | WARNING_CFLAGS = ( 295 | "-Wall", 296 | "-Wextra", 297 | "-Wno-unused-parameter", 298 | "-Werror", 299 | ); 300 | }; 301 | name = Release; 302 | }; 303 | /* End XCBuildConfiguration section */ 304 | 305 | /* Begin XCConfigurationList section */ 306 | C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "MakeThumbnail" */ = { 307 | isa = XCConfigurationList; 308 | buildConfigurations = ( 309 | C01FCF4B08A954540054247B /* Debug */, 310 | C01FCF4C08A954540054247B /* Release */, 311 | ); 312 | defaultConfigurationIsVisible = 0; 313 | defaultConfigurationName = Release; 314 | }; 315 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MakeThumbnail" */ = { 316 | isa = XCConfigurationList; 317 | buildConfigurations = ( 318 | C01FCF4F08A954540054247B /* Debug */, 319 | C01FCF5008A954540054247B /* Release */, 320 | ); 321 | defaultConfigurationIsVisible = 0; 322 | defaultConfigurationName = Release; 323 | }; 324 | /* End XCConfigurationList section */ 325 | }; 326 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 327 | } 328 | -------------------------------------------------------------------------------- /source/MakeThumbnail.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /source/MakeThumbnail.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uliwitness/IconFamily/ca922f7fb7cd3d15a4d7e0a4b672b77b999db088/source/MakeThumbnail.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /source/MakeThumbnail.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/MakeThumbnail.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 50 | 51 | 57 | 58 | 59 | 60 | 61 | 62 | 68 | 69 | 75 | 76 | 77 | 78 | 80 | 81 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /source/MakeThumbnail.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MakeThumbnail.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 8D1107260486CEB800E47090 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /source/MakeThumbnail_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'MakeThumbnail' target in the 'MakeThumbnail' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | --------------------------------------------------------------------------------