CGContext pdf页面纵横比适应。

9
我正在使用以下代码在CGContext上显示PDF页面:
- (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);
}

问题在于pdf页面被绘制在页面中心,四周留有边框。是否有任何方法使页面适应屏幕大小?
5个回答

18

对Tia的回答进行补充:内置方法CGPDFPageGetDrawingTransform会缩小而不是放大。如果您想要放大,则需要通过将CGPDFGetBoxRect的结果与您的内容区域进行比较来计算自己的转换。随口说话:

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

那么,先计算出需要将文档缩放多少才能占据视图的整个宽度,需要将其缩放多少才能占据整个高度,然后按照这两个值中较小的一个进行缩放。


你能否回答这个问题?我也在尝试同样的方法,但是我无法得到完全匹配的结果。https://dev59.com/71HTa4cB1Zd3GeqPORCb - ajay
这是指向此问题的链接;可能你想要的是http://stackoverflow.com/questions/4321681/how-to-fit-pdf-page-in-entire-view?我一有机会就会看一下,尽管我现在很遗憾要离开了... - Tommy
小更新,CGPDFGetBoxRect现在似乎变成了CGPDFPageGetBoxRect,但非常有帮助!这个尺寸问题一直让我发疯。此外,您可能会发现在CGContextDrawPDFPage之前包括以下行 CGContextConcatCTM(ctx, CGPDFPageGetDrawingTransform(myPageRef, kCGPDFCropBox, layer.bounds, 0, true)); 可以帮助处理任何旋转90度的PDF文件。 - sradforth

2
CGPDFPageGetDrawingTransform 如果 PDF 页面矩形小于 rect 参数,将不会返回放大变换。

嗨,我尝试在其他一些PDF阅读器应用程序中打开同一页,发现它可以适当地显示在屏幕上。那么有没有其他的绘制方式可以使其自适应呢? - Anil Sivadas

1

粗略阅读您的代码表明,应该用另一种设置替换kCGPDFBleedBox,也许是kCGPDFMediaBox。请参见此处以获取更多信息。


fbrereto,我尝试了kCGPDFMediaBox和所有其他可用选项。但是显示没有变化。 - Anil Sivadas

0

这是我的解决方案,还可以处理旋转。可能会有用。

// 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
其他答案是正确的,CGPDFPageGetDrawingTransform不会放大,但是你可以将矩形缩小以捕获所选择的框。使用CGPDFPageGetBoxRect()来计算比例,就像Tommy在接受的答案中建议的那样,然后使用该比例来缩小传递给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);
}

然后它很容易扩展到处理横向屏幕:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接