使用 CGPDFDocumentRef 的 PDF 阅读器

发布于 2024-09-10 22:17:50 字数 364 浏览 8 评论 0原文

我要做一个 PDF 阅读器,我正在尝试两种可能的解决方案:

  • UIWebView
  • CGPDFDocumentRef

第一个非常简单,但比第二个慢。 对于第二个,我找到了一个教程,我可以查看 pdf,并且可以用两根手指的移动来缩放它。但目前我不能做两件事:

1)以横向模式查看 PDF,保持正确的比例。 2)双击屏幕进行放大/缩小。

这些功能已经在 UIWebView 中实现了,但是前面说过,它有点慢,而且它打开整个 PDF 文档,而不仅仅是单个页面(所以我需要将文件拆分为许多“一页 pdf 文件”)。

任何人都可以帮助我提供有关此类问题的一些链接/参考资料/代码吗?

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 functions 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 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

娜些时光,永不杰束 2024-09-17 22:17:50

使用CGPDFDocumentRef,您需要使用CGPDFDocumentGetPage获取每个页面,然后使用CGPDFPageGetDrawingTransform获取绘图转换并将其应用到CGContextRef< /code> 在绘制页面之前。

如果启用缩放功能,则将 PDF 页面的视图放入 UIScrollView 中可以放大和缩小。您还可以使用缩放系数来绘制它,

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

但是您仍然会遇到非常复杂的 PDF 页面渲染速度很慢的问题,并且每次调用 CGContextDrawPDFPage(context, page); 时都会遇到问题必须渲染整个页面,例如当您更改缩放级别时。有很多方法可以解决这个问题,例如绘制到 CATiledLayer 中。

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.

柳絮泡泡 2024-09-17 22:17:50

确切地说,在我找到的示例中,他使用了 CATiledLayer。
这是我的代码:

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

这部分效果很好,但是如果我想引入横向模式,我需要修改这部分:

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

我尝试了几乎所有的方法,但我找不到好的解决方案!

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 !

深空失忆 2024-09-17 22:17:50

您可以通过以下方式手动调用任何图层的绘制图层方法
[你的图层设置需要显示]

you can call draw layer method of any layer manually by saying
[yourLayer setNeedsDisplay]

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文