-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.cpp
121 lines (99 loc) · 2.77 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <string>
#include <sstream>
#include <iostream>
#include <vector>
#include <poppler/PDFDoc.h>
#include <poppler/goo/GooString.h>
#include <poppler/PDFDocFactory.h>
#include <poppler/Outline.h>
#include <poppler/GlobalParams.h>
#include <poppler/UnicodeMap.h>
#include <poppler/Link.h>
#include <poppler/Object.h>
using namespace std;
static string unicode_to_char(const Unicode *unicode, int len) {
static GlobalParams *globalParams = NULL;
if (globalParams == NULL) {
globalParams = new GlobalParams();
}
static const UnicodeMap *uMap = NULL;
if (uMap == NULL) {
uMap = globalParams->getUnicodeMap("UTF-8");
}
stringstream ss;
char buf[8];
int i, n;
for (i = 0; i < len; ++i) {
n = uMap->mapUnicode(unicode[i], buf, sizeof(buf));
ss.write(buf, n);
}
return ss.str();
}
void printOutline(PDFDoc &doc, const vector<OutlineItem*> *items, int depth)
{
if (items == nullptr) return;
for (OutlineItem *item : *items) {
// Get title
const vector<Unicode> &rawTitle = item->getTitle();
auto title = unicode_to_char(rawTitle.data(), rawTitle.size());
int page_num = 0;
// Get destination
const LinkAction *action = item->getAction();
if (action != nullptr) {
if (action->getKind() != LinkActionKind::actionGoTo)
continue;
LinkGoTo *actionGoTo = (LinkGoTo *) action;
if (!actionGoTo->isOk())
continue;
const LinkDest *dest = actionGoTo->getDest();
// For lifetime management if we get a named destination
// from the document (which we will then own)
unique_ptr<const LinkDest> namedDest;
if (dest == NULL) {
const GooString *namedDestName = actionGoTo->getNamedDest();
namedDest = doc.findDest(namedDestName);
dest = namedDest.get();
}
if (dest == NULL || !dest->isOk())
continue;
if (dest->isPageRef()) {
Ref page_ref = dest->getPageRef();
page_num = doc.findPage(page_ref);
} else {
page_num = dest->getPageNum();
}
}
// Print the title and page number
static constexpr char stars[] = "****************";
static constexpr int len_stars = sizeof(stars) / sizeof(*stars) - 1;
int d = depth;
while (d > len_stars) {
cout << stars;
d -= len_stars;
}
cout << (stars + len_stars - d) << "!";
cout << title << " " << page_num << "\n";
// Print kids
if (!item->hasKids())
continue;
item->open();
const vector<OutlineItem*> *kids = item->getKids();
printOutline(doc, kids, depth+1);
}
}
int main(int argc, char **argv)
{
if (argc < 2) {
std::cout << "No pdf document given" << std::endl;
exit(1);
}
GooString fname(argv[1]);
unique_ptr<PDFDoc> doc = PDFDocFactory().createPDFDoc(fname);
if (!doc->isOk()) {
exit(1);
}
Outline *outline = doc->getOutline();
const vector<OutlineItem*> *items = outline->getItems();
printOutline(*doc, items, 0);
return 0;
}