[poppler] [PATCH] [C++ frontend] - show page numbers with Table of Contents items

Martin Pelikan martin.pelikan at gmail.com
Tue Oct 14 11:12:17 PDT 2014


Hi,

I've developed a C++ application that uses poppler heavily, and I wanted
to go over the hyperref indexes that poppler::document::create_toc()
returns.  Because all relevant poppler guts are marked "private",
you could only get strings with TOC entries, but not where they point to.
Until now.  The page number returned can go directly to create_page().

Hope I didn't violate the coding style too much... feel free to change
it; I didn't go for the complete support of Actions, because 1) my time
is limited, 2) I don't actually need it.

Diff against the git HEAD cloned from the link on poppler web page.

ok?
--
Martin Pelikan


diff --git a/cpp/poppler-document.cpp b/cpp/poppler-document.cpp
index 1c24b47..ad20c90 100644
--- a/cpp/poppler-document.cpp
+++ b/cpp/poppler-document.cpp
@@ -554,7 +554,7 @@ font_iterator* document::create_font_iterator(int start_page) const
  */
 toc* document::create_toc() const
 {
-    return toc_private::load_from_outline(d->doc->getOutline());
+    return toc_private::load_from_pdfdoc(d->doc);
 }
 
 /**
diff --git a/cpp/poppler-toc-private.h b/cpp/poppler-toc-private.h
index e8841ff..5b75cec 100644
--- a/cpp/poppler-toc-private.h
+++ b/cpp/poppler-toc-private.h
@@ -25,6 +25,7 @@
 #include <vector>
 
 class GooList;
+class PDFDoc;
 class Outline;
 class OutlineItem;
 
@@ -37,7 +38,7 @@ public:
     toc_private();
     ~toc_private();
 
-    static toc* load_from_outline(Outline *outline);
+    static toc* load_from_pdfdoc(PDFDoc *);
 
     toc_item root;
 };
@@ -49,12 +50,13 @@ public:
     toc_item_private();
     ~toc_item_private();
 
-    void load(OutlineItem *item);
-    void load_children(GooList *items);
+    void load(PDFDoc *, OutlineItem *item);
+    void load_children(PDFDoc *, GooList *items);
 
     std::vector<toc_item*> children;
     ustring title;
     bool is_open;
+    unsigned page_number;
 };
 
 }
diff --git a/cpp/poppler-toc.cpp b/cpp/poppler-toc.cpp
index a3149c6..ebe2221 100644
--- a/cpp/poppler-toc.cpp
+++ b/cpp/poppler-toc.cpp
@@ -23,6 +23,8 @@
 
 #include "GooList.h"
 #include "Outline.h"
+#include "PDFDoc.h"
+#include "Link.h"
 
 using namespace poppler;
 
@@ -34,8 +36,9 @@ toc_private::~toc_private()
 {
 }
 
-toc* toc_private::load_from_outline(Outline *outline)
+toc* toc_private::load_from_pdfdoc(PDFDoc *doc)
 {
+    Outline *outline = doc->getOutline();
     if (!outline) {
         return 0;
     }
@@ -47,7 +50,7 @@ toc* toc_private::load_from_outline(Outline *outline)
 
     toc *newtoc = new toc();
     newtoc->d->root.d->is_open = true;
-    newtoc->d->root.d->load_children(items);
+    newtoc->d->root.d->load_children(doc, items);
 
     return newtoc;
 }
@@ -62,15 +65,38 @@ toc_item_private::~toc_item_private()
     delete_all(children);
 }
 
-void toc_item_private::load(OutlineItem *item)
+void toc_item_private::load(PDFDoc *doc, OutlineItem *item)
 {
     const Unicode *title_unicode = item->getTitle();
     const int title_length = item->getTitleLength();
     title = detail::unicode_to_ustring(title_unicode, title_length);
     is_open = item->isOpen();
+
+    LinkAction *link_action = item->getAction();
+    switch (link_action->getKind()) {
+    case actionGoTo:
+        if (LinkGoTo *l = dynamic_cast<LinkGoTo *>(link_action)) {
+            LinkDest *ld = l->getDest();
+
+            if (ld == NULL)
+                ld = doc->findDest(l->getNamedDest());
+
+            if (ld != NULL) {
+                if (ld->isPageRef()) {
+                    Ref pr = ld->getPageRef();
+                    page_number = doc->findPage(pr.num, pr.gen);
+                }
+                else
+                    page_number = ld->getPageNum();
+            }
+        }
+        break;
+    default:
+        break;
+    }
 }
 
-void toc_item_private::load_children(GooList *items)
+void toc_item_private::load_children(PDFDoc *doc, GooList *items)
 {
     const int num_items = items->getLength();
     children.resize(num_items);
@@ -78,13 +104,13 @@ void toc_item_private::load_children(GooList *items)
         OutlineItem *item = (OutlineItem *)items->get(i);
 
         toc_item *new_item = new toc_item();
-        new_item->d->load(item);
+        new_item->d->load(doc, item);
         children[i] = new_item;
 
         item->open();
         GooList *item_children = item->getKids();
         if (item_children) {
-            new_item->d->load_children(item_children);
+            new_item->d->load_children(doc, item_children);
         }
     }
 }
@@ -175,6 +201,14 @@ bool toc_item::is_open() const
 }
 
 /**
+ Returns the page number this TOC item points to, to be used in create_page.
+ */
+unsigned toc_item::page_number() const
+{
+    return d->page_number - 1;
+}
+
+/**
  \returns the children of the TOC item
  */
 std::vector<toc_item *> toc_item::children() const
diff --git a/cpp/poppler-toc.h b/cpp/poppler-toc.h
index 8b09736..a2ddb96 100644
--- a/cpp/poppler-toc.h
+++ b/cpp/poppler-toc.h
@@ -55,6 +55,7 @@ public:
 
     ustring title() const;
     bool is_open() const;
+    unsigned page_number() const;
 
     std::vector<toc_item *> children() const;
     iterator children_begin() const;


More information about the poppler mailing list