views:

722

answers:

2

Hi, i'm going to make a PDF reader and i'm trying two possible solutions:

  • UIWebView
  • CGPDFDocumentRef

The first one is very simple, but is slower than the second one. For the second one, i found a tutorial and i can view a pdf and i can zoom it with the two fingers movement. But at the moment i can't do 2 things :

1) View the PDF in landscape mode, maintaining the correct proportions. 2) Do a zoom in / zoom out with the double tap on the screen.

Those funtions are already implemented in the UIWebView, but how said before, it's a little bit slow and it opens the entire PDF doc and not only a single page (so i need to split the file in many "one page pdf files").

Anyone can help me with some links/references/code about those kind of problems ?

Thank you

A: 

With CGPDFDocumentRef, you need to get each page with CGPDFDocumentGetPage and then get the drawing transform with CGPDFPageGetDrawingTransform and apply that to the CGContextRef before you draw the page.

Putting the view with your PDF page in a UIScrollView will let you zoom in and out, if you enable zooming. You can also draw it with a zoom factor using

    CGContextTranslateCTM (context, -sourceRect.origin.x * zoom, -sourceRect.origin.y * zoom);
    CGContextScaleCTM (context, zoom, zoom);

But you'll still run into the issue that very complex PDF pages will be slow to render, and every time you call CGContextDrawPDFPage(context, page); it has to render the entire page, such as when you change the zoom level. There are ways around this, such as drawing into a CATiledLayer.

lucius
A: 

Exactly, in the example that i found, he uses the CATiledLayer.
Here there is my code:

- (void)viewDidLoad
{
    [super viewDidLoad];
    CFURLRef pdfURL = CFBundleCopyResourceURL(
                                              CFBundleGetMainBundle(),
                                              CFSTR(filename),
                                              CFSTR("pdf"), NULL);
    myDocumentRef = CGPDFDocumentCreateWithURL(pdfURL);
    myPageRef = CGPDFDocumentGetPage(myDocumentRef, 1);
    CGRect pageRect = CGRectMake(0, 0, 320, 480); 

    tiledLayer = [CATiledLayer layer];
    tiledLayer.delegate = self;
    tiledLayer.tileSize = CGSizeMake(1024.0, 1024.0);
    tiledLayer.levelsOfDetail = 1000;
    tiledLayer.levelsOfDetailBias = 1000;
    tiledLayer.frame = pageRect;

    myContentView = [[UIView alloc] initWithFrame:pageRect];
    [myContentView.layer addSublayer:tiledLayer];

    CGRect viewFrame = self.view.frame;
    viewFrame.origin = CGPointZero;
    scrollView = [[UIScrollView alloc] initWithFrame:viewFrame];
    scrollView.delegate = self;
    scrollView.contentSize = pageRect.size;
    scrollView.maximumZoomScale = 100;
    [scrollView addSubview:myContentView];

    [self.view addSubview:scrollView];
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return myContentView;
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
    CGContextFillRect(ctx, CGContextGetClipBoundingBox(ctx));
    CGContextTranslateCTM(ctx, 0.0, layer.bounds.size.height);
    CGContextScaleCTM(ctx, 1.0, -1.0);
    CGContextConcatCTM(ctx, CGPDFPageGetDrawingTransform(myPageRef, kCGPDFCropBox, layer.bounds, 0, true));
    CGContextDrawPDFPage(ctx, myPageRef);
}

This part works great, but if i want to introduce the landscape mode, i need to modify this part:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    if( (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) ||
       (interfaceOrientation == UIInterfaceOrientationLandscapeRight)){
        //SOMETHING TO DO FOR LANDSCAPE MODE
    }
    else if((interfaceOrientation == UIInterfaceOrientationPortrait)){
        //SOMETHING TO DO TO RESTORE TO PORTRAIT
    }
    // Return YES for supported orientations
    return ((interfaceOrientation == UIInterfaceOrientationPortrait) ||
            (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) ||
            (interfaceOrientation == UIInterfaceOrientationLandscapeRight));
}

I tried pratically everything, but i can't find a good solution !

Marco
How about this: save the orientation, then when you're drawing the PDF, if it's landscape, use CGContextRotateCTM to rotate the PDF.
jtbandes
Ok, but the problem is that if i call CGContextRotateCTM inside the shouldAutorotateToInterfaceOrientation method, the transformation doesn't go ! I see that the only way to apply the transformation is to put it inside the drawLayer method. (And i don't know i can recall it manually) Any suggestion or trick ?
Marco