2012年9月6日 星期四

PDF中的索引和書籤(二)

從 poppler-0.20.3\glib\poppler-page.cc 來看, poppler_page_get_link_mapping 這個函數是將所給定的頁面中的 Annots (似乎很確定就是Links) 走過一遍,然後回傳。

另一方面,從該檔的標頭檔看來,與cairo有很深的糾葛,或許是glib本來就是負責繪圖的部份使然。

在使用google 查詢 getAnnots()時,發現另外有個 Ruby 的專案 origami-pdf 也能parse pdf檔,不過看起來比較沒有在更新,而且個人猜測是單純對poppler作複製而已。

poppler-0.20.3\qt4\demos\toc.cpp 中似乎透露著更多顯示 TOC (table of contents) 的更多細節。其中定義了此一靜態函數 static void fillToc(...) ,是一個明顯的遞迴呼叫,同時對外它也被void TocDock::fillInfo() 呼叫,其中比較令人在意的是這行敘述

const QDomDocument *toc = document()->toc();

其定義應來自於 poppler-0.20.3\qt4\src\poppler-qt4.h

    class POPPLER_QT4_EXPORT Document {
...
QDomDocument *toc() const;

然後其定義依序又呼叫了 getOutline() ,

poppler-0.20.3\poppler\PDFDoc.cc(1466): Outline *PDFDoc::getOutline(){
poppler-0.20.3\poppler\PDFDoc.cc(1470):     outline = new Outline(catalog->getOutline(), xref);

看看 getOutline() 的定義 @poppler-0.20.3\poppler\Catalog.cc(827):

Object *Catalog::getOutline()
{
  if (outline.isNone())
  {
     Object catDict;

     xref->getCatalog(&catDict);
     if (catDict.isDict()) {
       catDict.dictLookup("Outlines", &outline);
     } else {
       error(errSyntaxError, -1, "Catalog object is wrong type ({0:s})", catDict.getTypeName());
       outline.initNull();
     }
     catDict.free();
  }
  return &outline;
}
大意是說,從xref(p-67)中取得catalog(p-77),存入catDict,找出其中的  Outlines(96) 並回傳之

結論就是,我們主要需要改寫的地方就是 static void fillToc(...) ,頂多再加上 void TocDock::fillInfo() 的小修改即可,為方便起見透過xs由perl來呼叫,這待下回分解

p.s.另外我也意外地發現 poppler-0.20.3\cpp\poppler-toc.h 中也定義了 toc(),但為 private
p.s.2.提及頁數的部分,均指"PDF 1.2 Reference Manual"

p.s.3. 原來已經有人用swig寫好了!!  http://search.cpan.org/~cornelius/Poppler-0.04/lib/Poppler.pm

沒有留言:

張貼留言