9

I am displaying a pdf page on the CGContext using the code

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

The problem is that the pdf page is getting drawn on the center of the page leaving border on all four sides. Is there any way to make the page fit to screen.

fbrereto
  • 35,429
  • 19
  • 126
  • 178
Anil Sivadas
  • 1,658
  • 3
  • 16
  • 26

5 Answers5

18

To expand on Tia's answer; the built-in method CGPDFPageGetDrawingTransform will scale down but not up. If you want to scale up then you need to work out your own transform by comparing the results of CGPDFGetBoxRect to your content area. Typing extemporaneously:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
    CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
    CGContextFillRect(ctx, layer.bounds);
    CGContextTranslateCTM(ctx, 0.0, layer.bounds.size.height);
    CGContextScaleCTM(ctx, 1.0, -1.0);

    CGRect cropBox = CGPDFGetBoxRect(myPageRef, kCGPDFCropBox);
    CGRect targetRect = layer.bounds;
    CGFloat xScale = targetRect.size.width / cropBox.size.width;
    CGFloat yScale = targetRect.size.height / cropBox.size.height;
    CGFloat scaleToApply = xScale < yScale ? xScale : yScale;
    CGContextConcatCTM(ctx, CGAffineTransformMakeScale(scaleToApply, scaleToApply)); 

    CGContextDrawPDFPage(ctx, myPageRef);
}

So: work out how much you'd have to scale the document by for it to occupy the entire width of the view, how much to occupy the entire height and then actually scale by the lesser of those two values.

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • can you please answer this question i am also trying same way but i cant get the exact fit http://stackoverflow.com/questions/3908624/cgcontext-pdf-page-aspect-fit – ajay Jan 14 '11 at 05:27
  • That's a link to this question; probably you meant http://stackoverflow.com/questions/4321681/how-to-fit-pdf-page-in-entire-view ? I'll take a look as soon as I get an opportunity, though I'm sadly on the way out now... – Tommy Jan 14 '11 at 13:26
  • Minor update, CGPDFGetBoxRect seems to be now CGPDFPageGetBoxRect but incredibly helpful! This sizing has been driving me crazy. Also you may find including the line CGContextConcatCTM(ctx, CGPDFPageGetDrawingTransform(myPageRef, kCGPDFCropBox, layer.bounds, 0, true)); before the CGContextDrawPDFPage helps with any PDFs that are rotated 90 degees – sradforth Aug 23 '12 at 22:24
2

The CGPDFPageGetDrawingTransform just will not return scale-up transformation if the PDF page rectangle is smaller than the rect parameter.

tia
  • 9,518
  • 1
  • 30
  • 44
  • tia, i tried the same page in some other pdf reader applications and is getting displayed properly fitting to the screen. So is there any other way for drawing it to make it aspect fit. – Anil Sivadas Oct 12 '10 at 06:41
1

Cursory reading of your code suggests the use of kCGPDFBleedBox should be replaced by another setting, perhaps kCGPDFMediaBox. See here for more information.

fbrereto
  • 35,429
  • 19
  • 126
  • 178
0

The other answers are correct that CGPDFPageGetDrawingTransform will not scale up, however you can scale the rectangle down to capture just the chosen box. Use CGPDFPageGetBoxRect() and calculate the scale as Tommy suggested in the accepted answer, then use that to scale down the capture rectangle passed into CGPDFPageGetDrawingTransform().

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
    CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
    CGContextFillRect(ctx, layer.bounds);
    CGContextTranslateCTM(ctx, 0.0, layer.bounds.size.height);

    CGRect box = CGPDFGetBoxRect(myPageRef, kCGPDFBleedBox);
    CGFloat xScale = layer.bounds.size.width / cropBox.size.width;
    CGFloat yScale = layer.bounds.size.height / cropBox.size.height;
    CGFloat scaleToApply = xScale < yScale ? xScale : yScale;

    CGRect captureRect = CGRectMake(0, 0,
                                    layer.bounds.size.width/scaleToApply,
                                    layer.bounds.size.height/scaleToApply);

    CGAffineTransform drawXfm = CGPDFPageGetDrawingTransform(myPageRef,
                                                             kCGPDFBleedBox,
                                                             captureRect,
                                                             0,
                                                             true);

    CGContextScaleCTM(ctx, scaleToApply, -scaleToApply);
    CGContextConcatCTM(ctx, drawXfm);
    CGContextDrawPDFPage(ctx, myPageRef);
}

Then it's easily extended to handle landscape too:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
    CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
    CGContextFillRect(ctx, layer.bounds);
    CGContextTranslateCTM(ctx, 0.0, layer.bounds.size.height);

    CGRect box = CGPDFGetBoxRect(myPageRef, kCGPDFBleedBox);
    int rotate;
    CGFloat xScale, yScale;
    if (box.size.width > box.size.height) {
        // landscape
        rotate = 270;
        xScale = layer.bounds.size.height / cropBox.size.width;
        yScale = layer.bounds.size.width / cropBox.size.height;
    } else {
        // portrait
        rotate = 0;
        xScale = layer.bounds.size.width / cropBox.size.width;
        yScale = layer.bounds.size.height / cropBox.size.height;
    }
    CGFloat scaleToApply = xScale < yScale ? xScale : yScale;

    CGRect captureRect = CGRectMake(0, 0,
                                    layer.bounds.size.width/scaleToApply,
                                    layer.bounds.size.height/scaleToApply);

    CGAffineTransform drawXfm = CGPDFPageGetDrawingTransform(myPageRef,
                                               kCGPDFBleedBox,
                                               captureRect,
                                               rotate,
                                               true);

    CGContextScaleCTM(ctx, scaleToApply, -scaleToApply);
    CGContextConcatCTM(ctx, drawXfm);
    CGContextDrawPDFPage(ctx, myPageRef);
}
John Lemberger
  • 2,689
  • 26
  • 25
0

Here is my solution, which also handles rotation. Might by useful.

// Create transformation
int rotation = CGPDFPageGetRotationAngle(pdfPage);
CGRect rect = CGPDFPageGetBoxRect(pdfPage, kCGPDFCropBox);
CGRect rotatedRect = rect;
CGRectApplyAffineTransform(rotatedRect, CGAffineTransformMakeRotation(M_PI * rotation / 180.0));

CGFloat scale = MIN(self.bounds.size.width / rotatedRect.size.width, self.bounds.size.height / rotatedRect.size.height);
// Scale
CGContextConcatCTM(context, CGAffineTransformMakeScale(scale, scale));  
// Move left bottom cornet to 0, 0
CGContextConcatCTM(context, CGAffineTransformMakeTranslation(rotatedRect.size.width * 0.5, rotatedRect.size.height * 0.5));    
// Rotate
CGContextConcatCTM(context, CGAffineTransformMakeRotation(-M_PI * rotation / 180.0));    
// Move center into 0, 0
CGContextConcatCTM(context, CGAffineTransformMakeTranslation(-rect.origin.x - rect.size.width * 0.5, -rect.origin.y - rect.size.height * 0.5));

CGContextDrawPDFPage(context, pdfPage);
Split
  • 4,319
  • 4
  • 19
  • 10