CGContext pdf page aspect fit

前端 未结 5 611
星月不相逢
星月不相逢 2020-12-28 10:07

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

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
    CGContextSetRGBFillColor(         


        
相关标签:
5条回答
  • 2020-12-28 10:45

    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);
    }
    
    0 讨论(0)
  • 2020-12-28 10:46

    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.

    0 讨论(0)
  • 2020-12-28 11:01

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

    0 讨论(0)
  • 2020-12-28 11:02

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

    0 讨论(0)
  • 2020-12-28 11:08

    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);
    
    0 讨论(0)
提交回复
热议问题