0

I have a PDF document that I'd like to show the named destinations for. I'm using Poppler to do so. What I need is a list of the named destination in the document, including the names and the locations. For now, I am considering only XYZ destinations.

Let's use the LaTeX hyperbar manual as an example PDF. From pdfinfo -dests hyperbar.pdf, we can see there are some XYZ named destinations in this document:

Page  Destination                 Name
   1 [ XYZ  145  716 null      ] "Doc-Start"
   1 [ XYZ   71  502 null      ] "HD.1"
   1 [ XYZ  144  754 null      ] "page.1"
   ....

Let's take HD.1 as an example. This named destination can be looked up from the PopplerDocument as expected, including the position. However, the named_dest field is NULL:

PopplerDoc* poppler_doc = poppler_document_new_from_file("hyperbar.pdf", NULL, NULL);

PopplerDest* dest = poppler_document_find_dest (poppler_doc, "HD.1");

printf("pos:  p %d L %f T %f\n", dest->page_num, dest->left, dest->top);
printf("name: %s\n", dest->named_dest);

produces:

pos:  p 1 L 71.004000 T 502.496000
name: (null)

According to the Poppler documentation, the PopplerDest.named_dest field is only set when the destination is a POPPLER_DEST_NAMED, which this is not.

Iterating all the destinations in the document returned via poppler_document_create_dests_tree() is the same - named_dest is always NULL.

So, my question is: considering that pdfinfo is able to report the names of the destinations, even for XYZ destinations, can I get these names from a PDF file using Poppler?

Inductiveload
  • 6,094
  • 4
  • 29
  • 55

1 Answers1

0

Loop over all pages of a document, extract link objects and there you can obtain named destinations.

GError *err = NULL;
PopplerDocument *doc = poppler_document_new_from_file("<uri to your file>",
                                                      NULL,
                                                      &err);
if(!doc){
    g_print("Failed to load document.\ndomain: %d, \ncode: %d, \nmessage: %s\n",
            err->domain, err->code, err->message);
    return;
}
int num_pages = poppler_document_get_n_pages(doc);
for(int page_num = 0; page_num < num_pages; page_num++){
    PopplerPage *page = poppler_document_get_page(doc,
                                                  page_num);

    GList *link_mappings = poppler_page_get_link_mapping(page);
    GList *link_p = link_mappings;
    while(link_p){
        PopplerLinkMapping *link_mapping = link_p->data;
        switch(link_mapping->action->type){
            case POPPLER_ACTION_GOTO_DEST:
            {
                PopplerActionGotoDest *goto_dest_action = (PopplerActionGotoDest*)
                    link_mapping->action;
                if(goto_dest_action->dest->type == POPPLER_DEST_NAMED){
                    g_print("Page: '%d', named_dest: '%s'\n",
                            page_num, dest->named_dest);
                } 
                break;
            }
            default:;
        }
        link_p = link_p->next;
    }
    poppler_page_free_link_mapping(link_mappings);
    g_object_unref(page);
}
g_object_unref(doc);
reza
  • 90
  • 1
  • 14