我一直在阅读adobe pdf规范,以及用于pdf渲染和解析的apple的quartz 2d文档。我还下载了Voyeur并用它检查了一个本地pdf以查看它的内部数据。此时我可以获取文档目录,然后从那里获取轮廓字典。我可以看到嵌套在轮廓词典词典中的是名为“/ Dest”的节点,其值如下:
G1.1025588 等
我想知道我是否有办法使用这些值来获取对页面的引用,使用一些方法来渲染我已经看过github项目,如Reader,以及Apple记录的示例。
PDF处理绝对是一个挑战,所以任何帮助都会受到赞赏。
答案 0 :(得分:3)
大纲项目词典中的/Dest
条目可以是名称,字符串或数组。< / p>
最简单的情况是它是数组;然后第一项是大纲条目指向的页面对象(字典)。要获取页码,您必须遍历文档中的所有页面,并查看哪一页与您拥有的词典相同(==
)(CGPDFPageRef
s实际为CGPDFDictionaryRef
s) 。你也可以遍历页面树,这有点难,但可能更快(没有你想象的那么多,我不会在这里过早优化)。数组中的其他项目是页面上的位置等,在PDF规范中搜索“显式目的地”以了解更多信息。
如果条目是名称或字符串,则它是指定目的地。您必须从文档目录的/Dests
条目将名称映射到目标,该条目是包含名称树的字典。名称树本质上是一个树映射,允许快速访问命名值,而无需一次读取所有数据(与普通字典一样)。不幸的是,Quartz中没有对名称树的直接支持,所以你需要做更多的工作来递归地解析这个结构(参见PDF spec中的“名称树”)。
请注意,大纲项目不一定具有/Dest
条目,它还可以通过/A
(操作)条目指定其目标,这有点复杂。但是,在大多数情况下,操作将是一个“GoTo”操作,它本质上是目标的包装器。
名称到目的地的映射也可以存储为普通字典。在这种情况下,它位于文档目录中/ Names字典的/Dests
条目中。我很少见到这一点,它在PDF 1.2(当前为1.7)之后被弃用。
您肯定需要PDF规范:http://www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf
答案 1 :(得分:0)
感谢Omz,这是一段代码,用于检索PDF文件中大纲目的地的页码:
// Get Page Number from an array
- (int) getPageNumberFromArray:(CGPDFArrayRef)array ofPdfDoc:(CGPDFDocumentRef)pdfDoc withNumberOfPages:(int)numberOfPages
{
int pageNumber = -1;
// Page number reference is the first element of array (el 0)
CGPDFDictionaryRef pageDic;
CGPDFArrayGetDictionary(array, 0, &pageDic);
// page searching
for (int p=1; p<=numberOfPages; p++)
{
CGPDFPageRef page = CGPDFDocumentGetPage(pdfDoc, p);
if (CGPDFPageGetDictionary(page) == pageDic)
{
pageNumber = p;
break;
}
}
return pageNumber;
}
// Get page number from an outline. Only support "Dest" and "A" entries
- (int) getPageNumber:(CGPDFDictionaryRef)node ofPdfDoc:(CGPDFDocumentRef)pdfDoc withNumberOfPages:(int)numberOfPages
{
int pageNumber = -1;
CGPDFArrayRef destArray;
CGPDFDictionaryRef dicoActions;
if(CGPDFDictionaryGetArray(node, "Dest", &destArray))
{
pageNumber = [self getPageNumberFromArray:destArray ofPdfDoc:pdfDoc withNumberOfPages:numberOfPages];
}
else if(CGPDFDictionaryGetDictionary(node, "A", &dicoActions))
{
const char * typeOfActionConstChar;
CGPDFDictionaryGetName(dicoActions, "S", &typeOfActionConstChar);
NSString * typeOfAction = [NSString stringWithUTF8String:typeOfActionConstChar];
if([typeOfAction isEqualToString:@"GoTo"]) // only support "GoTo" entry. See PDF spec p653
{
CGPDFArrayRef dArray;
if(CGPDFDictionaryGetArray(dicoActions, "D", &dArray))
{
pageNumber = [self getPageNumberFromArray:dArray ofPdfDoc:pdfDoc withNumberOfPages:numberOfPages];
}
}
}
return pageNumber;
}