[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