I have build such kind of application using approximatively the same approach except :
- I cache the generated image on the disk and always generate two to three images in advance in a separate thread.
- I don't overlay with a
UIImage
but instead draw the image in the layer when zooming is 1. Those tiles will be released automatically when memory warnings are issued.
Whenever the user start zooming, I acquire the CGPDFPage
and render it using the appropriate CTM. The code in - (void)drawLayer: (CALayer*)layer inContext: (CGContextRef) context
is like :
CGAffineTransform currentCTM = CGContextGetCTM(context);
if (currentCTM.a == 1.0 && baseImage) {
//Calculate ideal scale
CGFloat scaleForWidth = baseImage.size.width/self.bounds.size.width;
CGFloat scaleForHeight = baseImage.size.height/self.bounds.size.height;
CGFloat imageScaleFactor = MAX(scaleForWidth, scaleForHeight);
CGSize imageSize = CGSizeMake(baseImage.size.width/imageScaleFactor, baseImage.size.height/imageScaleFactor);
CGRect imageRect = CGRectMake((self.bounds.size.width-imageSize.width)/2, (self.bounds.size.height-imageSize.height)/2, imageSize.width, imageSize.height);
CGContextDrawImage(context, imageRect, [baseImage CGImage]);
} else {
@synchronized(issue) {
CGPDFPageRef pdfPage = CGPDFDocumentGetPage(issue.pdfDoc, pageIndex+1);
pdfToPageTransform = CGPDFPageGetDrawingTransform(pdfPage, kCGPDFMediaBox, layer.bounds, 0, true);
CGContextConcatCTM(context, pdfToPageTransform);
CGContextDrawPDFPage(context, pdfPage);
}
}
issue is the object containg the CGPDFDocumentRef
. I synchronize the part where I access the pdfDoc
property because I release it and recreate it when receiving memoryWarnings. It seems that the CGPDFDocumentRef
object do some internal caching that I did not find how to get rid of.
Assuming that you have a PDPage object:
PDRectangle mediaBox = page.findMediaBox();
boolean isLandscape = mediaBox.getWidth() > mediaBox.getHeight();
however... the page could be rotated:
int rotation = page.findRotation();
if (rotation == 90 || rotation == 270)
isLandscape = !isLandscape;
This is for 1.8.* only. In the 2.* versions, use getMediaBox()
and getRotation()
. Don't use the get*
methods in the 1.8.* versions because they don't look up the page tree if the info is missing at the page level.
Best Answer
I'm the author of CAM::PDF.
Well, there's two parts to this. One is the page's dimensions, as you noted. That works as expected: I used Apple's Preview.app to rotate a PDF file and ran these two command lines:
But there's also the `/Rotate' page attribute. The argument is a number of degrees (default 0, but 90 or 270 are not uncommon). Like page dimensions, it's an inheritable property so you have to navigate to parent pages. Here's a quick-and-dirty command line tool to output the rotation value: