[poppler] 3 commits - cpp/CMakeLists.txt cpp/poppler-destination.cpp cpp/poppler-destination.h cpp/poppler-destination-private.h cpp/poppler-document.cpp cpp/poppler-document.h cpp/tests

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jan 15 23:24:32 UTC 2019


 cpp/CMakeLists.txt                |    2 
 cpp/poppler-destination-private.h |   55 +++++++
 cpp/poppler-destination.cpp       |  285 ++++++++++++++++++++++++++++++++++++++
 cpp/poppler-destination.h         |   68 +++++++++
 cpp/poppler-document.cpp          |   56 +++++++
 cpp/poppler-document.h            |    8 +
 cpp/tests/poppler-dump.cpp        |   97 ++++++++++++
 7 files changed, 571 insertions(+)

New commits:
commit eae71a6b497f0bbafeaf3d8a09dc735e591cdf10
Author: Masamichi Hosoda <trueroad at trueroad.jp>
Date:   Sat Jan 12 21:55:17 2019 +0900

    cpp: Add named destination for poppler-dump

diff --git a/cpp/tests/poppler-dump.cpp b/cpp/tests/poppler-dump.cpp
index a1a68251..2451be2e 100644
--- a/cpp/tests/poppler-dump.cpp
+++ b/cpp/tests/poppler-dump.cpp
@@ -3,6 +3,7 @@
  * Copyright (C) 2017, 2018, Albert Astals Cid <aacid at kde.org>
  * Copyright (C) 2017, Jason Alan Palmer <jalanpalmer at gmail.com>
  * Copyright (C) 2018, Suzuki Toshiya <mpsuzuki at hiroshima-u.ac.jp>
+ * Copyright (C) 2019, Masamichi Hosoda <trueroad at trueroad.jp>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,6 +21,7 @@
  */
 
 #include <goo/glibc.h>
+#include <poppler-destination.h>
 #include <poppler-document.h>
 #include <poppler-embedded-file.h>
 #include <poppler-font.h>
@@ -29,9 +31,11 @@
 #include <cstdlib>
 #include <cstring>
 #include <ctime>
+#include <algorithm>
 #include <iomanip>
 #include <ios>
 #include <iostream>
+#include <map>
 #include <memory>
 #include <sstream>
 
@@ -49,6 +53,7 @@ bool show_toc = false;
 bool show_fonts = false;
 bool show_embedded_files = false;
 bool show_pages = false;
+bool show_destinations = false;
 bool show_help = false;
 char show_text[32];
 bool show_text_list = false;
@@ -71,6 +76,8 @@ static const ArgDesc the_args[] = {
       "show the document-level embedded files" },
     { "--show-pages",          argFlag,  &show_pages,          0,
       "show pages information" },
+    { "--show-destinations",   argFlag,  &show_destinations,   0,
+      "show named destinations" },
     { "--show-text",           argString, &show_text,          sizeof(show_text),
       "show text (physical|raw) extracted from all pages" },
     { "--show-text-list",      argFlag, &show_text_list,       0,
@@ -317,6 +324,84 @@ static void print_page(poppler::page *p)
     std::cout << std::endl;
 }
 
+static void print_destination(const poppler::destination *d)
+{
+    if (d) {
+        std::cout << std::setw(out_width) << "Type" << ": ";
+        switch (d->type()) {
+        case poppler::destination::unknown:
+            std::cout << "unknown" << std::endl;
+            break;
+        case poppler::destination::xyz:
+            std::cout << "xyz" << std::endl
+                      << std::setw(out_width)
+                      << "Page" << ": " << d->page_number() << std::endl
+                      << std::setw(out_width)
+                      << "Left" << ": " << d->left() << std::endl
+                      << std::setw(out_width)
+                      << "Top" << ": " << d->top() << std::endl
+                      << std::setw(out_width)
+                      << "Zoom" << ": " << d->zoom() << std::endl;
+            break;
+        case poppler::destination::fit:
+            std::cout << "fit" << std::endl
+                      << std::setw(out_width)
+                      << "Page" << ": " << d->page_number() << std::endl;
+            break;
+        case poppler::destination::fit_h:
+            std::cout << "fit_h" << std::endl
+                      << std::setw(out_width)
+                      << "Page" << ": " << d->page_number() << std::endl
+                      << std::setw(out_width)
+                      << "Top" << ": " << d->top() << std::endl;
+            break;
+        case poppler::destination::fit_v:
+            std::cout << "fit_v" << std::endl
+                      << std::setw(out_width)
+                      << "Page" << ": " << d->page_number() << std::endl
+                      << std::setw(out_width)
+                      << "Left" << ": " << d->left() << std::endl;
+            break;
+        case poppler::destination::fit_r:
+            std::cout << "fit_r" << std::endl
+                      << std::setw(out_width)
+                      << "Page" << ": " << d->page_number() << std::endl
+                      << std::setw(out_width)
+                      << "Left" << ": " << d->left() << std::endl
+                      << std::setw(out_width)
+                      << "Bottom" << ": " << d->bottom() << std::endl
+                      << std::setw(out_width)
+                      << "Right" << ": " << d->right() << std::endl
+                      << std::setw(out_width)
+                      << "Top" << ": " << d->top() << std::endl;
+            break;
+        case poppler::destination::fit_b:
+            std::cout << "fit_b" << std::endl
+                      << std::setw(out_width)
+                      << "Page" << ": " << d->page_number() << std::endl;
+            break;
+        case poppler::destination::fit_b_h:
+            std::cout << "fit_b_h" << std::endl
+                      << std::setw(out_width)
+                      << "Page" << ": " << d->page_number() << std::endl
+                      << std::setw(out_width)
+                      << "Top" << ": " << d->top() << std::endl;
+            break;
+        case poppler::destination::fit_b_v:
+            std::cout << "fit_b_v" << std::endl
+                      << std::setw(out_width)
+                      << "Page" << ": " << d->page_number() << std::endl
+                      << std::setw(out_width)
+                      << "Left" << ": " << d->left() << std::endl;
+            break;
+        default:
+            std::cout << "error" << std::endl;
+            break;
+        }
+    }
+    std::cout << std::endl;
+}
+
 static void print_page_text(poppler::page *p)
 {
     if (p) {
@@ -416,6 +501,18 @@ int main(int argc, char *argv[])
             print_page(p.get());
         }
     }
+    if (show_destinations) {
+        auto map = doc->create_destination_map();
+        for (const auto &pair: map) {
+            std::string s = pair.first;
+            for (auto &c: s) {
+                if (c < 0x20 || c>0x7e )
+                    c = '.';
+            }
+            std::cout << "Named destination \"" << s << "\":" << std::endl;
+            print_destination(&pair.second);
+        }
+    }
     if (show_text[0]) {
         const int pages = doc->pages();
         for (int i = 0; i < pages; ++i) {
commit ec67506c3d0b1c519bb3e2f0bee90fac328e7ddb
Author: Masamichi Hosoda <trueroad at trueroad.jp>
Date:   Sat Jan 12 18:44:42 2019 +0900

    cpp: Add document::create_destination_map()
    
    Creates a map of all the named destinations in the document.

diff --git a/cpp/poppler-document.cpp b/cpp/poppler-document.cpp
index 4ce4f780..c58f9663 100644
--- a/cpp/poppler-document.cpp
+++ b/cpp/poppler-document.cpp
@@ -3,6 +3,7 @@
  * Copyright (C) 2016 Jakub Alba <jakubalba at gmail.com>
  * Copyright (C) 2017, Albert Astals Cid <aacid at kde.org>
  * Copyright (C) 2018, Adam Reichold <adam.reichold at t-online.de>
+ * Copyright (C) 2019, Masamichi Hosoda <trueroad at trueroad.jp>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,11 +20,13 @@
  * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+#include "poppler-destination.h"
 #include "poppler-document.h"
 #include "poppler-embedded-file.h"
 #include "poppler-page.h"
 #include "poppler-toc.h"
 
+#include "poppler-destination-private.h"
 #include "poppler-document-private.h"
 #include "poppler-embedded-file-private.h"
 #include "poppler-page-private.h"
@@ -34,6 +37,7 @@
 #include "DateInfo.h"
 #include "ErrorCodes.h"
 #include "GlobalParams.h"
+#include "Link.h"
 #include "Outline.h"
 
 #include <algorithm>
@@ -1023,6 +1027,58 @@ std::vector<embedded_file *> document::embedded_files() const
 }
 
 /**
+ Creates a map of all the named destinations in the %document.
+
+ \note The destination names may contain \\0 and other binary values
+ so they are not printable and cannot convert to null-terminated C strings.
+
+ \returns the map of the each name and destination
+
+ \since 0.74
+ */
+std::map<std::string, destination> document::create_destination_map() const
+{
+    std::map<std::string, destination> m;
+
+    Catalog *catalog = d->doc->getCatalog();
+    if (!catalog)
+        return m;
+
+    // Iterate from name-dict
+    const int nDests = catalog->numDests();
+    for (int i = 0; i < nDests; ++i ) {
+        std::string key(catalog->getDestsName (i));
+        LinkDest *link_dest = catalog->getDestsDest (i);
+
+        if (link_dest) {
+            destination dest(new destination_private(link_dest, d->doc));
+
+            m.emplace(std::move(key), std::move(dest));
+
+            delete link_dest;
+        }
+    }
+
+    // Iterate from name-tree
+    const int nDestsNameTree = catalog->numDestNameTree();
+    for (int i = 0; i < nDestsNameTree; ++i ) {
+        std::string key(catalog->getDestNameTreeName (i)->c_str (),
+                        catalog->getDestNameTreeName (i)->getLength ());
+        LinkDest *link_dest = catalog->getDestNameTreeDest (i);
+
+        if (link_dest) {
+            destination dest(new destination_private(link_dest, d->doc));
+
+            m.emplace(std::move(key), std::move(dest));
+
+            delete link_dest;
+        }
+    }
+
+    return m;
+}
+
+/**
  Saves the %document to file \p file_name.
 
  \returns true on success, false on failure
diff --git a/cpp/poppler-document.h b/cpp/poppler-document.h
index c2322634..07bd6eef 100644
--- a/cpp/poppler-document.h
+++ b/cpp/poppler-document.h
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2009-2010, Pino Toscano <pino at kde.org>
  * Copyright (C) 2016 Jakub Alba <jakubalba at gmail.com>
+ * Copyright (C) 2019, Masamichi Hosoda <trueroad at trueroad.jp>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,9 +24,12 @@
 #include "poppler-global.h"
 #include "poppler-font.h"
 
+#include <map>
+
 namespace poppler
 {
 
+class destination;
 class document_private;
 class embedded_file;
 class page;
@@ -106,6 +110,10 @@ public:
     bool has_embedded_files() const;
     std::vector<embedded_file *> embedded_files() const;
 
+    // Named destinations are bytestrings, not string.
+    // So we use std::string instead of ustring.
+    std::map<std::string, destination> create_destination_map() const;
+
     bool save(const std::string &filename) const;
     bool save_a_copy(const std::string &filename) const;
 
commit dbed0702722336baf3ed9fc0e780e14fcdec6f3b
Author: Masamichi Hosoda <trueroad at trueroad.jp>
Date:   Sat Jan 12 16:08:44 2019 +0900

    cpp: Add destination class
    
    The information about a destination used in a PDF document.

diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 4e049bbf..e8e8e9cc 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -9,6 +9,7 @@ configure_file(poppler-version.h.in ${CMAKE_CURRENT_BINARY_DIR}/poppler-version.
 add_subdirectory(tests)
 
 set(poppler_cpp_SRCS
+  poppler-destination.cpp
   poppler-document.cpp
   poppler-embedded-file.cpp
   poppler-font.cpp
@@ -33,6 +34,7 @@ target_link_libraries(poppler-cpp poppler ${ICONV_LIBRARIES})
 install(TARGETS poppler-cpp RUNTIME DESTINATION bin LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
 
 install(FILES
+  poppler-destination.h
   poppler-document.h
   poppler-embedded-file.h
   poppler-font.h
diff --git a/cpp/poppler-destination-private.h b/cpp/poppler-destination-private.h
new file mode 100644
index 00000000..5e9b06cc
--- /dev/null
+++ b/cpp/poppler-destination-private.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019, Masamichi Hosoda <trueroad at trueroad.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef POPPLER_DESTINATION_PRIVATE_H
+#define POPPLER_DESTINATION_PRIVATE_H
+
+#include "poppler-global.h"
+#include "poppler-destination.h"
+
+#include "Object.h"
+
+class PDFDoc;
+class LinkDest;
+
+namespace poppler
+{
+
+class destination_private
+{
+public:
+    destination_private(const LinkDest *ld, PDFDoc *doc);
+
+    destination::type_enum type;
+    bool page_number_unresolved;
+    union {
+        Ref page_ref;
+        int page_number;
+    };
+    double left, bottom;
+    double right, top;
+    double zoom;
+    bool change_left : 1, change_top : 1;
+    bool change_zoom : 1;
+
+    PDFDoc *pdf_doc;
+};
+
+}
+
+#endif
diff --git a/cpp/poppler-destination.cpp b/cpp/poppler-destination.cpp
new file mode 100644
index 00000000..2fcc98db
--- /dev/null
+++ b/cpp/poppler-destination.cpp
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2019, Masamichi Hosoda <trueroad at trueroad.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "poppler-destination.h"
+
+#include "poppler-destination-private.h"
+
+#include "PDFDoc.h"
+#include "Link.h"
+
+#include <utility>
+
+using namespace poppler;
+
+destination_private::destination_private(const LinkDest *ld, PDFDoc *doc)
+  : pdf_doc(doc)
+{
+    if (!ld) {
+        type = destination::unknown;
+        return;
+    }
+
+    switch (ld->getKind()) {
+    case ::destXYZ:
+        type = destination::xyz;
+        break;
+    case ::destFit:
+        type = destination::fit;
+        break;
+    case ::destFitH:
+        type = destination::fit_h;
+        break;
+    case ::destFitV:
+        type = destination::fit_v;
+        break;
+    case ::destFitR:
+        type = destination::fit_r;
+        break;
+    case ::destFitB:
+        type = destination::fit_b;
+        break;
+    case ::destFitBH:
+        type = destination::fit_b_h;
+        break;
+    case ::destFitBV:
+        type = destination::fit_b_v;
+        break;
+    default:
+        type = destination::unknown;
+        break;
+    }
+
+    if (!ld->isPageRef()) {
+        // The page number has been resolved.
+        page_number_unresolved = false;
+        page_number = ld->getPageNum();
+    } else if (doc) {
+        // It is necessary to resolve the page number by its accessor.
+        page_number_unresolved = true;
+        page_ref = ld->getPageRef();
+    } else {
+        // The page number cannot be resolved because there is no PDFDoc.
+        page_number_unresolved = false;
+        page_number = 0;
+    }
+
+    left = ld->getLeft();
+    bottom = ld->getBottom();
+    right = ld->getRight();
+    top = ld->getTop();
+    zoom = ld->getZoom();
+    change_left = ld->getChangeLeft();
+    change_top = ld->getChangeTop();
+    change_zoom = ld->getChangeZoom();
+}
+
+/**
+ \class poppler::destination poppler-destination.h "poppler/cpp/poppler-destination.h"
+
+ The information about a destination used in a PDF %document.
+ */
+
+/**
+ \enum poppler::destination::type_enum
+
+ The various types of destinations available in a PDF %document.
+*/
+/**
+ \var poppler::destination::type_enum poppler::destination::unknown
+
+ unknown destination
+*/
+/**
+ \var poppler::destination::type_enum poppler::destination::xyz
+
+ go to page with coordinates (left, top) positioned at the upper-left
+ corner of the window and the contents of the page magnified
+ by the factor zoom
+*/
+/**
+ \var poppler::destination::type_enum poppler::destination::fit
+
+ go to page with its contents magnified just enough to fit the entire page
+ within the window both horizontally and vertically
+*/
+/**
+ \var poppler::destination::type_enum poppler::destination::fit_h
+
+ go to page with the vertical coordinate top positioned at the top edge
+ of the window and the contents of the page magnified just enough to fit
+ the entire width of the page within the window
+*/
+/**
+ \var poppler::destination::type_enum poppler::destination::fit_v
+
+ go to page with the horizontal coordinate left positioned at the left edge
+ of the window and the contents of the page magnified just enough to fit
+ the entire height of the page within the window
+*/
+/**
+ \var poppler::destination::type_enum poppler::destination::fit_r
+
+ go to page with its contents magnified just enough to fit the rectangle
+ specified by the coordinates left, bottom, right, and top entirely
+ within the window both horizontally and vertically
+*/
+/**
+ \var poppler::destination::type_enum poppler::destination::fit_b
+
+ go to page with its contents magnified just enough to fit its bounding box
+ entirely within the window both horizontally and vertically
+*/
+/**
+ \var poppler::destination::type_enum poppler::destination::fit_b_h
+
+ go to page with the vertical coordinate top positioned at the top edge
+ of the window and the contents of the page magnified just enough to fit
+ the entire width of its bounding box within the window
+*/
+/**
+ \var poppler::destination::type_enum poppler::destination::fit_b_v
+
+ go to page with the horizontal coordinate left positioned at the left edge
+ of the window and the contents of the page magnified just enough to fit
+ the entire height of its bounding box within the window
+*/
+
+
+destination::destination(destination_private *dd)
+  : d(dd)
+{
+}
+
+/**
+ Move constructor.
+ */
+destination::destination(destination &&other)
+{
+    *this = std::move(other);
+}
+
+/**
+ \returns the type of the destination
+ */
+destination::type_enum destination::type() const
+{
+    return d->type;
+}
+
+/**
+ \note It is necessary not to destruct parent poppler::document
+ before calling this function for the first time.
+
+ \returns the page number of the destination
+ */
+int destination::page_number() const
+{
+    if (d->page_number_unresolved) {
+        d->page_number_unresolved = false;
+        d->page_number =
+            d->pdf_doc->findPage(d->page_ref.num, d->page_ref.gen);
+    }
+
+    return d->page_number;
+}
+
+/**
+ \returns the left coordinate of the destination
+ */
+double destination::left() const
+{
+    return d->left;
+}
+
+/**
+ \returns the bottom coordinate of the destination
+ */
+double destination::bottom() const
+{
+    return d->bottom;
+}
+
+/**
+ \returns the right coordinate of the destination
+ */
+double destination::right() const
+{
+    return d->right;
+}
+
+/**
+ \returns the top coordinate of the destination
+ */
+double destination::top() const
+{
+    return d->top;
+}
+
+/**
+ \returns the scale factor of the destination
+ */
+double destination::zoom() const
+{
+    return d->zoom;
+}
+
+/**
+ \returns whether left coordinate should be changed
+ */
+bool destination::is_change_left() const
+{
+    return d->change_left;
+}
+
+/**
+ \returns whether top coordinate should be changed
+ */
+bool destination::is_change_top() const
+{
+    return d->change_top;
+}
+
+/**
+ \returns whether scale factor should be changed
+ */
+bool destination::is_change_zoom() const
+{
+    return d->change_zoom;
+}
+
+/**
+ Move assignment operator.
+ */
+destination& destination::operator=(destination &&other)
+{
+    if (this != &other) {
+        d = other.d;
+        other.d = nullptr;
+    }
+
+    return *this;
+}
+
+/**
+ Destructor.
+ */
+destination::~destination()
+{
+    delete d;
+}
diff --git a/cpp/poppler-destination.h b/cpp/poppler-destination.h
new file mode 100644
index 00000000..964c1b5f
--- /dev/null
+++ b/cpp/poppler-destination.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019, Masamichi Hosoda <trueroad at trueroad.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef POPPLER_DESTINATION_H
+#define POPPLER_DESTINATION_H
+
+#include "poppler-global.h"
+
+namespace poppler
+{
+class destination_private;
+
+class POPPLER_CPP_EXPORT destination : public poppler::noncopyable
+{
+public:
+    enum type_enum {
+        unknown,
+        xyz,
+        fit,
+        fit_h,
+        fit_v,
+        fit_r,
+        fit_b,
+        fit_b_h,
+        fit_b_v
+    };
+
+    ~destination();
+    destination(destination &&other);
+
+    type_enum type() const;
+    int page_number() const;
+    double left() const;
+    double bottom() const;
+    double right() const;
+    double top() const;
+    double zoom() const;
+    bool is_change_left() const;
+    bool is_change_top() const;
+    bool is_change_zoom() const;
+
+    destination& operator=(destination &&other);
+
+private:
+    destination(destination_private *dd);
+
+    destination_private *d;
+    friend class document;
+};
+
+}
+
+#endif


More information about the poppler mailing list