CGContext pdf page aspect fit

穿精又带淫゛_ 提交于 2019-12-30 00:42:06

问题


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.


回答1:


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.




回答2:


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




回答3:


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




回答4:


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);
}



回答5:


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);


来源:https://stackoverflow.com/questions/3908624/cgcontext-pdf-page-aspect-fit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!