NSImageRep mess
I have an NSImage that comes from PDF, so it has one representation of type NSPDFImageRep. I am making the image setDataRetained: YES; to make sure it remains NSPDFImageRep. Later I want to change the page, so I get the rep and set the current page. This is normal.
The problem is when drawing the image, only the first page is rendered.
My impression is that when I draw NSImage, it selects a view and draws that view. Now the image only has one rep, so the one that is being drawn and that is the PDFrep. So why, when I draw the image, isn't the correct page drawing?
HOWEVER, when I draw the view, I get the correct page.
What am I missing?
source to share
NSImage caches NSImageRep on first display. In the case of NSPDFImageRep, the "setCacheMode:" message has no effect. This way, the page to be displayed will always be the first page. See this guide for details .
You have two solutions:
- Direct representation of the drawing.
- Call the "recache" message on NSImage to force rasterization of the selected page.
source to share
An alternative mechanism for creating PDF is to use the CGPDF * functions. To do this, use CGPDFDocumentCreateWithURL
to create an object CGPDFDocumentRef
. Then use CGPDFDocumentGetPage
to get the object CGPDFPageRef
. Then you can use CGContextDrawPDFPage
to draw the page in a graphical context.
You may need to apply a transform to ensure that the document is exactly what you want. Use CGAffineTransform
and CGContextConcatCTM
to do so.
Here is some sample code extracted from one of my projects:
// use your own constants here
NSString *path = @"/path/to/my.pdf";
NSUInteger pageNumber = 14;
CGSize size = [self frame].size;
// if we're drawing into an NSView, then we need to get the current graphics context
CGContextRef context = (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)path, kCFURLPOSIXPathStyle, NO);
CGPDFDocumentRef document = CGPDFDocumentCreateWithURL(url);
CGPDFPageRef page = CGPDFDocumentGetPage(document, pageNumber);
// in my case, I wanted the PDF page to fill in the view
// so we apply a scaling transform to fir the page into the view
double ratio = size.width / CGPDFPageGetBoxRect(page, kCGPDFTrimBox).size.width;
CGAffineTransform transform = CGAffineTransformMakeScale(ratio, ratio);
CGContextConcatCTM(context, transform);
// now we draw the PDF into the context
CGContextDrawPDFPage(context, page);
// don't forget memory management!
CGPDFDocumentRelease(document);
source to share