├── .gitignore ├── Example ├── en.lproj │ └── InfoPlist.strings ├── Default.png ├── Default@2x.png ├── Default-568h@2x.png ├── restaurant-icon-mask.pdf ├── restaurant-icon-mask.png ├── restaurant-icon-mask@2x.png ├── AppDelegate.h ├── FTAssetRenderer.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── project.pbxproj ├── main.m ├── FTAssetRenderer-Prefix.pch ├── AppDelegate.m └── FTAssetRenderer-Info.plist ├── FTAssetRendererTests ├── FTAssetRendererTests.h ├── FTPDFAssetRendererTests.h ├── FTImageAssetRendererTests.h ├── Info.plist ├── FTAssetRendererTests.m ├── FTImageAssetRendererTests.m └── FTPDFAssetRendererTests.m ├── Source ├── FTImageAssetRenderer.h ├── FTPDFAssetRenderer.h ├── FTAssetRenderer.h ├── FTImageAssetRenderer.m ├── FTAssetRenderer.m └── FTPDFAssetRenderer.m ├── FTAssetRenderer.podspec ├── LICENSE └── README.markdown /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .*.sw? 3 | 4 | xcuserdata 5 | DerivedData 6 | -------------------------------------------------------------------------------- /Example/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fingertips/FTAssetRenderer/HEAD/Example/Default.png -------------------------------------------------------------------------------- /Example/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fingertips/FTAssetRenderer/HEAD/Example/Default@2x.png -------------------------------------------------------------------------------- /Example/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fingertips/FTAssetRenderer/HEAD/Example/Default-568h@2x.png -------------------------------------------------------------------------------- /Example/restaurant-icon-mask.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fingertips/FTAssetRenderer/HEAD/Example/restaurant-icon-mask.pdf -------------------------------------------------------------------------------- /Example/restaurant-icon-mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fingertips/FTAssetRenderer/HEAD/Example/restaurant-icon-mask.png -------------------------------------------------------------------------------- /Example/restaurant-icon-mask@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fingertips/FTAssetRenderer/HEAD/Example/restaurant-icon-mask@2x.png -------------------------------------------------------------------------------- /Example/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface AppDelegate : UIResponder 4 | 5 | @property (strong, nonatomic) UIWindow *window; 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /FTAssetRendererTests/FTAssetRendererTests.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "FTAssetRenderer.h" 3 | 4 | @interface FTAssetRendererTests : XCTestCase 5 | 6 | @property (nonatomic) FTAssetRenderer *renderer; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /FTAssetRendererTests/FTPDFAssetRendererTests.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "FTPDFAssetRenderer.h" 3 | 4 | @interface FTPDFAssetRendererTests : XCTestCase 5 | 6 | @property (nonatomic) FTPDFAssetRenderer *renderer; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /FTAssetRendererTests/FTImageAssetRendererTests.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "FTImageAssetRenderer.h" 3 | 4 | @interface FTImageAssetRendererTests : XCTestCase 5 | 6 | @property (nonatomic) FTImageAssetRenderer *renderer; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /Example/FTAssetRenderer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Example/FTAssetRenderer-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'FTPDFIconRenderer' target in the 'FTPDFIconRenderer' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /Source/FTImageAssetRenderer.h: -------------------------------------------------------------------------------- 1 | #import "FTAssetRenderer.h" 2 | 3 | 4 | NS_ASSUME_NONNULL_BEGIN 5 | 6 | @interface FTImageAssetRenderer : FTAssetRenderer 7 | 8 | @property (nonatomic, readonly, nullable) UIImage *sourceImage; 9 | 10 | @end 11 | 12 | @interface FTAssetRenderer (FTPDFAssetRenderer) 13 | 14 | + (FTImageAssetRenderer *)rendererForImageNamed:(NSString *)imageName withExtension:(NSString *)extName; 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /FTAssetRenderer.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "FTAssetRenderer" 3 | s.version = "0.1.1" 4 | s.summary = "Create image assets at runtime in any color when used as mask and/or at any resolution when it’s a PDF." 5 | s.homepage = "https://github.com/Fingertips/FTAssetRenderer" 6 | s.license = 'MIT' 7 | s.author = { "Eloy Durán" => "eloy.de.enige@gmail.com" } 8 | s.source = { :git => "https://github.com/Fingertips/FTAssetRenderer.git", :tag => "0.1.1" } 9 | s.platform = :ios, '4.0' 10 | s.source_files = 'Source' 11 | s.requires_arc = true 12 | end 13 | -------------------------------------------------------------------------------- /FTAssetRendererTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Source/FTPDFAssetRenderer.h: -------------------------------------------------------------------------------- 1 | #import "FTAssetRenderer.h" 2 | 3 | 4 | NS_ASSUME_NONNULL_BEGIN 5 | 6 | // This object is supposed to be short-lived, because an open PDF document can consume quite some memory. 7 | @interface FTPDFAssetRenderer : FTAssetRenderer 8 | 9 | @property (nonatomic, assign) size_t sourcePageIndex; 10 | @property (nonatomic, readonly) CGPDFPageRef sourcePage; 11 | @property (nonatomic, assign) CGSize targetSize; 12 | @property (nonatomic, readonly) BOOL isMask; 13 | 14 | - (instancetype)initWithURL:(NSURL * _Nullable)URL NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)initWithData:(NSData *)data NS_DESIGNATED_INITIALIZER; 16 | 17 | - (void)fitSize:(CGSize)maxSize; 18 | - (void)fitWidth:(CGFloat)targetWidth; 19 | - (void)fitHeight:(CGFloat)targetHeight; 20 | 21 | @end 22 | 23 | @interface FTAssetRenderer (FTPDFAssetRenderer) 24 | 25 | + (FTPDFAssetRenderer *)rendererForPDFNamed:(NSString *)pdfName; 26 | 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012 Eloy Durán, Fingertips, 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. 8 | -------------------------------------------------------------------------------- /Example/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "FTPDFAssetRenderer.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(__unused NSDictionary *)launchOptions 7 | { 8 | CGRect frame = [[UIScreen mainScreen] bounds]; 9 | 10 | self.window = [[UIWindow alloc] initWithFrame:frame]; 11 | self.window.backgroundColor = [UIColor lightGrayColor]; 12 | self.window.rootViewController = [UIViewController new]; 13 | 14 | UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 15 | button.frame = CGRectMake(CGRectGetMidX(frame) - 50, 40, 100, 40); 16 | [self.window addSubview:button]; 17 | 18 | FTPDFAssetRenderer *renderer = [FTPDFAssetRenderer rendererForPDFNamed:@"restaurant-icon-mask"]; 19 | [renderer fitSize:button.bounds.size]; 20 | 21 | renderer.targetColor = [UIColor blueColor]; 22 | [button setImage:[renderer imageWithCacheIdentifier:@"normal"] forState:UIControlStateNormal]; 23 | renderer.targetColor = [UIColor whiteColor]; 24 | [button setImage:[renderer imageWithCacheIdentifier:@"highlighted"] forState:UIControlStateHighlighted]; 25 | 26 | [self.window makeKeyAndVisible]; 27 | return YES; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Source/FTAssetRenderer.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class FTPDFAssetRenderer; 4 | 5 | 6 | NS_ASSUME_NONNULL_BEGIN 7 | 8 | @interface FTAssetRenderer : NSObject 9 | 10 | @property (nonatomic, readonly, nullable) NSURL *URL; 11 | @property (nonatomic, strong, nullable) UIColor *targetColor; 12 | @property (nonatomic, assign) BOOL useCache; // defaults to YES 13 | @property (nonatomic, readonly) CGSize targetSize; 14 | 15 | + (NSString *)cacheDirectory; 16 | 17 | - (instancetype)initWithURL:(NSURL * _Nullable)URL NS_DESIGNATED_INITIALIZER; 18 | 19 | // When caching is enabled and the image is used as a mask then an identifier 20 | // *has* to be specified. 21 | // 22 | // For example, when generating button icons, you could use an identifier like 23 | // `normal` or `highlighted`, depending on the state. 24 | - (UIImage *)image; 25 | - (UIImage *)imageWithCacheIdentifier:(nullable NSString *)identifier; 26 | 27 | @end 28 | 29 | 30 | @interface FTAssetRenderer (FTProtected) 31 | 32 | - (void)drawImageInContext:(CGContextRef)context; 33 | - (void)drawTargetColorInContext:(CGContextRef)context; 34 | 35 | - (void)assertCanCacheWithIdentifier:(NSString * _Nullable)identifier; 36 | - (NSString *)cachePathWithIdentifier:(NSString * _Nullable)identifier; 37 | - (NSString *)cacheRawFilenameWithIdentifier:(NSString * _Nullable)identifier; 38 | 39 | @end 40 | 41 | 42 | NS_ASSUME_NONNULL_END 43 | -------------------------------------------------------------------------------- /Example/FTAssetRenderer-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.fngtps.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /FTAssetRendererTests/FTAssetRendererTests.m: -------------------------------------------------------------------------------- 1 | #import "FTAssetRendererTests.h" 2 | 3 | @implementation FTAssetRendererTests 4 | 5 | - (void)setUp 6 | { 7 | [super setUp]; 8 | [[NSFileManager defaultManager] createDirectoryAtPath:[FTAssetRenderer cacheDirectory] 9 | withIntermediateDirectories:YES 10 | attributes:nil 11 | error:NULL]; 12 | NSURL *URL = [[NSBundle mainBundle] URLForResource:@"restaurant-icon-mask" withExtension:@"pdf"]; 13 | self.renderer = [[FTAssetRenderer alloc] initWithURL:URL]; 14 | } 15 | 16 | - (void)tearDown 17 | { 18 | [super tearDown]; 19 | self.renderer = nil; 20 | [[NSFileManager defaultManager] removeItemAtPath:[FTAssetRenderer cacheDirectory] 21 | error:NULL]; 22 | } 23 | 24 | #pragma mark - caching 25 | 26 | - (void)testCachesInSpecificCacheDirectory 27 | { 28 | NSString *expected = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]; 29 | expected = [expected stringByAppendingPathComponent:@"__FTAssetRenderer_Cache__"]; 30 | XCTAssertEqualObjects(expected, [FTAssetRenderer cacheDirectory]); 31 | } 32 | 33 | - (void)testChangesCachePathBasedOnIdentifier 34 | { 35 | NSString *path = [self.renderer cachePathWithIdentifier:@"normal"]; 36 | XCTAssertEqualObjects(path, [self.renderer cachePathWithIdentifier:@"normal"]); 37 | 38 | NSString *newPath = [self.renderer cachePathWithIdentifier:@"highlighted"]; 39 | XCTAssertFalse([path isEqualToString:newPath]); 40 | XCTAssertEqualObjects(newPath, [self.renderer cachePathWithIdentifier:@"highlighted"]); 41 | } 42 | 43 | - (void)testCacheWithEmptyURL 44 | { 45 | FTAssetRenderer *renderer = [[FTAssetRenderer alloc] initWithURL:nil]; 46 | XCTAssertThrows([renderer assertCanCacheWithIdentifier:@"normal"]); 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /FTAssetRendererTests/FTImageAssetRendererTests.m: -------------------------------------------------------------------------------- 1 | #import "FTImageAssetRendererTests.h" 2 | 3 | @implementation FTImageAssetRendererTests 4 | 5 | - (void)setUp 6 | { 7 | [super setUp]; 8 | [[NSFileManager defaultManager] createDirectoryAtPath:[FTAssetRenderer cacheDirectory] 9 | withIntermediateDirectories:YES 10 | attributes:nil 11 | error:NULL]; 12 | self.renderer = [FTAssetRenderer rendererForImageNamed:@"restaurant-icon-mask" withExtension:@"png"]; 13 | self.renderer.targetColor = [UIColor redColor]; 14 | } 15 | 16 | - (void)tearDown 17 | { 18 | [super tearDown]; 19 | self.renderer = nil; 20 | [[NSFileManager defaultManager] removeItemAtPath:[FTAssetRenderer cacheDirectory] 21 | error:NULL]; 22 | } 23 | 24 | - (void)testConvenienceMethodLoadsImageAppropriateForScreenScale 25 | { 26 | NSString *filename = [[self.renderer.URL lastPathComponent] stringByDeletingPathExtension]; 27 | int scale = (int)[[UIScreen mainScreen] scale]; 28 | if (scale > 1) { 29 | XCTAssertTrue([filename hasSuffix:@"@2x"]); 30 | } else { 31 | XCTAssertFalse([filename hasSuffix:@"@2x"]); 32 | } 33 | } 34 | 35 | - (void)testReturnsImageOfExpectedSizeAndScale 36 | { 37 | UIImage *result = [self.renderer imageWithCacheIdentifier:@"test"]; 38 | XCTAssertTrue(CGSizeEqualToSize(self.renderer.sourceImage.size, result.size)); 39 | } 40 | 41 | - (void)testCreatesExpectedSizeImageAtCachePath 42 | { 43 | NSString *path = [self.renderer cachePathWithIdentifier:@"test"]; 44 | [self.renderer imageWithCacheIdentifier:@"test"]; 45 | sleep(2); // lame, should check if file exists with timeout 46 | UIImage *result = [UIImage imageWithContentsOfFile:path]; 47 | CGFloat scale = [[UIScreen mainScreen] scale]; 48 | CGSize sourceSize = self.renderer.sourceImage.size; 49 | XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(sourceSize.width * scale, sourceSize.height * scale), result.size)); 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Source/FTImageAssetRenderer.m: -------------------------------------------------------------------------------- 1 | #import "FTImageAssetRenderer.h" 2 | 3 | @implementation FTAssetRenderer (FTPDFAssetRenderer) 4 | 5 | + (FTImageAssetRenderer *)rendererForImageNamed:(NSString *)imageName withExtension:(NSString *)extName 6 | { 7 | NSURL *URL = nil; 8 | 9 | // First check if the main screen has a higher scale than 1 and if a explicit 10 | // image for that scale exists. 11 | int scale = (int)[[UIScreen mainScreen] scale]; 12 | if (scale > 1) { 13 | NSString *scaledImageName = [NSString stringWithFormat:@"%@@%dx", imageName, scale]; 14 | URL = [[NSBundle mainBundle] URLForResource:scaledImageName withExtension:extName]; 15 | } 16 | 17 | // Otherwise load the normal image, without a scale in its name. 18 | if (URL == nil) { 19 | URL = [[NSBundle mainBundle] URLForResource:imageName withExtension:extName]; 20 | } 21 | 22 | if (URL != nil) { 23 | FTImageAssetRenderer *renderer = [[FTImageAssetRenderer alloc] initWithURL:URL]; 24 | return renderer; 25 | } 26 | return nil; 27 | } 28 | 29 | @end 30 | 31 | 32 | @implementation FTImageAssetRenderer 33 | 34 | @synthesize sourceImage = _sourceImage; 35 | 36 | #pragma mark - FTAssetRenderer 37 | 38 | - (CGSize)targetSize 39 | { 40 | return self.sourceImage.size; 41 | } 42 | 43 | - (UIImage *)imageWithCacheIdentifier:(NSString *)identifier 44 | { 45 | if (self.sourceImage == nil) { 46 | [NSException raise:@"FTAssetRendererError" 47 | format:@"Can’t render an image without a source image."]; 48 | } 49 | return [super imageWithCacheIdentifier:identifier]; 50 | } 51 | 52 | - (void)drawImageInContext:(CGContextRef)context 53 | { 54 | UIImage *source = self.sourceImage; 55 | CGRect rect = CGRectMake(0, 0, source.size.width, source.size.height); 56 | CGContextDrawImage(context, rect, [source CGImage]); 57 | } 58 | 59 | #pragma mark - FTImageAssetRenderer 60 | 61 | - (UIImage *)sourceImage 62 | { 63 | if (_sourceImage == nil && self.URL.path != nil) { 64 | _sourceImage = [[UIImage alloc] initWithContentsOfFile:self.URL.path]; 65 | } 66 | 67 | return _sourceImage; 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # FTAssetRenderer 2 | 3 | Create image assets, at runtime, in _any_ color when used as mask and/or at _any_ resolution when it’s a PDF. 4 | 5 | 6 | ### Install 7 | 8 | If you’re using [CocoaPods](https://github.com/CocoaPods/CocoaPods), add the following to your Podfile: 9 | 10 | ```ruby 11 | pod 'FTAssetRenderer' 12 | ``` 13 | 14 | Otherwise, simply add the files from the `Source` dir to your project. 15 | 16 | 17 | ### Usage 18 | 19 | If you have a bitmap image that’s used as a mask to generate images in different colors, then you can use it like so: 20 | 21 | ```objc 22 | FTImageAssetRenderer *renderer = [FTAssetRenderer rendererForImageNamed:@"my-icon" withExtension:@"png"]; 23 | renderer.targetColor = [UIColor redColor]; 24 | UIImage *result = [renderer imageWithCacheIdentifier:@"red"]; 25 | ``` 26 | 27 | If, on the other hand, you have a vector based PDF image, you should generally indicate the size at which it should be rendered as well: 28 | 29 | ```objc 30 | FTPDFAssetRenderer *renderer = [FTAssetRenderer rendererForPDFNamed:@"my-scalable-icon"]; 31 | renderer.targetColor = [UIColor blueColor]; 32 | renderer.targetSize = CGSizeMake(123, 456); 33 | UIImage *result = [renderer imageWithCacheIdentifier:@"without-preserving-aspect-ratio"]; 34 | ``` 35 | 36 | In the above example, an explicit width and height is given for the result image, which might lead to the image not preserving its original aspect ratio. To ensure the ratio is preserved, a few convience methods are available: 37 | 38 | * `-[FTPDFAssetRenderer fitWidth:]` will make the result image as wide as the given width, while the height is based on it. 39 | * `-[FTPDFAssetRenderer fitHeight:]` will make the result image as high as the given height, while the width is based on it. 40 | * `-[FTPDFAssetRenderer fitSize:]` will make the image as large as possible, inside the bounding size, but without cropping any part of the image, thus only fully covering one of the two sides. 41 | 42 | By default, the resulting image is cached on disk. For each different target color, a different cache identifier should be used. For instance, for controls you might use identifiers such as `normal`, `highlighted`, and `selected`. 43 | 44 | 45 | ### Acknowledgements 46 | 47 | Based on work by: 48 | * [Oliver Drobnik](https://github.com/Cocoanetics) - http://www.cocoanetics.com/2010/06/rendering-pdf-is-easier-than-you-thought 49 | * [Nigel Timothy Barber](https://github.com/mindbrix) - https://github.com/mindbrix/UIImage-PDF 50 | * [Jeffrey Sambells](https://github.com/iamamused) - http://jeffreysambells.com/2012/03/02/beating-the-20mb-size-limit-ipad-retina-displays 51 | * [Ole Zorn](https://github.com/omz) - https://gist.github.com/1102091 52 | 53 | Thanks to [Peter Steinberger](https://github.com/steipete) (of [PSPDFKit](http://pspdfkit.com) fame) for his invaluable advice during the creation of this library. 54 | -------------------------------------------------------------------------------- /FTAssetRendererTests/FTPDFAssetRendererTests.m: -------------------------------------------------------------------------------- 1 | #import "FTPDFAssetRendererTests.h" 2 | 3 | // TODO 4 | // * add portrait and landscape fixtures 5 | 6 | @implementation FTPDFAssetRendererTests 7 | 8 | - (void)setUp 9 | { 10 | [super setUp]; 11 | [[NSFileManager defaultManager] createDirectoryAtPath:[FTAssetRenderer cacheDirectory] 12 | withIntermediateDirectories:YES 13 | attributes:nil 14 | error:NULL]; 15 | self.renderer = [FTAssetRenderer rendererForPDFNamed:@"restaurant-icon-mask"]; 16 | } 17 | 18 | - (void)tearDown 19 | { 20 | [super tearDown]; 21 | self.renderer = nil; 22 | [[NSFileManager defaultManager] removeItemAtPath:[FTAssetRenderer cacheDirectory] 23 | error:NULL]; 24 | } 25 | 26 | #pragma - mark sizing 27 | 28 | - (void)testByDefaultUsesMediaBoxSizeAsTarget 29 | { 30 | XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(88, 88), self.renderer.targetSize)); 31 | } 32 | 33 | - (void)testFitsPDFWithinGivenSizeFillingShortestEdge 34 | { 35 | [self.renderer fitSize:CGSizeMake(100, 200)]; 36 | XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 100), self.renderer.targetSize)); 37 | [self.renderer fitSize:CGSizeMake(300, 200)]; 38 | XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(200, 200), self.renderer.targetSize)); 39 | } 40 | 41 | - (void)testFitsPDFWithinGivenTargetWidth 42 | { 43 | [self.renderer fitWidth:100]; 44 | XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 100), self.renderer.targetSize)); 45 | } 46 | 47 | - (void)testFitsPDFWithinGivenTargetHeight 48 | { 49 | [self.renderer fitHeight:100]; 50 | XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 100), self.renderer.targetSize)); 51 | } 52 | 53 | #pragma mark - caching 54 | 55 | - (void)testChangesCachePathBasedOnTargetSize 56 | { 57 | NSString *path = [self.renderer cachePathWithIdentifier:nil]; 58 | XCTAssertEqualObjects(path, [self.renderer cachePathWithIdentifier:nil]); 59 | 60 | self.renderer.targetSize = CGSizeMake(123, 456); 61 | NSString *newPath = [self.renderer cachePathWithIdentifier:nil]; 62 | XCTAssertFalse([path isEqualToString:newPath]); 63 | XCTAssertEqualObjects(newPath, [self.renderer cachePathWithIdentifier:nil]); 64 | } 65 | 66 | - (void)testChangesCachePathBasedOnSourcePageIndex 67 | { 68 | NSString *path = [self.renderer cachePathWithIdentifier:nil]; 69 | XCTAssertEqualObjects(path, [self.renderer cachePathWithIdentifier:nil]); 70 | 71 | self.renderer.sourcePageIndex = 2; 72 | NSString *newPath = [self.renderer cachePathWithIdentifier:nil]; 73 | XCTAssertFalse([path isEqualToString:newPath]); 74 | XCTAssertEqualObjects(newPath, [self.renderer cachePathWithIdentifier:nil]); 75 | } 76 | 77 | - (void)testRaisesWhenUsedAsMaskAndCachingWithoutCacheIdentifier 78 | { 79 | self.renderer.targetColor = [UIColor redColor]; 80 | 81 | self.renderer.useCache = NO; 82 | XCTAssertNoThrow([self.renderer imageWithCacheIdentifier:nil]); 83 | 84 | self.renderer.useCache = YES; 85 | XCTAssertThrowsSpecificNamed([self.renderer imageWithCacheIdentifier:nil], NSException, @"FTAssetRendererError"); 86 | } 87 | 88 | #pragma mark - drawing 89 | 90 | - (void)testReturnsImageOfExpectedSizeAndScale 91 | { 92 | self.renderer.targetSize = CGSizeMake(100, 50); 93 | XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 50), [self.renderer image].size)); 94 | } 95 | 96 | - (void)testCreatesExpectedSizeImageAtCachePath 97 | { 98 | self.renderer.targetSize = CGSizeMake(100, 50); 99 | NSString *path = [self.renderer cachePathWithIdentifier:nil]; 100 | [self.renderer image]; 101 | sleep(2); // lame, should check if file exists with timeout 102 | UIImage *image = [UIImage imageWithContentsOfFile:path]; 103 | CGFloat scale = [[UIScreen mainScreen] scale]; 104 | XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100 * scale, 50 * scale), image.size)); 105 | } 106 | 107 | #pragma mark - data 108 | 109 | - (void)testRendererWithNSData 110 | { 111 | NSURL *URL = [[NSBundle mainBundle] URLForResource:@"restaurant-icon-mask" withExtension:@"pdf"]; 112 | NSData *data = [NSData dataWithContentsOfURL:URL]; 113 | FTPDFAssetRenderer *dataRenderer = [[FTPDFAssetRenderer alloc] initWithData:data]; 114 | 115 | XCTAssertTrue(CGSizeEqualToSize(dataRenderer.targetSize, CGSizeMake(88, 88))); 116 | XCTAssertTrue(CGSizeEqualToSize(dataRenderer.image.size, CGSizeMake(88, 88))); 117 | } 118 | 119 | @end 120 | -------------------------------------------------------------------------------- /Source/FTAssetRenderer.m: -------------------------------------------------------------------------------- 1 | #import "FTAssetRenderer.h" 2 | #import "TargetConditionals.h" 3 | 4 | // From: https://gist.github.com/1209911 5 | #import 6 | static NSString * FTPDFMD5String(NSString *input) { 7 | const char *cStr = [input UTF8String]; 8 | unsigned char result[16]; 9 | CC_MD5(cStr, (CC_LONG)strlen(cStr), result); 10 | return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 11 | result[0], result[1], result[2], result[3], 12 | result[4], result[5], result[6], result[7], 13 | result[8], result[9], result[10], result[11], 14 | result[12], result[13], result[14], result[15]]; 15 | } 16 | 17 | 18 | @implementation FTAssetRenderer 19 | 20 | #pragma mark - Lifecycle 21 | 22 | - (instancetype)initWithURL:(NSURL *)URL 23 | { 24 | self = [super init]; 25 | if (self == nil) { 26 | return nil; 27 | } 28 | 29 | _URL = URL; 30 | _useCache = YES; 31 | 32 | return self; 33 | } 34 | 35 | - (instancetype)init 36 | { 37 | return [self initWithURL:nil]; 38 | } 39 | 40 | #pragma mark - FTAssetRenderer 41 | 42 | + (NSString *)cacheDirectory 43 | { 44 | static NSString *cacheDirectory; 45 | static dispatch_once_t onceToken; 46 | dispatch_once(&onceToken, ^{ 47 | cacheDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]; 48 | cacheDirectory = [cacheDirectory stringByAppendingPathComponent:@"__FTAssetRenderer_Cache__"]; 49 | [[NSFileManager new] createDirectoryAtPath:cacheDirectory 50 | withIntermediateDirectories:YES 51 | attributes:nil 52 | error:NULL]; 53 | }); 54 | return cacheDirectory; 55 | } 56 | 57 | // Should be overriden by subclass. 58 | - (CGSize)targetSize 59 | { 60 | return CGSizeZero; 61 | } 62 | 63 | - (UIImage *)image 64 | { 65 | return [self imageWithCacheIdentifier:nil]; 66 | } 67 | 68 | - (UIImage *)imageWithCacheIdentifier:(NSString *)identifier 69 | { 70 | if (self.useCache) { 71 | [self assertCanCacheWithIdentifier:identifier]; 72 | } 73 | 74 | UIImage *image = nil; 75 | NSString *cachePath = nil; 76 | 77 | if (self.useCache) { 78 | cachePath = [self cachePathWithIdentifier:identifier]; 79 | image = [self cachedImageAtPath:cachePath]; 80 | if (image != nil) { 81 | return image; 82 | } 83 | } 84 | 85 | // Setup context for target size and with main screen scale factor. 86 | CGSize targetSize = self.targetSize; 87 | UIGraphicsBeginImageContextWithOptions(targetSize, false, 0); 88 | CGContextRef context = UIGraphicsGetCurrentContext(); 89 | // Flip context, making bottom-left the origin. 90 | CGContextConcatCTM(context, CGAffineTransformMake(1, 0, 0, -1, 0, targetSize.height)); 91 | 92 | [self drawImageInContext:context]; 93 | [self drawTargetColorInContext:context]; 94 | 95 | image = UIGraphicsGetImageFromCurrentImageContext(); 96 | UIGraphicsEndImageContext(); 97 | 98 | if (self.useCache) { 99 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 100 | [UIImagePNGRepresentation(image) writeToFile:cachePath atomically:NO]; 101 | }); 102 | } 103 | 104 | return image; 105 | } 106 | 107 | #pragma mark - Protected 108 | 109 | - (void)drawImageInContext:(__unused CGContextRef)context 110 | { 111 | [NSException raise:@"AbstractClassError" 112 | format:@"This class is supposed to be subclassed."]; 113 | } 114 | 115 | - (void)drawTargetColorInContext:(CGContextRef)context 116 | { 117 | CGContextSetFillColorWithColor(context, self.targetColor.CGColor); 118 | CGContextSetBlendMode(context, kCGBlendModeSourceAtop); 119 | CGSize targetSize = self.targetSize; 120 | CGContextFillRect(context, CGRectMake(0, 0, targetSize.width, targetSize.height)); 121 | } 122 | 123 | - (void)assertCanCacheWithIdentifier:(NSString *)identifier 124 | { 125 | if (identifier == nil) { 126 | [NSException raise:@"FTAssetRendererError" 127 | format:@"A masked result can’t be cached without a cache identifier."]; 128 | } else if (self.targetColor == nil) { 129 | [NSException raise:@"FTAssetRendererError" 130 | format:@"Can’t produce an image from a mask without a target color."]; 131 | } 132 | } 133 | 134 | - (NSString *)cachePathWithIdentifier:(NSString *)identifier 135 | { 136 | NSString *cachePath = [self cacheRawFilenameWithIdentifier:identifier]; 137 | #if TARGET_IPHONE_SIMULATOR 138 | // On the simulator, the cache dir is shared between retina and non-retina 139 | // devices, so include the device's main screen scale factor to ensure the 140 | // right dimensions are used per device. 141 | cachePath = [NSString stringWithFormat:@"%@-%f", cachePath, [[UIScreen mainScreen] scale]]; 142 | #endif 143 | cachePath = FTPDFMD5String(cachePath); 144 | cachePath = [[[self class] cacheDirectory] stringByAppendingPathComponent:cachePath]; 145 | cachePath = [cachePath stringByAppendingPathExtension:@"png"]; 146 | return cachePath; 147 | } 148 | 149 | - (NSString *)cacheRawFilenameWithIdentifier:(NSString *)identifier 150 | { 151 | NSDictionary *attributes = [[NSFileManager new] attributesOfItemAtPath:self.URL.path error:NULL]; 152 | NSString *filename = [NSString stringWithFormat:@"%@-%@-%@-%@-%@", 153 | self.URL.lastPathComponent ?: @"", 154 | attributes[NSFileSize] ?: @"", 155 | attributes[NSFileModificationDate] ?: @"", 156 | NSStringFromCGSize(self.targetSize), 157 | identifier ?: @""]; 158 | return filename; 159 | } 160 | 161 | #pragma mark - Private 162 | 163 | - (UIImage *)cachedImageAtPath:(NSString *)cachePath 164 | { 165 | UIImage *image = nil; 166 | 167 | NSData *data = [NSData dataWithContentsOfFile:cachePath]; 168 | if (data != nil) { 169 | CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data); 170 | CGImageRef imageRef = CGImageCreateWithPNGDataProvider(provider, NULL, NO, kCGRenderingIntentDefault); 171 | CGDataProviderRelease(provider); 172 | image = [UIImage imageWithCGImage:imageRef 173 | scale:[[UIScreen mainScreen] scale] 174 | orientation:UIImageOrientationUp]; 175 | CGImageRelease(imageRef); 176 | } 177 | 178 | return image; 179 | } 180 | 181 | @end 182 | -------------------------------------------------------------------------------- /Source/FTPDFAssetRenderer.m: -------------------------------------------------------------------------------- 1 | #import "FTPDFAssetRenderer.h" 2 | 3 | // From: https://gist.github.com/1209911 4 | #import 5 | static NSString * FTPDFMD5String(NSData *input) { 6 | unsigned char result[16]; 7 | CC_MD5(input.bytes, (CC_LONG)input.length, result); 8 | return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 9 | result[0], result[1], result[2], result[3], 10 | result[4], result[5], result[6], result[7], 11 | result[8], result[9], result[10], result[11], 12 | result[12], result[13], result[14], result[15]]; 13 | } 14 | 15 | 16 | @implementation FTAssetRenderer (FTPDFAssetRenderer) 17 | 18 | + (FTPDFAssetRenderer *)rendererForPDFNamed:(NSString *)pdfName 19 | { 20 | NSURL *URL = [[NSBundle mainBundle] URLForResource:pdfName withExtension:@"pdf"]; 21 | if (URL != nil) { 22 | FTPDFAssetRenderer *renderer = [[FTPDFAssetRenderer alloc] initWithURL:URL]; 23 | return renderer; 24 | } 25 | 26 | return nil; 27 | } 28 | 29 | @end 30 | 31 | 32 | @interface FTPDFAssetRenderer () { 33 | CGPDFDocumentRef _document; 34 | NSString *_cachePathIdentifier; 35 | } 36 | 37 | @property (nonatomic, readonly, nullable) NSData *data; 38 | 39 | @end 40 | 41 | @implementation FTPDFAssetRenderer 42 | 43 | @synthesize targetSize = _targetSize; 44 | 45 | #pragma mark - Lifecycle 46 | 47 | - (instancetype)initWithURL:(NSURL *)URL 48 | { 49 | self = [super initWithURL:URL]; 50 | if (self == nil) { 51 | return nil; 52 | } 53 | 54 | [self _commonPDFAssetRendererInit]; 55 | 56 | return self; 57 | } 58 | 59 | - (instancetype)initWithData:(NSData *)data 60 | { 61 | self = [super initWithURL:nil]; 62 | if (self == nil) { 63 | return nil; 64 | } 65 | 66 | [self _commonPDFAssetRendererInit]; 67 | _data = data; 68 | 69 | return self; 70 | } 71 | 72 | - (void)_commonPDFAssetRendererInit 73 | { 74 | // Don't open the PDF yet, as the user may want the actual work to be done on a background thread. 75 | _document = NULL; 76 | _sourcePageIndex = 1; 77 | _targetSize = CGSizeZero; 78 | } 79 | 80 | - (void)dealloc 81 | { 82 | CGPDFDocumentRelease(_document); 83 | } 84 | 85 | #pragma mark - FTAssetRenderer 86 | 87 | // A PDF does not necessarily have to be used as a mask. 88 | - (void)assertCanCacheWithIdentifier:(NSString *)identifier 89 | { 90 | if (self.URL == nil && self.cachePathIdentifier == nil) { 91 | [NSException raise:@"FTAssetRendererError" 92 | format:@"An image can't be cached without a valid cache path identifier."]; 93 | } 94 | 95 | if (self.isMask) { 96 | [super assertCanCacheWithIdentifier:identifier]; 97 | } 98 | } 99 | 100 | - (UIImage *)imageWithCacheIdentifier:(NSString *)identifier 101 | { 102 | if (self.sourcePage == NULL) { 103 | [NSException raise:@"FTAssetRendererError" 104 | format:@"Can’t render an image without a source page."]; 105 | } 106 | 107 | return [super imageWithCacheIdentifier:identifier]; 108 | } 109 | 110 | - (void)drawImageInContext:(CGContextRef)context 111 | { 112 | // Draw page scaled to the target size. 113 | CGContextSaveGState(context); 114 | CGRect mediaRect = self.mediaRectOfSourcePage; 115 | CGSize targetSize = self.targetSize; 116 | CGContextScaleCTM(context, targetSize.width / mediaRect.size.width, 117 | targetSize.height / mediaRect.size.height); 118 | CGContextTranslateCTM(context, -mediaRect.origin.x, -mediaRect.origin.y); 119 | CGContextDrawPDFPage(context, self.sourcePage); 120 | CGContextRestoreGState(context); 121 | } 122 | 123 | - (void)drawTargetColorInContext:(CGContextRef)context 124 | { 125 | if (self.isMask) { 126 | [super drawTargetColorInContext:context]; 127 | } 128 | } 129 | 130 | - (NSString *)cacheRawFilenameWithIdentifier:(NSString *)identifier 131 | { 132 | NSString *filename = [super cacheRawFilenameWithIdentifier:identifier]; 133 | if (self.URL == nil) { 134 | filename = [filename stringByAppendingFormat:@"-%@", self.cachePathIdentifier]; 135 | } 136 | 137 | return [NSString stringWithFormat:@"%@-%zd", filename, self.sourcePageIndex]; 138 | } 139 | 140 | #pragma mark - FTPDFAssetRenderer 141 | 142 | - (CGPDFDocumentRef)document 143 | { 144 | if (_document == NULL) { 145 | NSAssert(self.URL != nil || self.data != nil, @"PDF Asset Renderer needs either a valid URL or NSData object"); 146 | if (self.URL != nil) { 147 | _document = CGPDFDocumentCreateWithURL((__bridge CFURLRef)self.URL); 148 | } else if (self.data != nil) { 149 | CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)self.data); 150 | _document = CGPDFDocumentCreateWithProvider(provider); 151 | CGDataProviderRelease(provider); 152 | } 153 | } 154 | 155 | return _document; 156 | } 157 | 158 | - (CGPDFPageRef)sourcePage 159 | { 160 | return CGPDFDocumentGetPage(self.document, self.sourcePageIndex); 161 | } 162 | 163 | - (CGSize)sourceSize 164 | { 165 | return self.mediaRectOfSourcePage.size; 166 | } 167 | 168 | - (CGRect)mediaRectOfSourcePage 169 | { 170 | return CGPDFPageGetBoxRect(self.sourcePage, kCGPDFCropBox); 171 | } 172 | 173 | - (BOOL)isMask 174 | { 175 | return self.targetColor != nil; 176 | } 177 | 178 | // Returns the full size of the source page, unless one is specified. 179 | - (CGSize)targetSize 180 | { 181 | if (CGSizeEqualToSize(_targetSize, CGSizeZero)) { 182 | _targetSize = self.sourceSize; 183 | } 184 | 185 | return _targetSize; 186 | } 187 | 188 | - (void)fitSize:(CGSize)maxSize 189 | { 190 | CGSize sourceSize = self.sourceSize; 191 | CGFloat scaleFactor = MAX(sourceSize.width / maxSize.width, sourceSize.height / maxSize.height); 192 | self.targetSize = CGSizeMake((CGFloat)ceil(sourceSize.width / scaleFactor), (CGFloat)ceil(sourceSize.height / scaleFactor)); 193 | } 194 | 195 | - (void)fitWidth:(CGFloat)targetWidth 196 | { 197 | CGSize sourceSize = self.sourceSize; 198 | CGFloat aspectRatio = sourceSize.width / sourceSize.height; 199 | self.targetSize = CGSizeMake(targetWidth, (CGFloat)ceil(targetWidth / aspectRatio)); 200 | } 201 | 202 | - (void)fitHeight:(CGFloat)targetHeight 203 | { 204 | CGSize sourceSize = self.sourceSize; 205 | CGFloat aspectRatio = sourceSize.width / sourceSize.height; 206 | self.targetSize = CGSizeMake((CGFloat)ceil(targetHeight * aspectRatio), targetHeight); 207 | } 208 | 209 | #pragma mark - Private 210 | 211 | - (NSString *)cachePathIdentifier 212 | { 213 | if (_cachePathIdentifier == nil && self.data != nil) { 214 | _cachePathIdentifier = FTPDFMD5String(self.data); 215 | } 216 | 217 | return _cachePathIdentifier; 218 | } 219 | 220 | @end 221 | -------------------------------------------------------------------------------- /Example/FTAssetRenderer.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 51C4097A1625F62900AF7C06 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51C409791625F62900AF7C06 /* UIKit.framework */; }; 11 | 51C4097C1625F62900AF7C06 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51C4097B1625F62900AF7C06 /* Foundation.framework */; }; 12 | 51C4097E1625F62900AF7C06 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51C4097D1625F62900AF7C06 /* CoreGraphics.framework */; }; 13 | 51C409841625F62900AF7C06 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 51C409821625F62900AF7C06 /* InfoPlist.strings */; }; 14 | 51C409861625F62900AF7C06 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 51C409851625F62900AF7C06 /* main.m */; }; 15 | 51C4098A1625F62900AF7C06 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 51C409891625F62900AF7C06 /* AppDelegate.m */; }; 16 | 51C4098C1625F62900AF7C06 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 51C4098B1625F62900AF7C06 /* Default.png */; }; 17 | 51C4098E1625F62900AF7C06 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 51C4098D1625F62900AF7C06 /* Default@2x.png */; }; 18 | 51C409901625F62900AF7C06 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 51C4098F1625F62900AF7C06 /* Default-568h@2x.png */; }; 19 | 51C409BA1626014200AF7C06 /* FTPDFAssetRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 51C409B91626014200AF7C06 /* FTPDFAssetRenderer.m */; }; 20 | 51C409BD1626038900AF7C06 /* restaurant-icon-mask.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 51C409BC1626038900AF7C06 /* restaurant-icon-mask.pdf */; }; 21 | 51C409DB1627191600AF7C06 /* FTAssetRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 51C409DA1627191600AF7C06 /* FTAssetRenderer.m */; }; 22 | 51C409DF1627240D00AF7C06 /* FTImageAssetRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 51C409DE1627240D00AF7C06 /* FTImageAssetRenderer.m */; }; 23 | 51C409E7162C0C1000AF7C06 /* restaurant-icon-mask.png in Resources */ = {isa = PBXBuildFile; fileRef = 51C409E6162C0C1000AF7C06 /* restaurant-icon-mask.png */; }; 24 | 51C409E9162C0C8A00AF7C06 /* restaurant-icon-mask@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 51C409E8162C0C8A00AF7C06 /* restaurant-icon-mask@2x.png */; }; 25 | 9B6203561CC7C228005020F4 /* FTAssetRendererTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B6203511CC7C228005020F4 /* FTAssetRendererTests.m */; }; 26 | 9B6203571CC7C228005020F4 /* FTImageAssetRendererTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B6203531CC7C228005020F4 /* FTImageAssetRendererTests.m */; }; 27 | 9B6203581CC7C228005020F4 /* FTPDFAssetRendererTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B6203551CC7C228005020F4 /* FTPDFAssetRendererTests.m */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXContainerItemProxy section */ 31 | 9B62034B1CC7C1FB005020F4 /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = 51C4096C1625F62900AF7C06 /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = 51C409741625F62900AF7C06; 36 | remoteInfo = FTAssetRenderer; 37 | }; 38 | /* End PBXContainerItemProxy section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | 51C409751625F62900AF7C06 /* FTAssetRenderer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FTAssetRenderer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 51C409791625F62900AF7C06 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 43 | 51C4097B1625F62900AF7C06 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 44 | 51C4097D1625F62900AF7C06 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 45 | 51C409811625F62900AF7C06 /* FTAssetRenderer-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FTAssetRenderer-Info.plist"; sourceTree = ""; }; 46 | 51C409831625F62900AF7C06 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 47 | 51C409851625F62900AF7C06 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 48 | 51C409871625F62900AF7C06 /* FTAssetRenderer-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FTAssetRenderer-Prefix.pch"; sourceTree = ""; }; 49 | 51C409881625F62900AF7C06 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 50 | 51C409891625F62900AF7C06 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 51 | 51C4098B1625F62900AF7C06 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 52 | 51C4098D1625F62900AF7C06 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 53 | 51C4098F1625F62900AF7C06 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 54 | 51C409B81626014200AF7C06 /* FTPDFAssetRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTPDFAssetRenderer.h; path = ../Source/FTPDFAssetRenderer.h; sourceTree = ""; }; 55 | 51C409B91626014200AF7C06 /* FTPDFAssetRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FTPDFAssetRenderer.m; path = ../Source/FTPDFAssetRenderer.m; sourceTree = ""; }; 56 | 51C409BC1626038900AF7C06 /* restaurant-icon-mask.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = "restaurant-icon-mask.pdf"; sourceTree = SOURCE_ROOT; }; 57 | 51C409D91627191600AF7C06 /* FTAssetRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTAssetRenderer.h; path = ../Source/FTAssetRenderer.h; sourceTree = ""; }; 58 | 51C409DA1627191600AF7C06 /* FTAssetRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FTAssetRenderer.m; path = ../Source/FTAssetRenderer.m; sourceTree = ""; }; 59 | 51C409DD1627240D00AF7C06 /* FTImageAssetRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTImageAssetRenderer.h; path = ../Source/FTImageAssetRenderer.h; sourceTree = ""; }; 60 | 51C409DE1627240D00AF7C06 /* FTImageAssetRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FTImageAssetRenderer.m; path = ../Source/FTImageAssetRenderer.m; sourceTree = ""; }; 61 | 51C409E6162C0C1000AF7C06 /* restaurant-icon-mask.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "restaurant-icon-mask.png"; sourceTree = ""; }; 62 | 51C409E8162C0C8A00AF7C06 /* restaurant-icon-mask@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "restaurant-icon-mask@2x.png"; sourceTree = ""; }; 63 | 9B6203461CC7C1FB005020F4 /* FTAssetRendererTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FTAssetRendererTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | 9B62034A1CC7C1FB005020F4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../../FTAssetRendererTests/Info.plist; sourceTree = ""; }; 65 | 9B6203501CC7C228005020F4 /* FTAssetRendererTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTAssetRendererTests.h; path = ../../FTAssetRendererTests/FTAssetRendererTests.h; sourceTree = ""; }; 66 | 9B6203511CC7C228005020F4 /* FTAssetRendererTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FTAssetRendererTests.m; path = ../../FTAssetRendererTests/FTAssetRendererTests.m; sourceTree = ""; }; 67 | 9B6203521CC7C228005020F4 /* FTImageAssetRendererTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTImageAssetRendererTests.h; path = ../../FTAssetRendererTests/FTImageAssetRendererTests.h; sourceTree = ""; }; 68 | 9B6203531CC7C228005020F4 /* FTImageAssetRendererTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FTImageAssetRendererTests.m; path = ../../FTAssetRendererTests/FTImageAssetRendererTests.m; sourceTree = ""; }; 69 | 9B6203541CC7C228005020F4 /* FTPDFAssetRendererTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTPDFAssetRendererTests.h; path = ../../FTAssetRendererTests/FTPDFAssetRendererTests.h; sourceTree = ""; }; 70 | 9B6203551CC7C228005020F4 /* FTPDFAssetRendererTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FTPDFAssetRendererTests.m; path = ../../FTAssetRendererTests/FTPDFAssetRendererTests.m; sourceTree = ""; }; 71 | /* End PBXFileReference section */ 72 | 73 | /* Begin PBXFrameworksBuildPhase section */ 74 | 51C409721625F62900AF7C06 /* Frameworks */ = { 75 | isa = PBXFrameworksBuildPhase; 76 | buildActionMask = 2147483647; 77 | files = ( 78 | 51C4097A1625F62900AF7C06 /* UIKit.framework in Frameworks */, 79 | 51C4097C1625F62900AF7C06 /* Foundation.framework in Frameworks */, 80 | 51C4097E1625F62900AF7C06 /* CoreGraphics.framework in Frameworks */, 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | 9B6203431CC7C1FB005020F4 /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | /* End PBXFrameworksBuildPhase section */ 92 | 93 | /* Begin PBXGroup section */ 94 | 51C4096A1625F62900AF7C06 = { 95 | isa = PBXGroup; 96 | children = ( 97 | 51C409C21626044E00AF7C06 /* Example */, 98 | 51C409B31626000A00AF7C06 /* Source */, 99 | 9B6203471CC7C1FB005020F4 /* FTAssetRendererTests */, 100 | 51C409781625F62900AF7C06 /* Frameworks */, 101 | 51C409761625F62900AF7C06 /* Products */, 102 | ); 103 | sourceTree = ""; 104 | }; 105 | 51C409761625F62900AF7C06 /* Products */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 51C409751625F62900AF7C06 /* FTAssetRenderer.app */, 109 | 9B6203461CC7C1FB005020F4 /* FTAssetRendererTests.xctest */, 110 | ); 111 | name = Products; 112 | sourceTree = ""; 113 | }; 114 | 51C409781625F62900AF7C06 /* Frameworks */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 51C409791625F62900AF7C06 /* UIKit.framework */, 118 | 51C4097B1625F62900AF7C06 /* Foundation.framework */, 119 | 51C4097D1625F62900AF7C06 /* CoreGraphics.framework */, 120 | ); 121 | name = Frameworks; 122 | sourceTree = ""; 123 | }; 124 | 51C409B31626000A00AF7C06 /* Source */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 51C409D91627191600AF7C06 /* FTAssetRenderer.h */, 128 | 51C409DA1627191600AF7C06 /* FTAssetRenderer.m */, 129 | 51C409DD1627240D00AF7C06 /* FTImageAssetRenderer.h */, 130 | 51C409DE1627240D00AF7C06 /* FTImageAssetRenderer.m */, 131 | 51C409B81626014200AF7C06 /* FTPDFAssetRenderer.h */, 132 | 51C409B91626014200AF7C06 /* FTPDFAssetRenderer.m */, 133 | ); 134 | name = Source; 135 | sourceTree = ""; 136 | }; 137 | 51C409C21626044E00AF7C06 /* Example */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 51C409E6162C0C1000AF7C06 /* restaurant-icon-mask.png */, 141 | 51C409E8162C0C8A00AF7C06 /* restaurant-icon-mask@2x.png */, 142 | 51C409BC1626038900AF7C06 /* restaurant-icon-mask.pdf */, 143 | 51C409881625F62900AF7C06 /* AppDelegate.h */, 144 | 51C409891625F62900AF7C06 /* AppDelegate.m */, 145 | 51C409C41626047E00AF7C06 /* Supporting Files */, 146 | ); 147 | name = Example; 148 | sourceTree = ""; 149 | }; 150 | 51C409C41626047E00AF7C06 /* Supporting Files */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 51C409811625F62900AF7C06 /* FTAssetRenderer-Info.plist */, 154 | 51C409821625F62900AF7C06 /* InfoPlist.strings */, 155 | 51C409851625F62900AF7C06 /* main.m */, 156 | 51C409871625F62900AF7C06 /* FTAssetRenderer-Prefix.pch */, 157 | 51C4098B1625F62900AF7C06 /* Default.png */, 158 | 51C4098D1625F62900AF7C06 /* Default@2x.png */, 159 | 51C4098F1625F62900AF7C06 /* Default-568h@2x.png */, 160 | ); 161 | name = "Supporting Files"; 162 | sourceTree = ""; 163 | }; 164 | 9B6203471CC7C1FB005020F4 /* FTAssetRendererTests */ = { 165 | isa = PBXGroup; 166 | children = ( 167 | 9B62034A1CC7C1FB005020F4 /* Info.plist */, 168 | 9B6203501CC7C228005020F4 /* FTAssetRendererTests.h */, 169 | 9B6203511CC7C228005020F4 /* FTAssetRendererTests.m */, 170 | 9B6203521CC7C228005020F4 /* FTImageAssetRendererTests.h */, 171 | 9B6203531CC7C228005020F4 /* FTImageAssetRendererTests.m */, 172 | 9B6203541CC7C228005020F4 /* FTPDFAssetRendererTests.h */, 173 | 9B6203551CC7C228005020F4 /* FTPDFAssetRendererTests.m */, 174 | ); 175 | path = FTAssetRendererTests; 176 | sourceTree = ""; 177 | }; 178 | /* End PBXGroup section */ 179 | 180 | /* Begin PBXNativeTarget section */ 181 | 51C409741625F62900AF7C06 /* FTAssetRenderer */ = { 182 | isa = PBXNativeTarget; 183 | buildConfigurationList = 51C409A81625F62A00AF7C06 /* Build configuration list for PBXNativeTarget "FTAssetRenderer" */; 184 | buildPhases = ( 185 | 51C409711625F62900AF7C06 /* Sources */, 186 | 51C409721625F62900AF7C06 /* Frameworks */, 187 | 51C409731625F62900AF7C06 /* Resources */, 188 | ); 189 | buildRules = ( 190 | ); 191 | dependencies = ( 192 | ); 193 | name = FTAssetRenderer; 194 | productName = FTPDFIconRenderer; 195 | productReference = 51C409751625F62900AF7C06 /* FTAssetRenderer.app */; 196 | productType = "com.apple.product-type.application"; 197 | }; 198 | 9B6203451CC7C1FB005020F4 /* FTAssetRendererTests */ = { 199 | isa = PBXNativeTarget; 200 | buildConfigurationList = 9B62034D1CC7C1FC005020F4 /* Build configuration list for PBXNativeTarget "FTAssetRendererTests" */; 201 | buildPhases = ( 202 | 9B6203421CC7C1FB005020F4 /* Sources */, 203 | 9B6203431CC7C1FB005020F4 /* Frameworks */, 204 | 9B6203441CC7C1FB005020F4 /* Resources */, 205 | ); 206 | buildRules = ( 207 | ); 208 | dependencies = ( 209 | 9B62034C1CC7C1FB005020F4 /* PBXTargetDependency */, 210 | ); 211 | name = FTAssetRendererTests; 212 | productName = FTAssetRendererTests; 213 | productReference = 9B6203461CC7C1FB005020F4 /* FTAssetRendererTests.xctest */; 214 | productType = "com.apple.product-type.bundle.unit-test"; 215 | }; 216 | /* End PBXNativeTarget section */ 217 | 218 | /* Begin PBXProject section */ 219 | 51C4096C1625F62900AF7C06 /* Project object */ = { 220 | isa = PBXProject; 221 | attributes = { 222 | LastUpgradeCheck = 0450; 223 | ORGANIZATIONNAME = "Fingertips BV"; 224 | TargetAttributes = { 225 | 9B6203451CC7C1FB005020F4 = { 226 | CreatedOnToolsVersion = 7.3; 227 | TestTargetID = 51C409741625F62900AF7C06; 228 | }; 229 | }; 230 | }; 231 | buildConfigurationList = 51C4096F1625F62900AF7C06 /* Build configuration list for PBXProject "FTAssetRenderer" */; 232 | compatibilityVersion = "Xcode 3.2"; 233 | developmentRegion = English; 234 | hasScannedForEncodings = 0; 235 | knownRegions = ( 236 | en, 237 | ); 238 | mainGroup = 51C4096A1625F62900AF7C06; 239 | productRefGroup = 51C409761625F62900AF7C06 /* Products */; 240 | projectDirPath = ""; 241 | projectRoot = ""; 242 | targets = ( 243 | 51C409741625F62900AF7C06 /* FTAssetRenderer */, 244 | 9B6203451CC7C1FB005020F4 /* FTAssetRendererTests */, 245 | ); 246 | }; 247 | /* End PBXProject section */ 248 | 249 | /* Begin PBXResourcesBuildPhase section */ 250 | 51C409731625F62900AF7C06 /* Resources */ = { 251 | isa = PBXResourcesBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | 51C409841625F62900AF7C06 /* InfoPlist.strings in Resources */, 255 | 51C4098C1625F62900AF7C06 /* Default.png in Resources */, 256 | 51C4098E1625F62900AF7C06 /* Default@2x.png in Resources */, 257 | 51C409901625F62900AF7C06 /* Default-568h@2x.png in Resources */, 258 | 51C409BD1626038900AF7C06 /* restaurant-icon-mask.pdf in Resources */, 259 | 51C409E7162C0C1000AF7C06 /* restaurant-icon-mask.png in Resources */, 260 | 51C409E9162C0C8A00AF7C06 /* restaurant-icon-mask@2x.png in Resources */, 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | }; 264 | 9B6203441CC7C1FB005020F4 /* Resources */ = { 265 | isa = PBXResourcesBuildPhase; 266 | buildActionMask = 2147483647; 267 | files = ( 268 | ); 269 | runOnlyForDeploymentPostprocessing = 0; 270 | }; 271 | /* End PBXResourcesBuildPhase section */ 272 | 273 | /* Begin PBXSourcesBuildPhase section */ 274 | 51C409711625F62900AF7C06 /* Sources */ = { 275 | isa = PBXSourcesBuildPhase; 276 | buildActionMask = 2147483647; 277 | files = ( 278 | 51C409861625F62900AF7C06 /* main.m in Sources */, 279 | 51C4098A1625F62900AF7C06 /* AppDelegate.m in Sources */, 280 | 51C409BA1626014200AF7C06 /* FTPDFAssetRenderer.m in Sources */, 281 | 51C409DB1627191600AF7C06 /* FTAssetRenderer.m in Sources */, 282 | 51C409DF1627240D00AF7C06 /* FTImageAssetRenderer.m in Sources */, 283 | ); 284 | runOnlyForDeploymentPostprocessing = 0; 285 | }; 286 | 9B6203421CC7C1FB005020F4 /* Sources */ = { 287 | isa = PBXSourcesBuildPhase; 288 | buildActionMask = 2147483647; 289 | files = ( 290 | 9B6203561CC7C228005020F4 /* FTAssetRendererTests.m in Sources */, 291 | 9B6203581CC7C228005020F4 /* FTPDFAssetRendererTests.m in Sources */, 292 | 9B6203571CC7C228005020F4 /* FTImageAssetRendererTests.m in Sources */, 293 | ); 294 | runOnlyForDeploymentPostprocessing = 0; 295 | }; 296 | /* End PBXSourcesBuildPhase section */ 297 | 298 | /* Begin PBXTargetDependency section */ 299 | 9B62034C1CC7C1FB005020F4 /* PBXTargetDependency */ = { 300 | isa = PBXTargetDependency; 301 | target = 51C409741625F62900AF7C06 /* FTAssetRenderer */; 302 | targetProxy = 9B62034B1CC7C1FB005020F4 /* PBXContainerItemProxy */; 303 | }; 304 | /* End PBXTargetDependency section */ 305 | 306 | /* Begin PBXVariantGroup section */ 307 | 51C409821625F62900AF7C06 /* InfoPlist.strings */ = { 308 | isa = PBXVariantGroup; 309 | children = ( 310 | 51C409831625F62900AF7C06 /* en */, 311 | ); 312 | name = InfoPlist.strings; 313 | sourceTree = ""; 314 | }; 315 | /* End PBXVariantGroup section */ 316 | 317 | /* Begin XCBuildConfiguration section */ 318 | 51C409A61625F62A00AF7C06 /* Debug */ = { 319 | isa = XCBuildConfiguration; 320 | buildSettings = { 321 | ALWAYS_SEARCH_USER_PATHS = NO; 322 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 323 | CLANG_CXX_LIBRARY = "libc++"; 324 | CLANG_ENABLE_OBJC_ARC = YES; 325 | CLANG_WARN_ASSIGN_ENUM = YES; 326 | CLANG_WARN_BOOL_CONVERSION = YES; 327 | CLANG_WARN_CONSTANT_CONVERSION = YES; 328 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 329 | CLANG_WARN_EMPTY_BODY = YES; 330 | CLANG_WARN_ENUM_CONVERSION = YES; 331 | CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; 332 | CLANG_WARN_INT_CONVERSION = YES; 333 | CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; 334 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; 335 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 336 | CLANG_WARN_UNREACHABLE_CODE = YES; 337 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 338 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 339 | COPY_PHASE_STRIP = NO; 340 | GCC_C_LANGUAGE_STANDARD = gnu99; 341 | GCC_DYNAMIC_NO_PIC = NO; 342 | GCC_OPTIMIZATION_LEVEL = 0; 343 | GCC_PREPROCESSOR_DEFINITIONS = ( 344 | "DEBUG=1", 345 | "$(inherited)", 346 | ); 347 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 348 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 349 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 350 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 351 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 352 | GCC_WARN_SHADOW = YES; 353 | GCC_WARN_SIGN_COMPARE = YES; 354 | GCC_WARN_STRICT_SELECTOR_MATCH = YES; 355 | GCC_WARN_UNDECLARED_SELECTOR = YES; 356 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 357 | GCC_WARN_UNUSED_FUNCTION = YES; 358 | GCC_WARN_UNUSED_LABEL = YES; 359 | GCC_WARN_UNUSED_PARAMETER = YES; 360 | GCC_WARN_UNUSED_VARIABLE = YES; 361 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 362 | SDKROOT = iphoneos; 363 | TARGETED_DEVICE_FAMILY = "1,2"; 364 | }; 365 | name = Debug; 366 | }; 367 | 51C409A71625F62A00AF7C06 /* Release */ = { 368 | isa = XCBuildConfiguration; 369 | buildSettings = { 370 | ALWAYS_SEARCH_USER_PATHS = NO; 371 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 372 | CLANG_CXX_LIBRARY = "libc++"; 373 | CLANG_ENABLE_OBJC_ARC = YES; 374 | CLANG_WARN_ASSIGN_ENUM = YES; 375 | CLANG_WARN_BOOL_CONVERSION = YES; 376 | CLANG_WARN_CONSTANT_CONVERSION = YES; 377 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 378 | CLANG_WARN_EMPTY_BODY = YES; 379 | CLANG_WARN_ENUM_CONVERSION = YES; 380 | CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; 381 | CLANG_WARN_INT_CONVERSION = YES; 382 | CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; 383 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; 384 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 385 | CLANG_WARN_UNREACHABLE_CODE = YES; 386 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 387 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 388 | COPY_PHASE_STRIP = YES; 389 | GCC_C_LANGUAGE_STANDARD = gnu99; 390 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 391 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 392 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 393 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 394 | GCC_WARN_SHADOW = YES; 395 | GCC_WARN_SIGN_COMPARE = YES; 396 | GCC_WARN_STRICT_SELECTOR_MATCH = YES; 397 | GCC_WARN_UNDECLARED_SELECTOR = YES; 398 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 399 | GCC_WARN_UNUSED_FUNCTION = YES; 400 | GCC_WARN_UNUSED_LABEL = YES; 401 | GCC_WARN_UNUSED_PARAMETER = YES; 402 | GCC_WARN_UNUSED_VARIABLE = YES; 403 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 404 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 405 | SDKROOT = iphoneos; 406 | TARGETED_DEVICE_FAMILY = "1,2"; 407 | VALIDATE_PRODUCT = YES; 408 | }; 409 | name = Release; 410 | }; 411 | 51C409A91625F62A00AF7C06 /* Debug */ = { 412 | isa = XCBuildConfiguration; 413 | buildSettings = { 414 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 415 | GCC_PREFIX_HEADER = "FTAssetRenderer-Prefix.pch"; 416 | INFOPLIST_FILE = "FTAssetRenderer-Info.plist"; 417 | PRODUCT_NAME = "$(TARGET_NAME)"; 418 | WRAPPER_EXTENSION = app; 419 | }; 420 | name = Debug; 421 | }; 422 | 51C409AA1625F62A00AF7C06 /* Release */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 426 | GCC_PREFIX_HEADER = "FTAssetRenderer-Prefix.pch"; 427 | INFOPLIST_FILE = "FTAssetRenderer-Info.plist"; 428 | PRODUCT_NAME = "$(TARGET_NAME)"; 429 | WRAPPER_EXTENSION = app; 430 | }; 431 | name = Release; 432 | }; 433 | 9B62034E1CC7C1FC005020F4 /* Debug */ = { 434 | isa = XCBuildConfiguration; 435 | buildSettings = { 436 | BUNDLE_LOADER = "$(TEST_HOST)"; 437 | CLANG_ANALYZER_NONNULL = YES; 438 | CLANG_ENABLE_MODULES = YES; 439 | CLANG_WARN_BOOL_CONVERSION = YES; 440 | CLANG_WARN_CONSTANT_CONVERSION = YES; 441 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 442 | CLANG_WARN_ENUM_CONVERSION = YES; 443 | CLANG_WARN_INT_CONVERSION = YES; 444 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 445 | CLANG_WARN_UNREACHABLE_CODE = YES; 446 | DEBUG_INFORMATION_FORMAT = dwarf; 447 | ENABLE_STRICT_OBJC_MSGSEND = YES; 448 | ENABLE_TESTABILITY = YES; 449 | GCC_NO_COMMON_BLOCKS = YES; 450 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 451 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 452 | GCC_WARN_UNDECLARED_SELECTOR = YES; 453 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 454 | GCC_WARN_UNUSED_FUNCTION = YES; 455 | INFOPLIST_FILE = ../FTAssetRendererTests/Info.plist; 456 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 457 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 458 | MTL_ENABLE_DEBUG_INFO = YES; 459 | ONLY_ACTIVE_ARCH = YES; 460 | PRODUCT_BUNDLE_IDENTIFIER = com.fngtps.FTAssetRendererTests; 461 | PRODUCT_NAME = "$(TARGET_NAME)"; 462 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/FTAssetRenderer.app/FTAssetRenderer"; 463 | }; 464 | name = Debug; 465 | }; 466 | 9B62034F1CC7C1FC005020F4 /* Release */ = { 467 | isa = XCBuildConfiguration; 468 | buildSettings = { 469 | BUNDLE_LOADER = "$(TEST_HOST)"; 470 | CLANG_ANALYZER_NONNULL = YES; 471 | CLANG_ENABLE_MODULES = YES; 472 | CLANG_WARN_BOOL_CONVERSION = YES; 473 | CLANG_WARN_CONSTANT_CONVERSION = YES; 474 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 475 | CLANG_WARN_ENUM_CONVERSION = YES; 476 | CLANG_WARN_INT_CONVERSION = YES; 477 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 478 | CLANG_WARN_UNREACHABLE_CODE = YES; 479 | COPY_PHASE_STRIP = NO; 480 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 481 | ENABLE_NS_ASSERTIONS = NO; 482 | ENABLE_STRICT_OBJC_MSGSEND = YES; 483 | GCC_NO_COMMON_BLOCKS = YES; 484 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 485 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 486 | GCC_WARN_UNDECLARED_SELECTOR = YES; 487 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 488 | GCC_WARN_UNUSED_FUNCTION = YES; 489 | INFOPLIST_FILE = ../FTAssetRendererTests/Info.plist; 490 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 491 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 492 | MTL_ENABLE_DEBUG_INFO = NO; 493 | PRODUCT_BUNDLE_IDENTIFIER = com.fngtps.FTAssetRendererTests; 494 | PRODUCT_NAME = "$(TARGET_NAME)"; 495 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/FTAssetRenderer.app/FTAssetRenderer"; 496 | }; 497 | name = Release; 498 | }; 499 | /* End XCBuildConfiguration section */ 500 | 501 | /* Begin XCConfigurationList section */ 502 | 51C4096F1625F62900AF7C06 /* Build configuration list for PBXProject "FTAssetRenderer" */ = { 503 | isa = XCConfigurationList; 504 | buildConfigurations = ( 505 | 51C409A61625F62A00AF7C06 /* Debug */, 506 | 51C409A71625F62A00AF7C06 /* Release */, 507 | ); 508 | defaultConfigurationIsVisible = 0; 509 | defaultConfigurationName = Release; 510 | }; 511 | 51C409A81625F62A00AF7C06 /* Build configuration list for PBXNativeTarget "FTAssetRenderer" */ = { 512 | isa = XCConfigurationList; 513 | buildConfigurations = ( 514 | 51C409A91625F62A00AF7C06 /* Debug */, 515 | 51C409AA1625F62A00AF7C06 /* Release */, 516 | ); 517 | defaultConfigurationIsVisible = 0; 518 | defaultConfigurationName = Release; 519 | }; 520 | 9B62034D1CC7C1FC005020F4 /* Build configuration list for PBXNativeTarget "FTAssetRendererTests" */ = { 521 | isa = XCConfigurationList; 522 | buildConfigurations = ( 523 | 9B62034E1CC7C1FC005020F4 /* Debug */, 524 | 9B62034F1CC7C1FC005020F4 /* Release */, 525 | ); 526 | defaultConfigurationIsVisible = 0; 527 | defaultConfigurationName = Release; 528 | }; 529 | /* End XCConfigurationList section */ 530 | }; 531 | rootObject = 51C4096C1625F62900AF7C06 /* Project object */; 532 | } 533 | --------------------------------------------------------------------------------