[poppler] utils/pdfinfo.1 utils/pdfinfo.cc
Adrian Johnson
ajohnson at kemper.freedesktop.org
Tue Aug 15 22:56:07 UTC 2017
utils/pdfinfo.1 | 4 +
utils/pdfinfo.cc | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 143 insertions(+), 1 deletion(-)
New commits:
commit a8d670b59b0301040e716f3a11a78fce1177337d
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Tue Aug 15 21:35:27 2017 +0930
pdfinfo: add -dests option to print named destinations
Bug 97262
diff --git a/utils/pdfinfo.1 b/utils/pdfinfo.1
index 741219fc..b699dff1 100644
--- a/utils/pdfinfo.1
+++ b/utils/pdfinfo.1
@@ -113,6 +113,10 @@ Prints dates in ISO-8601 format (including the time zone).
.B \-rawdates
Prints the raw (undecoded) date strings, directly from the PDF file.
.TP
+.B \-dests
+Print a list of all named destinations. If a page range is specified using "\-f" and "\-l", only
+destinations in the page range are listed.
+.TP
.BI \-enc " encoding-name"
Sets the encoding to use for text output. This defaults to "UTF-8".
.TP
diff --git a/utils/pdfinfo.cc b/utils/pdfinfo.cc
index 738a506d..f9fde5a3 100644
--- a/utils/pdfinfo.cc
+++ b/utils/pdfinfo.cc
@@ -36,6 +36,7 @@
#include <string.h>
#include <time.h>
#include <math.h>
+#include <map>
#include "parseargs.h"
#include "printencodings.h"
#include "goo/GooString.h"
@@ -77,6 +78,7 @@ static GBool printHelp = gFalse;
static GBool printEnc = gFalse;
static GBool printStructure = gFalse;
static GBool printStructureText = gFalse;
+static GBool printDests = gFalse;
static const ArgDesc argDesc[] = {
{"-f", argInt, &firstPage, 0,
@@ -97,6 +99,8 @@ static const ArgDesc argDesc[] = {
"print the dates in ISO-8601 format"},
{"-rawdates", argFlag, &rawDates, 0,
"print the undecoded date strings directly from the PDF file"},
+ {"-dests", argFlag, &printDests, 0,
+ "print all named destinations in the PDF"},
{"-enc", argString, textEncName, sizeof(textEncName),
"output text encoding name"},
{"-listenc",argFlag, &printEnc, 0,
@@ -286,6 +290,135 @@ static void printStruct(const StructElement *element, unsigned indent) {
}
}
+struct RefCompare {
+ bool operator() (const Ref& lhs, const Ref& rhs) const {
+ return lhs.num < rhs.num;
+ }
+};
+
+struct GooStringCompare {
+ bool operator() (GooString* lhs, GooString* rhs) const {
+ return lhs->cmp(const_cast<GooString*>(rhs)) < 0;
+ }
+};
+
+static void printLinkDest(LinkDest *dest) {
+ char buf[100];
+
+ switch (dest->getKind()) {
+ case destXYZ:
+ sprintf(buf, "[ XYZ ");
+ if (dest->getChangeLeft()) {
+ sprintf(buf+strlen(buf), "%4.f ", dest->getLeft());
+ } else {
+ strcat(buf, "null ");
+ }
+ if (dest->getChangeTop()) {
+ sprintf(buf+strlen(buf), "%4.f ", dest->getTop());
+ } else {
+ strcat(buf, "null ");
+ }
+ if (dest->getChangeZoom()) {
+ sprintf(buf+strlen(buf), "%4.2f ", dest->getZoom());
+ } else {
+ strcat(buf, "null ");
+ }
+ break;
+ case destFit:
+ sprintf(buf, "[ Fit ");
+ break;
+ case destFitH:
+ if (dest->getChangeTop()) {
+ sprintf(buf, "[ FitH %4.f ", dest->getTop());
+ } else {
+ sprintf(buf, "[ FitH null ");
+ }
+ break;
+ case destFitV:
+ if (dest->getChangeLeft()) {
+ sprintf(buf, "[ FitV %4.f ", dest->getLeft());
+ } else {
+ strcat(buf, "[ FitV null ");
+ }
+ break;
+ case destFitR:
+ sprintf(buf, "[ FitR %4.f %4.f %4.f %4.f ",
+ dest->getLeft(),
+ dest->getBottom(),
+ dest->getRight(),
+ dest->getTop());
+ break;
+ case destFitB:
+ sprintf(buf, "[ FitB ");
+ break;
+ case destFitBH:
+ if (dest->getChangeTop()) {
+ sprintf(buf, "[ FitBH %4.f ", dest->getTop());
+ } else {
+ sprintf(buf, "[ FitBH null ");
+ }
+ break;
+ case destFitBV:
+ if (dest->getChangeLeft()) {
+ sprintf(buf, "[ FitBV %4.f ", dest->getLeft());
+ } else {
+ strcat(buf, "[ FitBV null ");
+ }
+ break;
+ }
+
+ strcat(buf, " ");
+ buf[26] = ']';
+ buf[27] = 0;
+ printf(buf);
+}
+
+static void printDestinations(PDFDoc *doc, UnicodeMap *uMap) {
+ std::map<Ref,std::map<GooString*,LinkDest*,GooStringCompare>, RefCompare > map;
+
+ int numDests = doc->getCatalog()->numDestNameTree();
+ for (int i = 0; i < numDests; i++) {
+ GooString *name = doc->getCatalog()->getDestNameTreeName(i);
+ LinkDest *dest = doc->getCatalog()->getDestNameTreeDest(i);
+ if (dest->isPageRef()) {
+ map[dest->getPageRef()].insert(std::make_pair(name, dest));
+ }
+ }
+
+ numDests = doc->getCatalog()->numDests();
+ for (int i = 0; i < numDests; i++) {
+ GooString *name = new GooString(doc->getCatalog()->getDestsName(i));
+ LinkDest *dest = doc->getCatalog()->getDestsDest(i);
+ if (dest->isPageRef()) {
+ map[dest->getPageRef()].insert(std::make_pair(name, dest));
+ }
+ }
+
+ printf("Page Destination Name\n");
+ for (int i = firstPage; i <= lastPage; i++) {
+ Ref *ref = doc->getCatalog()->getPageRef(i);
+ auto pageDests = map.find(*ref);
+ if (pageDests != map.end()) {
+ for (auto& it: pageDests->second) {
+ it.first->getCString()[4] = 0;
+ printf("%4d ", i);
+ printLinkDest(it.second);
+ printf(" \"");
+ Unicode *u;
+ char buf[8];
+ int n, len;
+ len = TextStringToUCS4(it.first, &u);
+ for (int i = 0; i < len; i++) {
+ n = uMap->mapUnicode(u[i], buf, sizeof(buf));
+ fwrite(buf, 1, n, stdout);
+ }
+ gfree(u);
+ printf("\"\n");
+ }
+ }
+ }
+}
+
void printInfo(PDFDoc *doc, UnicodeMap *uMap, long long filesize, GBool multiPage) {
Page *page;
char buf[256];
@@ -549,7 +682,6 @@ int main(int argc, char *argv[]) {
}
if (lastPage == 0) {
multiPage = gFalse;
- lastPage = 1;
} else {
multiPage = gTrue;
}
@@ -583,6 +715,8 @@ int main(int argc, char *argv[]) {
printStruct(structTree->getChild(i), 0);
}
}
+ } else if (printDests) {
+ printDestinations(doc, uMap);
} else {
// print info
long long filesize = 0;
@@ -597,6 +731,10 @@ int main(int argc, char *argv[]) {
filesize = Gftell(f);
fclose(f);
}
+
+ if (multiPage == gFalse)
+ lastPage = 1;
+
printInfo(doc, uMap, filesize, multiPage);
}
exitCode = 0;
More information about the poppler
mailing list