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 <[email protected]> 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 <[email protected]> * Copyright (C) 2017, Jason Alan Palmer <[email protected]> * Copyright (C) 2018, Suzuki Toshiya <[email protected]> + * Copyright (C) 2019, Masamichi Hosoda <[email protected]> * * 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 <[email protected]> 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 <[email protected]> * Copyright (C) 2017, Albert Astals Cid <[email protected]> * Copyright (C) 2018, Adam Reichold <[email protected]> + * Copyright (C) 2019, Masamichi Hosoda <[email protected]> * * 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 <[email protected]> * Copyright (C) 2016 Jakub Alba <[email protected]> + * Copyright (C) 2019, Masamichi Hosoda <[email protected]> * * 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 <[email protected]> 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 <[email protected]> + * + * 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 <[email protected]> + * + * 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 <[email protected]> + * + * 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 _______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
