views:

218

answers:

2

Currently implementing vectorial interface elements on iOS is very peculiar, UIImage advertises support only for raster formats but i am able to set a pdf file as the image of a UIButton in IB here and it renders with good antialiasing, however the image is not visible on either iphone or ipad running iOS 4.x and 3.x, the only way to have it show is to recreate the same button in code and leave out the .pdf extension :

searchButton = [UIButton buttonWithType:UIButtonTypeCustom];
[searchButton setImage:[UIImage imageNamed:@"search"] forState:UIControlStateNormal];
[self.view addSubview:searchButton]; 

However this only shows the image on iOS 4.x and with considerable resize pixelation and no antialiasing as illustrated:

alt text

Besides the obvious questions of why it looks this bad, why it only works in 4.x, and why the IB version does not work at all, does anyone know any ways to properly user vectorial art in apps?

It does not have to be necessarily PDF but I have seen Apple use that a lot on the mac side apps, both the code and IB approaches above work perfectly on OSX apps BTW.

A: 

I don't know why UIImage doesn't work well with PDF, but it should be possible to write your own code to draw a PDF. See the "Opening and Viewing a PDF" section in the Quartz 2D Programming Guide. You could draw the PDF into a CGBitmapContext, use that to create a CGImage, and use that to create a UIImage.

JWWalker
+1  A: 

As iOS misses the PDFKit.framework i guess that the issue with the limited/broken PDF support of UIImage is that it is not supposed to have any support in the first place, in that respect i have reported the limited support it has as a bug (rdar:8338627) and it is a bug in IB too with the rendering support being probably carried over from osx.

I have settled to just rendering the pdf manually in a context then saving that to a UIImage, the code for which is below (tested on iOS 3.x and 4.x)

#include <dlfcn.h>

-(UIImage *)UIImageFromPDF:(NSString*)fileName size:(CGSize)size{
    CFURLRef pdfURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), (CFStringRef)fileName, NULL, NULL);  
    if (pdfURL) {       
        CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL(pdfURL);
        CFRelease(pdfURL);  
        //create context with scaling 0.0 as to get the main screen's if iOS4+
        if (dlsym(RTLD_DEFAULT,"UIGraphicsBeginImageContextWithOptions") == NULL) {
            UIGraphicsBeginImageContext(size);      
        }else {
            UIGraphicsBeginImageContextWithOptions(size,NO,0.0);        
        }
        CGContextRef context = UIGraphicsGetCurrentContext();       
        //translate the content
        CGContextTranslateCTM(context, 0.0, size.height);   
        CGContextScaleCTM(context, 1.0, -1.0);      
        CGContextSaveGState(context);   
        //scale to our desired size
        CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);
        CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(page, kCGPDFCropBox, CGRectMake(0, 0, size.width, size.height), 0, true);
        CGContextConcatCTM(context, pdfTransform);
        CGContextDrawPDFPage(context, page);    
        CGContextRestoreGState(context);
        //return autoreleased UIImage
        UIImage *ret = UIGraphicsGetImageFromCurrentImageContext();     
        UIGraphicsEndImageContext();
        CGPDFDocumentRelease(pdf);      
        return ret;     
    }else {
        NSLog(@"Could not load %@",fileName);
    }
    return nil; 
}
valexa