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

Martin Pelikan martin.pelikan at gmail.com
Thu Oct 16 09:11:45 PDT 2014


Hi,

version 2 of my previous patch (that didn't make it to the list
apparently) is tested on multiple different documents (mostly hw/sw
manuals and documentation, some books or theses).

The problem it solves is simple -- the current C++ frontend does have a
TOC, but it only contains titles and not pages where the TOC entries
point to.  This patch (inspired by glib frontend) adds an API to get
a page number passable to poppler::document::create_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..b626fae 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;
+    int page_number;
 };
 
 }
diff --git a/cpp/poppler-toc.cpp b/cpp/poppler-toc.cpp
index a3149c6..504e696 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,13 +50,13 @@ 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;
 }
 
 toc_item_private::toc_item_private()
-    : is_open(false)
+    : is_open(false), page_number(0)
 {
 }
 
@@ -62,15 +65,41 @@ 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();
+    if (link_action == NULL)
+        return;
+
+    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 +107,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 +204,14 @@ bool toc_item::is_open() const
 }
 
 /**
+ Returns the page number this TOC item points to, to be used in create_page.
+ */
+int 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..9d9618d 100644
--- a/cpp/poppler-toc.h
+++ b/cpp/poppler-toc.h
@@ -55,6 +55,7 @@ public:
 
     ustring title() const;
     bool is_open() const;
+    int page_number() const;
 
     std::vector<toc_item *> children() const;
     iterator children_begin() const;


More information about the poppler mailing list