使用 Quartz 在 iOS 上获取 PDF 超链接 [英] Get PDF hyperlinks on iOS with Quartz

查看:35
本文介绍了使用 Quartz 在 iOS 上获取 PDF 超链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一整天都在尝试从 iPad 应用程序中的 PDF 获取超链接元数据.CGPDF* API 是一场真正的噩梦,我在网上找到的关于这一切的唯一信息是我必须寻找Annots"字典,但我在我的 PDF 中找不到它.

I've spent all day trying to get hyperlinks metadata from PDFs in my iPad application. The CGPDF* APIs are a true nightmare, and the only piece of information I've found on the net about all this is that I have to look for an "Annots" dictionary, but I just can't find it in my PDFs.

我什至使用旧的 Voyeur Xcode 示例 来检查我的测试 PDF 文件,但没有这本Annots"字典的踪迹...

I even used the old Voyeur Xcode sample to inspect my test PDF file, but no trace of this "Annots" dictionary...

你知道,这是我在每个 PDF 阅读器上看到的一个功能——同样的问题有 去过询问 多个 times 这里没有真正实用的答案.我通常从不直接索要示例代码,但显然这次我真的需要它......有人可以使用示例代码吗?

You know, this is a feature I see on every PDF reader - this same question has been asked multiple times here with no real practical answers. I usually never ask for sample code directly but apparently this time I really need it... anyone got this working, possibly with sample code?

更新:我刚刚意识到完成我的测试 PDF 的人刚刚插入了一个 URL 作为文本,而不是真正的注释.他尝试添加注释,我的代码现在可以工作了……但这不是我需要的,所以看来我必须分析文本并搜索 URL.但那是另一回事了...

Update: I just realized the guy who has done my testing PDF had just inserted an URL as text, and not a real annotation. He tried putting an annotation and my code works now... But that's not what I need, so it seems I'll have to analyze text and search for URLs. But that's another story...

更新 2:所以我终于想出了一些工作代码.我把它张贴在这里,希望它能帮助别人.它假定 PDF 文档实际上包含注释.

Update 2: So I finally came up with some working code. I'm posting it here so hopefully it'll help someone. It assumes the PDF document actually contains annotations.

for(int i=0; i<pageCount; i++) {
    CGPDFPageRef page = CGPDFDocumentGetPage(doc, i+1);

    CGPDFDictionaryRef pageDictionary = CGPDFPageGetDictionary(page);

    CGPDFArrayRef outputArray;
    if(!CGPDFDictionaryGetArray(pageDictionary, "Annots", &outputArray)) {
        return;
    }

    int arrayCount = CGPDFArrayGetCount( outputArray );
    if(!arrayCount) {
        continue;
    }

    for( int j = 0; j < arrayCount; ++j ) {
        CGPDFObjectRef aDictObj;
        if(!CGPDFArrayGetObject(outputArray, j, &aDictObj)) {
            return;
        }

        CGPDFDictionaryRef annotDict;
        if(!CGPDFObjectGetValue(aDictObj, kCGPDFObjectTypeDictionary, &annotDict)) {
            return;
        }

        CGPDFDictionaryRef aDict;
        if(!CGPDFDictionaryGetDictionary(annotDict, "A", &aDict)) {
            return;
        }

        CGPDFStringRef uriStringRef;
        if(!CGPDFDictionaryGetString(aDict, "URI", &uriStringRef)) {
            return;
        }

        CGPDFArrayRef rectArray;
        if(!CGPDFDictionaryGetArray(annotDict, "Rect", &rectArray)) {
            return;
        }

        int arrayCount = CGPDFArrayGetCount( rectArray );
        CGPDFReal coords[4];
        for( int k = 0; k < arrayCount; ++k ) {
            CGPDFObjectRef rectObj;
            if(!CGPDFArrayGetObject(rectArray, k, &rectObj)) {
                return;
            }

            CGPDFReal coord;
            if(!CGPDFObjectGetValue(rectObj, kCGPDFObjectTypeReal, &coord)) {
                return;
            }

            coords[k] = coord;
        }               

        char *uriString = (char *)CGPDFStringGetBytePtr(uriStringRef);

        NSString *uri = [NSString stringWithCString:uriString encoding:NSUTF8StringEncoding];
        CGRect rect = CGRectMake(coords[0],coords[1],coords[2],coords[3]);

        CGPDFInteger pageRotate = 0;
        CGPDFDictionaryGetInteger( pageDictionary, "Rotate", &pageRotate ); 
        CGRect pageRect = CGRectIntegral( CGPDFPageGetBoxRect( page, kCGPDFMediaBox ));
        if( pageRotate == 90 || pageRotate == 270 ) {
            CGFloat temp = pageRect.size.width;
            pageRect.size.width = pageRect.size.height;
            pageRect.size.height = temp;
        }

        rect.size.width -= rect.origin.x;
        rect.size.height -= rect.origin.y;

        CGAffineTransform trans = CGAffineTransformIdentity;
        trans = CGAffineTransformTranslate(trans, 0, pageRect.size.height);
        trans = CGAffineTransformScale(trans, 1.0, -1.0);

        rect = CGRectApplyAffineTransform(rect, trans);

        // do whatever you need with the coordinates.
        // e.g. you could create a button and put it on top of your page
        // and use it to open the URL with UIApplication's openURL
    }
}

推荐答案

这里是至少为每个页面获取注释 CGPDFDictionary 的基本思想.之后,您应该能够在 Adob​​e 的 PDF 规范的帮助下弄清楚.

heres the basic idea to get to the annots CGPDFDictionary for each page atleast. after that you should be able to figure it out with help from the PDF spec from Adobe.

1.) 获取 CGPDFDocumentRef.

1.) get the CGPDFDocumentRef.

2.) 获取每一页.

3.) 在每个页面上,使用 CGPDFDictionaryGetArray(pageDictionary, "Annots", &outputArray) 其中 pageDictionary 是表示 CGPDFPage 的 CGPDFDictionary,outputArray 是变量 (CGPDFArrayRef) 来存储注释该页面的数组.

3.) on each page, use CGPDFDictionaryGetArray(pageDictionary, "Annots", &outputArray) where pageDictionary is the CGPDFDictionary representing the CGPDFPage, and outputArray is the variable (CGPDFArrayRef) to store the Annots array of that page in.

这篇关于使用 Quartz 在 iOS 上获取 PDF 超链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆