2010-12-12 79 views
8

Je construis une application iPad qui affiche des fichiers PDF, et je voudrais être en mesure d'afficher la table des matières et de laisser l'utilisateur naviguer vers les pages pertinentes.Comment obtenir des données de table des matières (contour) PDF dans iOS (iPad)?

J'ai investi plusieurs heures dans la recherche à ce stade, et il semble que depuis PDFKit [n'est pas supporté par iOS], ma seule option est d'analyser les méta-données PDF manuellement.

J'ai examiné plusieurs solutions, mais elles sont toutes muettes sur un point: comment associer une page dans les métadonnées "outline" au numéro de page réel de l'élément. J'ai examiné mon document PDF avec [l'outil Voyeur] et je peux voir le contour dans l'arbre.

[Cette solution] m'a aidé à comprendre comment naviguer dans l'arborescence Outline/A/S/D pour trouver l'objet «Dest», mais il effectue une sorte de comparaison d'objet en utilisant [self.pages indexOfObjectIdenticalTo: destPageDic] que je ne comprends pas.

J'ai lu la [spécification PDF officielle d'Adobe], et la section « 12.3.2.3 destinations nommées » décrit la façon dont une entrée de plan peut pointer vers une page:

Au lieu d'être défini directement avec la syntaxe explicite indiquée dans le tableau 151, une destination peut être référencée indirectement au moyen d'un objet de nom (PDF 1.1) ou d'une chaîne d'octets (PDF 1.2).

Et continue avec cette ligne qui est tout à fait incompréhensible pour moi:

La valeur de cette entrée est un dictionnaire dans lequel chaque clé est un nom de destination et la valeur correspondant est soit un tableau définissant la destination , en utilisant la syntaxe indiquée dans Tableau 151, ou un dictionnaire avec une entrée D dont la valeur est un tel tableau.

Ceci fait référence à la page 366, « 12.3.2.2 Destination explicite » où une table décrit une page: « Dans chaque cas, la page est une référence indirecte à un objet page »

est le résultat Alors CGPDFDocumentGetPage ou CGPDFPageGetDictionary une "référence indirecte à un objet de page"?

J'ai trouvé un [discussion sur lists.apple.com] qui traite. [Ce commentaire] implique que vous pouvez comparer l'adresse (en mémoire?) D'un objet CGPDFPageGetDictionary pour une page donnée et la comparer aux pages de l'arborescence "Outline" des métadonnées PDF.

Toutefois, lorsque je regarde l'adresse des objets de la page dans l'arborescence hiérarchique et les compare aux adresses, ils ne sont jamais les mêmes. La ligne utilisée dans ce fil "TTDPRINT (@"% d =>% p ", k + 1, dict);" est l'impression "dict" comme un pointeur dans la mémoire .. il n'y a aucune raison de croire qu'un objet retourné là serait le même que celui retourné ailleurs ... ils seraient dans des endroits différents en mémoire! Mon dernier espoir était de regarder le code source de l'outil "contour" de la ligne de commande d'Apple [mentionné dans ce livre] (comme [suggéré par ce fil]), mais je ne le trouve nulle part.

Bottom line - Quelqu'un a-t-il un aperçu du fonctionnement des contours PDF, ou connaît-il un code source ouvert (de préférence objective-c) qui lit les contours PDF?

Argg: J'avais toutes sortes de liens posté ici, mais apparemment un nouvel utilisateur ne peut afficher un lien à la fois

Répondre

3

Le résultat de CGPDFDocumentGetPage est identique à une page de référence indirecte que vous obtenez lors de la résolution une destination dans un élément de plan. Les deux sont essentiellement des dictionnaires et vous pouvez les comparer en utilisant ==. Lorsque vous avez un CGPDFDictionaryRef que vous voulez connaître le numéro de page, vous pouvez faire quelque chose comme ceci:

CGPDFDocumentRef doc = ...; 
CGPDFDictionaryRef outlinePageRef = ...; 
for (int p=1; p<=CGPDFDocumentGetNumberOfPages(doc); p++) { 
    CGPDFPageRef page = CGPDFDocumentGetPage(doc, p); 
    if (page == outlinePageRef) { 
    printf("found the page number: %i", p); 
    break; 
    } 
} 

Une destination explicite est cependant pas une page, mais un tableau avec le premier élément étant la page. Les autres éléments sont la position de défilement sur la page, etc.

+0

Ceci est une excellente réponse. Votre objectif à la fin devrait être de créer un nsdictionary qui contient des paires clé/val pour le titre-> numéro de page. Cela constituera le TOC. – shawnwall

+1

En fait, vous ne pouvez pas comparer outlinePageRef directement à CGPDFPageRef, mais vous pouvez le comparer à 'CGPDFPageGetDictionary (page)'. – 0xced